mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-06-02 22:08:36 -05:00
Merge 09ea21109c into 3d25154b04
This commit is contained in:
commit
1f4866f9a9
|
|
@ -300,22 +300,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,
|
||||
|
|
|
|||
|
|
@ -1329,7 +1329,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;
|
||||
|
|
@ -1599,7 +1600,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);
|
||||
|
|
@ -1614,7 +1616,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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -563,25 +563,9 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
pp: 5,
|
||||
priority: 0,
|
||||
flags: { snatch: 1, distance: 1, metronome: 1 },
|
||||
onHit(target, source, move) {
|
||||
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;
|
||||
// activation message in sim/battle-actions.ts
|
||||
onHit(target) {
|
||||
target.cureStatus();
|
||||
},
|
||||
target: "allyTeam",
|
||||
type: "Grass",
|
||||
|
|
@ -8248,24 +8232,9 @@ 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) {
|
||||
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;
|
||||
// activation message in sim/battle-actions.ts
|
||||
onHit(target, source, move) {
|
||||
target.cureStatus();
|
||||
},
|
||||
target: "allyTeam",
|
||||
type: "Normal",
|
||||
|
|
|
|||
|
|
@ -503,7 +503,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;
|
||||
|
|
@ -614,7 +615,12 @@ 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)) {
|
||||
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']) {
|
||||
|
|
@ -1059,7 +1065,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);
|
||||
|
|
@ -1074,7 +1081,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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -796,7 +796,6 @@ export class Pokemon {
|
|||
case 'all':
|
||||
case 'foeSide':
|
||||
case 'allySide':
|
||||
case 'allyTeam':
|
||||
if (!move.target.startsWith('foe')) {
|
||||
targets.push(...this.alliesAndSelf());
|
||||
}
|
||||
|
|
@ -807,6 +806,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
|
||||
|
|
|
|||
80
test/sim/moves/aromatherapy.js
Normal file
80
test/sim/moves/aromatherapy.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('./../../assert');
|
||||
const common = require('./../../common');
|
||||
|
||||
let battle;
|
||||
|
||||
describe('Aromatherapy', () => {
|
||||
afterEach(() => {
|
||||
battle.destroy();
|
||||
});
|
||||
|
||||
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, '');
|
||||
});
|
||||
|
||||
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: '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, '');
|
||||
});
|
||||
|
||||
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, '');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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' }, [[
|
||||
|
|
@ -51,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'] },
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user