From 07f08877c18a027b9ff6c473476796b3d57b992b Mon Sep 17 00:00:00 2001 From: PigeonBar <56974298+PigeonBar@users.noreply.github.com> Date: Sun, 17 Nov 2024 12:16:54 -0500 Subject: [PATCH] [Balance] Multi Lens damage reduction on fixed-damage moves (#4896) --- src/field/pokemon.ts | 4 ++++ src/modifier/modifier.ts | 16 +++++++++++---- src/test/abilities/parental_bond.test.ts | 2 +- src/test/items/multi_lens.test.ts | 25 ++++++++++++++++++++++-- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index f9e7d7d1cad..f14fc954c84 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2622,6 +2622,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const fixedDamage = new Utils.IntegerHolder(0); applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage); if (fixedDamage.value) { + const multiLensMultiplier = new Utils.NumberHolder(1); + source.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, move.id, null, multiLensMultiplier); + fixedDamage.value = Utils.toDmgValue(fixedDamage.value * multiLensMultiplier.value); + return { cancelled: false, result: HitResult.EFFECTIVE, diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index bbd1763cd84..5e5246269a3 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -2727,10 +2727,18 @@ export class PokemonMultiHitModifier extends PokemonHeldItemModifier { * Additional strikes beyond that are given a 0.25x damage multiplier */ private applyDamageModifier(pokemon: Pokemon, damageMultiplier: NumberHolder): boolean { - damageMultiplier.value = (pokemon.turnData.hitsLeft === pokemon.turnData.hitCount) - ? (1 - (0.25 * this.getStackCount())) - : 0.25; - return true; + if (pokemon.turnData.hitsLeft === pokemon.turnData.hitCount) { + // Reduce first hit by 25% for each stack count + damageMultiplier.value *= 1 - 0.25 * this.getStackCount(); + return true; + } else if (pokemon.turnData.hitCount - pokemon.turnData.hitsLeft !== this.getStackCount() + 1) { + // Deal 25% damage for each remaining Multi Lens hit + damageMultiplier.value *= 0.25; + return true; + } else { + // An extra hit not caused by Multi Lens -- assume it is Parental Bond + return false; + } } getMaxHeldItemCount(pokemon: Pokemon): number { diff --git a/src/test/abilities/parental_bond.test.ts b/src/test/abilities/parental_bond.test.ts index 4189941a51e..10048a774cd 100644 --- a/src/test/abilities/parental_bond.test.ts +++ b/src/test/abilities/parental_bond.test.ts @@ -313,7 +313,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("MoveEndPhase", false); - expect(enemyPokemon.hp).toBe(enemyStartingHp - 300); + expect(enemyPokemon.hp).toBe(enemyStartingHp - 200); } ); diff --git a/src/test/items/multi_lens.test.ts b/src/test/items/multi_lens.test.ts index d389ca70555..c5e60c9f9e5 100644 --- a/src/test/items/multi_lens.test.ts +++ b/src/test/items/multi_lens.test.ts @@ -32,8 +32,8 @@ describe("Items - Multi Lens", () => { .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) - .startingLevel(100) - .enemyLevel(100); + .startingLevel(99) // Check for proper rounding on Seismic Toss damage reduction + .enemyLevel(99); }); it.each([ @@ -114,4 +114,25 @@ describe("Items - Multi Lens", () => { expect(magikarp.turnData.hitCount).toBe(2); }); + + it("should enhance fixed-damage moves while also applying damage reduction", async () => { + game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]) + .moveset(Moves.SEISMIC_TOSS); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + const spy = vi.spyOn(enemyPokemon, "getAttackDamage"); + + game.move.select(Moves.SEISMIC_TOSS); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + + await game.phaseInterceptor.to("MoveEndPhase"); + const damageResults = spy.mock.results.map(result => result.value?.damage); + + expect(damageResults).toHaveLength(2); + expect(damageResults[0]).toBe(Math.floor(playerPokemon.level * 0.75)); + expect(damageResults[1]).toBe(Math.floor(playerPokemon.level * 0.25)); + }); });