diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index f4c12932f..e3749a2e4 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -1536,7 +1536,7 @@ items.wands.wandofblastwave.desc=This wand is made of a sort of marbled stone, w items.wands.wandofblastwave.typical_stats_desc=This wand shoots a bolt which violently detonates at a target location. The force of this blast typically deals _%1$d-%2$d damage_ and is strong enough to send most enemies flying. items.wands.wandofblastwave.stats_desc=This wand shoots a bolt which violently detonates at a target location. The force of this blast deals _%1$d-%2$d damage_ and is strong enough to send most enemies flying. items.wands.wandofblastwave.upgrade_stat_name_2=Knockback -items.wands.wandofblastwave.bmage_desc=When _the Battlemage_ strikes an enemy with a staff of blast wave, the enemy has a chance to be knocked back, as if the staff had an elastic enchantment. +items.wands.wandofblastwave.bmage_desc=When _the Battlemage_ strikes a paralyzed enemy with a staff of blast wave, it will consume the paralysis to deal a burst of bonus magic damage. items.wands.wandofblastwave.eleblast_desc=An elemental blast with a staff of blast wave deals 67% damage and knocks all enemies outside of the blast area. items.wands.wandofcorrosion.name=wand of corrosion @@ -1573,7 +1573,7 @@ items.wands.wandoffireblast.stats_desc=This wand blasts out a cone of fire when items.wands.wandoffireblast.upgrade_stat_name_1=1 Charge Damage items.wands.wandoffireblast.upgrade_stat_name_2=2 Charge Damage items.wands.wandoffireblast.upgrade_stat_name_3=3 Charge Damage -items.wands.wandoffireblast.bmage_desc=When _the Battlemage_ strikes an enemy with a staff of fireblast, the enemy has a chance to burst into flames, as if the staff had a blazing enchantment. +items.wands.wandoffireblast.bmage_desc=When _the Battlemage_ strikes an enemy with a staff of fireblast, there is a chance for it to produce an explosion that damages enemies and consumes all nearby fire! This chance increases the more fire is adjacent to the enemy. items.wands.wandoffireblast.eleblast_desc=An elemental blast with a staff of fireblast deals 100% damage, bursts open doors, and sets enemies and terrain on fire. items.wands.wandoffrost.name=wand of frost @@ -1589,8 +1589,10 @@ items.wands.wandoflightning.staff_name=staff of lightning items.wands.wandoflightning.ondeath=You killed yourself with your own Wand of Lightning... items.wands.wandoflightning.desc=This wand is made out of solid metal, making it surprisingly heavy. Two prongs curve together at the tip, and electricity arcs between them. items.wands.wandoflightning.stats_desc=This wand sends powerful lightning arcing through whatever it is shot at, dealing _%1$d-%2$d damage._ This electricity will arc to nearby characters, and spreads more easily in water. The arcs from this wand can damage you, but won't hurt your allies. -items.wands.wandoflightning.bmage_desc=When _the Battlemage_ strikes an enemy with a staff of lightning, the staff has a chance to arc lightning to other nearby enemies, as if it had a shocking enchantment. +items.wands.wandoflightning.bmage_desc=When _the Battlemage_ strikes an enemy with a staff of lightning, he has a chance to electrically charge himself for 10 turns. While charged the Battlemage is immune to lightning damage and will arc lightning further. items.wands.wandoflightning.eleblast_desc=An elemental blast with a staff of lightning deals 100% damage, stuns enemies for 5 turns, and electrifies water. +items.wands.wandoflightning$lightningcharge.name=Electrically charged +items.wands.wandoflightning$lightningcharge.desc=The Battlemage is currently charged with energy, granting him immunity to his staff of lightning and increasing the range that lightning can arc from it.\n\nTurns Remaining: %s. items.wands.wandoflivingearth.name=wand of living earth items.wands.wandoflivingearth.staff_name=staff of living earth @@ -1667,8 +1669,8 @@ items.wands.wandofwarding.desc=This short metal wand has a bright purple gem flo items.wands.wandofwarding.stats_desc=Rather than directly damaging an enemy, this wand will summon stationary wards and sentries. Wards can be summoned anywhere, even through walls if you have vision. This wand can sustain _%d energy_ worth of wards at a time. items.wands.wandofwarding.upgrade_stat_name_1=Ward Damage items.wands.wandofwarding.upgrade_stat_name_2=Ward Energy -items.wands.wandofwarding.bmage_desc=When _the Battlemage_ strikes an enemy with a staff of warding, all active sentries have a chance to be healed. -items.wands.wandofwarding.eleblast_desc=An elemental blast with a staff of warding heals all sentries in the blast area. +items.wands.wandofwarding.bmage_desc=When _the Battlemage_ strikes an enemy with a staff of warding, all active wards and sentries have a chance to be healed. +items.wands.wandofwarding.eleblast_desc=An elemental blast with a staff of warding heals all wards and sentries in the blast area. items.wands.wandofwarding$ward.desc_generic_ward=This ward will automatically zap any enemy which comes into its range of vision.\n\nZapping this ward with your wand of warding will upgrade it.\n\nWards have a limited number of zaps before dissipating. items.wands.wandofwarding$ward.desc_generic_sentry=This sentry has the same firepower as a ward, but has health instead of a set number of charges. It resembles the gem at the tip of your wand of warding.\n\nZapping this sentry with your wand of warding will upgrade and heal it.\n\nThis sentry will spend some health each time it zaps an enemy, but can be healed by using your wand of warding on it. items.wands.wandofwarding$ward.name_1=lesser ward diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java index 934f270b0..0978673f2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java @@ -27,11 +27,9 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.effects.Effects; import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile; import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing; -import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Elastic; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door; @@ -195,36 +193,12 @@ public class WandOfBlastWave extends DamageWand { @Override public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) { - Talent.EmpoweredStrikeTracker tracker = attacker.buff(Talent.EmpoweredStrikeTracker.class); - - if (tracker != null){ - tracker.delayedDetach = true; - } - - //acts like elastic enchantment - //we delay this with an actor to prevent conflicts with regular elastic - //so elastic always fully resolves first, then this effect activates - Actor.add(new Actor() { - { - actPriority = VFX_PRIO+9; //act after pushing effects - } - - @Override - protected boolean act() { - Actor.remove(this); - if (defender.isAlive()) { - new BlastWaveOnHit().proc(staff, attacker, defender, damage); - } - if (tracker != null) tracker.detach(); - return true; - } - }); - } - - private static class BlastWaveOnHit extends Elastic{ - @Override - protected float procChanceMultiplier(Char attacker) { - return Wand.procChanceMultiplier(attacker); + if (defender.buff(Paralysis.class) != null){ + defender.buff(Paralysis.class).detach(); + int dmg = Random.NormalIntRange(6+buffedLvl(), 12+2*buffedLvl()); + defender.damage(Math.round(procChanceMultiplier(attacker) * dmg), this); + BlastWave.blast(defender.pos); + Sample.INSTANCE.play( Assets.Sounds.BLAST ); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java index 4063f7fed..ca8b6aad8 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java @@ -32,7 +32,10 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.mage.WildMagic; +import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.BlastParticle; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SmokeParticle; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Blazing; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; @@ -46,6 +49,7 @@ import com.watabou.noosa.audio.Sample; import com.watabou.utils.Callback; import com.watabou.utils.GameMath; import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; import java.util.ArrayList; @@ -151,8 +155,60 @@ public class WandOfFireblast extends DamageWand { @Override public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) { - //acts like blazing enchantment - new FireBlastOnHit().proc( staff, attacker, defender, damage); + + //proc chance is initially 0.. + float procChance = 0; + for (int i : PathFinder.NEIGHBOURS9) { + + //+25% proc chance per burning char within 3x3 of target + // this includes the attacker and defender + if (Actor.findChar(defender.pos + i) != null + && Actor.findChar(defender.pos + i).buff(Burning.class) != null) { + procChance += 0.25f; + + //otherwise +5% proc chance per burning tile within 3x3 of target + } else if (Fire.volumeAt(defender.pos+i, Fire.class) > 0){ + procChance += 0.05f; + } + + } + + procChance = Math.min(1f, procChance); + procChance *= Wand.procChanceMultiplier(attacker); + + if (Random.Float() < procChance){ + + float powerMulti = Math.max(1f, procChance); + + Blob fire = Dungeon.level.blobs.get(Fire.class); + + //explode, dealing damage to enemies in 3x3, and clearing all fire + CellEmitter.center(defender.pos).burst(BlastParticle.FACTORY, 30); + if (fire != null) { + for (int i : PathFinder.NEIGHBOURS9) { + CellEmitter.get(defender.pos + i).burst(SmokeParticle.FACTORY, 4); + if (Fire.volumeAt(defender.pos+i, Fire.class) > 0){ + Dungeon.level.destroy(defender.pos + i); + GameScene.updateMap(defender.pos + i); + fire.clear(defender.pos + i); + } + + Char ch = Actor.findChar(defender.pos + i); + if (ch != null) { + if (ch.buff(Burning.class) != null) { + ch.buff(Burning.class).detach(); + } + if (ch.alignment == Char.Alignment.ENEMY) { + //A 2-charge zap's base dmg with a 1-charge zap's scaling + ch.damage(Math.round(powerMulti*Random.NormalIntRange(2 + buffedLvl(), 8 + 2*buffedLvl())), this); + } + } + } + } + + Sample.INSTANCE.play( Assets.Sounds.BLAST ); + + } } public static class FireBlastOnHit extends Blazing { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLightning.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLightning.java index a016c42d9..fc50674c0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLightning.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLightning.java @@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DwarfKing; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.Lightning; @@ -38,6 +39,8 @@ import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.watabou.noosa.Image; import com.watabou.utils.BArray; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.watabou.noosa.audio.Sample; @@ -78,8 +81,11 @@ public class WandOfLightning extends DamageWand { ch.sprite.centerEmitter().burst( SparkParticle.FACTORY, 3 ); ch.sprite.flash(); + //TODO these still reduce DMG, perhaps remove earlier? if (ch != curUser && ch.alignment == curUser.alignment && ch.pos != bolt.collisionPos){ continue; + } else if (ch.buff(LightningCharge.class) != null){ + continue; } wandProc(ch, chargesPerCast()); if (ch == curUser && ch.isAlive()) { @@ -97,8 +103,38 @@ public class WandOfLightning extends DamageWand { @Override public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) { - //acts like shocking enchantment - new LightningOnHit().proc(staff, attacker, defender, damage); + + // lvl 0 - 25% + // lvl 1 - 40% + // lvl 2 - 50% + float procChance = (buffedLvl()+1f)/(buffedLvl()+4f) * procChanceMultiplier(attacker); + if (Random.Float() < procChance) { + + FlavourBuff.prolong(attacker, LightningCharge.class, LightningCharge.DURATION); + attacker.sprite.centerEmitter().burst( SparkParticle.FACTORY, 10 ); + attacker.sprite.flash(); + Sample.INSTANCE.play( Assets.Sounds.LIGHTNING ); + + } + } + + public static class LightningCharge extends FlavourBuff { + + { + type = buffType.POSITIVE; + } + + public static float DURATION = 10f; + + @Override + public int icon() { + return BuffIndicator.IMBUE; + } + + @Override + public void tintIcon(Image icon) { + icon.hardlight(1, 1, 0); + } } public static class LightningOnHit extends Shocking { @@ -112,6 +148,10 @@ public class WandOfLightning extends DamageWand { int dist = Dungeon.level.water[ch.pos] ? 2 : 1; + if (curUser.buff(LightningCharge.class) != null){ + dist++; + } + ArrayList hitThisArc = new ArrayList<>(); PathFinder.buildDistanceMap( ch.pos, BArray.not( Dungeon.level.solid, null ), dist ); for (int i = 0; i < PathFinder.distance.length; i++) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java index c42b7355f..6dd3e76f1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java @@ -307,18 +307,28 @@ public class WandOfWarding extends Wand { switch(tier){ default: return; + case 2: + heal = Math.round(1 * healFactor); + break; + case 3: + heal = Math.round(Random.IntRange(1, 2) * healFactor); + break; case 4: - heal = Math.round(9 * healFactor); + heal = Math.round(9 * healFactor); //9/5 1.8 break; case 5: - heal = Math.round(12 * healFactor); + heal = Math.round(12 * healFactor); //12/6, 2 break; case 6: - heal = Math.round(16 * healFactor); + heal = Math.round(16 * healFactor); //16/7, 2.28 break; } - HP = Math.min(HT, HP+heal); + if (tier <= 3){ + totalZaps = (Math.max(0, totalZaps-heal)); + } else { + HP = Math.min(HT, HP + heal); + } if (sprite != null) sprite.showStatusWithIcon(CharSprite.POSITIVE, Integer.toString(heal), FloatingText.HEALING); }