diff --git a/core/src/main/assets/interfaces/buffs.png b/core/src/main/assets/interfaces/buffs.png index 30c06e58f..cda8b5127 100644 Binary files a/core/src/main/assets/interfaces/buffs.png and b/core/src/main/assets/interfaces/buffs.png differ diff --git a/core/src/main/assets/interfaces/large_buffs.png b/core/src/main/assets/interfaces/large_buffs.png index 482a26130..356472bd0 100644 Binary files a/core/src/main/assets/interfaces/large_buffs.png and b/core/src/main/assets/interfaces/large_buffs.png differ diff --git a/core/src/main/assets/interfaces/talent_icons.png b/core/src/main/assets/interfaces/talent_icons.png index a2c7a2d11..ca6a8a98f 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/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index dec11a70b..613dab26c 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -303,6 +303,9 @@ actors.buffs.corrosion.desc=Powerful acid melts away flesh, metal, and bone at a actors.buffs.vertigo.name=Vertigo actors.buffs.vertigo.desc=Walking in a straight line can be difficult when the whole world is spinning.\n\nWhile under the effects of vertigo, characters who attempt to move will go in a random direction, instead of the one they intended to go in.\n\nTurns of vertigo remaining: %s. +actors.buffs.wandempower.name=Wands Empowered +actors.buffs.wandempower.desc=Your damage-dealing wands have been empowered, increasing the amount of damage they deal for a few zaps.\n\nBonus damage: %1$d.\nZaps remaining: %2$d. + actors.buffs.weakness.name=Weakened actors.buffs.weakness.heromsg=You feel weakened! actors.buffs.weakness.desc=Everything suddenly seems much heavier.\n\nWeakening magic reduces a character's physical strength, causing them to deal 33%% reduced damage.\n\nTurns of weakness remaining: %s. @@ -321,14 +324,20 @@ 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.energizing_meal.title=energizing meal -actors.hero.talent.energizing_meal.desc=_+1:_ Eating food grants the Mage _5 turns of wand recharging_.\n\n_+2:_ Eating food grants the Mage _8 turns of wand recharging_. + +actors.hero.talent.empowering_meal.title=empowering meal +actors.hero.talent.empowering_meal.desc=_+1:_ Eating food grants the Mage _2 bonus damage_ on his next 3 wand zaps.\n\n_+1:_ Eating food grants the Mage _3 bonus damage_ on his next 3 wand zaps. actors.hero.talent.scholars_intuition.title=scholar's intuition actors.hero.talent.scholars_intuition.desc=_+1:_ The Mage identifies wands _3x faster_.\n\n_+2:_ The Mage identifies wands _when he uses them_. actors.hero.talent.tested_hypothesis.title=tested hypothesis -actors.hero.talent.tested_hypothesis.desc=_+1:_ Whenever he identifies a scroll by using it, the Mage gains _6 shielding_.\n\n_+2:_ Whenever he identifies a scroll by using it, the Mage gains _9 shielding_. +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.energizing_meal.title=energizing meal +actors.hero.talent.energizing_meal.desc=_+1:_ Eating food grants the Mage _5 turns of wand recharging_.\n\n_+2:_ Eating food grants the Mage _8 turns of wand recharging_. actors.hero.talent.energizing_upgrade.title=energizing upgrade actors.hero.talent.energizing_upgrade.desc=_+1:_ The Mage's staff recharges for _1 extra charge_ whenever the Mage upgrades it.\n\n_+2:_ The Mage's staff recharges for _2 extra charges_ whenever the Mage upgrades it. + actors.hero.talent.rationed_meal.title=rationed meal actors.hero.talent.rationed_meal.desc=_+1:_ Eating food gives the Rogue _15% more satiety_.\n\n_+2:_ Eating food gives the Rogue _25% more satiety_. actors.hero.talent.thiefs_intuition.title=thief's intuition @@ -337,6 +346,7 @@ 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.mending_shadows.title=mending shadows actors.hero.talent.mending_shadows.desc=_+1:_ The Rogue heals for 1 HP every _5 consecutive turns_ that he is hidden by his cloak.\n\n_+2:_ The Rogue heals for 1 HP every _3 consecutive turns_ that he is hidden by his cloak. + actors.hero.talent.invigorating_meal.title=invigorating meal actors.hero.talent.invigorating_meal.desc=_+1:_ Eating food takes 1 turn and grants the Huntress _1 turn of haste_.\n\n_+2:_ Eating food takes 1 turn and grants the Huntress _2 turns of haste_. actors.hero.talent.survivalists_intuition.title=survivalist's intuition diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/WandEmpower.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/WandEmpower.java new file mode 100644 index 000000000..59663f865 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/WandEmpower.java @@ -0,0 +1,85 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2020 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.actors.buffs; + +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.watabou.noosa.Image; +import com.watabou.utils.Bundle; + +public class WandEmpower extends Buff { + + { + type = buffType.POSITIVE; + } + + @Override + public int icon() { + return BuffIndicator.UPGRADE; + } + + @Override + public void tintIcon(Image icon) { + icon.hardlight(1, 1, 0); + } + + @Override + public float iconFadePercent() { + return Math.max(0, (3-left) / 3f); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dmgBoost, left); + } + + public int dmgBoost; + public int left; + + public void set(int dmg, int shots){ + dmgBoost = dmg; + left = Math.max(left, shots); + } + + private static final String BOOST = "boost"; + private static final String LEFT = "left"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( BOOST, dmgBoost ); + bundle.put( LEFT, left ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + dmgBoost = bundle.getInt( BOOST ); + left = bundle.getInt( LEFT ); + } + +} 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 40a7a101b..e187a1a5c 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 @@ -24,17 +24,16 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.hero; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Haste; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Recharging; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.WandEmpower; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring; -import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging; import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; @@ -62,12 +61,12 @@ public enum Talent { TEST_WARRIOR_T2_4(7), TEST_WARRIOR_T2_5(8), - ENERGIZING_MEAL(16), + EMPOWERING_MEAL(16), SCHOLARS_INTUITION(17), TESTED_HYPOTHESIS(18), - ENERGIZING_UPGRADE(19), - TEST_MAGE_T2_1(20), - TEST_MAGE_T2_2(21), + BACKUP_BARRIER(19), + ENERGIZING_MEAL(20), + ENERGIZING_UPGRADE(21), TEST_MAGE_T2_3(22), TEST_MAGE_T2_4(23), TEST_MAGE_T2_5(24), @@ -149,6 +148,11 @@ public enum Talent { hero.sprite.emitter().burst(Speck.factory(Speck.HEALING), 1+hero.pointsInTalent(HEARTY_MEAL)); } } + if (hero.hasTalent(EMPOWERING_MEAL)){ + //2/3 bonus wand damage for next 3 zaps + Buff.affect( hero, WandEmpower.class).set(1 + hero.pointsInTalent(EMPOWERING_MEAL), 3); + ScrollOfRecharging.charge( hero ); + } if (hero.hasTalent(ENERGIZING_MEAL)){ //5/8 turns of recharging Buff.affect( hero, Recharging.class, 2 + 3*(hero.pointsInTalent(ENERGIZING_MEAL)) ); @@ -213,8 +217,9 @@ public enum Talent { Emitter e = hero.sprite.emitter(); if (e != null) e.burst(Speck.factory(Speck.HEALING), hero.pointsInTalent(TEST_SUBJECT)); } - if (item instanceof Scroll && hero.hasTalent(TESTED_HYPOTHESIS)){ - Buff.affect(hero, Barrier.class).setShield(3 + (3 * hero.pointsInTalent(Talent.TESTED_HYPOTHESIS)), 1); + if (hero.hasTalent(TESTED_HYPOTHESIS)){ + //2/3 turns of wand recharging + Buff.affect(hero, Recharging.class, 1f + hero.pointsInTalent(TESTED_HYPOTHESIS)); ScrollOfRecharging.charge(hero); } } @@ -264,7 +269,7 @@ public enum Talent { Collections.addAll(tierTalents, HEARTY_MEAL, ARMSMASTERS_INTUITION, TEST_SUBJECT, IRON_WILL); break; case MAGE: - Collections.addAll(tierTalents, ENERGIZING_MEAL, SCHOLARS_INTUITION, TESTED_HYPOTHESIS, ENERGIZING_UPGRADE); + Collections.addAll(tierTalents, EMPOWERING_MEAL, SCHOLARS_INTUITION, TESTED_HYPOTHESIS, BACKUP_BARRIER); break; case ROGUE: Collections.addAll(tierTalents, RATIONED_MEAL, THIEFS_INTUITION, SUCKER_PUNCH, MENDING_SHADOWS); @@ -284,7 +289,7 @@ public enum Talent { Collections.addAll(tierTalents, TEST_WARRIOR_T2_1, TEST_WARRIOR_T2_2, TEST_WARRIOR_T2_3, TEST_WARRIOR_T2_4, TEST_WARRIOR_T2_5); break; case MAGE: - Collections.addAll(tierTalents, TEST_MAGE_T2_1, TEST_MAGE_T2_2, TEST_MAGE_T2_3, TEST_MAGE_T2_4, TEST_MAGE_T2_5); + Collections.addAll(tierTalents, ENERGIZING_MEAL, ENERGIZING_UPGRADE, TEST_MAGE_T2_3, TEST_MAGE_T2_4, TEST_MAGE_T2_5); break; case ROGUE: Collections.addAll(tierTalents, TEST_ROGUE_T2_1, TEST_ROGUE_T2_2, TEST_ROGUE_T2_3, TEST_ROGUE_T2_4, TEST_ROGUE_T2_5); @@ -307,32 +312,41 @@ public enum Talent { //Nothing here yet. Hm..... } - private static final String TALENTS = "talents"; + private static final String TALENT_TIER = "talents_tier_"; public static void storeTalentsInBundle( Bundle bundle, Hero hero ){ - Bundle talentBundle = new Bundle(); + for (int i = 0; i < MAX_TALENT_TIERS; i++){ + LinkedHashMap tier = hero.talents.get(i); + Bundle tierBundle = new Bundle(); - for (Talent talent : values()){ - if (hero.hasTalent(talent)){ - talentBundle.put(talent.name(), hero.pointsInTalent(talent)); + for (Talent talent : tier.keySet()){ + if (tier.get(talent) > 0){ + tierBundle.put(talent.name(), tier.get(talent)); + } + if (tierBundle.contains(talent.name())){ + tier.put(talent, Math.min(tierBundle.getInt(talent.name()), talent.maxPoints())); + } } + bundle.put(TALENT_TIER+(i+1), tierBundle); } - - bundle.put(TALENTS, talentBundle); } public static void restoreTalentsFromBundle( Bundle bundle, Hero hero ){ if (hero.heroClass != null) initClassTalents(hero); if (hero.subClass != null) initSubclassTalents(hero); - if (!bundle.contains(TALENTS)) return; - Bundle talentBundle = bundle.getBundle(TALENTS); + for (int i = 0; i < MAX_TALENT_TIERS; i++){ + LinkedHashMap tier = hero.talents.get(i); + Bundle tierBundle = bundle.contains(TALENT_TIER+(i+1)) ? bundle.getBundle(TALENT_TIER+(i+1)) : null; + //pre-0.9.1 saves + if (tierBundle == null && i == 0 && bundle.contains("talents")){ + tierBundle = bundle.getBundle("talents"); + } - for (Talent talent : values()){ - if (talentBundle.contains(talent.name())){ - for (LinkedHashMap tier : hero.talents){ - if (tier.containsKey(talent)){ - tier.put(talent, Math.min(talentBundle.getInt(talent.name()), talent.maxPoints())); + if (tierBundle != null){ + for (Talent talent : tier.keySet()){ + if (tierBundle.contains(talent.name())){ + tier.put(talent, Math.min(tierBundle.getInt(talent.name()), talent.maxPoints())); } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/DamageWand.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/DamageWand.java index e02d73fc4..fc36bbd3b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/DamageWand.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/DamageWand.java @@ -21,7 +21,11 @@ package com.shatteredpixel.shatteredpixeldungeon.items.wands; +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.WandEmpower; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.watabou.noosa.audio.Sample; import com.watabou.utils.Random; //for wands that directly damage a target @@ -41,11 +45,21 @@ public abstract class DamageWand extends Wand{ public abstract int max(int lvl); public int damageRoll(){ - return Random.NormalIntRange(min(), max()); + return damageRoll(buffedLvl()); } public int damageRoll(int lvl){ - return Random.NormalIntRange(min(lvl), max(lvl)); + int dmg = Random.NormalIntRange(min(lvl), max(lvl)); + WandEmpower emp = Dungeon.hero.buff(WandEmpower.class); + if (emp != null){ + dmg += emp.dmgBoost; + emp.left--; + if (emp.left <= 0) { + emp.detach(); + } + Sample.INSTANCE.play(Assets.Sounds.HIT_STRONG, 0.75f, 1.2f); + } + return dmg; } @Override 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 706c8e35f..bfb3667b8 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 @@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor; @@ -343,6 +344,15 @@ public abstract class Wand extends Item { buff.detach(); } + //if the wand is owned by the hero, but not in their inventory, it must be in the staff + if (curCharges == 0 + && charger.target == Dungeon.hero + && !Dungeon.hero.belongings.contains(this) + && 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)); + } + Invisibility.dispel(); updateQuickslot(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfMagicMissile.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfMagicMissile.java index c254c6862..7dbe63670 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfMagicMissile.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfMagicMissile.java @@ -119,7 +119,7 @@ public class WandOfMagicMissile extends DamageWand { @Override public int icon() { - return BuffIndicator.RECHARGING; + return BuffIndicator.UPGRADE; } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java index 1c19a5d38..061df9eaa 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java @@ -95,6 +95,7 @@ public class BuffIndicator extends Component { public static final int HEX = 47; public static final int DEGRADE = 48; public static final int PINCUSHION = 49; + public static final int UPGRADE = 50; public static final int SIZE = 7;