From 3f370d62acd76f74a28b423c9c0204d03a176bf9 Mon Sep 17 00:00:00 2001 From: andrebastosdias Date: Mon, 16 Feb 2026 18:22:01 +0000 Subject: [PATCH 1/6] Refactor Aromatherapy and Heal Bell --- data/mods/gen5/moves.ts | 2 ++ data/mods/gen7/moves.ts | 16 ---------- data/mods/gen9ssb/scripts.ts | 9 ++++-- data/moves.ts | 44 +++++----------------------- sim/battle-actions.ts | 11 ++++--- sim/pokemon.ts | 7 ++++- test/sim/moves/aromatherapy.js | 53 ++++++++++++++++++++++++++++++++++ test/sim/moves/healbell.js | 35 ++++++++++++++-------- 8 files changed, 105 insertions(+), 72 deletions(-) create mode 100644 test/sim/moves/aromatherapy.js diff --git a/data/mods/gen5/moves.ts b/data/mods/gen5/moves.ts index 4328d70e1e..756eff6113 100644 --- a/data/mods/gen5/moves.ts +++ b/data/mods/gen5/moves.ts @@ -17,6 +17,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { }, aromatherapy: { inherit: true, + onPrepareHit() {}, onHit(target, source) { this.add('-activate', source, 'move: Aromatherapy'); const allies = [...target.side.pokemon, ...target.side.allySide?.pokemon || []]; @@ -345,6 +346,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { healbell: { inherit: true, flags: { snatch: 1, sound: 1, metronome: 1 }, + onPrepareHit() {}, onHit(target, source) { this.add('-activate', source, 'move: Heal Bell'); const allies = [...target.side.pokemon, ...target.side.allySide?.pokemon || []]; diff --git a/data/mods/gen7/moves.ts b/data/mods/gen7/moves.ts index 62c55d6c4a..005b310f25 100644 --- a/data/mods/gen7/moves.ts +++ b/data/mods/gen7/moves.ts @@ -362,22 +362,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { inherit: true, isNonstandard: null, }, - healbell: { - inherit: true, - onHit(target, source) { - this.add('-activate', source, 'move: Heal Bell'); - let success = false; - const allies = [...target.side.pokemon, ...target.side.allySide?.pokemon || []]; - for (const ally of allies) { - if (ally.hasAbility('soundproof') && !this.suppressingAbility(ally)) { - this.add('-immune', ally, '[from] ability: Soundproof'); - continue; - } - if (ally.cureStatus()) success = true; - } - return success; - }, - }, healblock: { inherit: true, isNonstandard: null, diff --git a/data/mods/gen9ssb/scripts.ts b/data/mods/gen9ssb/scripts.ts index 4113928614..d66df9373d 100644 --- a/data/mods/gen9ssb/scripts.ts +++ b/data/mods/gen9ssb/scripts.ts @@ -1324,7 +1324,8 @@ export const Scripts: ModdedBattleScriptsData = { } let damage: number | false | undefined | '' = false; - if (move.target === 'all' || move.target === 'foeSide' || move.target === 'allySide' || move.target === 'allyTeam') { + if (move.target === 'all' || move.target === 'foeSide' || move.target === 'allySide' || + (move.target === 'allyTeam' && this.battle.gen <= 5)) { damage = this.tryMoveHit(targets, pokemon, move); if (damage === this.battle.NOT_FAIL) pokemon.moveThisTurnResult = null; if (damage || damage === 0 || damage === undefined) moveResult = true; @@ -1594,7 +1595,8 @@ export const Scripts: ModdedBattleScriptsData = { if (!moveData.flags) moveData.flags = {}; if (move.target === 'all' && !isSelf) { hitResult = this.battle.singleEvent('TryHitField', moveData, {}, target || null, pokemon, move); - } else if ((move.target === 'foeSide' || move.target === 'allySide' || move.target === 'allyTeam') && !isSelf) { + } else if ((move.target === 'foeSide' || move.target === 'allySide' || + (move.target === 'allyTeam' && this.battle.gen <= 5)) && !isSelf) { hitResult = this.battle.singleEvent('TryHitSide', moveData, {}, target || null, pokemon, move); } else if (target) { hitResult = this.battle.singleEvent('TryHit', moveData, {}, target, pokemon, move); @@ -1609,7 +1611,8 @@ export const Scripts: ModdedBattleScriptsData = { // 0. check for substitute if (!isSecondary && !isSelf) { - if (move.target !== 'all' && move.target !== 'allyTeam' && move.target !== 'allySide' && move.target !== 'foeSide') { + if (move.target !== 'all' && move.target !== 'allySide' && move.target !== 'foeSide' && + (move.target !== 'allyTeam' || this.battle.gen > 5)) { damage = this.tryPrimaryHitEvent(damage, targets, pokemon, move, moveData, isSecondary); } } diff --git a/data/moves.ts b/data/moves.ts index 8004f48dfb..ad1ac0ae35 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -584,25 +584,11 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { pp: 5, priority: 0, flags: { snatch: 1, distance: 1, metronome: 1 }, - onHit(target, source, move) { + onPrepareHit(target, source) { this.add('-activate', source, 'move: Aromatherapy'); - let success = false; - const allies = [...target.side.pokemon, ...target.side.allySide?.pokemon || []]; - for (const ally of allies) { - if (ally !== source && !this.suppressingAbility(ally)) { - if (ally.hasAbility('sapsipper')) { - this.add('-immune', ally, '[from] ability: Sap Sipper'); - continue; - } - if (ally.hasAbility('goodasgold')) { - this.add('-immune', ally, '[from] ability: Good as Gold'); - continue; - } - if (ally.volatiles['substitute'] && !move.infiltrates) continue; - } - if (ally.cureStatus()) success = true; - } - return success; + }, + onHit(target) { + target.cureStatus(); }, target: "allyTeam", type: "Grass", @@ -8543,24 +8529,11 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { pp: 5, priority: 0, flags: { snatch: 1, sound: 1, distance: 1, bypasssub: 1, metronome: 1 }, - onHit(target, source) { + onPrepareHit(target, source) { this.add('-activate', source, 'move: Heal Bell'); - let success = false; - const allies = [...target.side.pokemon, ...target.side.allySide?.pokemon || []]; - for (const ally of allies) { - if (ally !== source && !this.suppressingAbility(ally)) { - if (ally.hasAbility('soundproof')) { - this.add('-immune', ally, '[from] ability: Soundproof'); - continue; - } - if (ally.hasAbility('goodasgold')) { - this.add('-immune', ally, '[from] ability: Good as Gold'); - continue; - } - } - if (ally.cureStatus()) success = true; - } - return success; + }, + onHit(target, source, move) { + target.cureStatus(); }, target: "allyTeam", type: "Normal", @@ -18034,7 +18007,6 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { flags: { protect: 1, mirror: 1 }, self: { onHit(pokemon, source, move) { - this.add('-activate', source, 'move: Aromatherapy'); for (const ally of source.side.pokemon) { if (ally !== source && (ally.volatiles['substitute'] && !move.infiltrates)) { continue; diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 9df9dceb52..c6676237b2 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -505,7 +505,8 @@ export class BattleActions { } let damage: number | false | undefined | '' = false; - if (move.target === 'all' || move.target === 'foeSide' || move.target === 'allySide' || move.target === 'allyTeam') { + if (move.target === 'all' || move.target === 'foeSide' || move.target === 'allySide' || + (move.target === 'allyTeam' && this.battle.gen <= 5)) { damage = this.tryMoveHit(targets, pokemon, move); if (damage === this.battle.NOT_FAIL) pokemon.moveThisTurnResult = null; if (damage || damage === 0 || damage === undefined) moveResult = true; @@ -616,7 +617,7 @@ export class BattleActions { return moveResult; } hitStepInvulnerabilityEvent(targets: Pokemon[], pokemon: Pokemon, move: ActiveMove) { - if (move.id === 'helpinghand') return new Array(targets.length).fill(true); + if (['aromatherapy', 'healbell', 'helpinghand'].includes(move.id)) return new Array(targets.length).fill(true); const hitResults: boolean[] = []; for (const [i, target] of targets.entries()) { if (target.volatiles['commanding']) { @@ -1060,7 +1061,8 @@ export class BattleActions { if (!moveData.flags) moveData.flags = {}; if (move.target === 'all' && !isSelf) { hitResult = this.battle.singleEvent('TryHitField', moveData, {}, target || null, pokemon, move); - } else if ((move.target === 'foeSide' || move.target === 'allySide' || move.target === 'allyTeam') && !isSelf) { + } else if ((move.target === 'foeSide' || move.target === 'allySide' || + (move.target === 'allyTeam' && this.battle.gen <= 5)) && !isSelf) { hitResult = this.battle.singleEvent('TryHitSide', moveData, {}, target || null, pokemon, move); } else if (target) { hitResult = this.battle.singleEvent('TryHit', moveData, {}, target, pokemon, move); @@ -1075,7 +1077,8 @@ export class BattleActions { // 0. check for substitute if (!isSecondary && !isSelf) { - if (move.target !== 'all' && move.target !== 'allyTeam' && move.target !== 'allySide' && move.target !== 'foeSide') { + if (move.target !== 'all' && move.target !== 'allySide' && move.target !== 'foeSide' && + (move.target !== 'allyTeam' || this.battle.gen > 5)) { damage = this.tryPrimaryHitEvent(damage, targets, pokemon, move, moveData, isSecondary); } } diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 6ff69ec153..ca34df3e12 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -779,7 +779,6 @@ export class Pokemon { case 'all': case 'foeSide': case 'allySide': - case 'allyTeam': if (!move.target.startsWith('foe')) { targets.push(...this.alliesAndSelf()); } @@ -790,6 +789,12 @@ export class Pokemon { this.battle.retargetLastMove(targets[targets.length - 1]); } break; + case 'allyTeam': + targets.push(...this.side.pokemon.filter(ally => ally.hp)); + if (this.side.allySide) { + targets.push(...this.side.allySide.pokemon.filter(ally => ally.hp)); + } + break; case 'allAdjacent': targets.push(...this.adjacentAllies()); // falls through diff --git a/test/sim/moves/aromatherapy.js b/test/sim/moves/aromatherapy.js new file mode 100644 index 0000000000..7cee17d9fe --- /dev/null +++ b/test/sim/moves/aromatherapy.js @@ -0,0 +1,53 @@ +'use strict'; + +const assert = require('./../../assert'); +const common = require('./../../common'); + +let battle; + +describe('Aromatherapy', () => { + afterEach(() => { + battle.destroy(); + }); + + for (let gen = Dex.gen; gen >= 3; gen--) { + it(`should handle the interaction with Sap Sipper and Substitute correctly in Gen ${gen}`, () => { + const existsSapSipper = gen >= 5; + const ability = existsSapSipper ? 'sapsipper' : ''; + + battle = common.gen(gen).createBattle({ gameType: 'doubles' }, [[ + { species: 'Meganium', ability, moves: ['sleeptalk'] }, + { species: 'Typhlosion', ability, moves: ['sleeptalk', 'substitute', 'aromatherapy'] }, + { species: 'Feraligatr', ability, moves: ['sleeptalk'] }, + { species: 'Furret', moves: ['sleeptalk', 'substitute'] }, + ], [ + { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, + { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, + { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, + ]]); + if (existsSapSipper) { + battle.forceRandomChance = true; + battle.makeChoices('auto', 'move glare 1, move glare 2'); + battle.makeChoices('switch 3, move sleeptalk', 'move glare 1, move glare 2'); + battle.forceRandomChance = false; + battle.makeChoices('move sleeptalk, move aromatherapy', 'move sleeptalk, move sleeptalk'); + const self = battle.p1.pokemon[1]; + const active = battle.p1.pokemon[0]; + const back = battle.p1.pokemon[2]; + assert.equal(self.status, ''); + assert.equal(active.status, gen <= 5 && existsSapSipper ? '' : 'par'); + assert.equal(back.status, ''); + } + + battle.forceRandomChance = true; + battle.makeChoices('switch 4, move sleeptalk', 'move glare 1, move glare 2'); + battle.forceRandomChance = false; + battle.makeChoices('move substitute, move substitute', 'move sleeptalk, move sleeptalk'); + battle.makeChoices('move sleeptalk, move aromatherapy', 'move sleeptalk, move sleeptalk'); + const self = battle.p1.pokemon[1]; + const substitute = battle.p1.pokemon[0]; + assert.equal(self.status, ''); + assert.equal(substitute.status, gen <= 5 ? '' : 'par'); + }); + } +}); diff --git a/test/sim/moves/healbell.js b/test/sim/moves/healbell.js index 0814907b4e..2818c6bced 100644 --- a/test/sim/moves/healbell.js +++ b/test/sim/moves/healbell.js @@ -25,18 +25,29 @@ describe('Heal Bell', () => { assert.equal(battle.p1.pokemon[1].status, ''); }); - it(`should not heal the major status conditions of a Pokemon with Soundproof`, () => { - battle = common.createBattle({ gameType: 'doubles' }, [[ - { species: 'Kommo-o', ability: 'soundproof', moves: ['sleeptalk'] }, - { species: 'Chansey', moves: ['sleeptalk', 'healbell'] }, - ], [ - { species: 'Nidoking', moves: ['sleeptalk', 'toxic'] }, - { species: 'Wynaut', moves: ['sleeptalk'] }, - ]]); - battle.makeChoices('auto', 'move toxic 1, move sleeptalk'); - battle.makeChoices('move sleeptalk, move healbell', 'auto'); - assert.equal(battle.p1.pokemon[0].status, 'tox'); - }); + for (let gen = Dex.gen; gen >= 3; gen--) { + it(`should handle the interaction with Soundproof correctly in Gen ${gen}`, () => { + battle = common.gen(gen).createBattle({ gameType: 'doubles' }, [[ + { species: 'Meganium', ability: 'soundproof', moves: ['sleeptalk'] }, + { species: 'Typhlosion', ability: 'soundproof', moves: ['sleeptalk', 'healbell'] }, + { species: 'Feraligatr', ability: 'soundproof', moves: ['sleeptalk'] }, + ], [ + { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, + { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, + ]]); + battle.forceRandomChance = true; + battle.makeChoices('auto', 'move glare 1, move glare 2'); + battle.makeChoices('switch 3, move sleeptalk', 'move glare 1, move glare 2'); + battle.forceRandomChance = false; + battle.makeChoices('move sleeptalk, move healbell', 'move sleeptalk, move sleeptalk'); + const self = battle.p1.pokemon[1]; + const active = battle.p1.pokemon[0]; + const back = battle.p1.pokemon[2]; + assert.equal(self.status, gen >= 8 || gen === 5 ? '' : 'par'); + assert.equal(active.status, gen === 5 ? '' : 'par'); + assert.equal(back.status, gen > 4 ? '' : 'par'); + }); + } it(`with Mold Breaker should heal the major status conditions of a Pokemon with Soundproof`, () => { battle = common.createBattle({ gameType: 'doubles' }, [[ From 1e08bcbc72fd581b82e33b13bf577ca349cbe938 Mon Sep 17 00:00:00 2001 From: andrebastosdias Date: Sun, 1 Mar 2026 19:56:20 +0000 Subject: [PATCH 2/6] Add Electrify + Volt Absorb test --- test/sim/moves/aromatherapy.js | 99 +++++++++++++++++++++------------- test/sim/moves/healbell.js | 14 +++++ 2 files changed, 77 insertions(+), 36 deletions(-) diff --git a/test/sim/moves/aromatherapy.js b/test/sim/moves/aromatherapy.js index 7cee17d9fe..4d8f5d654a 100644 --- a/test/sim/moves/aromatherapy.js +++ b/test/sim/moves/aromatherapy.js @@ -10,44 +10,71 @@ describe('Aromatherapy', () => { battle.destroy(); }); - for (let gen = Dex.gen; gen >= 3; gen--) { - it(`should handle the interaction with Sap Sipper and Substitute correctly in Gen ${gen}`, () => { - const existsSapSipper = gen >= 5; - const ability = existsSapSipper ? 'sapsipper' : ''; + it(`should heal the major status conditions of the user's team`, () => { + battle = common.createBattle([[ + { species: 'Dunsparce', moves: ['sleeptalk'] }, + { species: 'Chansey', moves: ['aromatherapy'] }, + ], [ + { species: 'Nidoking', moves: ['toxic', 'glare'] }, + ]]); + battle.makeChoices('auto', 'move glare'); + battle.makeChoices('switch chansey', 'auto'); + battle.makeChoices(); + assert.equal(battle.p1.pokemon[0].status, ''); + assert.equal(battle.p1.pokemon[1].status, ''); + }); - battle = common.gen(gen).createBattle({ gameType: 'doubles' }, [[ - { species: 'Meganium', ability, moves: ['sleeptalk'] }, - { species: 'Typhlosion', ability, moves: ['sleeptalk', 'substitute', 'aromatherapy'] }, - { species: 'Feraligatr', ability, moves: ['sleeptalk'] }, - { species: 'Furret', moves: ['sleeptalk', 'substitute'] }, + it(`should not heal the major status conditions of a Pokemon with Sap Sipper`, () => { + battle = common.createBattle({ gameType: 'doubles' }, [[ + { species: 'Azumarill', ability: 'sapsipper', moves: ['sleeptalk'] }, + { species: 'Chansey', moves: ['sleeptalk', 'aromatherapy'] }, + ], [ + { species: 'Nidoking', moves: ['sleeptalk', 'toxic'] }, + { species: 'Wynaut', moves: ['sleeptalk'] }, + ]]); + battle.makeChoices('auto', 'move toxic 1, move sleeptalk'); + battle.makeChoices('move sleeptalk, move aromatherapy', 'auto'); + assert.equal(battle.p1.pokemon[0].status, 'tox'); + }); + + it(`should not heal the major status conditions of a Pokemon behind a Substitute`, () => { + battle = common.createBattle({ gameType: 'doubles' }, [[ + { species: 'Azumarill', moves: ['sleeptalk', 'substitute'] }, + { species: 'Chansey', moves: ['sleeptalk', 'aromatherapy'] }, + ], [ + { species: 'Nidoking', moves: ['sleeptalk', 'toxic'] }, + { species: 'Wynaut', moves: ['sleeptalk'] }, + ]]); + battle.makeChoices('move substitute, move sleeptalk', 'move toxic 1, move sleeptalk'); + battle.makeChoices('move sleeptalk, move aromatherapy', 'move sleeptalk, move sleeptalk'); + assert.equal(battle.p1.pokemon[0].status, 'tox'); + }); + + describe('[Gen 5]', () => { + it(`should heal the major status conditions of a Pokemon with Sap Sipper`, () => { + battle = common.gen(5).createBattle({ gameType: 'doubles' }, [[ + { species: 'Azumarill', ability: 'sapsipper', moves: ['sleeptalk'] }, + { species: 'Chansey', moves: ['sleeptalk', 'aromatherapy'] }, ], [ - { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, - { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, - { species: 'Wynaut', moves: ['glare', 'sleeptalk'] }, + { species: 'Nidoking', moves: ['sleeptalk', 'toxic'] }, + { species: 'Wynaut', moves: ['sleeptalk'] }, ]]); - if (existsSapSipper) { - battle.forceRandomChance = true; - battle.makeChoices('auto', 'move glare 1, move glare 2'); - battle.makeChoices('switch 3, move sleeptalk', 'move glare 1, move glare 2'); - battle.forceRandomChance = false; - battle.makeChoices('move sleeptalk, move aromatherapy', 'move sleeptalk, move sleeptalk'); - const self = battle.p1.pokemon[1]; - const active = battle.p1.pokemon[0]; - const back = battle.p1.pokemon[2]; - assert.equal(self.status, ''); - assert.equal(active.status, gen <= 5 && existsSapSipper ? '' : 'par'); - assert.equal(back.status, ''); - } - - battle.forceRandomChance = true; - battle.makeChoices('switch 4, move sleeptalk', 'move glare 1, move glare 2'); - battle.forceRandomChance = false; - battle.makeChoices('move substitute, move substitute', 'move sleeptalk, move sleeptalk'); - battle.makeChoices('move sleeptalk, move aromatherapy', 'move sleeptalk, move sleeptalk'); - const self = battle.p1.pokemon[1]; - const substitute = battle.p1.pokemon[0]; - assert.equal(self.status, ''); - assert.equal(substitute.status, gen <= 5 ? '' : 'par'); + battle.makeChoices('auto', 'move toxic 1, move sleeptalk'); + battle.makeChoices('move sleeptalk, move aromatherapy', 'auto'); + assert.equal(battle.p1.pokemon[0].status, ''); }); - } + + it(`should heal the major status conditions of a Pokemon behind a Substitute`, () => { + battle = common.gen(5).createBattle({ gameType: 'doubles' }, [[ + { species: 'Azumarill', moves: ['sleeptalk', 'substitute'] }, + { species: 'Chansey', moves: ['sleeptalk', 'aromatherapy'] }, + ], [ + { species: 'Nidoking', moves: ['sleeptalk', 'toxic'] }, + { species: 'Wynaut', moves: ['sleeptalk'] }, + ]]); + battle.makeChoices('move substitute, move sleeptalk', 'move toxic 1, move sleeptalk'); + battle.makeChoices('move sleeptalk, move aromatherapy', 'move sleeptalk, move sleeptalk'); + assert.equal(battle.p1.pokemon[0].status, ''); + }); + }); }); diff --git a/test/sim/moves/healbell.js b/test/sim/moves/healbell.js index 2818c6bced..e573dbb33c 100644 --- a/test/sim/moves/healbell.js +++ b/test/sim/moves/healbell.js @@ -62,6 +62,20 @@ describe('Heal Bell', () => { assert.equal(battle.p1.pokemon[0].status, ''); }); + it(`with Electrify should trigger an ally's Volt Absorb`, () => { + battle = common.createBattle({ gameType: 'doubles' }, [[ + { species: 'Raichu', ability: 'voltabsorb', moves: ['electrify'] }, + { species: 'Chansey', moves: ['healbell'] }, + ], [ + { species: 'Regieleki', moves: ['tackle'] }, + { species: 'Deoxys', moves: ['toxic'] }, + ]]); + battle.makeChoices('move electrify -2, move healbell', 'move tackle 1, move toxic 1'); + const voltAbsorb = battle.p1.pokemon[0]; + assert.equal(voltAbsorb.status, 'tox'); + assert.equal(voltAbsorb.maxhp - voltAbsorb.hp, Math.floor(voltAbsorb.maxhp / 16)); + }); + it(`in a Multi Battle, should heal the major status conditions of the ally's team`, () => { battle = common.createBattle({ gameType: 'multi' }, [[ { species: 'Machamp', ability: 'noguard', moves: ['poisongas'] }, From cd965852ca9f30c37efc38f60f273b420b23abb6 Mon Sep 17 00:00:00 2001 From: andrebastosdias Date: Sun, 1 Mar 2026 20:23:00 +0000 Subject: [PATCH 3/6] Lint --- data/mods/gen9ssb/scripts.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/mods/gen9ssb/scripts.ts b/data/mods/gen9ssb/scripts.ts index d66df9373d..96c32d2cd2 100644 --- a/data/mods/gen9ssb/scripts.ts +++ b/data/mods/gen9ssb/scripts.ts @@ -1325,7 +1325,7 @@ export const Scripts: ModdedBattleScriptsData = { let damage: number | false | undefined | '' = false; if (move.target === 'all' || move.target === 'foeSide' || move.target === 'allySide' || - (move.target === 'allyTeam' && this.battle.gen <= 5)) { + (move.target === 'allyTeam' && this.battle.gen <= 5)) { damage = this.tryMoveHit(targets, pokemon, move); if (damage === this.battle.NOT_FAIL) pokemon.moveThisTurnResult = null; if (damage || damage === 0 || damage === undefined) moveResult = true; @@ -1596,7 +1596,7 @@ export const Scripts: ModdedBattleScriptsData = { if (move.target === 'all' && !isSelf) { hitResult = this.battle.singleEvent('TryHitField', moveData, {}, target || null, pokemon, move); } else if ((move.target === 'foeSide' || move.target === 'allySide' || - (move.target === 'allyTeam' && this.battle.gen <= 5)) && !isSelf) { + (move.target === 'allyTeam' && this.battle.gen <= 5)) && !isSelf) { hitResult = this.battle.singleEvent('TryHitSide', moveData, {}, target || null, pokemon, move); } else if (target) { hitResult = this.battle.singleEvent('TryHit', moveData, {}, target, pokemon, move); From 081571c8b645ec8e315352b078cade5aae34b286 Mon Sep 17 00:00:00 2001 From: andrebastosdias Date: Sun, 1 Mar 2026 20:26:57 +0000 Subject: [PATCH 4/6] Revert change --- data/moves.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/data/moves.ts b/data/moves.ts index ad1ac0ae35..55cd0291c6 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -18007,6 +18007,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { flags: { protect: 1, mirror: 1 }, self: { onHit(pokemon, source, move) { + this.add('-activate', source, 'move: Aromatherapy'); for (const ally of source.side.pokemon) { if (ally !== source && (ally.volatiles['substitute'] && !move.infiltrates)) { continue; From 59e21dd57e1c7f42532b0e13ee88012cda677094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Sat, 7 Mar 2026 20:37:16 +0000 Subject: [PATCH 5/6] Fix activation message --- data/moves.ts | 8 ++------ sim/battle-actions.ts | 7 ++++++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/data/moves.ts b/data/moves.ts index 55cd0291c6..b5ca5f04c9 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -584,9 +584,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { pp: 5, priority: 0, flags: { snatch: 1, distance: 1, metronome: 1 }, - onPrepareHit(target, source) { - this.add('-activate', source, 'move: Aromatherapy'); - }, + // activation message in sim/battle-actions.ts onHit(target) { target.cureStatus(); }, @@ -8529,9 +8527,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { pp: 5, priority: 0, flags: { snatch: 1, sound: 1, distance: 1, bypasssub: 1, metronome: 1 }, - onPrepareHit(target, source) { - this.add('-activate', source, 'move: Heal Bell'); - }, + // activation message in sim/battle-actions.ts onHit(target, source, move) { target.cureStatus(); }, diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 48a3eca804..2671eabbd1 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -617,7 +617,12 @@ export class BattleActions { return moveResult; } hitStepInvulnerabilityEvent(targets: Pokemon[], pokemon: Pokemon, move: ActiveMove) { - if (['aromatherapy', 'healbell', 'helpinghand'].includes(move.id)) return new Array(targets.length).fill(true); + if (['aromatherapy', 'healbell', 'helpinghand'].includes(move.id)) { + if (this.battle.gen > 5 && (move.id === 'aromatherapy' || move.id === 'healbell')) { + this.battle.add('-activate', pokemon, `move: ${move.name}`); + } + return new Array(targets.length).fill(true); + } const hitResults: boolean[] = []; for (const [i, target] of targets.entries()) { if (target.volatiles['commanding']) { From 09ea21109cc86108f066060747e5f1467a1127c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Sat, 7 Mar 2026 20:38:20 +0000 Subject: [PATCH 6/6] Remove unused onPrepareHit code --- data/mods/gen5/moves.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/data/mods/gen5/moves.ts b/data/mods/gen5/moves.ts index 756eff6113..4328d70e1e 100644 --- a/data/mods/gen5/moves.ts +++ b/data/mods/gen5/moves.ts @@ -17,7 +17,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { }, aromatherapy: { inherit: true, - onPrepareHit() {}, onHit(target, source) { this.add('-activate', source, 'move: Aromatherapy'); const allies = [...target.side.pokemon, ...target.side.allySide?.pokemon || []]; @@ -346,7 +345,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { healbell: { inherit: true, flags: { snatch: 1, sound: 1, metronome: 1 }, - onPrepareHit() {}, onHit(target, source) { this.add('-activate', source, 'move: Heal Bell'); const allies = [...target.side.pokemon, ...target.side.allySide?.pokemon || []];