From d8c54ff8324fc64d0c170a9b508eb367f2e9b0bb Mon Sep 17 00:00:00 2001 From: muscode13 Date: Fri, 1 Nov 2024 14:37:13 -0600 Subject: [PATCH] added multi-lens logic --- public/locales | 2 +- src/data/ability.ts | 12 ++++++++---- src/test/abilities/wimp_out.test.ts | 21 +++++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/public/locales b/public/locales index 3cf6d553541..71390cba88f 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 3cf6d553541d79ba165387bc73fb06544d00f1f9 +Subproject commit 71390cba88f4103d0d2273d59a6dd8340a4fa54f diff --git a/src/data/ability.ts b/src/data/ability.ts index f407ea329f4..335f6d480bd 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -9,7 +9,7 @@ import { StatusEffect, getNonVolatileStatusEffects, getStatusEffectDescriptor, g import { Gender } from "./gender"; import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, FlinchAttr, OneHitKOAttr, HitHealAttr, allMoves, StatusMove, SelfStatusMove, VariablePowerAttr, applyMoveAttrs, IncrementMovePriorityAttr, VariableMoveTypeAttr, RandomMovesetMoveAttr, RandomMoveAttr, NaturePowerAttr, CopyMoveAttr, MoveAttr, MultiHitAttr, SacrificialAttr, SacrificialAttrOnHit, NeutralDamageAgainstFlyingTypeMultiplierAttr, FixedDamageAttr } from "./move"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; -import { BerryModifier, HitHealModifier, PokemonHeldItemModifier } from "../modifier/modifier"; +import { BerryModifier, HitHealModifier, PokemonHeldItemModifier, PokemonMultiHitModifier } from "../modifier/modifier"; import { TerrainType } from "./terrain"; import { SpeciesFormChangeManualTrigger, SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "./pokemon-forms"; import i18next from "i18next"; @@ -5041,14 +5041,16 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr { } else if (opponent.turnData.hitsLeft > 1) { return false; } - + const multiHitModifier = opponent.getHeldItems().find(m => m instanceof PokemonMultiHitModifier); if (allMoves[enemyLastMoveUsed.move].hasAttr(MultiHitAttr)) { damage = pokemon.turnData.damageTaken; } + if (multiHitModifier) { + // Ideally should be in the MultiHitAttr check, but turnData doesn't have proper data from MultiHitAttr. + damage *= 1 + multiHitModifier.stackCount; + } } } - - if (pokemon.hp + damage >= pokemon.getMaxHp() * this.hpRatio) { // Activates if it falls below half and recovers back above half from a Shell Bell const shellBellHeal = calculateShellBellRecovery(pokemon); @@ -5852,9 +5854,11 @@ export function initAbilities() { .attr(PostDefendStatStageChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, Stat.DEF, 1), new Ability(Abilities.WIMP_OUT, 7) .attr(PostDamageForceSwitchAbAttr) + .edgeCase() // Doesn't account for damage differences with Multi-Lens (damage rolls, critical hits), Multi-Lens does not update turnData properly .edgeCase(), // Should not trigger when hurting itself in confusion new Ability(Abilities.EMERGENCY_EXIT, 7) .attr(PostDamageForceSwitchAbAttr) + .edgeCase() // Doesn't account for damage differences with Multi-Lens (damage rolls, critical hits), Multi-Lens does not update turnData properly .edgeCase(), // Should not trigger when hurting itself in confusion new Ability(Abilities.WATER_COMPACTION, 7) .attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveType(move) === Type.WATER && move.category !== MoveCategory.STATUS, Stat.DEF, 2), diff --git a/src/test/abilities/wimp_out.test.ts b/src/test/abilities/wimp_out.test.ts index e2be51f2e66..9b44de6c070 100644 --- a/src/test/abilities/wimp_out.test.ts +++ b/src/test/abilities/wimp_out.test.ts @@ -548,6 +548,27 @@ describe("Abilities - Wimp Out", () => { confirmSwitch(); }); + it("triggers after last hit of multi hit move (multi lens)", async () => { + game.override + .enemyMoveset(Moves.TACKLE) + .enemyHeldItems([{ name: "MULTI_LENS", count: 1 }]); + await game.classicMode.startBattle([ + Species.WIMPOD, + Species.TYRUNT + ]); + + game.scene.getPlayerPokemon()!.hp *= 0.51; + + game.move.select(Moves.ENDURE); + game.doSelectPartyPokemon(1); + await game.phaseInterceptor.to("TurnEndPhase"); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + expect(enemyPokemon.turnData.hitsLeft).toBe(0); + expect(enemyPokemon.turnData.hitCount).toBe(2); + confirmSwitch(); + }); + // TODO: This interaction is not implemented yet it.todo("Wimp Out will not activate if the Pokémon's HP falls below half due to hurting itself in confusion", async () => { game.override