diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index a2f9a7936..b388c07ea 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -516,11 +516,13 @@ actors.hero.talent.test_subject.title=test subject actors.hero.talent.test_subject.desc=_+1:_ Whenever the Warrior identifies an item, he heals for _2 HP_.\n\n_+2:_ Whenever the Warrior identifies an item, he heals for _3 HP_. actors.hero.talent.iron_will.title=iron will actors.hero.talent.iron_will.desc=_+1:_ The max shield provided by the Warrior's seal is _increased by 1_.\n\n_+2:_ The max shield provided by the Warrior's seal is _increased by 2_. +actors.hero.talent.iron_will.meta_desc=_If this talent is gained by a different hero_ it will grant its shielding benefit without the broken seal. actors.hero.talent.iron_stomach.title=iron stomach actors.hero.talent.iron_stomach.desc=_+1:_ Eating food takes the Warrior 1 turn and grants him _75% damage resistance_ while eating.\n\n_+2:_ Eating food takes the Warrior 1 turn and grants him _100% damage resistance_ while eating. actors.hero.talent.restored_willpower.title=restored willpower actors.hero.talent.restored_willpower.desc=_+1:_ Drinking a potion of healing instantly recharges _67% of the shielding_ from the Warrior's broken seal.\n\n_+2:_ Drinking a potion of healing instantly recharges _100% of the shielding_ from the Warrior's broken seal.\n\nThis talent also triggers when drinking potions or elixirs based on potions of healing. +actors.hero.talent.restored_willpower.meta_desc=_If this talent is gained by a different hero_ it will instead grant shielding equal to 5% max hp at +1, or 7.5% max hp at +2. actors.hero.talent.runic_transference.title=runic transference actors.hero.talent.runic_transference.desc=_+1:_ The Warrior's broken seal can transfer _regular glyphs_ in the same way it transfers an upgrade.\n\n_+2:_ The Warrior's broken seal can transfer _regular, powerful, and curse glyphs_ in the same way it transfers an upgrade. actors.hero.talent.lethal_momentum.title=lethal momentum @@ -577,11 +579,13 @@ actors.hero.talent.tested_hypothesis.title=tested hypothesis actors.hero.talent.tested_hypothesis.desc=_+1:_ Whenever the Mage identifies an item, he gains _2 turns of wand recharging_.\n\n_+2:_ Whenever the Mage identifies an item, he gains _3 turns of wand recharging_. actors.hero.talent.backup_barrier.title=backup barrier actors.hero.talent.backup_barrier.desc=_+1:_ The Mage gains _3 shielding_ whenever he spends the last charge in his staff.\n\n_+2:_ The Mage gains _5 shielding_ whenever he spends the last charge in his staff. +actors.hero.talent.backup_barrier.meta_desc=_If this talent is gained by a different hero_ it will instead trigger from the hero's highest level wand. actors.hero.talent.energizing_meal.title=energizing meal actors.hero.talent.energizing_meal.desc=_+1:_ Eating food takes the Mage 1 turn and grants him _5 turns of wand recharging_.\n\n_+2:_ Eating food takes the Mage 1 turn and grants him _8 turns of wand recharging_. actors.hero.talent.energizing_upgrade.title=energizing upgrade actors.hero.talent.energizing_upgrade.desc=_+1:_ Using a scroll of upgrade instantly recharges the Mage's staff _for 4 charges_, this can put it above its current charge cap.\n\n_+2:_ Using a scroll of upgrade instantly recharges the Mage's staff _for 6 charges_, this can put it above its current charge cap.\n\nThis talent also triggers when using scrolls or spells based on scrolls of upgrade. +actors.hero.talent.energizing_upgrade.meta_desc=_If this talent is gained by a different hero_ it will instead grant 12 turns of wand recharging at +1, or 20 turns at +2. actors.hero.talent.wand_preservation.title=wand preservation actors.hero.talent.wand_preservation.desc=_+1:_ When the Mage imbues a new wand into his staff, the old wand has an _50% chance_ of being returned at +0, otherwise it will be returned as 1 arcane resin.\n\n_+2:_ When the Mage imbues a new wand into his staff, the old wand has a _100% chance_ of being returned at +0.\n\nThis talent can preserve wands a maximum of five times, afterward it will always grant 1 arcane resin. actors.hero.talent.arcane_vision.title=arcane vision @@ -637,14 +641,16 @@ actors.hero.talent.thiefs_intuition.desc=_+1:_ The Rogue identifies rings _2x fa actors.hero.talent.sucker_punch.title=sucker punch actors.hero.talent.sucker_punch.desc=_+1:_ The Rogue deals _1-2 bonus damage_ the first time he surprise attacks an enemy.\n\n_+2:_ The Rogue deals _2 bonus damage_ the first time he surprise attacks an enemy. actors.hero.talent.protective_shadows.title=protective shadows -actors.hero.talent.protective_shadows.desc=_+1:_ The Rogue gains one shielding _every other turn_ his cloak is activated, _to a max of 3_.\n\n_+2:_ The Rogue gains one shielding _every turn_ his cloak is activated, _to a max of 5_. +actors.hero.talent.protective_shadows.desc=_+1:_ The Rogue gains one shielding _every other turn_ he is invisible, _to a max of 3_.\n\n_+2:_ The Rogue gains one shielding _every turn_ he is invisible, _to a max of 5_. actors.hero.talent.mystical_meal.title=mystical meal actors.hero.talent.mystical_meal.desc=_+1:_ Eating food takes the Rogue 1 turn and grants him _3 turns of artifact recharging_.\n\n_+2:_ Eating food takes the Rogue 1 turn and grants him _5 turns of artifact recharging_.\n\nThis talent cannot be used to let the horn of plenty recharge itself. actors.hero.talent.mystical_upgrade.title=mystical upgrade actors.hero.talent.mystical_upgrade.desc=_+1:_ Using a scroll of upgrade instantly recharges the Rogue's cloak _for 2 charges_, this can put it above its current charge cap.\n\n_+2:_ Using a scroll of upgrade instantly recharges the Rogue's cloak _for 3 charges_, this can put it above its current charge cap.\n\nThis talent also triggers when using scrolls or spells based on scrolls of upgrade. +actors.hero.talent.mystical_upgrade.meta_desc=_If this talent is gained by a different hero_ it will instead grant 6 turns of artifact recharging at +1, or 10 turns at +2. actors.hero.talent.wide_search.title=wide search actors.hero.talent.wide_search.desc=_+1:_ The Rogue’s search radius is increased from a 5x5 square to a _7x7 circle_.\n\n_+2:_ The Rogue’s search radius is increased from a 5x5 square to a _7x7 square_. +actors.hero.talent.wide_search.meta_desc=_If this talent is gained by a different hero_ it will instead increase their search radius from a 3x3 square to a 5x5 circle at +1, or a 5x5 square at +2. actors.hero.talent.silent_steps.title=silent steps actors.hero.talent.silent_steps.desc=_+1:_ The Rogue will not wake sleeping enemies while he is _3 or more tiles away from them_.\n\n_+2:_ The Rogue will not wake sleeping enemies while he is _not adjacent to them_. actors.hero.talent.rogues_foresight.title=rogue's foresight @@ -652,6 +658,7 @@ actors.hero.talent.rogues_foresight.desc=_+1:_ When the Rogue is on a level with actors.hero.talent.light_cloak.title=light cloak actors.hero.talent.light_cloak.desc=_+1:_ The Rogue can use his cloak of shadows when it is not equipped, but it recharges at _25% speed_.\n\n_+2:_ The Rogue can use his cloak of shadows when it is not equipped, but it recharges at _50% speed_.\n\n_+3:_ The Rogue can use his cloak of shadows when it is not equipped, but it recharges at _75% speed_. +actors.hero.talent.light_cloak.meta_desc=_If this talent is gained by a different hero_ it will instead increase the charging speed of all artifacts by 7/13/20% at +1/+2/+3. actors.hero.talent.enhanced_rings.title=enhanced rings actors.hero.talent.enhanced_rings.desc=_+1:_ When the Rogue uses an artifact, his rings gain +1 upgrade for _3 turns_.\n\n_+2:_ When the Rogue uses an artifact, his rings gain +1 upgrade for _6 turns_.\n\n_+3:_When the Rogue uses an artifact, his rings gain +1 upgrade for _9 turns_. @@ -715,6 +722,7 @@ actors.hero.talent.point_blank.title=point blank actors.hero.talent.point_blank.desc=_+1:_ When the Huntress uses her bow or a thrown weapon at melee range it has _-30% accuracy,_ instead of -50%.\n\n_+2:_ When the Huntress uses her bow or a thrown weapon at melee range it has _-10% accuracy,_ instead of -50%.\n\n_+3:_ When the Huntress uses her bow or a thrown weapon at melee range it has _+10% accuracy,_ instead of -50%.\n\nNote that thrown weapons or the spirit bow always have +50% accuracy when used at a distance. actors.hero.talent.seer_shot.title=seer shot actors.hero.talent.seer_shot.desc=_+1:_ When the Huntress fires an arrow at the ground, it grants vision in a 3x3 area around it for _5 turns_. This has a 20 turn cooldown.\n\n_+2:_ When the Huntress fires an arrow at the ground, it grants vision in a 3x3 area around it for _10 turns_. This has a 20 turn cooldown.\n\n_+3:_ When the Huntress fires an arrow at the ground, it grants vision in a 3x3 area around it for _15 turns_. This has a 20 turn cooldown. +actors.hero.talent.seer_shot.meta_desc=_If this talent is gained by a different hero_ it will trigger from any thrown weapon. actors.hero.talent.farsight.title=farsight actors.hero.talent.farsight.desc=_+1:_ The Sniper's vision range is _increased by 25%_.\n\n_+2:_ The Sniper's vision range is _increased by 50%_.\n\n_+3:_ The Sniper's vision range is _increased by 75%_. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java index cf6050ca7..2391d7cb9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java @@ -281,7 +281,7 @@ public enum Rankings { return Messages.get(this, "something"); } else { String result = Messages.get(cause, "rankings_desc", (Messages.get(cause, "name"))); - if (result.contains("!!!NO TEXT FOUND!!!")){ + if (result.contains(Messages.NO_TEXT_FOUND)){ return Messages.get(this, "something"); } else { return result; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Invisibility.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Invisibility.java index f86b3c86d..1702049bd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Invisibility.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Invisibility.java @@ -25,6 +25,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CloakOfShadows; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; @@ -48,6 +49,9 @@ public class Invisibility extends FlavourBuff { if (target instanceof Hero && ((Hero) target).subClass == HeroSubClass.ASSASSIN){ Buff.affect(target, Preparation.class); } + if (target instanceof Hero && ((Hero) target).hasTalent(Talent.PROTECTIVE_SHADOWS)){ + Buff.affect(target, Talent.ProtectiveShadowsTracker.class); + } return true; } else { return false; 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 b836daf0f..99adaab10 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 @@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.GamesInProgress; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ArtifactRecharge; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.CounterBuff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.EnhancedRings; @@ -160,6 +161,43 @@ public enum Talent { public static class StrikingWaveTracker extends FlavourBuff{}; public static class WandPreservationCounter extends CounterBuff{{revivePersists = true;}}; public static class EmpoweredStrikeTracker extends FlavourBuff{}; + public static class ProtectiveShadowsTracker extends Buff { + float barrierInc = 0.5f; + + @Override + public boolean act() { + //barrier every 2/1 turns, to a max of 3/5 + if (((Hero)target).hasTalent(Talent.PROTECTIVE_SHADOWS) && target.invisible > 0){ + Barrier barrier = Buff.affect(target, Barrier.class); + if (barrier.shielding() < 1 + 2*((Hero)target).pointsInTalent(Talent.PROTECTIVE_SHADOWS)) { + barrierInc += 0.5f * ((Hero) target).pointsInTalent(Talent.PROTECTIVE_SHADOWS); + } + if (barrierInc >= 1){ + barrierInc = 0; + barrier.incShield(1); + } else { + barrier.incShield(0); //resets barrier decay + } + } else { + detach(); + } + spend( TICK ); + return true; + } + + private static final String BARRIER_INC = "barrier_inc"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( BARRIER_INC, barrierInc); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + barrierInc = bundle.getFloat( BARRIER_INC ); + } + } public static class BountyHunterTracker extends FlavourBuff{}; public static class RejuvenatingStepsCooldown extends FlavourBuff{ public int icon() { return BuffIndicator.TIME; } @@ -225,11 +263,25 @@ public enum Talent { return Messages.get(this, name() + ".title"); } - public String desc(){ + public final String desc(){ + return desc(false); + } + + public String desc(boolean metamorphed){ + if (metamorphed){ + String metaDesc = Messages.get(this, name() + ".meta_desc"); + if (!metaDesc.equals(Messages.NO_TEXT_FOUND)){ + return Messages.get(this, name() + ".desc") + "\n\n" + metaDesc; + } + } return Messages.get(this, name() + ".desc"); } public static void onTalentUpgraded( Hero hero, Talent talent ){ + //for metamorphosis + if (talent == IRON_WILL && hero.heroClass != HeroClass.WARRIOR){ + Buff.affect(hero, BrokenSeal.WarriorShield.class); + } if (talent == ARMSMASTERS_INTUITION && hero.pointsInTalent(ARMSMASTERS_INTUITION) == 2){ if (hero.belongings.weapon() != null) hero.belongings.weapon().identify(); @@ -249,7 +301,7 @@ public enum Talent { if (hero.belongings.misc instanceof Ring) ((Ring) hero.belongings.misc).setKnown(); } - if (talent == LIGHT_CLOAK && hero.pointsInTalent(LIGHT_CLOAK) == 1){ + if (talent == LIGHT_CLOAK && hero.heroClass == HeroClass.ROGUE){ for (Item item : Dungeon.hero.belongings.backpack){ if (item instanceof CloakOfShadows){ if (hero.buff(LostInventory.class) == null || item.keptThoughLostInvent) { @@ -334,10 +386,15 @@ public enum Talent { public static void onHealingPotionUsed( Hero hero ){ if (hero.hasTalent(RESTORED_WILLPOWER)){ - BrokenSeal.WarriorShield shield = hero.buff(BrokenSeal.WarriorShield.class); - if (shield != null){ - int shieldToGive = Math.round(shield.maxShield() * 0.33f*(1+hero.pointsInTalent(RESTORED_WILLPOWER))); - shield.supercharge(shieldToGive); + if (hero.heroClass == HeroClass.WARRIOR) { + BrokenSeal.WarriorShield shield = hero.buff(BrokenSeal.WarriorShield.class); + if (shield != null) { + int shieldToGive = Math.round(shield.maxShield() * 0.33f * (1 + hero.pointsInTalent(RESTORED_WILLPOWER))); + shield.supercharge(shieldToGive); + } + } else { + int shieldToGive = Math.round( hero.HT * (0.025f * (1+hero.pointsInTalent(RESTORED_WILLPOWER)))); + Buff.affect(hero, Barrier.class).setShield(shieldToGive); } } if (hero.hasTalent(RESTORED_NATURE)){ @@ -379,19 +436,27 @@ public enum Talent { public static void onUpgradeScrollUsed( Hero hero ){ if (hero.hasTalent(ENERGIZING_UPGRADE)){ - MagesStaff staff = hero.belongings.getItem(MagesStaff.class); - if (staff != null){ - staff.gainCharge(2 + 2*hero.pointsInTalent(ENERGIZING_UPGRADE), true); - ScrollOfRecharging.charge( Dungeon.hero ); - SpellSprite.show( hero, SpellSprite.CHARGE ); + if (hero.heroClass == HeroClass.MAGE) { + MagesStaff staff = hero.belongings.getItem(MagesStaff.class); + if (staff != null) { + staff.gainCharge(2 + 2 * hero.pointsInTalent(ENERGIZING_UPGRADE), true); + ScrollOfRecharging.charge(Dungeon.hero); + SpellSprite.show(hero, SpellSprite.CHARGE); + } + } else { + Buff.affect(hero, Recharging.class, 4 + 8 * hero.pointsInTalent(ENERGIZING_UPGRADE)); } } if (hero.hasTalent(MYSTICAL_UPGRADE)){ - CloakOfShadows cloak = hero.belongings.getItem(CloakOfShadows.class); - if (cloak != null){ - cloak.overCharge(1 + hero.pointsInTalent(MYSTICAL_UPGRADE)); - ScrollOfRecharging.charge( Dungeon.hero ); - SpellSprite.show( hero, SpellSprite.CHARGE ); + if (hero.heroClass == HeroClass.ROGUE) { + CloakOfShadows cloak = hero.belongings.getItem(CloakOfShadows.class); + if (cloak != null) { + cloak.overCharge(1 + hero.pointsInTalent(MYSTICAL_UPGRADE)); + ScrollOfRecharging.charge(Dungeon.hero); + SpellSprite.show(hero, SpellSprite.CHARGE); + } + } else { + Buff.affect(hero, ArtifactRecharge.class).set( 2 + 4*hero.pointsInTalent(MYSTICAL_UPGRADE) ).ignoreHornOfPlenty = false; } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java index 3d368ac5a..3279c4fa5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java @@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ShieldBuff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag; @@ -213,6 +214,11 @@ public class BrokenSeal extends Item { } public synchronized int maxShield() { + //metamorphed iron will logic + if (((Hero)target).heroClass != HeroClass.WARRIOR && ((Hero) target).hasTalent(Talent.IRON_WILL)){ + return ((Hero) target).pointsInTalent(Talent.IRON_WILL); + } + if (armor != null && armor.isEquipped((Hero)target) && armor.checkSeal() != null) { return armor.checkSeal().maxShield(armor.tier, armor.level()); } else { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/CloakOfShadows.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/CloakOfShadows.java index f3d9b032d..66ed15628 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/CloakOfShadows.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/CloakOfShadows.java @@ -285,29 +285,18 @@ public class CloakOfShadows extends Artifact { if (target instanceof Hero && ((Hero) target).subClass == HeroSubClass.ASSASSIN){ Buff.affect(target, Preparation.class); } + if (target instanceof Hero && ((Hero) target).hasTalent(Talent.PROTECTIVE_SHADOWS)){ + Buff.affect(target, Talent.ProtectiveShadowsTracker.class); + } return true; } else { return false; } } - float barrierInc = 0.5f; - @Override public boolean act(){ turnsToCost--; - - //barrier every 2/1 turns, to a max of 3/5 - if (((Hero)target).hasTalent(Talent.PROTECTIVE_SHADOWS)){ - Barrier barrier = Buff.affect(target, Barrier.class); - if (barrier.shielding() < 1 + 2*((Hero)target).pointsInTalent(Talent.PROTECTIVE_SHADOWS)) { - barrierInc += 0.5f * ((Hero) target).pointsInTalent(Talent.PROTECTIVE_SHADOWS); - } - if (barrierInc >= 1 ){ - barrierInc = 0; - barrier.incShield(1); - } - } if (turnsToCost <= 0){ charge--; @@ -384,7 +373,6 @@ public class CloakOfShadows extends Artifact { super.storeInBundle(bundle); bundle.put( TURNSTOCOST , turnsToCost); - bundle.put( BARRIER_INC, barrierInc); } @Override @@ -392,7 +380,6 @@ public class CloakOfShadows extends Artifact { super.restoreFromBundle(bundle); turnsToCost = bundle.getInt( TURNSTOCOST ); - barrierInc = bundle.getFloat( BARRIER_INC ); } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java index a0bca2c73..3a6b40254 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java @@ -22,6 +22,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.rings; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; @@ -55,7 +58,13 @@ public class RingOfEnergy extends Ring { } public static float artifactChargeMultiplier( Char target ){ - return (float)Math.pow(1.15, getBuffedBonus(target, Energy.class)); + float bonus = (float)Math.pow(1.15, getBuffedBonus(target, Energy.class)); + + if (target instanceof Hero && ((Hero) target).heroClass != HeroClass.ROGUE && ((Hero) target).hasTalent(Talent.LIGHT_CLOAK)){ + bonus *= 1f + (0.2f * ((Hero) target).pointsInTalent(Talent.LIGHT_CLOAK)/3f); + } + + return bonus; } public class Energy extends RingBuff { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfMetamorphosis.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfMetamorphosis.java index a5d8e4eb2..dd411ea9d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfMetamorphosis.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfMetamorphosis.java @@ -71,6 +71,10 @@ public class ScrollOfMetamorphosis extends ExoticScroll { Sample.INSTANCE.play( Assets.Sounds.READ ); curUser.sprite.emitter().start(Speck.factory(Speck.CHANGE), 0.2f, 10); Transmuting.show(curUser, oldTalent, newTalent); + + if (Dungeon.hero.hasTalent(newTalent)) { + Talent.onTalentUpgraded(Dungeon.hero, newTalent); + } } private void confirmCancelation( Window chooseWindow ) { @@ -167,22 +171,10 @@ public class ScrollOfMetamorphosis extends ExoticScroll { public static class WndMetamorphReplace extends Window { //talents that can only be used by one hero class - //TODO could some of these be made more generic? private static HashMap restrictedTalents = new HashMap<>(); static { - restrictedTalents.put(Talent.IRON_WILL, HeroClass.WARRIOR); - restrictedTalents.put(Talent.RESTORED_WILLPOWER, HeroClass.WARRIOR); restrictedTalents.put(Talent.RUNIC_TRANSFERENCE, HeroClass.WARRIOR); - - restrictedTalents.put(Talent.BACKUP_BARRIER, HeroClass.MAGE); - restrictedTalents.put(Talent.ENERGIZING_UPGRADE, HeroClass.MAGE); restrictedTalents.put(Talent.WAND_PRESERVATION, HeroClass.MAGE); - - restrictedTalents.put(Talent.PROTECTIVE_SHADOWS, HeroClass.ROGUE); - restrictedTalents.put(Talent.MYSTICAL_UPGRADE, HeroClass.ROGUE); - restrictedTalents.put(Talent.LIGHT_CLOAK, HeroClass.ROGUE); - - restrictedTalents.put(Talent.SEER_SHOT, HeroClass.HUNTRESS); } public static WndMetamorphReplace INSTANCE; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java index c9ddf9236..98f345b58 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java @@ -35,6 +35,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Recharging; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ScrollEmpower; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SoulMark; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +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.actors.hero.abilities.mage.WildMagic; @@ -405,19 +406,35 @@ public abstract class Wand extends Item { } } - //if the wand is owned by the hero, but not in their inventory, it must be in the staff if (charger != null - && charger.target == Dungeon.hero - && !Dungeon.hero.belongings.contains(this)) { - if (curCharges == 0 && Dungeon.hero.hasTalent(Talent.BACKUP_BARRIER)) { - //grants 3/5 shielding - Buff.affect(Dungeon.hero, Barrier.class).setShield(1 + 2 * Dungeon.hero.pointsInTalent(Talent.BACKUP_BARRIER)); - } - if (Dungeon.hero.hasTalent(Talent.EMPOWERED_STRIKE)){ - Buff.prolong(Dungeon.hero, Talent.EmpoweredStrikeTracker.class, 10f); + && charger.target == Dungeon.hero){ + + //if the wand is owned by the hero, but not in their inventory, it must be in the staff + if (!Dungeon.hero.belongings.contains(this)) { + if (curCharges == 0 && Dungeon.hero.hasTalent(Talent.BACKUP_BARRIER)) { + //grants 3/5 shielding + Buff.affect(Dungeon.hero, Barrier.class).setShield(1 + 2 * Dungeon.hero.pointsInTalent(Talent.BACKUP_BARRIER)); + } + if (Dungeon.hero.hasTalent(Talent.EMPOWERED_STRIKE)) { + Buff.prolong(Dungeon.hero, Talent.EmpoweredStrikeTracker.class, 10f); + } + + //otherwise process logic for metamorphed backup barrier + } else if (curCharges == 0 + && Dungeon.hero.heroClass != HeroClass.MAGE + && Dungeon.hero.hasTalent(Talent.BACKUP_BARRIER)){ + boolean highest = true; + for (Item i : Dungeon.hero.belongings.getAllItems(Wand.class)){ + if (i.level() > level()){ + highest = false; + } + } + if (highest){ + //grants 3/5 shielding + Buff.affect(Dungeon.hero, Barrier.class).setShield(1 + 2 * Dungeon.hero.pointsInTalent(Talent.BACKUP_BARRIER)); + } } } - Invisibility.dispel(); updateQuickslot(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java index 794ffa7b0..a718b1cc4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java @@ -28,7 +28,9 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicImmune; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Momentum; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.PinCushion; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RevealedArea; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag; @@ -187,8 +189,21 @@ abstract public class MissileWeapon extends Weapon { protected void onThrow( int cell ) { Char enemy = Actor.findChar( cell ); if (enemy == null || enemy == curUser) { - parent = null; - super.onThrow( cell ); + parent = null; + + //metamorphed seer shot logic + if (curUser.hasTalent(Talent.SEER_SHOT) + && curUser.heroClass != HeroClass.HUNTRESS + && curUser.buff(Talent.SeerShotCooldown.class) == null){ + if (Actor.findChar(cell) == null) { + RevealedArea a = Buff.affect(curUser, RevealedArea.class, 5 * curUser.pointsInTalent(Talent.SEER_SHOT)); + a.depth = Dungeon.depth; + a.pos = cell; + Buff.affect(curUser, Talent.SeerShotCooldown.class, 20f); + } + } + + super.onThrow( cell ); } else { if (!curUser.shoot( enemy, this )) { rangedMiss( cell ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/messages/Messages.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/messages/Messages.java index cd49a1104..510db5efd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/messages/Messages.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/messages/Messages.java @@ -45,6 +45,8 @@ public class Messages { private static ArrayList bundles; private static Languages lang; + public static final String NO_TEXT_FOUND = "!!!NO TEXT FOUND!!!"; + public static Languages lang(){ return lang; } @@ -117,7 +119,7 @@ public class Messages { if (c != null && c.getSuperclass() != null){ return get(c.getSuperclass(), k, args); } else { - return "!!!NO TEXT FOUND!!!"; + return NO_TEXT_FOUND; } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java index 01dac5ed6..9199d2f94 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java @@ -136,6 +136,11 @@ public class TalentButton extends Button { return Messages.titleCase(Messages.get(ScrollOfMetamorphosis.class, "metamorphose_talent")); } + @Override + public boolean metamorphDesc() { + return true; + } + @Override public void call() { if (ScrollOfMetamorphosis.WndMetamorphChoose.INSTANCE != null){ @@ -152,6 +157,11 @@ public class TalentButton extends Button { return Messages.titleCase(Messages.get(ScrollOfMetamorphosis.class, "metamorphose_talent")); } + @Override + public boolean metamorphDesc() { + return true; + } + @Override public void call() { Talent replacing = ScrollOfMetamorphosis.WndMetamorphReplace.INSTANCE.replacing; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java index 152184194..f94568fb1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java @@ -21,6 +21,7 @@ package com.shatteredpixel.shatteredpixeldungeon.windows; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; @@ -51,11 +52,13 @@ public class WndInfoTalent extends Window { titlebar.setRect( 0, 0, WIDTH, 0 ); add( titlebar ); - RenderedTextBlock txtInfo = PixelScene.renderTextBlock(talent.desc(), 6); + boolean metaDesc = (buttonCallback != null && buttonCallback.metamorphDesc()) || + (Dungeon.hero != null && Dungeon.hero.metamorphedTalents.containsValue(talent)); + + RenderedTextBlock txtInfo = PixelScene.renderTextBlock(talent.desc(metaDesc), 6); txtInfo.maxWidth(WIDTH); txtInfo.setPos(titlebar.left(), titlebar.bottom() + 2*GAP); add( txtInfo ); - resize( WIDTH, (int)(txtInfo.bottom() + GAP) ); if (buttonCallback != null) { @@ -79,6 +82,10 @@ public class WndInfoTalent extends Window { public abstract String prompt(); + public boolean metamorphDesc(){ + return false; + } + } }