From 9052a7acf87b3f6ee85de079975cd3ff14d7df9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 13 Feb 2025 04:15:27 +0000 Subject: [PATCH 1/9] Add AfterMoveSecondaryLast event --- data/abilities.ts | 2 +- data/moves.ts | 7 +------ sim/battle-actions.ts | 4 ++++ sim/dex-conditions.ts | 1 + sim/dex-moves.ts | 1 + test/sim/abilities/pickpocket.js | 2 +- test/sim/moves/icespinner.js | 14 +++++++++++++- 7 files changed, 22 insertions(+), 9 deletions(-) diff --git a/data/abilities.ts b/data/abilities.ts index 4ea628ea91..74c1dde199 100644 --- a/data/abilities.ts +++ b/data/abilities.ts @@ -3156,7 +3156,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { num: 253, }, pickpocket: { - onAfterMoveSecondary(target, source, move) { + onAfterMoveSecondaryLast(target, source, move) { if (source && source !== target && move?.flags['contact']) { if (target.item || target.switchFlag || target.forceSwitchFlag || source.switchFlag === true) { return; diff --git a/data/moves.ts b/data/moves.ts index 9c55e38bb4..cbe0d9f2de 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -9759,12 +9759,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { pp: 15, priority: 0, flags: {contact: 1, protect: 1, mirror: 1, metronome: 1}, - onAfterHit(target, source) { - if (source.hp) { - this.field.clearTerrain(); - } - }, - onAfterSubDamage(damage, target, source) { + onAfterMoveSecondaryLast(target, source) { if (source.hp) { this.field.clearTerrain(); } diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 841639b2a7..4e1ea6f476 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -536,6 +536,10 @@ export class BattleActions { this.battle.runEvent('EmergencyExit', pokemon, pokemon); } } + for (const i of targets.keys()) { + this.battle.singleEvent('AfterMoveSecondaryLast', move, null, targets[i], pokemon, move); + this.battle.runEvent('AfterMoveSecondaryLast', targets[i], pokemon, move); + } } return true; diff --git a/sim/dex-conditions.ts b/sim/dex-conditions.ts index f8c160c980..40eeec2a7d 100644 --- a/sim/dex-conditions.ts +++ b/sim/dex-conditions.ts @@ -24,6 +24,7 @@ export interface EventMethods { onAfterTakeItem?: (this: Battle, item: Item, pokemon: Pokemon) => void; onAfterBoost?: (this: Battle, boost: SparseBoostsTable, target: Pokemon, source: Pokemon, effect: Effect) => void; onAfterFaint?: (this: Battle, length: number, target: Pokemon, source: Pokemon, effect: Effect) => void; + onAfterMoveSecondaryLast?: MoveEventMethods['onAfterMoveSecondaryLast']; onAfterMoveSecondarySelf?: MoveEventMethods['onAfterMoveSecondarySelf']; onAfterMoveSecondary?: MoveEventMethods['onAfterMoveSecondary']; onAfterMove?: MoveEventMethods['onAfterMove']; diff --git a/sim/dex-moves.ts b/sim/dex-moves.ts index 06786d3295..075ac7e647 100644 --- a/sim/dex-moves.ts +++ b/sim/dex-moves.ts @@ -112,6 +112,7 @@ export interface MoveEventMethods { onAfterHit?: CommonHandlers['VoidSourceMove']; onAfterSubDamage?: (this: Battle, damage: number, target: Pokemon, source: Pokemon, move: ActiveMove) => void; + onAfterMoveSecondaryLast?: CommonHandlers['VoidMove']; onAfterMoveSecondarySelf?: CommonHandlers['VoidSourceMove']; onAfterMoveSecondary?: CommonHandlers['VoidMove']; onAfterMove?: CommonHandlers['VoidSourceMove']; diff --git a/test/sim/abilities/pickpocket.js b/test/sim/abilities/pickpocket.js index 188f967deb..4ae7c53320 100644 --- a/test/sim/abilities/pickpocket.js +++ b/test/sim/abilities/pickpocket.js @@ -46,7 +46,7 @@ describe('Pickpocket', function () { assert.holdsItem(battle.p2.active[0]); }); - it.skip(`should steal items back and forth when hit by a Magician user`, function () { + it(`should steal items back and forth when hit by a Magician user`, function () { battle = common.createBattle([[ {species: 'Weavile', ability: 'pickpocket', item: 'cheriberry', moves: ['agility']}, ], [ diff --git a/test/sim/moves/icespinner.js b/test/sim/moves/icespinner.js index 2b844b68e1..ff863115cc 100644 --- a/test/sim/moves/icespinner.js +++ b/test/sim/moves/icespinner.js @@ -21,7 +21,19 @@ describe(`Ice Spinner`, function () { assert.false(battle.field.isTerrain('psychicterrain')); }); - it.skip(`should not remove Terrains if the user faints from Life Orb`, function () { + it(`should remove Terrains if behind a substitute`, function () { + battle = common.createBattle([[ + {species: 'wynaut', moves: ['substitute', 'icespinner']}, + ], [ + {species: 'registeel', ability: 'psychicsurge', moves: ['sleeptalk']}, + ]]); + + battle.makeChoices(); + battle.makeChoices('move ice spinner', 'auto'); + assert.false(battle.field.isTerrain('psychicterrain')); + }); + + it(`should not remove Terrains if the user faints from Life Orb`, function () { battle = common.createBattle([[ {species: 'shedinja', item: 'lifeorb', moves: ['icespinner']}, {species: 'wynaut', moves: ['sleeptalk']}, From 57ef34d5e5cbc0ccbad0893293914669d2147703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 13 Feb 2025 08:41:56 +0000 Subject: [PATCH 2/9] Fix test --- test/sim/moves/icespinner.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/sim/moves/icespinner.js b/test/sim/moves/icespinner.js index ff863115cc..dcc40c9fcd 100644 --- a/test/sim/moves/icespinner.js +++ b/test/sim/moves/icespinner.js @@ -21,15 +21,15 @@ describe(`Ice Spinner`, function () { assert.false(battle.field.isTerrain('psychicterrain')); }); - it(`should remove Terrains if behind a substitute`, function () { + it(`should remove Terrains if target has a substitute`, function () { battle = common.createBattle([[ - {species: 'wynaut', moves: ['substitute', 'icespinner']}, + {species: 'wynaut', moves: ['sleeptalk', 'icespinner']}, ], [ - {species: 'registeel', ability: 'psychicsurge', moves: ['sleeptalk']}, + {species: 'registeel', ability: 'psychicsurge', moves: ['substitute', 'sleeptalk']}, ]]); - battle.makeChoices(); - battle.makeChoices('move ice spinner', 'auto'); + battle.makeChoices('move sleeptalk', 'move substitute'); + battle.makeChoices('move ice spinner', 'move sleeptalk'); assert.false(battle.field.isTerrain('psychicterrain')); }); From 9fe6ccc75e8b94cb4a3950cc9a7e9a39f46495ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 13 Feb 2025 08:45:17 +0000 Subject: [PATCH 3/9] Fix another test --- data/moves.ts | 2 +- test/sim/moves/icespinner.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/moves.ts b/data/moves.ts index cbe0d9f2de..0a2014ae99 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -9760,7 +9760,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { priority: 0, flags: {contact: 1, protect: 1, mirror: 1, metronome: 1}, onAfterMoveSecondaryLast(target, source) { - if (source.hp) { + if (source.hp && !source.forceSwitchFlag) { this.field.clearTerrain(); } }, diff --git a/test/sim/moves/icespinner.js b/test/sim/moves/icespinner.js index dcc40c9fcd..4b5c2db893 100644 --- a/test/sim/moves/icespinner.js +++ b/test/sim/moves/icespinner.js @@ -57,7 +57,7 @@ describe(`Ice Spinner`, function () { assert(battle.field.isTerrain('psychicterrain')); }); - it.skip(`should not remove Terrains if the user is forced out via Red Card`, function () { + it(`should not remove Terrains if the user is forced out via Red Card`, function () { battle = common.createBattle([[ {species: 'shedinja', moves: ['icespinner']}, {species: 'wynaut', moves: ['sleeptalk']}, From b3a0c25f9c0d68f56d158f8ad033fbd3e850057e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 13 Feb 2025 08:50:04 +0000 Subject: [PATCH 4/9] Add Emergency Exit check --- sim/battle-actions.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 4e1ea6f476..e414bbe3b1 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -528,7 +528,7 @@ export class BattleActions { !(move.hasSheerForce && pokemon.hasAbility('sheerforce')) && !move.flags['futuremove'] ) { - const originalHp = pokemon.hp; + let originalHp = pokemon.hp; this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move); this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move); if (pokemon && pokemon !== target && move.category !== 'Status') { @@ -536,9 +536,13 @@ export class BattleActions { this.battle.runEvent('EmergencyExit', pokemon, pokemon); } } - for (const i of targets.keys()) { - this.battle.singleEvent('AfterMoveSecondaryLast', move, null, targets[i], pokemon, move); - this.battle.runEvent('AfterMoveSecondaryLast', targets[i], pokemon, move); + for (const target of targets) { + originalHp = target.hp; + this.battle.singleEvent('AfterMoveSecondaryLast', move, null, target, pokemon, move); + this.battle.runEvent('AfterMoveSecondaryLast', target, pokemon, move); + if (target.hp <= target.maxhp / 2 && originalHp > target.maxhp / 2) { + this.battle.runEvent('EmergencyExit', target, target); + } } } From a44bab0c58a0011ccb2814a78a84cc27e486a7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 13 Feb 2025 08:56:31 +0000 Subject: [PATCH 5/9] Fix lint --- sim/battle-actions.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index e414bbe3b1..f3b39aaddb 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -536,12 +536,12 @@ export class BattleActions { this.battle.runEvent('EmergencyExit', pokemon, pokemon); } } - for (const target of targets) { - originalHp = target.hp; - this.battle.singleEvent('AfterMoveSecondaryLast', move, null, target, pokemon, move); - this.battle.runEvent('AfterMoveSecondaryLast', target, pokemon, move); - if (target.hp <= target.maxhp / 2 && originalHp > target.maxhp / 2) { - this.battle.runEvent('EmergencyExit', target, target); + for (const i of targets.keys()) { + originalHp = targets[i].hp; + this.battle.singleEvent('AfterMoveSecondaryLast', move, null, targets[i], pokemon, move); + this.battle.runEvent('AfterMoveSecondaryLast', targets[i], pokemon, move); + if (targets[i].hp <= targets[i].maxhp / 2 && originalHp > targets[i].maxhp / 2) { + this.battle.runEvent('EmergencyExit', targets[i], targets[i]); } } } From abcaf37156d15a742cc883237386f0d2bac768f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Sat, 15 Feb 2025 04:56:44 +0000 Subject: [PATCH 6/9] Refactor loop Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> --- sim/battle-actions.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index f3b39aaddb..f7d2cc7f09 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -536,12 +536,12 @@ export class BattleActions { this.battle.runEvent('EmergencyExit', pokemon, pokemon); } } - for (const i of targets.keys()) { - originalHp = targets[i].hp; - this.battle.singleEvent('AfterMoveSecondaryLast', move, null, targets[i], pokemon, move); - this.battle.runEvent('AfterMoveSecondaryLast', targets[i], pokemon, move); - if (targets[i].hp <= targets[i].maxhp / 2 && originalHp > targets[i].maxhp / 2) { - this.battle.runEvent('EmergencyExit', targets[i], targets[i]); + for (const curTarget of targets) { + originalHp = curTarget.hp; + this.battle.singleEvent('AfterMoveSecondaryLast', move, null, curTarget, pokemon, move); + this.battle.runEvent('AfterMoveSecondaryLast', curTarget, pokemon, move); + if (curTarget.hp <= curTarget.maxhp / 2 && originalHp > curTarget.maxhp / 2) { + this.battle.runEvent('EmergencyExit', curTarget, curTarget); } } } From eba5bb23d0ec059eef17cd60ef8bbb00cf055758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Wed, 26 Feb 2025 20:56:02 +0000 Subject: [PATCH 7/9] Update to ESLint 9 --- data/moves.ts | 2 +- test/sim/abilities/pickpocket.js | 2 +- test/sim/moves/icespinner.js | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/data/moves.ts b/data/moves.ts index 41d8b5ba27..28847f54cc 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -9760,7 +9760,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { name: "Ice Spinner", pp: 15, priority: 0, - flags: {contact: 1, protect: 1, mirror: 1, metronome: 1}, + flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 }, onAfterMoveSecondaryLast(target, source) { if (source.hp && !source.forceSwitchFlag) { this.field.clearTerrain(); diff --git a/test/sim/abilities/pickpocket.js b/test/sim/abilities/pickpocket.js index 4ba69d9dae..e89678b192 100644 --- a/test/sim/abilities/pickpocket.js +++ b/test/sim/abilities/pickpocket.js @@ -46,7 +46,7 @@ describe('Pickpocket', () => { assert.holdsItem(battle.p2.active[0]); }); - it(`should steal items back and forth when hit by a Magician user`, function () { + it(`should steal items back and forth when hit by a Magician user`, () => { battle = common.createBattle([[ { species: 'Weavile', ability: 'pickpocket', item: 'cheriberry', moves: ['agility'] }, ], [ diff --git a/test/sim/moves/icespinner.js b/test/sim/moves/icespinner.js index e41cffbbeb..2c44daad8e 100644 --- a/test/sim/moves/icespinner.js +++ b/test/sim/moves/icespinner.js @@ -21,11 +21,11 @@ describe(`Ice Spinner`, () => { assert.false(battle.field.isTerrain('psychicterrain')); }); - it(`should remove Terrains if target has a substitute`, function () { + it(`should remove Terrains if target has a substitute`, () => { battle = common.createBattle([[ - {species: 'wynaut', moves: ['sleeptalk', 'icespinner']}, + { species: 'wynaut', moves: ['sleeptalk', 'icespinner'] }, ], [ - {species: 'registeel', ability: 'psychicsurge', moves: ['substitute', 'sleeptalk']}, + { species: 'registeel', ability: 'psychicsurge', moves: ['substitute', 'sleeptalk'] }, ]]); battle.makeChoices('move sleeptalk', 'move substitute'); @@ -33,7 +33,7 @@ describe(`Ice Spinner`, () => { assert.false(battle.field.isTerrain('psychicterrain')); }); - it(`should not remove Terrains if the user faints from Life Orb`, function () { + it(`should not remove Terrains if the user faints from Life Orb`, () => { battle = common.createBattle([[ { species: 'shedinja', item: 'lifeorb', moves: ['icespinner'] }, { species: 'wynaut', moves: ['sleeptalk'] }, @@ -57,7 +57,7 @@ describe(`Ice Spinner`, () => { assert(battle.field.isTerrain('psychicterrain')); }); - it(`should not remove Terrains if the user is forced out via Red Card`, function () { + it(`should not remove Terrains if the user is forced out via Red Card`, () => { battle = common.createBattle([[ { species: 'shedinja', moves: ['icespinner'] }, { species: 'wynaut', moves: ['sleeptalk'] }, From 32373537dbfce98b80c12e5c706a1c71f6f5f1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Sat, 16 May 2026 18:47:27 +0100 Subject: [PATCH 8/9] Fix Sheer Force + Ice Spinner interaction in Champions --- data/mods/champions/scripts.ts | 167 +++++++++++++++++++++++++++++++++ sim/battle-actions.ts | 8 +- 2 files changed, 169 insertions(+), 6 deletions(-) diff --git a/data/mods/champions/scripts.ts b/data/mods/champions/scripts.ts index 78b37ae99d..cb1b5cab1e 100644 --- a/data/mods/champions/scripts.ts +++ b/data/mods/champions/scripts.ts @@ -552,5 +552,172 @@ export const Scripts: ModdedBattleScriptsData = { return damage; }, + // Sheer Force shouldnt suppress Ice Spinner + useMoveInner(moveOrMoveName, pokemon, options) { + let target = options?.target; + let sourceEffect = options?.sourceEffect; + const zMove = options?.zMove; + const maxMove = options?.maxMove; + if (!sourceEffect && this.battle.effect.id) sourceEffect = this.battle.effect; + if (sourceEffect && ['instruct', 'custapberry'].includes(sourceEffect.id)) sourceEffect = null; + + let move = this.dex.getActiveMove(moveOrMoveName); + pokemon.lastMoveUsed = move; + if (move.id === 'weatherball' && zMove) { + // Z-Weather Ball only changes types if it's used directly, + // not if it's called by Z-Sleep Talk or something. + this.battle.singleEvent('ModifyType', move, null, pokemon, target, move, move); + if (move.type !== 'Normal') sourceEffect = move; + } + if (zMove || (move.category !== 'Status' && sourceEffect && (sourceEffect as ActiveMove).isZ)) { + move = this.getActiveZMove(move, pokemon); + } + if (maxMove && move.category !== 'Status') { + // Max move outcome is dependent on the move type after type modifications from ability and the move itself + this.battle.singleEvent('ModifyType', move, null, pokemon, target, move, move); + this.battle.runEvent('ModifyType', pokemon, target, move, move); + } + if (maxMove || (move.category !== 'Status' && sourceEffect && (sourceEffect as ActiveMove).isMax)) { + move = this.getActiveMaxMove(move, pokemon); + } + + if (this.battle.activeMove) { + move.priority = this.battle.activeMove.priority; + if (!move.hasBounced) move.pranksterBoosted = this.battle.activeMove.pranksterBoosted; + } + const baseTarget = move.target; + let targetRelayVar = { target }; + targetRelayVar = this.battle.runEvent('ModifyTarget', pokemon, target, move, targetRelayVar, true); + if (targetRelayVar.target !== undefined) target = targetRelayVar.target; + if (target === undefined) target = this.battle.getRandomTarget(pokemon, move); + if (move.target === 'self' || move.target === 'allies') { + target = pokemon; + } + if (sourceEffect) { + move.sourceEffect = sourceEffect.id; + move.ignoreAbility = (sourceEffect as ActiveMove).ignoreAbility; + } + let moveResult = false; + + this.battle.setActiveMove(move, pokemon, target); + + this.battle.singleEvent('ModifyType', move, null, pokemon, target, move, move); + this.battle.singleEvent('ModifyMove', move, null, pokemon, target, move, move); + if (baseTarget !== move.target) { + // Target changed in ModifyMove, so we must adjust it here + // Adjust before the next event so the correct target is passed to the + // event + target = this.battle.getRandomTarget(pokemon, move); + } + move = this.battle.runEvent('ModifyType', pokemon, target, move, move); + move = this.battle.runEvent('ModifyMove', pokemon, target, move, move); + if (baseTarget !== move.target) { + // Adjust again + target = this.battle.getRandomTarget(pokemon, move); + } + if (!move || pokemon.fainted) { + return false; + } + + let attrs = ''; + + let movename = move.name; + if (move.id === 'hiddenpower') movename = 'Hidden Power'; + if (sourceEffect) attrs += `|[from] ${sourceEffect.fullname}`; + if (zMove && move.isZ === true) { + attrs = `|[anim]${movename}${attrs}`; + movename = `Z-${movename}`; + } + this.battle.addMove('move', pokemon, movename, `${target}${attrs}`); + + if (zMove) this.runZPower(move, pokemon); + + if (!target) { + this.battle.attrLastMove('[notarget]'); + this.battle.add(this.battle.gen >= 5 ? '-fail' : '-notarget', pokemon); + return false; + } + + const { targets, pressureTargets } = pokemon.getMoveTargets(move, target); + if (targets.length) { + target = targets[targets.length - 1]; // in case of redirection + } + + const callerMoveForPressure = sourceEffect && (sourceEffect as ActiveMove).pp ? sourceEffect as ActiveMove : null; + if (!sourceEffect || callerMoveForPressure || sourceEffect.id === 'pursuit') { + let extraPP = 0; + for (const source of pressureTargets) { + const ppDrop = this.battle.runEvent('DeductPP', source, pokemon, move); + if (ppDrop !== true) { + extraPP += ppDrop || 0; + } + } + if (extraPP > 0) { + pokemon.deductPP(callerMoveForPressure || moveOrMoveName, extraPP); + } + } + + let tryMoveResult = this.battle.singleEvent('TryMove', move, null, pokemon, target, move); + if (tryMoveResult) { + tryMoveResult = this.battle.runEvent('TryMove', pokemon, target, move); + } + if (!tryMoveResult) { + move.mindBlownRecoil = false; + return tryMoveResult; + } + + this.battle.singleEvent('UseMoveMessage', move, null, pokemon, target, move); + + if (move.ignoreImmunity === undefined) { + move.ignoreImmunity = (move.category === 'Status'); + } + + if (this.battle.gen !== 4 && move.selfdestruct === 'always') { + this.battle.faint(pokemon, pokemon, move); + } + + let damage: number | false | undefined | '' = false; + if (move.target === 'all' || move.target === 'foeSide' || move.target === 'allySide' || move.target === 'allyTeam') { + damage = this.tryMoveHit(targets, pokemon, move); + if (damage === this.battle.NOT_FAIL) pokemon.moveThisTurnResult = null; + if (damage || damage === 0 || damage === undefined) moveResult = true; + } else { + if (!targets.length) { + this.battle.attrLastMove('[notarget]'); + this.battle.add(this.battle.gen >= 5 ? '-fail' : '-notarget', pokemon); + return false; + } + if (this.battle.gen === 4 && move.selfdestruct === 'always') { + this.battle.faint(pokemon, pokemon, move); + } + moveResult = this.trySpreadMoveHit(targets, pokemon, move); + } + if (move.selfBoost && moveResult) this.moveHit(pokemon, pokemon, move, move.selfBoost, false, true); + if (!pokemon.hp) { + this.battle.faint(pokemon, pokemon, move); + } + + if (!moveResult) { + this.battle.singleEvent('MoveFail', move, null, target, pokemon, move); + return false; + } + + if (!(move.hasSheerForce && pokemon.hasAbility('sheerforce')) && !move.flags['futuremove']) { + const originalHp = pokemon.hp; + this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move); + this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move); + if (pokemon && pokemon !== target && move.category !== 'Status') { + if (pokemon.hp <= pokemon.maxhp / 2 && originalHp > pokemon.maxhp / 2) { + this.battle.runEvent('EmergencyExit', pokemon, pokemon); + } + } + } + for (const curTarget of targets) { + this.battle.singleEvent('AfterMoveSecondaryLast', move, null, curTarget, pokemon, move); + this.battle.runEvent('AfterMoveSecondaryLast', curTarget, pokemon, move); + } + + return true; + }, }, }; diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 6ce13423ec..a58ff2cd0c 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -529,7 +529,7 @@ export class BattleActions { } if (!(move.hasSheerForce && pokemon.hasAbility('sheerforce')) && !move.flags['futuremove']) { - let originalHp = pokemon.hp; + const originalHp = pokemon.hp; this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move); this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move); if (pokemon && pokemon !== target && move.category !== 'Status') { @@ -538,12 +538,8 @@ export class BattleActions { } } for (const curTarget of targets) { - originalHp = curTarget.hp; this.battle.singleEvent('AfterMoveSecondaryLast', move, null, curTarget, pokemon, move); this.battle.runEvent('AfterMoveSecondaryLast', curTarget, pokemon, move); - if (curTarget.hp <= curTarget.maxhp / 2 && originalHp > curTarget.maxhp / 2) { - this.battle.runEvent('EmergencyExit', curTarget, curTarget); - } } } @@ -1755,7 +1751,7 @@ export class BattleActions { } // weather modifier - baseDamage = this.battle.priorityEvent('WeatherModifyDamage', pokemon, target, move, baseDamage); + baseDamage = this.battle.runEvent('WeatherModifyDamage', pokemon, target, move, baseDamage); // crit - not a modifier const isCrit = target.getMoveHitData(move).crit; From 4f423307dc71fc814bfc2975758cc1762d11502a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Sat, 16 May 2026 18:55:33 +0100 Subject: [PATCH 9/9] Fix comment --- data/mods/champions/scripts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/mods/champions/scripts.ts b/data/mods/champions/scripts.ts index cb1b5cab1e..a27ad3cb88 100644 --- a/data/mods/champions/scripts.ts +++ b/data/mods/champions/scripts.ts @@ -552,7 +552,7 @@ export const Scripts: ModdedBattleScriptsData = { return damage; }, - // Sheer Force shouldnt suppress Ice Spinner + // Sheer Force shouldnt suppress Pickpocket useMoveInner(moveOrMoveName, pokemon, options) { let target = options?.target; let sourceEffect = options?.sourceEffect;