mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-08-22 17:14:58 -05:00
Merge f131aa52d6 into 00c061991c
This commit is contained in:
@@ -819,7 +819,40 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
||||
dancer: {
|
||||
flags: {},
|
||||
name: "Dancer",
|
||||
// implemented in runMove in scripts.js
|
||||
onAnyAfterMovePriority: -200,
|
||||
onAnyAfterMove(source, target, move) {
|
||||
const dancer = this.effectState.target as Pokemon;
|
||||
if (dancer === source || dancer.isSemiInvulnerable() || !move.flags['dance'] ||
|
||||
!this.lastSuccessfulMoveThisTurn || move.isExternal) return;
|
||||
const targetOf1stDance = this.activeTarget!;
|
||||
const dancersTarget = !targetOf1stDance.isAlly(dancer) && source.isAlly(dancer) ?
|
||||
targetOf1stDance : source;
|
||||
const dancersTargetLoc = dancer.getLocOf(dancersTarget);
|
||||
// Gen 7: Dancer activates in order of lowest speed stat to highest
|
||||
// Note that the speed stat used is after any volatile replacements like Speed Swap,
|
||||
// but before any multipliers like Agility or Choice Scarf
|
||||
// Ties go to whichever Pokemon has had the ability for the least amount of time
|
||||
this.queue.prioritizeAction(this.queue.resolveAction({
|
||||
choice: 'move',
|
||||
effectOrder: dancer.abilityState.effectOrder,
|
||||
pokemon: dancer,
|
||||
moveid: move.id,
|
||||
targetLoc: dancersTargetLoc,
|
||||
sourceEffect: this.effect,
|
||||
externalMove: true,
|
||||
})[0] as MoveAction, this.effect);
|
||||
},
|
||||
onBeforeMovePriority: 200,
|
||||
onBeforeMove(source, target, move) {
|
||||
if (move.isExternal) {
|
||||
this.add('-activate', source, 'ability: Dancer');
|
||||
}
|
||||
},
|
||||
onTryAddVolatile(status, target, source, sourceEffect) {
|
||||
if (status.id === 'lockedmove' && (sourceEffect as ActiveMove)?.isExternal) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
rating: 1.5,
|
||||
num: 216,
|
||||
},
|
||||
|
||||
@@ -1093,8 +1093,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
move = this.getActiveMaxMove(baseMove, pokemon);
|
||||
}
|
||||
|
||||
move.isExternal = externalMove;
|
||||
|
||||
this.battle.setActiveMove(move, pokemon, target);
|
||||
|
||||
/* if (pokemon.moveThisTurn) {
|
||||
@@ -1140,10 +1138,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
pokemon.moveUsed(move, targetLoc);
|
||||
}
|
||||
|
||||
// Dancer Petal Dance hack
|
||||
// TODO: implement properly
|
||||
const noLock = externalMove && !pokemon.volatiles['lockedmove'];
|
||||
|
||||
if (zMove) {
|
||||
if (pokemon.illusion) {
|
||||
this.battle.singleEvent('End', this.dex.abilities.get('Illusion'), pokemon.abilityState, pokemon);
|
||||
@@ -1161,35 +1155,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
this.battle.singleEvent('AfterMove', move, null, pokemon, target, move);
|
||||
this.battle.runEvent('AfterMove', pokemon, target, move);
|
||||
|
||||
// Dancer's activation order is completely different from any other event, so it's handled separately
|
||||
if (move.flags['dance'] && moveDidSomething && !move.isExternal) {
|
||||
const dancers = [];
|
||||
for (const currentPoke of this.battle.getAllActive()) {
|
||||
if (pokemon === currentPoke) continue;
|
||||
if (currentPoke.hasAbility(['dancer', 'virtualidol']) && !currentPoke.isSemiInvulnerable()) {
|
||||
dancers.push(currentPoke);
|
||||
}
|
||||
}
|
||||
// Dancer activates in order of lowest speed stat to highest
|
||||
// Note that the speed stat used is after any volatile replacements like Speed Swap,
|
||||
// but before any multipliers like Agility or Choice Scarf
|
||||
// Ties go to whichever Pokemon has had the ability for the least amount of time
|
||||
dancers.sort(
|
||||
(a, b) => -(b.storedStats['spe'] - a.storedStats['spe']) || b.abilityState.effectOrder - a.abilityState.effectOrder
|
||||
);
|
||||
const targetOf1stDance = this.battle.activeTarget!;
|
||||
for (const dancer of dancers) {
|
||||
if (this.battle.faintMessages()) break;
|
||||
if (dancer.fainted) continue;
|
||||
this.battle.add('-activate', dancer, 'ability: ' + dancer.getAbility().name);
|
||||
const dancersTarget = !targetOf1stDance.isAlly(dancer) && pokemon.isAlly(dancer) ?
|
||||
targetOf1stDance :
|
||||
pokemon;
|
||||
const dancersTargetLoc = dancer.getLocOf(dancersTarget);
|
||||
this.runMove(move.id, dancer, dancersTargetLoc, { sourceEffect: dancer.getAbility(), externalMove: true });
|
||||
}
|
||||
}
|
||||
if (noLock && pokemon.volatiles['lockedmove']) delete pokemon.volatiles['lockedmove'];
|
||||
this.battle.faintMessages();
|
||||
this.battle.checkWin();
|
||||
|
||||
|
||||
@@ -398,8 +398,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
move = this.getActiveMaxMove(baseMove, pokemon);
|
||||
}
|
||||
|
||||
move.isExternal = externalMove;
|
||||
|
||||
this.battle.setActiveMove(move, pokemon, target);
|
||||
|
||||
/* if (pokemon.moveThisTurn) {
|
||||
@@ -451,10 +449,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
pokemon.moveUsed(move, targetLoc);
|
||||
}
|
||||
|
||||
// Dancer Petal Dance hack
|
||||
// TODO: implement properly
|
||||
const noLock = externalMove && !pokemon.volatiles['lockedmove'];
|
||||
|
||||
if (zMove) {
|
||||
if (pokemon.illusion) {
|
||||
this.battle.singleEvent('End', this.dex.abilities.get('Illusion'), pokemon.abilityState, pokemon);
|
||||
@@ -474,36 +468,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
this.battle.add('-hint', `Some effects can force a Pokemon to use ${move.name} again in a row.`);
|
||||
}
|
||||
|
||||
// TODO: Refactor to use BattleQueue#prioritizeAction in onAnyAfterMove handlers
|
||||
// Dancer's activation order is completely different from any other event, so it's handled separately
|
||||
if (move.flags['dance'] && moveDidSomething && !move.isExternal) {
|
||||
const dancers = [];
|
||||
for (const currentPoke of this.battle.getAllActive()) {
|
||||
if (pokemon === currentPoke) continue;
|
||||
if (currentPoke.hasAbility('dancer') && !currentPoke.isSemiInvulnerable()) {
|
||||
dancers.push(currentPoke);
|
||||
}
|
||||
}
|
||||
// Dancer activates in order of lowest speed stat to highest
|
||||
// Note that the speed stat used is after any volatile replacements like Speed Swap,
|
||||
// but before any multipliers like Agility or Choice Scarf
|
||||
// Ties go to whichever Pokemon has had the ability for the least amount of time
|
||||
dancers.sort(
|
||||
(a, b) => -(b.storedStats['spe'] - a.storedStats['spe']) || b.abilityState.effectOrder - a.abilityState.effectOrder
|
||||
);
|
||||
const targetOf1stDance = this.battle.activeTarget!;
|
||||
for (const dancer of dancers) {
|
||||
if (this.battle.faintMessages()) break;
|
||||
if (dancer.fainted) continue;
|
||||
this.battle.add('-activate', dancer, 'ability: Dancer');
|
||||
const dancersTarget = !targetOf1stDance.isAlly(dancer) && pokemon.isAlly(dancer) ?
|
||||
targetOf1stDance :
|
||||
pokemon;
|
||||
const dancersTargetLoc = dancer.getLocOf(dancersTarget);
|
||||
this.runMove(move.id, dancer, dancersTargetLoc, { sourceEffect: this.dex.abilities.get('dancer'), externalMove: true });
|
||||
}
|
||||
}
|
||||
if (noLock && pokemon.volatiles['lockedmove']) delete pokemon.volatiles['lockedmove'];
|
||||
this.battle.faintMessages();
|
||||
this.battle.checkWin();
|
||||
|
||||
|
||||
@@ -291,10 +291,6 @@ export class BattleActions {
|
||||
pokemon.moveUsed(move, targetLoc);
|
||||
}
|
||||
|
||||
// Dancer Petal Dance hack
|
||||
// TODO: implement properly
|
||||
const noLock = externalMove && !pokemon.volatiles['lockedmove'];
|
||||
|
||||
if (zMove) {
|
||||
if (pokemon.illusion) {
|
||||
this.battle.singleEvent('End', this.dex.abilities.get('Illusion'), pokemon.abilityState, pokemon);
|
||||
@@ -314,36 +310,6 @@ export class BattleActions {
|
||||
this.battle.add('-hint', `Some effects can force a Pokemon to use ${move.name} again in a row.`);
|
||||
}
|
||||
|
||||
// TODO: Refactor to use BattleQueue#prioritizeAction in onAnyAfterMove handlers
|
||||
// Dancer's activation order is completely different from any other event, so it's handled separately
|
||||
if (move.flags['dance'] && moveDidSomething && !move.isExternal) {
|
||||
const dancers = [];
|
||||
for (const currentPoke of this.battle.getAllActive()) {
|
||||
if (pokemon === currentPoke) continue;
|
||||
if (currentPoke.hasAbility('dancer') && !currentPoke.isSemiInvulnerable()) {
|
||||
dancers.push(currentPoke);
|
||||
}
|
||||
}
|
||||
// Dancer activates in order of lowest speed stat to highest
|
||||
// Note that the speed stat used is after any volatile replacements like Speed Swap,
|
||||
// but before any multipliers like Agility or Choice Scarf
|
||||
// Ties go to whichever Pokemon has had the ability for the least amount of time
|
||||
dancers.sort(
|
||||
(a, b) => -(b.storedStats['spe'] - a.storedStats['spe']) || b.abilityState.effectOrder - a.abilityState.effectOrder
|
||||
);
|
||||
const targetOf1stDance = this.battle.activeTarget!;
|
||||
for (const dancer of dancers) {
|
||||
if (this.battle.faintMessages()) break;
|
||||
if (dancer.fainted) continue;
|
||||
this.battle.add('-activate', dancer, 'ability: Dancer');
|
||||
const dancersTarget = !targetOf1stDance.isAlly(dancer) && pokemon.isAlly(dancer) ?
|
||||
targetOf1stDance :
|
||||
pokemon;
|
||||
const dancersTargetLoc = dancer.getLocOf(dancersTarget);
|
||||
this.runMove(move.id, dancer, dancersTargetLoc, { sourceEffect: this.dex.abilities.get('dancer'), externalMove: true });
|
||||
}
|
||||
}
|
||||
if (noLock && pokemon.volatiles['lockedmove']) delete pokemon.volatiles['lockedmove'];
|
||||
this.battle.faintMessages();
|
||||
this.battle.checkWin();
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import type { Battle } from './battle';
|
||||
export interface MoveAction {
|
||||
/** action type */
|
||||
choice: 'move' | 'beforeTurnMove' | 'priorityChargeMove';
|
||||
order: 3 | 5 | 200 | 201 | 199 | 106;
|
||||
order: 5 | 105 | 199 | 200 | 201;
|
||||
/** priority of the action (higher first) */
|
||||
priority: number;
|
||||
/** fractional priority of the action (higher first) */
|
||||
@@ -50,13 +50,15 @@ export interface MoveAction {
|
||||
maxMove?: string;
|
||||
/** effect that called the move (eg Instruct) if any */
|
||||
sourceEffect?: Effect | null;
|
||||
/** if external, skips LockMove and PP deduction, mostly for use by Dancer */
|
||||
externalMove?: boolean;
|
||||
}
|
||||
|
||||
/** A switch action */
|
||||
export interface SwitchAction {
|
||||
/** action type */
|
||||
choice: 'switch' | 'instaswitch' | 'revivalblessing';
|
||||
order: 3 | 6 | 103;
|
||||
order: 3 | 6 | 101;
|
||||
/** priority of the action (higher first) */
|
||||
priority: number;
|
||||
/** speed of pokemon switching (higher first if priority tie) */
|
||||
@@ -179,14 +181,12 @@ export class BattleQueue {
|
||||
beforeTurnMove: 5,
|
||||
revivalblessing: 6,
|
||||
|
||||
runSwitch: 101,
|
||||
switch: 103,
|
||||
megaEvo: 104,
|
||||
megaEvoX: 104,
|
||||
megaEvoY: 104,
|
||||
runDynamax: 105,
|
||||
terastallize: 106,
|
||||
priorityChargeMove: 107,
|
||||
runSwitch: 100,
|
||||
switch: 101,
|
||||
megaEvo: 102, megaEvoX: 102, megaEvoY: 102,
|
||||
runDynamax: 103,
|
||||
terastallize: 104,
|
||||
priorityChargeMove: 105,
|
||||
|
||||
shift: 200,
|
||||
// default is 200 (for moves)
|
||||
@@ -282,7 +282,7 @@ export class BattleQueue {
|
||||
}
|
||||
}
|
||||
action.sourceEffect = sourceEffect;
|
||||
action.order = 3;
|
||||
action.order = action.choice === 'move' ? 199 : 3;
|
||||
this.list.unshift(action);
|
||||
}
|
||||
|
||||
|
||||
@@ -1001,8 +1001,11 @@ export class Battle {
|
||||
if (handler.effectHolder && (handler.effectHolder as Pokemon).getStat) {
|
||||
const pokemon = handler.effectHolder as Pokemon;
|
||||
handler.speed = pokemon.speed;
|
||||
if (handler.effect.effectType === 'Ability' && handler.effect.name === 'Magic Bounce' &&
|
||||
callbackName === 'onAllyTryHitSide') {
|
||||
if (handler.effect.effectType === 'Ability' && (
|
||||
(handler.effect.name === 'Dancer' && callbackName === 'onAnyAfterMove') ||
|
||||
(handler.effect.name === 'Magic Bounce' && callbackName === 'onAllyTryHitSide')
|
||||
)) {
|
||||
// TODO: Check which other events are sorted based on the unmodified speed
|
||||
handler.speed = pokemon.getStat('spe', true, true);
|
||||
}
|
||||
if (callbackName.endsWith('SwitchIn')) {
|
||||
@@ -2703,7 +2706,7 @@ export class Battle {
|
||||
if (!action.pokemon.isActive) return false;
|
||||
if (action.pokemon.fainted) return false;
|
||||
this.actions.runMove(action.move, action.pokemon, action.targetLoc, {
|
||||
sourceEffect: action.sourceEffect, zMove: action.zmove,
|
||||
sourceEffect: action.sourceEffect, zMove: action.zmove, externalMove: action.externalMove,
|
||||
maxMove: action.maxMove, originalTarget: action.originalTarget,
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -433,6 +433,7 @@ export interface EventMethods {
|
||||
onAfterMoveSecondarySelfPriority?: number;
|
||||
onAfterMoveSelfPriority?: number;
|
||||
onAfterSetStatusPriority?: number;
|
||||
onAnyAfterMovePriority?: number;
|
||||
onAnyBasePowerPriority?: number;
|
||||
onAnyInvulnerabilityPriority?: number;
|
||||
onAnyModifyAccuracyPriority?: number;
|
||||
|
||||
@@ -21,13 +21,13 @@ describe('Dancer', () => {
|
||||
assert.statStage(battle.p2.active[0], 'atk', 3);
|
||||
});
|
||||
|
||||
it('should activate in order of lowest to highest raw speed', () => {
|
||||
it('should activate in order of fastest to slowest', () => {
|
||||
battle = common.createBattle({ gameType: 'doubles' }, [[
|
||||
{ species: 'Shedinja', level: 98, ability: 'dancer', item: 'focussash', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 99, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', ability: 'dancer', item: 'focussash', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 98, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
], [
|
||||
{ species: 'Shedinja', ability: 'wonderguard', moves: ['fierydance'] },
|
||||
{ species: 'Shedinja', ability: 'dancer', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 99, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
]]);
|
||||
const [, fastDancer] = battle.p1.active;
|
||||
const [wwDanceSource, foeDancer] = battle.p2.active;
|
||||
@@ -37,23 +37,36 @@ describe('Dancer', () => {
|
||||
assert.fainted(foeDancer);
|
||||
});
|
||||
|
||||
it('should activate in order of lowest to highest raw speed inside Trick Room', () => {
|
||||
it('should activate in order of slowest to faster inside Trick Room', () => {
|
||||
battle = common.createBattle({ gameType: 'doubles' }, [[
|
||||
{ species: 'Shedinja', level: 98, ability: 'dancer', item: 'focussash', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 99, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', ability: 'dancer', item: 'focussash', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 98, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
], [
|
||||
{ species: 'Shedinja', ability: 'wonderguard', moves: ['fierydance', 'trickroom'] },
|
||||
{ species: 'Shedinja', ability: 'dancer', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 99, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
]]);
|
||||
const [, fastDancer] = battle.p1.active;
|
||||
const [wwDanceSource, foeDancer] = battle.p2.active;
|
||||
fastDancer.boostBy({ spe: 6 });
|
||||
foeDancer.boostBy({ spe: 6 });
|
||||
battle.makeChoices('move sleeptalk, move sleeptalk', 'move trickroom, move sleeptalk');
|
||||
battle.makeChoices('move sleeptalk, move sleeptalk', 'move fierydance 1, move sleeptalk');
|
||||
assert.fainted(wwDanceSource);
|
||||
assert.fainted(foeDancer);
|
||||
});
|
||||
|
||||
it(`should copy a move that was called by Instruct`, () => {
|
||||
battle = common.createBattle({ gameType: 'doubles' }, [[
|
||||
{ species: 'oricoriopau', ability: 'dancer', moves: ['instruct'] },
|
||||
{ species: 'volcarona', moves: ['fierydance'] },
|
||||
], [
|
||||
{ species: 'shedinja', item: 'focussash', ability: 'wonderguard', moves: ['sleeptalk'] },
|
||||
{ species: 'shedinja', item: 'focussash', ability: 'wonderguard', moves: ['sleeptalk'] },
|
||||
]]);
|
||||
|
||||
battle.makeChoices('move instruct -2, move fierydance 1', 'auto');
|
||||
assert.fainted(battle.p2.active[0]);
|
||||
assert.fainted(battle.p2.active[1]);
|
||||
});
|
||||
|
||||
it(`should not copy a move that was blocked by Protect`, () => {
|
||||
battle = common.createBattle([[
|
||||
{ species: 'Oricorio', ability: 'dancer', moves: ['protect'] },
|
||||
@@ -183,4 +196,58 @@ describe('Dancer', () => {
|
||||
assert.equal(fletchinder.boosts.atk, -2);
|
||||
assert.equal(squawkabilly.boosts.atk, -4);
|
||||
});
|
||||
|
||||
it('should activate after Eject Button', () => {
|
||||
battle = common.createBattle({ gameType: 'doubles' }, [[
|
||||
{ species: 'oricoriopau', ability: 'dancer', moves: ['sleeptalk'] },
|
||||
{ species: 'volcarona', moves: ['fierydance'] },
|
||||
], [
|
||||
{ species: 'fletchinder', item: 'ejectbutton', moves: ['sleeptalk'] },
|
||||
{ species: 'squawkabilly', moves: ['sleeptalk'] },
|
||||
{ species: 'suicune', moves: ['sleeptalk'] },
|
||||
]]);
|
||||
const suicune = battle.p2.pokemon[2];
|
||||
battle.makeChoices('move sleeptalk, move fierydance 1', 'move sleeptalk, move sleeptalk');
|
||||
battle.makeChoices();
|
||||
assert.notEqual(suicune.hp, suicune.fullHP);
|
||||
});
|
||||
});
|
||||
|
||||
describe('[Gen 7] Dancer', () => {
|
||||
afterEach(() => {
|
||||
battle.destroy();
|
||||
});
|
||||
|
||||
it('should activate in order of lowest to highest raw speed', () => {
|
||||
battle = common.gen(7).createBattle({ gameType: 'doubles' }, [[
|
||||
{ species: 'Shedinja', level: 98, ability: 'dancer', item: 'focussash', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 99, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
], [
|
||||
{ species: 'Shedinja', ability: 'wonderguard', moves: ['fierydance'] },
|
||||
{ species: 'Shedinja', ability: 'dancer', moves: ['sleeptalk'] },
|
||||
]]);
|
||||
const [, fastDancer] = battle.p1.active;
|
||||
const [wwDanceSource, foeDancer] = battle.p2.active;
|
||||
fastDancer.boostBy({ spe: 6 });
|
||||
battle.makeChoices('move sleeptalk, move sleeptalk', 'move fierydance 1, move sleeptalk');
|
||||
assert.fainted(wwDanceSource);
|
||||
assert.fainted(foeDancer);
|
||||
});
|
||||
|
||||
it('should activate in order of lowest to highest raw speed inside Trick Room', () => {
|
||||
battle = common.gen(7).createBattle({ gameType: 'doubles' }, [[
|
||||
{ species: 'Shedinja', level: 98, ability: 'dancer', item: 'focussash', moves: ['sleeptalk'] },
|
||||
{ species: 'Shedinja', level: 99, ability: 'dancer', moves: ['sleeptalk'] },
|
||||
], [
|
||||
{ species: 'Shedinja', ability: 'wonderguard', moves: ['fierydance', 'trickroom'] },
|
||||
{ species: 'Shedinja', ability: 'dancer', moves: ['sleeptalk'] },
|
||||
]]);
|
||||
const [, fastDancer] = battle.p1.active;
|
||||
const [wwDanceSource, foeDancer] = battle.p2.active;
|
||||
fastDancer.boostBy({ spe: 6 });
|
||||
battle.makeChoices('move sleeptalk, move sleeptalk', 'move trickroom, move sleeptalk');
|
||||
battle.makeChoices('move sleeptalk, move sleeptalk', 'move fierydance 1, move sleeptalk');
|
||||
assert.fainted(wwDanceSource);
|
||||
assert.fainted(foeDancer);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,6 +18,19 @@ describe(`Instruct`, () => {
|
||||
assert.equal(battle.p1.active[0].boosts.def, 2);
|
||||
});
|
||||
|
||||
it(`should ignore moves called by Dancer`, () => {
|
||||
battle = common.createBattle([
|
||||
[{ species: "Murkrow", ability: "prankster", moves: ['aquastep', 'instruct'] }],
|
||||
[{ species: "Oricorio", ability: "dancer", moves: ['stockpile'] }],
|
||||
]);
|
||||
battle.makeChoices();
|
||||
battle.makeChoices('move instruct', 'auto');
|
||||
const oricorio = battle.p2.active[0];
|
||||
assert.equal(oricorio.boosts.def, 3);
|
||||
assert.equal(oricorio.boosts.spd, 3);
|
||||
assert.equal(oricorio.boosts.spe, 1);
|
||||
});
|
||||
|
||||
it(`should not trigger AfterMove effects of the instructed move for the Instruct user`, () => {
|
||||
battle = common.createBattle([[
|
||||
{ species: "Swalot", moves: ['stockpile', 'spitup'] },
|
||||
|
||||
Reference in New Issue
Block a user