v0.9.0: added info on talents to the hero select UI

This commit is contained in:
Evan Debenham 2020-09-20 17:26:26 -04:00
parent 0913c65d81
commit afb53fe171
7 changed files with 84 additions and 46 deletions

View File

@ -348,30 +348,26 @@ actors.hero.hero.pain_resist=The pain helps you resist the urge to sleep.
actors.hero.hero.revive=The ankh explodes with life-giving energy!
actors.hero.heroclass.warrior=warrior
actors.hero.heroclass.warrior_desc_item=The Warrior starts with a _unique broken seal,_ which he can affix to armor.\n\nHe will slowly generate shielding over his health while he is wearing armor with the seal affixed.\n\nThe seal can be moved between armor, carrying a single upgrade with it.
actors.hero.heroclass.warrior_desc_innate=The Warrior starts with a _unique broken seal,_ which he can affix to armor. He will slowly generate shielding over his health while he is wearing armor with the seal affixed. The seal can be moved between armor, carrying a single upgrade with it.\n\nThe Warrior automatically identifies:\n- Scrolls of Identify\n- Potions of Healing\n- Scrolls of Rage
actors.hero.heroclass.warrior_desc_loadout=The Warrior starts with a _worn shortsword,_ which offers more direct damage than other starter weapons.\n\nThe Warrior starts with _three throwing stones,_ which offer limited ranged damage.\n\nThe Warrior starts with a _potion bandolier,_ which can store various potions and protect them from the cold.
actors.hero.heroclass.warrior_desc_misc=The Warrior regains a small amount of HP whenever he eats food.\n\nThe Warrior automatically identifies:\n- Scrolls of Identify\n- Potions of Healing\n- Scrolls of Rage
actors.hero.heroclass.warrior_desc_subclasses=A subclass can be chosen after defeating the second boss. The Warrior has two subclasses:
actors.hero.heroclass.mage=mage
actors.hero.heroclass.mage_unlock=The Mage is an expert with wands, and carries a _unique magical staff._\n\nTo unlock him _use a scroll of upgrade to make an item stronger._
actors.hero.heroclass.mage_desc_item=The Mage starts with a _unique staff,_ which can be imbued with the properties of a wand.\n\nThe staff recharges significantly faster than a wand, and has 1 more maximum charge.\n\nThe staff starts out imbued with magic missile.
actors.hero.heroclass.mage_desc_innate=The Mage starts with a _unique staff,_ which can be imbued with the properties of a wand. The staff recharges significantly faster than a wand, and has 1 more maximum charge. The staff starts out imbued with magic missile.\n\nThe Mage automatically identifies:\n- Scrolls of Identify\n- Potions of Liquid Flame\n- Scrolls of Upgrade
actors.hero.heroclass.mage_desc_loadout=The Mage starts with his staff as his melee weapon. The staff deals less melee damage than other starter weapons.\n\nThe Mage can use the magic in his staff to attack at range.\n\nThe Mage starts with a _scroll holder,_ which can store various scrolls and protect them from fire.
actors.hero.heroclass.mage_desc_misc=The Mage partially identifies wands the moment he uses them.\n\nThe Mage regains a small amount of wand and staff charge whenever he eats food.\n\nThe Mage automatically identifies:\n- Scrolls of Identify\n- Potions of Liquid Flame\n- Scrolls of Upgrade
actors.hero.heroclass.mage_desc_subclasses=A subclass can be chosen after defeating the second boss. The Mage has two subclasses:
actors.hero.heroclass.rogue=rogue
actors.hero.heroclass.rogue_unlock=The Rogue can control the flow of battle and strike from invisibility using his _unique cloak of shadows._\n\nTo unlock him _perform 10 surprise attacks in one run._
actors.hero.heroclass.rogue_desc_item=The Rogue starts with a unique artifact: the _Cloak of Shadows,_ which he can use to become invisible at will.\n\nLike all artifacts, the cloak cannot be directly upgraded. Instead it becomes more powerful as it is used.
actors.hero.heroclass.rogue_desc_innate=The Rogue starts with a unique artifact: the _Cloak of Shadows,_ which he can use to become invisible at will. Like all artifacts, the cloak cannot be directly upgraded. Instead it becomes more powerful as it is used.\n\nThe Rogue detects secrets and traps from a greater distance.\n\nThe Rogue is able to find more secrets hidden in the dungeon.\n\nThe Rogue automatically identifies:\n- Scrolls of Identify\n- Potions of Invisibility\n- Scrolls of Magic Mapping
actors.hero.heroclass.rogue_desc_loadout=The Rogue starts with a _dagger,_ which deals more damage when surprising enemies.\n\nThe Rogue starts with _three throwing knives,_ which offer some ranged damage and deal more damage to surprised enemies.\n\nThe Rogue starts with a _velvet pouch,_ which can store small items like seeds and runestones.
actors.hero.heroclass.rogue_desc_misc=The Rogue detects secrets and traps from a greater distance.\n\nThe Rogue is able to find more secrets hidden in the dungeon.\n\nThe Rogue automatically identifies:\n- Scrolls of Identify\n- Potions of Invisibility\n- Scrolls of Magic Mapping
actors.hero.heroclass.rogue_desc_subclasses=A subclass can be chosen after defeating the second boss. The Rogue has two subclasses:
actors.hero.heroclass.huntress=huntress
actors.hero.heroclass.huntress_unlock=The Huntress is a master of thrown weapons, and has a _unique magical bow_ with infinite arrows.\n\nTo unlock her _hit 15 enemies with thrown weapons in one run._
actors.hero.heroclass.huntress_desc_item=The Huntress starts with a _unique spirit bow,_ which can fire an infinite number of conjured arrows.\n\nThe bow steadily grows stronger as the huntress levels up, and can be augmented and enchanted.
actors.hero.heroclass.huntress_desc_innate=The Huntress starts with a _unique spirit bow,_ which can fire an infinite number of conjured arrows. The bow steadily grows stronger as the huntress levels up, and can be augmented and enchanted.\n\nThe Huntress can travel through tall grass without trampling it.\n\nThe Huntress can use thrown weapons for longer before they break.\n\nThe Huntress senses nearby enemies even if they are hidden behind obstacles.\n\nThe Huntress automatically identifies:\n- Scrolls of Identify\n- Potions of Mind Vision\n- Scrolls of Lullaby
actors.hero.heroclass.huntress_desc_loadout=The Huntress starts with a pair of _studded gloves,_ which attack much faster than other starter weapons.\n\nThe Huntress starts with her bow as a ranged option.\n\nThe Huntress starts with a _velvet pouch,_ which can store small items like seeds and runestones.
actors.hero.heroclass.huntress_desc_misc=The Huntress can travel through tall grass without trampling it.\n\nThe Huntress can use thrown weapons for longer before they break.\n\nThe Huntress senses nearby enemies even if they are hidden behind obstacles.\n\nThe Huntress automatically identifies:\n- Scrolls of Identify\n- Potions of Mind Vision\n- Scrolls of Lullaby
actors.hero.heroclass.huntress_desc_subclasses=A subclass can be chosen after defeating the second boss. The Huntress has two subclasses:
actors.hero.herosubclass.gladiator=gladiator

