diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index f9efc7f93..5207fa3fe 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -369,11 +369,11 @@ actors.hero.abilities.rogue.shadowclone.name=shadow clone actors.hero.abilities.rogue.shadowclone.short_desc=The Rogue summons a _Shadow Clone_, which is frail, but can be directed and deals damage based on his weapon. actors.hero.abilities.rogue.shadowclone.desc=TODO actors.hero.abilities.huntress.spectralblades.name=spectral blades -actors.hero.abilities.huntress.spectralblades.short_desc=The Huntress throws a _Spectral Blade_ at a target, inflicting damage depending on her currently equipped melee weapon. +actors.hero.abilities.huntress.spectralblades.short_desc=The Huntress throws _Spectral Blades_ at a target, inflicting damage depending on her currently equipped melee weapon. actors.hero.abilities.huntress.spectralblades.desc=TODO -actors.hero.abilities.huntress.naturesstrength.name=Nature's Strength -actors.hero.abilities.huntress.naturesstrength.short_desc=The Huntress calls upon _Nature's Strength_ to empower her, increasing her movement speed and her bow's rate of fire for a short time. -actors.hero.abilities.huntress.naturesstrength.desc=TODO +actors.hero.abilities.huntress.naturespower.name=nature's power +actors.hero.abilities.huntress.naturespower.short_desc=The Huntress calls upon _Nature's Power_, increasing her movement speed and her bow's rate of fire for a short time. +actors.hero.abilities.huntress.naturespower.desc=TODO actors.hero.abilities.huntress.spirithawk.name=spirit hawk actors.hero.abilities.huntress.spirithawk.short_desc=The Huntress summons a _Spirit Hawk_ familiar, which can help her scout locations and distract enemies. actors.hero.abilities.huntress.spirithawk.desc=TODO @@ -676,19 +676,19 @@ actors.hero.talent.projecting_blades.desc=_+1:_ Spectral blades has _+25% accura actors.hero.talent.spirit_blades.title=spirit blades actors.hero.talent.spirit_blades.desc=_+1:_ Spectral blades has a _25% chance_ to also use the enchantment on the spirit bow.\n\n_+2:_ Spectral blades has a _50% chance_ to also use the enchantment on the spirit bow.\n\n_+3:_ Spectral blades has a _75% chance_ to also use the enchantment on the spirit bow.\n\n_+4:_ Spectral blades has a _100% chance_ to also use the enchantment on the spirit bow. -actors.hero.talent.huntress_2_1.title=TODO NAME -actors.hero.talent.huntress_2_1.desc=TODO DESC -actors.hero.talent.huntress_2_2.title=TODO NAME -actors.hero.talent.huntress_2_2.desc=TODO DESC -actors.hero.talent.huntress_2_3.title=TODO NAME -actors.hero.talent.huntress_2_3.desc=TODO DESC +actors.hero.talent.growing_power.title=growing power +actors.hero.talent.growing_power.desc=_+1:_ The attack and movespeed boosts from nature's power are increased to _38% and 125%_, from 33% and 100%.\n\n_+2:_ The attack and movespeed boosts from nature's power are increased to _42% and 150%_, from 33% and 50%.\n\n_+3:_ The attack and movespeed boosts from nature's power are increased to _46% and 150%_, from 33% and 100%.\n\n_+4:_ The attack and movespeed boosts from nature's power are increased to _50% and 200%_, from 33% and 100%. +actors.hero.talent.natures_wrath.title=nature's wrath +actors.hero.talent.natures_wrath.desc=_+1:_ While nature's power is active, shots from the spirit bow have an _8% chance_ to trigger a random harmful plant effect.\n\n_+2:_ While nature's power is active, shots from the spirit bow have a _17% chance_ to trigger a random harmful plant effect.\n\n_+3:_ While nature's power is active, shots from the spirit bow have an _25% chance_ to trigger a random harmful plant effect.\n\n_+4:_ While nature's power is active, shots from the spirit bow have a _33% chance_ to trigger a random harmful plant effect.\n\nThe plants that can be triggered are: blindweed, firebloom, icecap, sorrowmoss, and stormvine. +actors.hero.talent.wild_momentum.title=wild momentum +actors.hero.talent.wild_momentum.desc=_+1:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _1 turn_. The duration can be extended by a max of _2 turns_.\n\n_+2:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _2 turns_. The duration can be extended by a max of _4 turns_.\n\n_+3:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _3 turns_. The duration can be extended by a max of _6 turns_.\n\n_+4:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _4 turns_. The duration can be extended by a max of _8 turns_. actors.hero.talent.huntress_3_1.title=TODO NAME -actors.hero.talent.huntress_3_1.desc=TODO DESC +actors.hero.talent.huntress_3_1.desc=_+1:_ \n\n_+2:_ \n\n_+3:_ \n\n_+4:_ actors.hero.talent.huntress_3_2.title=TODO NAME -actors.hero.talent.huntress_3_2.desc=TODO DESC +actors.hero.talent.huntress_3_2.desc=_+1:_ \n\n_+2:_ \n\n_+3:_ \n\n_+4:_ actors.hero.talent.huntress_3_3.title=TODO NAME -actors.hero.talent.huntress_3_3.desc=TODO DESC +actors.hero.talent.huntress_3_3.desc=_+1:_ \n\n_+2:_ \n\n_+3:_ \n\n_+4:_ #universal actors.hero.talent.heroic_energy.title=heroic energy diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index e5e54e955..520222fb3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -53,6 +53,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Regeneration; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SnipersMark; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.NaturesPower; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Monk; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; @@ -530,6 +531,11 @@ public class Hero extends Char { } else { ((HeroSprite)sprite).sprint( 1f ); } + + NaturesPower.NaturesStrengthTracker natStrength = buff(NaturesPower.NaturesStrengthTracker.class); + if (natStrength != null){ + speed *= (2f + 0.25f*pointsInTalent(Talent.GROWING_POWER)); + } return speed; 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 43be32423..b1085514d 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 @@ -131,8 +131,8 @@ public enum Talent { DURABLE_TIPS(110, 3), BARKSKIN(111, 3), SHIELDING_DEW(112, 3), //Spectral Blades T4 FAN_OF_BLADES(113, 4), PROJECTING_BLADES(114, 4), SPIRIT_BLADES(115, 4), - //??? T4 - HUNTRESS_2_1(116, 4), HUNTRESS_2_2(117, 4), HUNTRESS_2_3(118, 4), + //Natures Power T4 + GROWING_POWER(116, 4), NATURES_WRATH(117, 4), WILD_MOMENTUM(118, 4), //??? T4 HUNTRESS_3_1(119, 4), HUNTRESS_3_2(120, 4), HUNTRESS_3_3(121, 4), diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/huntress/NaturesPower.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/huntress/NaturesPower.java new file mode 100644 index 000000000..ee7839c4d --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/huntress/NaturesPower.java @@ -0,0 +1,81 @@ +/* + * 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.actors.hero.abilities.huntress; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClassArmor; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.watabou.noosa.audio.Sample; + +public class NaturesPower extends ArmorAbility { + + @Override + protected void activate(ClassArmor armor, Hero hero, Integer target) { + + Buff.prolong(hero, NaturesStrengthTracker.class, NaturesStrengthTracker.DURATION); + hero.buff(NaturesStrengthTracker.class).extensionsLeft = 2; + hero.sprite.operate(hero.pos); + Sample.INSTANCE.play(Assets.Sounds.CHARGEUP); + hero.sprite.emitter().burst(LeafParticle.GENERAL, 10); + hero.spendAndNext(Actor.TICK); + + } + + @Override + public Talent[] talents() { + return new Talent[]{Talent.GROWING_POWER, Talent.NATURES_WRATH, Talent.WILD_MOMENTUM, Talent.HEROIC_ENERGY}; + } + + public static class NaturesStrengthTracker extends FlavourBuff{ + + public static final float DURATION = 8f; + + public int extensionsLeft = 2; + + public void extend( int turns ){ + if (extensionsLeft > 0 && turns > 0) { + spend(turns); + extensionsLeft--; + } + } + + @Override + public int icon() { + return BuffIndicator.SHADOWS; + } + + @Override + public float iconFadePercent() { + return Math.max(0, (DURATION - visualcooldown()) / DURATION); + } + + //TODO name/desc + + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/huntress/NaturesStrength.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/huntress/NaturesStrength.java deleted file mode 100644 index fce6ab799..000000000 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/huntress/NaturesStrength.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.actors.hero.abilities.huntress; - -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility; -import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClassArmor; - -public class NaturesStrength extends ArmorAbility { - - @Override - protected void activate(ClassArmor armor, Hero hero, Integer target) { - //TODO - } - - @Override - public Talent[] talents() { - return new Talent[]{Talent.HUNTRESS_2_1, Talent.HUNTRESS_2_2, Talent.HUNTRESS_2_3, Talent.HEROIC_ENERGY}; - } -} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java index f4a91ba50..f08c0aa22 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java @@ -29,19 +29,29 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RevealedArea; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.NaturesPower; import com.shatteredpixel.shatteredpixeldungeon.effects.Splash; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfFuror; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfSharpshooting; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.plants.Blindweed; +import com.shatteredpixel.shatteredpixeldungeon.plants.Firebloom; +import com.shatteredpixel.shatteredpixeldungeon.plants.Icecap; +import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; +import com.shatteredpixel.shatteredpixeldungeon.plants.Sorrowmoss; +import com.shatteredpixel.shatteredpixeldungeon.plants.Stormvine; import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.sprites.MissileSprite; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; import com.watabou.utils.Callback; import com.watabou.utils.Random; +import com.watabou.utils.Reflection; import java.util.ArrayList; @@ -83,7 +93,47 @@ public class SpiritBow extends Weapon { } } - + + private static Class[] harmfulPlants = new Class[]{ + Blindweed.class, Firebloom.class, Icecap.class, Sorrowmoss.class, Stormvine.class + }; + + @Override + public int proc(Char attacker, Char defender, int damage) { + + if (attacker.buff(NaturesPower.NaturesStrengthTracker.class) != null){ + + Actor.add(new Actor() { + { + actPriority = VFX_PRIO; + } + + @Override + protected boolean act() { + + if (Random.Int(12) < ((Hero)attacker).pointsInTalent(Talent.NATURES_WRATH)){ + Plant plant = (Plant) Reflection.newInstance(Random.element(harmfulPlants)); + plant.pos = defender.pos; + plant.activate( defender.isAlive() ? defender : null ); + } + + if (!defender.isAlive()){ + NaturesPower.NaturesStrengthTracker tracker = attacker.buff(NaturesPower.NaturesStrengthTracker.class); + if (tracker != null){ + tracker.extend(((Hero) attacker).pointsInTalent(Talent.WILD_MOMENTUM)); + } + } + + Actor.remove(this); + return true; + } + }); + + } + + return super.proc(attacker, defender, damage); + } + @Override public String info() { String info = desc(); @@ -199,7 +249,15 @@ public class SpiritBow extends Weapon { return 2f * RingOfFuror.attackDelayMultiplier(owner); } } else { - return super.speedFactor(owner); + + float speed = super.speedFactor(owner); + + if (owner.buff(NaturesPower.NaturesStrengthTracker.class) != null){ + // 1.33x speed to 1.5x speed, depending on talent points + speed /= ((32 + ((Hero)owner).pointsInTalent(Talent.GROWING_POWER)) / 24f); + } + + return speed; } } @@ -230,7 +288,20 @@ public class SpiritBow extends Weapon { hitSound = Assets.Sounds.HIT_ARROW; } - + + @Override + public Emitter emitter() { + if (Dungeon.hero.buff(NaturesPower.NaturesStrengthTracker.class) != null){ + Emitter e = new Emitter(); + e.pos(5, 5); + e.fillTarget = false; + e.pour(LeafParticle.GENERAL, 0.01f); + return e; + } else { + return super.emitter(); + } + } + @Override public int damageRoll(Char owner) { return SpiritBow.this.damageRoll(owner); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSprite.java index ffc9444e5..5756b02d4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSprite.java @@ -251,7 +251,10 @@ public class ItemSprite extends MovieClip { @Override public void kill() { super.kill(); - if (emitter != null) emitter.killAndErase(); + if (emitter != null) { + emitter.on = false; + emitter.autoKill = true; + } emitter = null; }