v0.9.3: Improved the subclass and ability selection windows

This commit is contained in:
Evan Debenham 2021-05-11 21:46:49 -04:00
parent 393c759104
commit 0d7dc3bee5
8 changed files with 259 additions and 121 deletions

View File

@ -7,9 +7,15 @@ windows.wndchallenges.title=Challenges
windows.wndchooseability.message=The crown glows as it rests on your head, and both it and your armor become hot to the touch. You can feel the magic of the crown begin to act on your armor, but it must be directed. Which armor ability do you choose? windows.wndchooseability.message=The crown glows as it rests on your head, and both it and your armor become hot to the touch. You can feel the magic of the crown begin to act on your armor, but it must be directed. Which armor ability do you choose?
windows.wndchooseability.message_no_crown=Choose an ability for your armor! windows.wndchooseability.message_no_crown=Choose an ability for your armor!
windows.wndchooseability.cancel=I'll decide later windows.wndchooseability.cancel=I'll decide later
windows.wndchooseability.are_you_sure=Are you sure you want to choose this ability?
windows.wndchooseability.yes=Yes, I've made my choice.
windows.wndchooseability.no=No, I'll decide later.
windows.wndchooseway.message=As the mask fits over your face, your eyesight fades and visions of new power flood into your mind. How will you direct the mask's power? windows.wndchoosesubclass.message=As the mask fits over your face, your eyesight fades and visions of new power flood into your mind. How will you direct the mask's power?
windows.wndchooseway.cancel=I'll decide later windows.wndchoosesubclass.cancel=I'll decide later
windows.wndchoosesubclass.are_you_sure=Are you sure you want to choose this subclass?
windows.wndchoosesubclass.yes=Yes, I've made my choice.
windows.wndchoosesubclass.no=No, I'll decide later.
windows.wndclass.mastery=Mastery windows.wndclass.mastery=Mastery

View File

@ -21,7 +21,10 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.hero; package com.shatteredpixel.shatteredpixeldungeon.actors.hero;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.watabou.noosa.Image;
public enum HeroSubClass { public enum HeroSubClass {
@ -47,4 +50,35 @@ public enum HeroSubClass {
return Messages.get(this, name()+"_desc"); return Messages.get(this, name()+"_desc");
} }
//FIXME shouldn't hardcode these, probably want to just have a BuffIcon class
public Image icon(){
switch (this){
case GLADIATOR: default:
return new Image(Assets.Interfaces.BUFFS_LARGE, 16, 16, 16, 16);
case BERSERKER:
return new Image(Assets.Interfaces.BUFFS_LARGE, 32, 16, 16, 16);
case WARLOCK:
return new Image(Assets.Interfaces.BUFFS_LARGE, 64, 32, 16, 16);
case BATTLEMAGE:
Image im = new Image(Assets.Interfaces.BUFFS_LARGE, 32, 48, 16, 16);
im.hardlight(1f, 1f, 0f);
return im;
case ASSASSIN:
im = new Image(Assets.Interfaces.BUFFS_LARGE, 160, 32, 16, 16);
im.hardlight(1f, 0f, 0f);
return im;
case FREERUNNER:
im = new Image(Assets.Interfaces.BUFFS_LARGE, 48, 48, 16, 16);
im.hardlight(1f, 1f, 0f);
return im;
case SNIPER:
return new Image(Assets.Interfaces.BUFFS_LARGE, 176, 16, 16, 16);
case WARDEN:
return new Image(Assets.Interfaces.BUFFS_LARGE, 208, 0, 16, 16);
}
}
} }

View File

@ -33,7 +33,7 @@ import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndChooseWay; import com.shatteredpixel.shatteredpixeldungeon.windows.WndChooseSubclass;
import com.watabou.noosa.audio.Sample; import com.watabou.noosa.audio.Sample;
import java.util.ArrayList; import java.util.ArrayList;
@ -64,28 +64,8 @@ public class TengusMask extends Item {
if (action.equals( AC_WEAR )) { if (action.equals( AC_WEAR )) {
curUser = hero; curUser = hero;
HeroSubClass way1 = null; GameScene.show( new WndChooseSubclass( this, hero ) );
HeroSubClass way2 = null;
switch (hero.heroClass) {
case WARRIOR:
way1 = HeroSubClass.GLADIATOR;
way2 = HeroSubClass.BERSERKER;
break;
case MAGE:
way1 = HeroSubClass.BATTLEMAGE;
way2 = HeroSubClass.WARLOCK;
break;
case ROGUE:
way1 = HeroSubClass.FREERUNNER;
way2 = HeroSubClass.ASSASSIN;
break;
case HUNTRESS:
way1 = HeroSubClass.SNIPER;
way2 = HeroSubClass.WARDEN;
break;
}
GameScene.show( new WndChooseWay( this, way1, way2 ) );
} }
} }

View File