View File

@ -35,6 +35,13 @@ scenes.gamescene.choose_examine=Choose Examine
scenes.gamescene.multiple_examine=There are multiple things of interest here, which one do you want to examine?
scenes.gamescene.dont_know=You don't know what is there.
scenes.heroselectscene.title=Choose Your Hero
scenes.heroselectscene$wndheroinfo.innate_title=innate powers
scenes.heroselectscene$wndheroinfo.loadout_title=loadout
scenes.heroselectscene$wndheroinfo.talents_title=talents
scenes.heroselectscene$wndheroinfo.talents_desc=Talents are unlocked as the hero levels up.
scenes.heroselectscene$wndheroinfo.subclasses_title=subclasses
scenes.interlevelscene$mode.descend=Descending...
scenes.interlevelscene$mode.ascend=Ascending...
scenes.interlevelscene$mode.continue=Loading...

View File

@ -51,7 +51,7 @@ windows.wndimp.reward=Take the ring
windows.wndinfocell.nothing=Nothing interesting here.
windows.wndinfotalent.upgrade=Upgrade Talent.
windows.wndinfotalent.upgrade=Upgrade Talent
windows.wndinfotrap.inactive=This trap is inactive, and can no longer be triggered.
@ -182,10 +182,6 @@ windows.wndsettings$langstab.credits=credits
windows.wndsettings$langstab.reviewers=reviewers
windows.wndsettings$langstab.translators=translators
windows.wndstartgame.title=Choose Your Hero
windows.wndstartgame.huntress_unlock=Defeat the boss on floor 15 to unlock this character
windows.wndstartgame.start=Start Game
windows.wndstory.sewers=The Dungeon lies right beneath the City, its upper levels actually constitute the City's sewer system.\n\nAs dark energy has crept up from below the usually harmless sewer creatures have become more and more dangerous. The city sends guard patrols down here to try and maintain safety for those above, but they are slowly failing.\n\nThis place is dangerous, but at least the evil magic at work here is weak.
windows.wndstory.prison=Many years ago a prison was built here to house dangerous criminals. Tightly regulated and secure, convicts from all over the land were brought here to serve time.\n\nBut soon dark miasma started to creep from below, twisting the minds of guard and prisoner alike.\n\nIn response to the mounting chaos, the city sealed off the entire prison. Nobody knows what became of those who were left for dead within these walls...
windows.wndstory.caves=These sparsely populated caves stretch down under the abandoned prison. Rich in minerals, they were once a center of bustling trade and industry for the dwarven society below, but they were abandoned as the dwarves became obsessed with dark magic.\n\nThe caves are now mostly inhabited by subterranean wildlife, gnolls, and derelict machinery; likely corrupted by the same power that has affected the regions above.

