diff --git a/core/src/main/assets/interfaces/talent_icons.png b/core/src/main/assets/interfaces/talent_icons.png index 22ce9c915..ee6714906 100644 Binary files a/core/src/main/assets/interfaces/talent_icons.png and b/core/src/main/assets/interfaces/talent_icons.png differ diff --git a/core/src/main/assets/messages/ui/ui.properties b/core/src/main/assets/messages/ui/ui.properties index 6878bd6aa..7e35ff495 100644 --- a/core/src/main/assets/messages/ui/ui.properties +++ b/core/src/main/assets/messages/ui/ui.properties @@ -2,6 +2,7 @@ ui.quickslotbutton.select_item=Quickslot an item ui.talentspane.tier=tier %d ui.talentspane.unlock_tier2=Reach level 6 to unlock more talents. +ui.talentspane.unlock_tier3=Reach level 12 and choose a subclass to unlock more talents. ui.talentspane.coming_soon=More talents coming soon! ui.toolbar.examine_prompt=Press again to search\nPress a tile to examine diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java index e661187e1..c5f5c7ab5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java @@ -66,45 +66,49 @@ import java.util.LinkedHashMap; public enum Talent { - HEARTY_MEAL(0), - ARMSMASTERS_INTUITION(1), - TEST_SUBJECT(2), - IRON_WILL(3), - IRON_STOMACH(4), - RESTORED_WILLPOWER(5), - RUNIC_TRANSFERENCE(6), - LETHAL_MOMENTUM(7), - IMPROVISED_PROJECTILES(8), + //Warrior T1 + HEARTY_MEAL(0), ARMSMASTERS_INTUITION(1), TEST_SUBJECT(2), IRON_WILL(3), + //Warrior T2 + IRON_STOMACH(4), RESTORED_WILLPOWER(5), RUNIC_TRANSFERENCE(6), LETHAL_MOMENTUM(7), IMPROVISED_PROJECTILES(8), + //Warrior T3 + WARRIOR_T3_1(9), WARRIOR_T3_2(10), WARRIOR_T3_3(11), + //Berserker T3 + BERSERKER_T3_1(12), BERSERKER_T3_2(13), BERSERKER_T3_3(14), + //Gladiator T3 + GLADIATOR_T3_1(15), GLADIATOR_T3_2(16), GLADIATOR_T3_3(17), - EMPOWERING_MEAL(16), - SCHOLARS_INTUITION(17), - TESTED_HYPOTHESIS(18), - BACKUP_BARRIER(19), - ENERGIZING_MEAL(20), - ENERGIZING_UPGRADE(21), - WAND_PRESERVATION(22), - ARCANE_VISION(23), - SHIELD_BATTERY(24), + //Mage T1 + EMPOWERING_MEAL(32), SCHOLARS_INTUITION(33), TESTED_HYPOTHESIS(34), BACKUP_BARRIER(35), + //Mage T2 + ENERGIZING_MEAL(36), ENERGIZING_UPGRADE(37), WAND_PRESERVATION(38), ARCANE_VISION(39), SHIELD_BATTERY(40), + //Mage T3 + MAGE_T3_1(41), MAGE_T3_2(42), MAGE_T3_3(43), + //Battlemage T3 + BATTLEMAGE_T3_1(44), BATTLEMAGE_T3_2(45), BATTLEMAGE_T3_3(46), + //Warlock T3 + WARLOCK_T3_1(47), WARLOCK_T3_2(48), WARLOCK_T3_3(49), - CACHED_RATIONS(32), - THIEFS_INTUITION(33), - SUCKER_PUNCH(34), - PROTECTIVE_SHADOWS(35), - MYSTICAL_MEAL(36), - MYSTICAL_UPGRADE(37), - WIDE_SEARCH(38), - SILENT_STEPS(39), - ROGUES_FORESIGHT(40), + //Rogue T1 + CACHED_RATIONS(64), THIEFS_INTUITION(65), SUCKER_PUNCH(66), PROTECTIVE_SHADOWS(67), + //Rogue T2 + MYSTICAL_MEAL(68), MYSTICAL_UPGRADE(69), WIDE_SEARCH(70), SILENT_STEPS(71), ROGUES_FORESIGHT(72), + //Rogue T3 + ROGUE_T3_1(73), ROGUE_T3_2(74), ROGUE_T3_3(75), + //Assassin T3 + ASSASSIN_T3_1(76), ASSASSIN_T3_2(77), ASSASSIN_T3_3(78), + //Freerunner T3 + FREERUNNER_T3_1(79), FREERUNNER_T3_2(80), FREERUNNER_T3_3(81), - NATURES_BOUNTY(48), - SURVIVALISTS_INTUITION(49), - FOLLOWUP_STRIKE(50), - NATURES_AID(51), - INVIGORATING_MEAL(52), - RESTORED_NATURE(53), - REJUVENATING_STEPS(54), - HEIGHTENED_SENSES(55), - DURABLE_PROJECTILES(56); + //Huntress T1 + NATURES_BOUNTY(96), SURVIVALISTS_INTUITION(97), FOLLOWUP_STRIKE(98), NATURES_AID(99), + //Huntress T2 + INVIGORATING_MEAL(100), RESTORED_NATURE(101), REJUVENATING_STEPS(102), HEIGHTENED_SENSES(103), DURABLE_PROJECTILES(104), + //Huntress T3 + HUNTRESS_T3_1(105), HUNTRESS_T3_2(106), HUNTRESS_T3_3(107), + //Sniper T3 + SNIPER_T3_1(108), SNIPER_T3_2(109), SNIPER_T3_3(110), + //Warden T3 + WARDEN_T3_1(111), WARDEN_T3_2(112), WARDEN_T3_3(113); public static class ImprovisedProjectileCooldown extends FlavourBuff{}; public static class LethalMomentumTracker extends FlavourBuff{}; @@ -349,7 +353,7 @@ public enum Talent { public static class SuckerPunchTracker extends Buff{}; public static class FollowupStrikeTracker extends Buff{}; - public static final int MAX_TALENT_TIERS = 2; + public static final int MAX_TALENT_TIERS = 3; public static void initClassTalents( Hero hero ){ initClassTalents( hero.heroClass, hero.talents ); @@ -382,7 +386,7 @@ public enum Talent { } tierTalents.clear(); - //tier 2+ + //tier 2 switch (cls){ case WARRIOR: default: Collections.addAll(tierTalents, IRON_STOMACH, RESTORED_WILLPOWER, RUNIC_TRANSFERENCE, LETHAL_MOMENTUM, IMPROVISED_PROJECTILES); @@ -402,13 +406,77 @@ public enum Talent { } tierTalents.clear(); + //tier 3 + switch (cls){ + case WARRIOR: default: + Collections.addAll(tierTalents, WARRIOR_T3_1, WARRIOR_T3_2, WARRIOR_T3_3); + break; + case MAGE: + Collections.addAll(tierTalents, MAGE_T3_1, MAGE_T3_2, MAGE_T3_3); + break; + case ROGUE: + Collections.addAll(tierTalents, ROGUE_T3_1, ROGUE_T3_2, ROGUE_T3_3); + break; + case HUNTRESS: + Collections.addAll(tierTalents, HUNTRESS_T3_1, HUNTRESS_T3_2, HUNTRESS_T3_3); + break; + } + for (Talent talent : tierTalents){ + talents.get(2).put(talent, 0); + } + tierTalents.clear(); - //tier 3+ + //tier4 //TBD } public static void initSubclassTalents( Hero hero ){ - //Nothing here yet. Hm..... + initSubclassTalents( hero.subClass, hero.talents ); + } + + public static void initSubclassTalents( HeroSubClass cls, ArrayList> talents ){ + if (cls == HeroSubClass.NONE) return; + + while (talents.size() < MAX_TALENT_TIERS){ + talents.add(new LinkedHashMap<>()); + } + + ArrayList tierTalents = new ArrayList<>(); + + //tier 3 + switch (cls){ + case BERSERKER: default: + Collections.addAll(tierTalents, BERSERKER_T3_1, BERSERKER_T3_2, BERSERKER_T3_3); + break; + case GLADIATOR: + Collections.addAll(tierTalents, GLADIATOR_T3_1, GLADIATOR_T3_2, GLADIATOR_T3_3); + break; + case BATTLEMAGE: + Collections.addAll(tierTalents, BATTLEMAGE_T3_1, BATTLEMAGE_T3_2, BATTLEMAGE_T3_3); + break; + case WARLOCK: + Collections.addAll(tierTalents, WARLOCK_T3_1, WARLOCK_T3_2, WARLOCK_T3_3); + break; + case ASSASSIN: + Collections.addAll(tierTalents, ASSASSIN_T3_1, ASSASSIN_T3_2, ASSASSIN_T3_3); + break; + case FREERUNNER: + Collections.addAll(tierTalents, FREERUNNER_T3_1, FREERUNNER_T3_2, FREERUNNER_T3_3); + break; + case SNIPER: + Collections.addAll(tierTalents, SNIPER_T3_1, SNIPER_T3_2, SNIPER_T3_3); + break; + case WARDEN: + Collections.addAll(tierTalents, WARDEN_T3_1, WARDEN_T3_2, WARDEN_T3_3); + break; + } + for (Talent talent : tierTalents){ + talents.get(2).put(talent, 0); + } + tierTalents.clear(); + + //tier4 + //TBD } private static final String TALENT_TIER = "talents_tier_"; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java index ae36b1060..4572e17df 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java @@ -39,6 +39,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.ExitButton; 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.StyledButton; import com.shatteredpixel.shatteredpixeldungeon.ui.TalentsPane; @@ -333,12 +334,16 @@ public class HeroSelectScene extends PixelScene { private RenderedTextBlock info; private TalentsPane talents; + private RedButton firstSub; + private RedButton secondSub; - private int WIDTH = 120; + private int WIDTH = 130; private int HEIGHT = 120; private int MARGIN = 2; private int INFO_WIDTH = WIDTH - MARGIN*2; + private static boolean secondSubclass = false; + public WndHeroInfo( HeroClass cl ){ title = PixelScene.renderTextBlock(9); @@ -350,9 +355,46 @@ public class HeroSelectScene extends PixelScene { ArrayList> talentList = new ArrayList<>(); Talent.initClassTalents(cl, talentList); + Talent.initSubclassTalents(cl.subClasses()[secondSubclass ? 1 : 0], talentList); talents = new TalentsPane(false, talentList); add(talents); + firstSub = new RedButton(Messages.titleCase(cl.subClasses()[0].title()), 7){ + @Override + protected void onClick() { + super.onClick(); + if (secondSubclass){ + secondSubclass = false; + hide(); + WndHeroInfo newWindow = new WndHeroInfo(cl); + newWindow.talents.scrollTo(0, talents.content().camera.scroll.y); + newWindow.select(2); + ShatteredPixelDungeon.scene().addToFront(newWindow); + } + } + }; + if (!secondSubclass) firstSub.textColor(Window.TITLE_COLOR); + firstSub.setSize(40, firstSub.reqHeight()+2); + add(firstSub); + + secondSub = new RedButton(Messages.titleCase(cl.subClasses()[1].title()), 7){ + @Override + protected void onClick() { + super.onClick(); + if (!secondSubclass){ + secondSubclass = true; + hide(); + WndHeroInfo newWindow = new WndHeroInfo(cl); + newWindow.talents.scrollTo(0, talents.content().camera.scroll.y); + newWindow.select(2); + ShatteredPixelDungeon.scene().addToFront(newWindow); + } + } + }; + if (secondSubclass) secondSub.textColor(Window.TITLE_COLOR); + secondSub.setSize(40, secondSub.reqHeight()+2); + add(secondSub); + Tab tab; Image[] tabIcons; switch (cl){ @@ -415,6 +457,8 @@ public class HeroSelectScene extends PixelScene { info.text(Messages.get(WndHeroInfo.class, "talents_desc"), INFO_WIDTH); } talents.visible = talents.active = value; + firstSub.visible = firstSub.active = value; + secondSub.visible = secondSub.active = value; } }; add(tab); @@ -435,6 +479,7 @@ public class HeroSelectScene extends PixelScene { }; add(tab); + resize(WIDTH, HEIGHT); select(0); } @@ -445,14 +490,13 @@ public class HeroSelectScene extends PixelScene { 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); - } + firstSub.setPos((title.left() - firstSub.width())/2, 0); + secondSub.setPos(title.right() + (WIDTH - title.right() - secondSub.width())/2, 0); + + talents.setRect(0, info.bottom()+2*MARGIN, WIDTH, HEIGHT - (info.bottom()+2*MARGIN)); + + resize(WIDTH, Math.max(HEIGHT, (int)info.bottom())); layoutTabs(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/ScrollPane.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/ScrollPane.java index 672a99bbe..5f8c1863d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/ScrollPane.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/ScrollPane.java @@ -61,6 +61,7 @@ public class ScrollPane extends Component { public void scrollTo( float x, float y ) { content.camera.scroll.set( x, y ); + thumb.y = y + height * content.camera.scroll.y / content.height(); } @Override @@ -92,7 +93,7 @@ public class ScrollPane extends Component { if (thumb.visible) { thumb.scale.set( 2, height * height / content.height() ); thumb.x = right() - thumb.width(); - thumb.y = y; + thumb.y = y + height * content.camera.scroll.y / content.height(); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java index 41202c6c6..df3b5bce1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java @@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.ui; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; @@ -58,6 +59,9 @@ public class TalentsPane extends ScrollPane { && Dungeon.hero.lvl+1 >= Talent.tierLevelThresholds[tiersAvailable+1]){ tiersAvailable++; } + if (tiersAvailable > 2 && Dungeon.hero.subClass == HeroSubClass.NONE){ + tiersAvailable = 2; + } } for (int i = 0; i < Math.min(tiersAvailable, talents.size()); i++){ @@ -78,6 +82,8 @@ public class TalentsPane extends ScrollPane { if (tiersAvailable == 1) { blockText = PixelScene.renderTextBlock(Messages.get(this, "unlock_tier2"), 6); + } else if (tiersAvailable == 2) { + blockText = PixelScene.renderTextBlock(Messages.get(this, "unlock_tier3"), 6); } else { blockText = PixelScene.renderTextBlock(Messages.get(this, "coming_soon"), 6); } @@ -102,13 +108,17 @@ public class TalentsPane extends ScrollPane { } + float bottom = Math.max(height, top + 20); + blocker.x = 0; blocker.y = top; - blocker.size(width, height - top); + blocker.size(width, bottom - top); blockText.maxWidth((int)width); blockText.align(RenderedTextBlock.CENTER_ALIGN); - blockText.setPos((width - blockText.width())/2f, blocker.y + (height - blocker.y - blockText.height())/2); + blockText.setPos((width - blockText.width())/2f, blocker.y + (bottom - blocker.y - blockText.height())/2); + + content.setSize(width, bottom); } public static class TalentTierPane extends Component { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java index 7588b4b35..03f1e680d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java @@ -48,8 +48,8 @@ import java.util.Locale; public class WndHero extends WndTabbed { - private static final int WIDTH = 120; - private static final int HEIGHT = 100; + private static final int WIDTH = 130; + private static final int HEIGHT = 120; private StatsTab stats; private TalentsTab talents; @@ -99,7 +99,11 @@ public class WndHero extends WndTabbed { } ); layoutTabs(); - + + talents.setRect(0, 0, WIDTH, HEIGHT); + talents.pane.scrollTo(0, talents.pane.content().height() - talents.pane.height()); + talents.layout(); + select( lastIdx ); }