@ -0,0 +1,31 @@
package com.shatteredpixel.shatteredpixeldungeon.ui;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndHeroInfo;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTitledMessage;
import com.watabou.noosa.Image;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class WndInfoArmorAbility extends WndTitledMessage {
public WndInfoArmorAbility(HeroClass cls, ArmorAbility ability){
//TODO longer descriptions?
super( new Image(cls.spritesheet(), 0, 90, 12, 15), Messages.titleCase(ability.name()), ability.desc());
ArrayList<LinkedHashMap<Talent, Integer>> talentList = new ArrayList<>();
Talent.initArmorTalents(ability, talentList);
TalentsPane.TalentTierPane talentPane = new TalentsPane.TalentTierPane(talentList.get(3), 4, false);
talentPane.title.text( Messages.titleCase(Messages.get(WndHeroInfo.class, "talents_title")));
talentPane.setRect(0, height + 5, width, talentPane.height());
add(talentPane);
resize(width, (int) talentPane.bottom());
}
}

View File

@ -0,0 +1,31 @@
package com.shatteredpixel.shatteredpixeldungeon.ui;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndHeroInfo;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTitledMessage;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class WndInfoSubclass extends WndTitledMessage {
public WndInfoSubclass(HeroClass cls, HeroSubClass subCls){
//TODO longer subclass description?
super( subCls.icon(), Messages.titleCase(subCls.title()), subCls.desc());
ArrayList<LinkedHashMap<Talent, Integer>> talentList = new ArrayList<>();
Talent.initClassTalents(cls, talentList);
Talent.initSubclassTalents(subCls, talentList);
TalentsPane.TalentTierPane talentPane = new TalentsPane.TalentTierPane(talentList.get(2), 3, false);
talentPane.title.text( Messages.titleCase(Messages.get(WndHeroInfo.class, "talents_title")));
talentPane.setRect(0, height + 5, width, talentPane.height());
add(talentPane);
resize(width, (int) talentPane.bottom());
}
}

View File

@ -21,20 +21,29 @@
package com.shatteredpixel.shatteredpixeldungeon.windows; package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility;
import com.shatteredpixel.shatteredpixeldungeon.items.KingsCrown; import com.shatteredpixel.shatteredpixeldungeon.items.KingsCrown;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton; import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window; import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.ui.WndInfoArmorAbility;
import com.shatteredpixel.shatteredpixeldungeon.ui.WndInfoSubclass;
import com.watabou.noosa.Image;
import javax.swing.Icon;
public class WndChooseAbility extends Window { public class WndChooseAbility extends Window {
private static final int WIDTH = 120; private static final int WIDTH = 130;
private static final float GAP = 2; private static final float GAP = 2;
public WndChooseAbility(final KingsCrown crown, final Armor armor, final Hero hero){ public WndChooseAbility(final KingsCrown crown, final Armor armor, final Hero hero){
@ -63,20 +72,42 @@ public class WndChooseAbility extends Window {
RedButton abilityButton = new RedButton("_" + Messages.titleCase(ability.name()) + ":_ " + ability.desc(), 6){ RedButton abilityButton = new RedButton("_" + Messages.titleCase(ability.name()) + ":_ " + ability.desc(), 6){
@Override @Override
protected void onClick() { protected void onClick() {
super.onClick(); GameScene.show(new WndOptions(new Image(hero.heroClass.spritesheet(), 0, 90, 12, 15),
hide(); Messages.titleCase(ability.name()),
if (crown != null) { Messages.get(WndChooseAbility.this, "are_you_sure"),
crown.upgradeArmor(hero, armor, ability); Messages.get(WndChooseAbility.this, "yes"),
} else { Messages.get(WndChooseAbility.this, "no")){
new KingsCrown().upgradeArmor(hero, null, ability);
} @Override
protected void onSelect(int index) {
hide();
if (index == 0 && WndChooseAbility.this.parent != null){
WndChooseAbility.this.hide();
if (crown != null) {
crown.upgradeArmor(hero, armor, ability);
} else {
new KingsCrown().upgradeArmor(hero, null, ability);
}
}
}
});
} }
}; };
abilityButton.leftJustify = true; abilityButton.leftJustify = true;
abilityButton.multiline = true; abilityButton.multiline = true;
abilityButton.setSize(WIDTH, abilityButton.reqHeight()+2); abilityButton.setSize(WIDTH-20, abilityButton.reqHeight()+2);
abilityButton.setRect(0, pos, WIDTH, abilityButton.reqHeight()+2); abilityButton.setRect(0, pos, WIDTH-20, abilityButton.reqHeight()+2);
add(abilityButton); add(abilityButton);
IconButton abilityInfo = new IconButton(Icons.get(Icons.INFO)){
@Override
protected void onClick() {
GameScene.show(new WndInfoArmorAbility(Dungeon.hero.heroClass, ability));
}
};
abilityInfo.setRect(WIDTH-20, abilityButton.top() + (abilityButton.height()-20)/2, 20, 20);
add(abilityInfo);
pos = abilityButton.bottom() + GAP; pos = abilityButton.bottom() + GAP;
} }
@ -86,7 +117,6 @@ public class WndChooseAbility extends Window {
hide(); hide();
} }
}; };
cancelButton.setSize(WIDTH, 18);
cancelButton.setRect(0, pos, WIDTH, 18); cancelButton.setRect(0, pos, WIDTH, 18);
add(cancelButton); add(cancelButton);
pos = cancelButton.bottom() + GAP; pos = cancelButton.bottom() + GAP;