View File

@ -197,14 +197,18 @@ public enum Talent {
private static final int TALENT_TIERS = 1;
public static void initClassTalents( Hero hero ){
while (hero.talents.size() < TALENT_TIERS){
hero.talents.add(new LinkedHashMap<>());
initClassTalents( hero.heroClass, hero.talents );
}
public static void initClassTalents( HeroClass cls, ArrayList<LinkedHashMap<Talent, Integer>> talents ){
while (talents.size() < TALENT_TIERS){
talents.add(new LinkedHashMap<>());
}
ArrayList<Talent> tierTalents = new ArrayList<>();
//tier 1
switch (hero.heroClass){
switch (cls){
case WARRIOR: default:
Collections.addAll(tierTalents, HEARTY_MEAL, ARMSMASTERS_INTUITION, TEST_SUBJECT, IRON_WILL);
break;
@ -219,7 +223,7 @@ public enum Talent {
break;
}
for (Talent talent : tierTalents){
hero.talents.get(0).put(talent, 0);
talents.get(0).put(talent, 0);
}
tierTalents.clear();

View File

@ -21,7 +21,6 @@
package com.shatteredpixel.shatteredpixeldungeon.scenes;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Chrome;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
@ -31,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
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.journal.Journal;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
@ -41,10 +41,10 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.StyledButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.TalentsPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndChallenges;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndMessage;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStartGame;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTabbed;
import com.watabou.gltextures.TextureCache;
import com.watabou.input.PointerEvent;
@ -56,6 +56,7 @@ import com.watabou.utils.DeviceCompat;
import com.watabou.utils.GameMath;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class HeroSelectScene extends PixelScene {
@ -108,7 +109,7 @@ public class HeroSelectScene extends PixelScene {
add(fadeRight);
}
prompt = PixelScene.renderTextBlock(Messages.get(WndStartGame.class, "title"), 12);
prompt = PixelScene.renderTextBlock(Messages.get(this, "title"), 12);
prompt.hardlight(Window.TITLE_COLOR);
prompt.setPos( (Camera.main.width - prompt.width())/2f, (Camera.main.height - HeroBtn.HEIGHT - prompt.height() - 4));
PixelScene.align(prompt);
@ -328,14 +329,30 @@ public class HeroSelectScene extends PixelScene {
private static class WndHeroInfo extends WndTabbed {
private RenderedTextBlock title;
private RenderedTextBlock info;
private TalentsPane talents;
private int WIDTH = 120;
private int MARGIN = 4;
private int HEIGHT = 120;
private int MARGIN = 2;
private int INFO_WIDTH = WIDTH - MARGIN*2;
public WndHeroInfo( HeroClass cl ){
title = PixelScene.renderTextBlock(9);
title.hardlight(TITLE_COLOR);
add(title);
info = PixelScene.renderTextBlock(6);
add(info);
ArrayList<LinkedHashMap<Talent, Integer>> talentList = new ArrayList<>();
Talent.initClassTalents(cl, talentList);
talents = new TalentsPane(false, talentList);
add(talents);
Tab tab;
Image[] tabIcons;
switch (cl){
@ -343,28 +360,28 @@ public class HeroSelectScene extends PixelScene {
tabIcons = new Image[]{
new ItemSprite(ItemSpriteSheet.SEAL, null),
new ItemSprite(ItemSpriteSheet.WORN_SHORTSWORD, null),
new ItemSprite(ItemSpriteSheet.RATION, null)
new ItemSprite(ItemSpriteSheet.ARMOR_WARRIOR, null)
};
break;
case MAGE:
tabIcons = new Image[]{
new ItemSprite(ItemSpriteSheet.MAGES_STAFF, null),
new ItemSprite(ItemSpriteSheet.HOLDER, null),
new ItemSprite(ItemSpriteSheet.WAND_MAGIC_MISSILE, null)
new ItemSprite(ItemSpriteSheet.ARMOR_MAGE, null)
};
break;
case ROGUE:
tabIcons = new Image[]{
new ItemSprite(ItemSpriteSheet.ARTIFACT_CLOAK, null),
new ItemSprite(ItemSpriteSheet.DAGGER, null),
Icons.get(Icons.DEPTH)
new ItemSprite(ItemSpriteSheet.ARMOR_ROGUE, null),
};
break;
case HUNTRESS:
tabIcons = new Image[]{
new ItemSprite(ItemSpriteSheet.SPIRIT_BOW, null),
new ItemSprite(ItemSpriteSheet.GLOVES, null),
new Image(Assets.Environment.TILES_SEWERS, 112, 96, 16, 16 )
new ItemSprite(ItemSpriteSheet.ARMOR_HUNTRESS, null)
};
break;
}
@ -374,7 +391,8 @@ public class HeroSelectScene extends PixelScene {
protected void select(boolean value) {
super.select(value);
if (value){
info.text(Messages.get(cl, cl.name() + "_desc_item"), INFO_WIDTH);
title.text(Messages.titleCase(Messages.get(WndHeroInfo.class, "innate_title")));
info.text(Messages.get(cl, cl.name() + "_desc_innate"), INFO_WIDTH);
}
}
};
@ -385,6 +403,7 @@ public class HeroSelectScene extends PixelScene {
protected void select(boolean value) {
super.select(value);
if (value){
title.text(Messages.titleCase(Messages.get(WndHeroInfo.class, "loadout_title")));
info.text(Messages.get(cl, cl.name() + "_desc_loadout"), INFO_WIDTH);
}
}
@ -396,8 +415,10 @@ public class HeroSelectScene extends PixelScene {
protected void select(boolean value) {
super.select(value);
if (value){
info.text(Messages.get(cl, cl.name() + "_desc_misc"), INFO_WIDTH);
title.text(Messages.titleCase(Messages.get(WndHeroInfo.class, "talents_title")));
info.text(Messages.get(WndHeroInfo.class, "talents_desc"), INFO_WIDTH);
}
talents.visible = talents.active = value;
}
};
add(tab);
@ -407,6 +428,7 @@ public class HeroSelectScene extends PixelScene {
protected void select(boolean value) {
super.select(value);
if (value){
title.text(Messages.titleCase(Messages.get(WndHeroInfo.class, "subclasses_title")));
String msg = Messages.get(cl, cl.name() + "_desc_subclasses");
for (HeroSubClass sub : cl.subClasses()){
msg += "\n\n" + sub.desc();
@ -417,10 +439,6 @@ public class HeroSelectScene extends PixelScene {
};
add(tab);
info = PixelScene.renderTextBlock(6);
info.setPos(MARGIN, MARGIN);
add(info);
select(0);
}
@ -428,8 +446,20 @@ public class HeroSelectScene extends PixelScene {
@Override
public void select(Tab tab) {
super.select(tab);
resize(WIDTH, (int)info.bottom()+MARGIN);
title.setPos((WIDTH-title.width())/2, MARGIN);
info.setPos(MARGIN, title.bottom()+2*MARGIN);
talents.setRect(0, info.bottom()+2*MARGIN, WIDTH, 100);
if (talents.visible) {
resize(WIDTH, (int) talents.bottom());
talents.setRect(0, info.bottom()+2*MARGIN, WIDTH, 100);
} else {
resize(WIDTH, (int) info.bottom() + 2*MARGIN);
}
layoutTabs();
}
}
}

View File

@ -47,6 +47,7 @@ public class TalentButton extends Button {
private TextureFilm film;
Talent talent;
int pointsInTalent;
boolean upgradeEnabled;
Image icon;
@ -54,9 +55,10 @@ public class TalentButton extends Button {
ColorBlock fill;
public TalentButton(Talent talent, boolean upgradeEnabled){
public TalentButton(Talent talent, int points, boolean upgradeEnabled){
super();
this.talent = talent;
this.pointsInTalent = points;
this.upgradeEnabled = upgradeEnabled;
icon.frame( film.get( talent.icon() ) );
@ -88,7 +90,7 @@ public class TalentButton extends Button {
fill.x = x;
fill.y = y + WIDTH - 1;
fill.size( Dungeon.hero.pointsInTalent(talent)/2f * WIDTH, 5);
fill.size( pointsInTalent/2f * WIDTH, 5);
bg.x = x;
bg.y = y;

View File

@ -31,6 +31,7 @@ import com.watabou.noosa.Image;
import com.watabou.noosa.ui.Component;
import java.util.ArrayList;
import java.util.LinkedHashMap;
//TODO some stuff here is currently coded without accounting for tiers
public class TalentsPane extends ScrollPane {
@ -38,24 +39,28 @@ public class TalentsPane extends ScrollPane {
RenderedTextBlock title;
ArrayList<TalentButton> buttons;
ArrayList<Image> stars;
ArrayList<Image> stars = new ArrayList<>();
ColorBlock sep;
ColorBlock blocker;
RenderedTextBlock blockText;
public TalentsPane( boolean canUpgrade ) {
this( canUpgrade, Dungeon.hero.talents );
}
public TalentsPane( boolean canUpgrade, ArrayList<LinkedHashMap<Talent, Integer>> talents ) {
super(new Component());
title = PixelScene.renderTextBlock(Messages.titleCase(Messages.get(this, "tier", 1)), 9);
title.hardlight(Window.TITLE_COLOR);
content.add(title);
setupStars();
if (canUpgrade) setupStars();
buttons = new ArrayList<>();
for (Talent talent : Dungeon.hero.talents.get(0).keySet()){
TalentButton btn = new TalentButton(talent, canUpgrade){
for (Talent talent : talents.get(0).keySet()){
TalentButton btn = new TalentButton(talent, talents.get(0).get(talent), canUpgrade){
@Override
public void upgradeTalent() {
super.upgradeTalent();
@ -78,13 +83,11 @@ public class TalentsPane extends ScrollPane {
}
private void setupStars(){
if (stars != null){
if (!stars.isEmpty()){
for (Image im : stars){
im.killAndErase();
}
stars.clear();
} else {
stars = new ArrayList<>();
}
int totStars = 5;
@ -108,7 +111,7 @@ public class TalentsPane extends ScrollPane {
float titleWidth = title.width();
titleWidth += 2 + stars.size()*6;
title.setPos(x + (width - titleWidth)/2f, y+2);
title.setPos((width - titleWidth)/2f, 2);
float left = title.right() + 2;
for (Image star : stars){
@ -119,21 +122,21 @@ public class TalentsPane extends ScrollPane {
}
float gap = (width - buttons.size()*TalentButton.WIDTH)/(buttons.size()+1);
left = x + gap;
left = gap;
for (TalentButton btn : buttons){
btn.setPos(left, title.bottom() + 4);
PixelScene.align(btn);
left += btn.width() + gap;
}
sep.x = x;
sep.x = 0;
sep.y = buttons.get(0).bottom() + 2;
sep.size(width, 1);
blocker.x = x;
blocker.x = 0;
blocker.y = sep.y + 1;
blocker.size(width, height - sep.y - 1);
blockText.setPos(x + (width - blockText.width())/2f, blocker.y + 10);
blockText.setPos((width - blockText.width())/2f, blocker.y + 10);
}
}