diff --git a/core/src/main/assets/messages/scenes/scenes.properties b/core/src/main/assets/messages/scenes/scenes.properties index bee51fe43..a80bdff53 100644 --- a/core/src/main/assets/messages/scenes/scenes.properties +++ b/core/src/main/assets/messages/scenes/scenes.properties @@ -39,11 +39,6 @@ scenes.gamescene.multiple_examine=There are multiple things of interest here, wh 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... diff --git a/core/src/main/assets/messages/windows/windows.properties b/core/src/main/assets/messages/windows/windows.properties index e417cbe8c..f0f7ca7a4 100644 --- a/core/src/main/assets/messages/windows/windows.properties +++ b/core/src/main/assets/messages/windows/windows.properties @@ -48,6 +48,12 @@ windows.wndhero$statstab.health=Health windows.wndhero$statstab.gold=Gold Collected windows.wndhero$statstab.depth=Maximum Depth +windows.wndheroinfo.innate_title=innate powers +windows.wndheroinfo.loadout_title=loadout +windows.wndheroinfo.talents_title=talents +windows.wndheroinfo.talents_desc=Talents are unlocked as the hero levels up. +windows.wndheroinfo.subclasses_title=subclasses + windows.wndimp.message=Oh yes! You are my hero!\nRegarding your reward, I don't have cash with me right now, but I have something better for you. This is my family heirloom ring: my granddad took it off a dead paladin's finger. windows.wndimp.reward=Take the ring 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 fd8a67488..a9856954b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java @@ -29,24 +29,18 @@ import com.shatteredpixel.shatteredpixeldungeon.Rankings; 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; -import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; 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; import com.shatteredpixel.shatteredpixeldungeon.ui.Window; import com.shatteredpixel.shatteredpixeldungeon.windows.WndChallenges; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndHeroInfo; import com.shatteredpixel.shatteredpixeldungeon.windows.WndMessage; -import com.shatteredpixel.shatteredpixeldungeon.windows.WndTabbed; import com.watabou.gltextures.TextureCache; import com.watabou.input.PointerEvent; import com.watabou.noosa.Camera; @@ -57,7 +51,6 @@ import com.watabou.utils.DeviceCompat; import com.watabou.utils.GameMath; import java.util.ArrayList; -import java.util.LinkedHashMap; public class HeroSelectScene extends PixelScene { @@ -328,178 +321,4 @@ public class HeroSelectScene extends PixelScene { } } - private static class WndHeroInfo extends WndTabbed { - - private RenderedTextBlock title; - private RenderedTextBlock info; - - private TalentsPane talents; - private RedButton firstSub; - private RedButton secondSub; - - private int WIDTH = 120; - 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); - title.hardlight(TITLE_COLOR); - add(title); - - info = PixelScene.renderTextBlock(6); - add(info); - - 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){ - case WARRIOR: default: - tabIcons = new Image[]{ - new ItemSprite(ItemSpriteSheet.SEAL, null), - new ItemSprite(ItemSpriteSheet.WORN_SHORTSWORD, null) - }; - break; - case MAGE: - tabIcons = new Image[]{ - new ItemSprite(ItemSpriteSheet.MAGES_STAFF, null), - new ItemSprite(ItemSpriteSheet.MAGES_STAFF, null) - }; - break; - case ROGUE: - tabIcons = new Image[]{ - new ItemSprite(ItemSpriteSheet.ARTIFACT_CLOAK, null), - new ItemSprite(ItemSpriteSheet.DAGGER, null) - }; - break; - case HUNTRESS: - tabIcons = new Image[]{ - new ItemSprite(ItemSpriteSheet.SPIRIT_BOW, null), - new ItemSprite(ItemSpriteSheet.GLOVES, null) - }; - break; - } - - tab = new IconTab( tabIcons[0] ){ - @Override - protected void select(boolean value) { - super.select(value); - if (value){ - title.text(Messages.titleCase(Messages.get(WndHeroInfo.class, "innate_title"))); - info.text(Messages.get(cl, cl.name() + "_desc_innate"), INFO_WIDTH); - } - } - }; - add(tab); - - tab = new IconTab( tabIcons[1] ){ - @Override - 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); - } - } - }; - add(tab); - - tab = new IconTab( Icons.get(Icons.TALENT) ){ - @Override - protected void select(boolean value) { - super.select(value); - if (value){ - 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; - firstSub.visible = firstSub.active = value; - secondSub.visible = secondSub.active = value; - } - }; - add(tab); - - tab = new IconTab(new ItemSprite(ItemSpriteSheet.MASTERY, null)){ - @Override - 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(); - } - info.text(msg, INFO_WIDTH); - } - } - }; - add(tab); - - resize(WIDTH, HEIGHT); - select(0); - - } - - @Override - public void select(Tab tab) { - super.select(tab); - - title.setPos((WIDTH-title.width())/2, MARGIN); - info.setPos(MARGIN, title.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()+MARGIN, WIDTH, HEIGHT - (info.bottom()+MARGIN)); - - resize(WIDTH, Math.max(HEIGHT, (int)info.bottom())); - - layoutTabs(); - - } - } } 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 27eeccfa1..5f3004900 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java @@ -21,6 +21,7 @@ package com.shatteredpixel.shatteredpixeldungeon.ui; +import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; @@ -53,7 +54,15 @@ public class TalentsPane extends ScrollPane { int tiersAvailable = 1; if (!canUpgrade){ - tiersAvailable = Talent.MAX_TALENT_TIERS; + if (!Badges.isUnlocked(Badges.Badge.LEVEL_REACHED_1)){ + tiersAvailable = 1; + } else if (!Badges.isUnlocked(Badges.Badge.LEVEL_REACHED_2) || !Badges.isUnlocked(Badges.Badge.BOSS_SLAIN_2)){ + tiersAvailable = 2; + } else if (!Badges.isUnlocked(Badges.Badge.BOSS_SLAIN_4)){ + tiersAvailable = 3; + } else { + tiersAvailable = Talent.MAX_TALENT_TIERS; + } } else { while (tiersAvailable < Talent.MAX_TALENT_TIERS && Dungeon.hero.lvl+1 >= Talent.tierLevelThresholds[tiersAvailable+1]){ 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 fe8953faf..3ffb48583 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.windows; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; @@ -31,6 +32,8 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton; +import com.shatteredpixel.shatteredpixeldungeon.ui.Icons; import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane; import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane; @@ -124,9 +127,19 @@ public class WndHero extends WndTabbed { else title.label((hero.name() + "\n" + Messages.get(this, "title", hero.lvl, hero.className())).toUpperCase(Locale.ENGLISH)); title.color(Window.TITLE_COLOR); - title.setRect( 0, 0, WIDTH, 0 ); + title.setRect( 0, 0, WIDTH-16, 0 ); add(title); + IconButton infoButton = new IconButton(Icons.get(Icons.INFO)){ + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.scene().addToFront(new WndHeroInfo(hero.heroClass)); + } + }; + infoButton.setRect(title.right(), 0, 16, 16); + add(infoButton); + pos = title.bottom() + 2*GAP; statSlot( Messages.get(this, "str"), hero.STR() ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java new file mode 100644 index 000000000..c995935af --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java @@ -0,0 +1,218 @@ +/* + * 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 + */ + +package com.shatteredpixel.shatteredpixeldungeon.windows; + +import com.shatteredpixel.shatteredpixeldungeon.Badges; +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.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.shatteredpixel.shatteredpixeldungeon.ui.Icons; +import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton; +import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; +import com.shatteredpixel.shatteredpixeldungeon.ui.TalentsPane; +import com.shatteredpixel.shatteredpixeldungeon.ui.Window; +import com.watabou.noosa.Image; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +public class WndHeroInfo extends WndTabbed { + + private RenderedTextBlock title; + private RenderedTextBlock info; + + private TalentsPane talents; + private RedButton firstSub; + private RedButton secondSub; + + private int WIDTH = 120; + private int HEIGHT = 125; + private int MARGIN = 2; + private int INFO_WIDTH = WIDTH - MARGIN*2; + + private static boolean secondSubclass = false; + + public WndHeroInfo( HeroClass cl ){ + + title = PixelScene.renderTextBlock(9); + title.hardlight(TITLE_COLOR); + add(title); + + info = PixelScene.renderTextBlock(6); + add(info); + + ArrayList> talentList = new ArrayList<>(); + Talent.initClassTalents(cl, talentList); + Talent.initSubclassTalents(cl.subClasses()[secondSubclass ? 1 : 0], talentList); + talents = new TalentsPane(false, talentList); + add(talents); + + boolean subsAvailable = Badges.isUnlocked(Badges.Badge.LEVEL_REACHED_2) && Badges.isUnlocked(Badges.Badge.BOSS_SLAIN_2); + + 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); + if (subsAvailable) 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); + if (subsAvailable) add(secondSub); + + Tab tab; + Image[] tabIcons; + switch (cl){ + case WARRIOR: default: + tabIcons = new Image[]{ + new ItemSprite(ItemSpriteSheet.SEAL, null), + new ItemSprite(ItemSpriteSheet.WORN_SHORTSWORD, null) + }; + break; + case MAGE: + tabIcons = new Image[]{ + new ItemSprite(ItemSpriteSheet.MAGES_STAFF, null), + new ItemSprite(ItemSpriteSheet.MAGES_STAFF, null) + }; + break; + case ROGUE: + tabIcons = new Image[]{ + new ItemSprite(ItemSpriteSheet.ARTIFACT_CLOAK, null), + new ItemSprite(ItemSpriteSheet.DAGGER, null) + }; + break; + case HUNTRESS: + tabIcons = new Image[]{ + new ItemSprite(ItemSpriteSheet.SPIRIT_BOW, null), + new ItemSprite(ItemSpriteSheet.GLOVES, null) + }; + break; + } + + tab = new IconTab( tabIcons[0] ){ + @Override + protected void select(boolean value) { + super.select(value); + if (value){ + title.text(Messages.titleCase(Messages.get(WndHeroInfo.class, "innate_title"))); + info.text(Messages.get(cl, cl.name() + "_desc_innate"), INFO_WIDTH); + } + } + }; + add(tab); + + tab = new IconTab( tabIcons[1] ){ + @Override + 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); + } + } + }; + add(tab); + + tab = new IconTab( Icons.get(Icons.TALENT) ){ + @Override + protected void select(boolean value) { + super.select(value); + if (value){ + 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; + firstSub.visible = firstSub.active = value; + secondSub.visible = secondSub.active = value; + } + }; + add(tab); + + tab = new IconTab(new ItemSprite(ItemSpriteSheet.MASTERY, null)){ + @Override + 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(); + } + info.text(msg, INFO_WIDTH); + } + } + }; + add(tab); + + resize(WIDTH, HEIGHT); + select(0); + + } + + @Override + public void select(Tab tab) { + super.select(tab); + + title.setPos((WIDTH-title.width())/2, MARGIN); + info.setPos(MARGIN, title.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()+MARGIN, WIDTH, HEIGHT - (info.bottom()+MARGIN)); + + resize(WIDTH, Math.max(HEIGHT, (int)info.bottom())); + + layoutTabs(); + + } +}