Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix eject pack interactions #10704

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/abilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
commander: {
onUpdate(pokemon) {
if (this.gameType !== 'doubles') return;
if (!pokemon.isStarted) return;
const ally = pokemon.allies()[0];
if (!ally || pokemon.baseSpecies.baseSpecies !== 'Tatsugiri' || ally.baseSpecies.baseSpecies !== 'Dondozo') {
// Handle any edge cases
Expand Down
6 changes: 0 additions & 6 deletions data/items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1551,9 +1551,6 @@ export const Items: import('../sim/dex-items').ItemDataTable = {
if (source && source !== target && target.hp && move && move.category !== 'Status' && !move.flags['futuremove']) {
if (!this.canSwitch(target.side) || target.forceSwitchFlag || target.beingCalledBack || target.isSkyDropped()) return;
if (target.volatiles['commanding'] || target.volatiles['commanded']) return;
for (const pokemon of this.getAllActive()) {
if (pokemon.switchFlag === true) return;
}
target.switchFlag = true;
if (target.useItem()) {
source.switchFlag = false;
Expand Down Expand Up @@ -1584,9 +1581,6 @@ export const Items: import('../sim/dex-items').ItemDataTable = {
if (target.hp) {
if (!this.canSwitch(target.side)) return;
if (target.volatiles['commanding'] || target.volatiles['commanded']) return;
for (const pokemon of this.getAllActive()) {
if (pokemon.switchFlag === true) return;
}
if (target.useItem()) target.switchFlag = true;
}
}
Expand Down
16 changes: 15 additions & 1 deletion sim/battle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2725,10 +2725,24 @@ export class Battle {
}
}

const allStarted = this.sides.every(
side => side.active.every(pokemon => !pokemon || pokemon.isStarted || pokemon.fainted)
);

const switches = this.sides.map(
side => side.active.some(pokemon => pokemon && !!pokemon.switchFlag)
side => allStarted &&
side.active.some(pokemon => pokemon && !!pokemon.switchFlag)
);

const allActive = this.sides.map(side => side.active).flat();
const aliveSwitches = allActive.filter(pokemon => !!pokemon?.switchFlag && !pokemon.fainted);
if (aliveSwitches.length > 1) {
const sortedSwitches = aliveSwitches.sort((a, b) => a && b ? b.speed - a.speed : 0);
for (let i = 1; i < sortedSwitches.length; i++) {
sortedSwitches[i].switchFlag = false;
}
}

for (let i = 0; i < this.sides.length; i++) {
let reviveSwitch = false; // Used to ignore the fake switch for Revival Blessing
if (switches[i] && !this.canSwitch(this.sides[i])) {
Expand Down
2 changes: 1 addition & 1 deletion test/sim/abilities/commander.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ describe('Commander', function () {
assert.false.fullHP(shuckle, `Shuckle should have taken damage from Dazzling Gleam`);
});

it.skip(`should activate after hazards run`, function () {
it(`should activate after hazards run`, function () {
battle = common.createBattle({gameType: 'doubles'}, [[
{species: 'regieleki', moves: ['toxicspikes']},
{species: 'registeel', moves: ['sleeptalk']},
Expand Down
49 changes: 37 additions & 12 deletions test/sim/items/ejectpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe(`Eject Pack`, function () {
assert.equal(battle.p1.requestState, 'switch');
});

it.skip(`should not switch out the user if the user acquired the Eject Pack after the stat drop occurred`, function () {
it(`should not switch out the user if the user acquired the Eject Pack after the stat drop occurred`, function () {
battle = common.createBattle([[
{species: 'Klefki', ability: 'magician', moves: ['lowsweep']},
{species: 'Wynaut', moves: ['sleeptalk']},
Expand All @@ -80,20 +80,23 @@ describe(`Eject Pack`, function () {
assert.false.equal(battle.requestState, 'switch');
});

it.skip(`should wait until after all other end-turn effects have resolved before switching out the holder`, function () {
it(`should wait until after all other end-turn effects have resolved before switching out the holder`, function () {
battle = common.createBattle([[
{species: 'Glalie', item: 'ejectpack', ability: 'moody', moves: ['icebeam']},
{species: 'Wynaut', moves: ['sleeptalk']},
], [
{species: 'Zygarde', item: 'focussash', ability: 'powerconstruct', moves: ['octolock']},
]]);
battle.makeChoices();
const log = battle.getDebugLog();
const moodyIndex = log.lastIndexOf('|-ability|p1a: Glalie|Moody|boost');
const powerConstructIndex = log.lastIndexOf('|-activate|p2a: Zygarde|ability: Power Construct');
const ejectPackIndex = log.lastIndexOf('|-enditem|p1a: Glalie|Eject Pack');
assert(moodyIndex < ejectPackIndex, 'Eject Pack should not activate before Moody');
assert(powerConstructIndex < ejectPackIndex, 'Eject Pack should not activate before Power Construct');
const boosts = battle.p1.active[0].boosts;
let hasBoost = false;
for (const i in boosts) {
if (boosts[i] > 0) {
hasBoost = true;
}
}
assert.species(battle.p2.active[0], 'Zygarde-Complete');
assert(hasBoost, 'Boost from Moody should be applied before switch');
});

it.skip(`should not activate when another switching effect was triggered as part of the move`, function () {
Expand All @@ -107,12 +110,13 @@ describe(`Eject Pack`, function () {
{species: 'Wynaut', moves: ['sleeptalk']},
]]);
battle.makeChoices();
assert.statStage(battle.p2.active[1], 'atk', -1, "Attack should be dropped before switching.");
battle.makeChoices();
assert.species(battle.p2.active[0], 'Zeraora', `Zeraora should not have switched out with its Eject Pack.`);
assert.species(battle.p2.active[1], 'Wynaut', `Mew should have switched out with its Eject Button.`);
});

it.skip(`should only trigger the fastest Eject Pack when multiple targets with Eject Pack have stats lowered`, function () {
it(`should only trigger the fastest Eject Pack when multiple targets with Eject Pack have stats lowered`, function () {
battle = common.createBattle({gameType: 'doubles'}, [[
{species: 'Hydreigon', moves: ['leer']},
{species: 'Horsea', moves: ['sleeptalk']},
Expand All @@ -128,7 +132,7 @@ describe(`Eject Pack`, function () {
assert.species(battle.p2.active[1], 'Wynaut');
});

it.skip(`should not trigger until after all entrance abilities have resolved during simultaneous switches`, function () {
it(`should not trigger until after all entrance abilities have resolved during simultaneous switches`, function () {
battle = common.createBattle({gameType: 'doubles'}, [[
{species: 'Hydreigon', ability: 'intimidate', moves: ['sleeptalk']},
{species: 'Wynaut', moves: ['sleeptalk']},
Expand All @@ -137,12 +141,13 @@ describe(`Eject Pack`, function () {
{species: 'Mew', level: 1, ability: 'electricsurge', moves: ['sleeptalk']},
{species: 'Wynaut', moves: ['sleeptalk']},
]]);
battle.makeChoices();
assert(battle.field.isWeather('sunnyday'));
assert(battle.field.isTerrain('electricterrain'));
assert.equal(battle.p2.requestState, 'switch');
});

// This is barely an eject pack bug, this switches should be determined by slot, not pokemon. This requires revamping that system
// Out of scope of this PR.
it.skip(`should not prohibit switchins if a switch has already resolved to a slot replaced by Eject Pack`, function () {
battle = common.createBattle({gameType: 'doubles'}, [[
{species: 'Pheromosa', moves: ['sleeptalk']},
Expand All @@ -154,8 +159,28 @@ describe(`Eject Pack`, function () {
{species: 'Wynaut', moves: ['sleeptalk']},
]]);
battle.makeChoices('switch 3, move sleeptalk', 'move sleeptalk, switch 3');
assert.species(battle.p2.active[1], 'Mew');
battle.makeChoices();
assert.species(battle.p2.active[0], 'Wynaut');
assert.species(battle.p2.active[0], 'Morelull');
assert.species(battle.p2.active[1], 'Morelull');
});

it(`Should be able to switch back in if ejected`, function () {
battle = common.createBattle({gameType: 'doubles'}, [[
{species: 'Typhlosion', moves: ['eruption']},
{species: 'Wynaut', moves: ['sleeptalk']},
], [
{species: 'Smeargle', ability: 'moody', moves: ['protect'], item: 'ejectpack'},
{species: 'Shedinja', moves: ['sleeptalk']},
{species: 'Wynaut', moves: ['sleeptalk']},
]]);
// Eruption
battle.makeChoices();
// Switch Smeargle -> Wynaut
battle.makeChoices();
// Switch Shedinja -> Smeargle
battle.makeChoices();
assert.species(battle.p2.active[0], 'Wynaut', 'Should be switched in by eject pack');
assert.species(battle.p2.active[1], 'Smeargle', 'Should be switched in by Shedinja fainting');
});
});
Loading