View File

@ -0,0 +1,111 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.items.TengusMask;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.ui.WndInfoSubclass;
import com.watabou.noosa.RenderedText;
public class WndChooseSubclass extends Window {
private static final int WIDTH = 130;
private static final float GAP = 2;
public WndChooseSubclass(final TengusMask tome, final Hero hero ) {
super();
IconTitle titlebar = new IconTitle();
titlebar.icon( new ItemSprite( tome.image(), null ) );
titlebar.label( tome.name() );
titlebar.setRect( 0, 0, WIDTH, 0 );
add( titlebar );
RenderedTextBlock message = PixelScene.renderTextBlock( 6 );
message.text( Messages.get(this, "message"), WIDTH );
message.setPos( titlebar.left(), titlebar.bottom() + GAP );
add( message );
float pos = message.bottom() + 3*GAP;
for (HeroSubClass subCls : hero.heroClass.subClasses()){
RedButton btnCls = new RedButton( subCls.desc(), 6 ) {
@Override
protected void onClick() {
GameScene.show(new WndOptions(subCls.icon(),
Messages.titleCase(subCls.title()),
Messages.get(WndChooseSubclass.this, "are_you_sure"),
Messages.get(WndChooseSubclass.this, "yes"),
Messages.get(WndChooseSubclass.this, "no")){
@Override
protected void onSelect(int index) {
hide();
if (index == 0 && WndChooseSubclass.this.parent != null){
WndChooseSubclass.this.hide();
tome.choose( subCls );
}
}
});
}
};
btnCls.leftJustify = true;
btnCls.multiline = true;
btnCls.setSize(WIDTH-20, btnCls.reqHeight()+2);
btnCls.setRect( 0, pos, WIDTH-20, btnCls.reqHeight()+2);
add( btnCls );
IconButton clsInfo = new IconButton(Icons.get(Icons.INFO)){
@Override
protected void onClick() {
GameScene.show(new WndInfoSubclass(Dungeon.hero.heroClass, subCls));
}
};
clsInfo.setRect(WIDTH-20, btnCls.top() + (btnCls.height()-20)/2, 20, 20);
add(clsInfo);
pos = btnCls.bottom() + GAP;
}
RedButton btnCancel = new RedButton( Messages.get(this, "cancel") ) {
@Override
protected void onClick() {
hide();
}
};
btnCancel.setRect( 0, pos, WIDTH, 18 );
add( btnCancel );
resize( WIDTH, (int)btnCancel.bottom() );
}
}

View File

@ -1,85 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.items.TengusMask;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
public class WndChooseWay extends Window {
private static final int WIDTH = 120;
private static final int BTN_HEIGHT = 18;
private static final float GAP = 2;
public WndChooseWay(final TengusMask tome, final HeroSubClass way1, final HeroSubClass way2 ) {
super();
IconTitle titlebar = new IconTitle();
titlebar.icon( new ItemSprite( tome.image(), null ) );
titlebar.label( tome.name() );
titlebar.setRect( 0, 0, WIDTH, 0 );
add( titlebar );
RenderedTextBlock hl = PixelScene.renderTextBlock( 6 );
hl.text( Messages.get(this, "message") + "\n\n" + way1.desc() + "\n\n" + way2.desc(), WIDTH );
hl.setPos( titlebar.left(), titlebar.bottom() + GAP );
add( hl );
RedButton btnWay1 = new RedButton( way1.title().toUpperCase() ) {
@Override
protected void onClick() {
hide();
tome.choose( way1 );
}
};
btnWay1.setRect( 0, hl.bottom() + GAP, (WIDTH - GAP) / 2, BTN_HEIGHT );
add( btnWay1 );
RedButton btnWay2 = new RedButton( way2.title().toUpperCase() ) {
@Override
protected void onClick() {
hide();
tome.choose( way2 );
}
};
btnWay2.setRect( btnWay1.right() + GAP, btnWay1.top(), btnWay1.width(), BTN_HEIGHT );
add( btnWay2 );
RedButton btnCancel = new RedButton( Messages.get(this, "cancel") ) {
@Override
protected void onClick() {
hide();
}
};
btnCancel.setRect( 0, btnWay2.bottom() + GAP, WIDTH, BTN_HEIGHT );
add( btnCancel );
resize( WIDTH, (int)btnCancel.bottom() );
}
}