Changed setTurnOrder to forbid BattlerIndex.ATTACKER

This commit is contained in:
Bertie690 2025-09-21 15:21:50 -04:00
parent 0dbb68c3ba
commit c4e2022e18
6 changed files with 21 additions and 18 deletions

View File

@ -10,7 +10,7 @@ interface hasPokemon {
} }
/** /**
* Sort an array of {@linkcode Pokemon} in _ascending_ speed order, taking Trick Room into account. * Sort an array of {@linkcode Pokemon} in speed order, taking Trick Room into account.
* @param pokemonList - An array of `Pokemon` or objects containing `Pokemon` to sort; * @param pokemonList - An array of `Pokemon` or objects containing `Pokemon` to sort;
* will be mutated and sorted in place. * will be mutated and sorted in place.
* @param shuffleFirst - Whether to shuffle the list before sorting (to handle speed ties); default `true`. * @param shuffleFirst - Whether to shuffle the list before sorting (to handle speed ties); default `true`.
@ -41,7 +41,7 @@ function shufflePokemonList<T extends Pokemon | hasPokemon>(pokemonList: T[]): T
return pokemonList; return pokemonList;
} }
/** Sort an array of {@linkcode Pokemon} in descending speed order (without shuffling) */ /** Sort an array of {@linkcode Pokemon} in speed order (without shuffling) */
function sortBySpeed<T extends Pokemon | hasPokemon>(pokemonList: T[]): void { function sortBySpeed<T extends Pokemon | hasPokemon>(pokemonList: T[]): void {
pokemonList.sort((a, b) => { pokemonList.sort((a, b) => {
const aSpeed = (a instanceof Pokemon ? a : a.getPokemon()).getEffectiveStat(Stat.SPD); const aSpeed = (a instanceof Pokemon ? a : a.getPokemon()).getEffectiveStat(Stat.SPD);

View File

@ -167,16 +167,16 @@ describe("Moves - Delayed Attacks", () => {
game.override.battleStyle("double"); game.override.battleStyle("double");
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]); await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
const [alomomola, blissey] = game.scene.getField(); const [alomomola, blissey] = game.scene.getPlayerField();
const oldOrder = game.field.getSpeedOrder(); const oldOrder = game.field.getSpeedOrder(true);
game.move.use(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER, BattlerIndex.ENEMY); game.move.use(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
game.move.use(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2); game.move.use(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2);
await game.move.forceEnemyMove(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER); await game.move.forceEnemyMove(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER);
await game.move.forceEnemyMove(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER_2); await game.move.forceEnemyMove(MoveId.FUTURE_SIGHT, BattlerIndex.PLAYER_2);
// Ensure that the moves are used deterministically in speed order (for speed ties) // Ensure that the moves are used deterministically in speed order (for speed ties)
await game.setTurnOrder(oldOrder.map(p => p.getBattlerIndex())); await game.setTurnOrder(oldOrder);
await game.toNextTurn(); await game.toNextTurn();
expectFutureSightActive(4); expectFutureSightActive(4);
@ -195,7 +195,10 @@ describe("Moves - Delayed Attacks", () => {
const MEPs = game.scene.phaseManager["phaseQueue"].findAll("MoveEffectPhase"); const MEPs = game.scene.phaseManager["phaseQueue"].findAll("MoveEffectPhase");
expect(MEPs).toHaveLength(4); expect(MEPs).toHaveLength(4);
expect(MEPs.map(mep => mep.getPokemon())).toEqual(oldOrder); expect(
MEPs.map(mep => mep.getPokemon().getBattlerIndex()),
"Delayed Attacks were not queued in correct order!",
).toEqual(oldOrder);
}); });
it("should vanish silently if it would otherwise hit the user", async () => { it("should vanish silently if it would otherwise hit the user", async () => {

View File

@ -17,8 +17,8 @@ describe("Moves - Destiny Bond", () => {
let game: GameManager; let game: GameManager;
const defaultParty = [SpeciesId.BULBASAUR, SpeciesId.SQUIRTLE]; const defaultParty = [SpeciesId.BULBASAUR, SpeciesId.SQUIRTLE];
const enemyFirst = [BattlerIndex.ENEMY, BattlerIndex.PLAYER]; const enemyFirst = [BattlerIndex.ENEMY, BattlerIndex.PLAYER] as const;
const playerFirst = [BattlerIndex.PLAYER, BattlerIndex.ENEMY]; const playerFirst = [BattlerIndex.PLAYER, BattlerIndex.ENEMY] as const;
beforeAll(() => { beforeAll(() => {
phaserGame = new Phaser.Game({ phaserGame = new Phaser.Game({

View File

@ -78,8 +78,9 @@ describe("Moves - Encore", () => {
game.move.select(MoveId.ENCORE); game.move.select(MoveId.ENCORE);
const turnOrder = delay ? [BattlerIndex.PLAYER, BattlerIndex.ENEMY] : [BattlerIndex.ENEMY, BattlerIndex.PLAYER]; await game.setTurnOrder(
await game.setTurnOrder(turnOrder); delay ? [BattlerIndex.PLAYER, BattlerIndex.ENEMY] : [BattlerIndex.ENEMY, BattlerIndex.PLAYER],
);
await game.phaseInterceptor.to("BerryPhase", false); await game.phaseInterceptor.to("BerryPhase", false);
expect(playerPokemon.getLastXMoves(1)[0].result).toBe(MoveResult.FAIL); expect(playerPokemon.getLastXMoves(1)[0].result).toBe(MoveResult.FAIL);
@ -88,25 +89,22 @@ describe("Moves - Encore", () => {
}); });
it("Pokemon under both Encore and Torment should alternate between Struggle and restricted move", async () => { it("Pokemon under both Encore and Torment should alternate between Struggle and restricted move", async () => {
const turnOrder = [BattlerIndex.ENEMY, BattlerIndex.PLAYER];
game.override.moveset([MoveId.ENCORE, MoveId.TORMENT, MoveId.SPLASH]); game.override.moveset([MoveId.ENCORE, MoveId.TORMENT, MoveId.SPLASH]);
await game.classicMode.startBattle([SpeciesId.FEEBAS]); await game.classicMode.startBattle([SpeciesId.FEEBAS]);
const enemyPokemon = game.field.getEnemyPokemon(); const enemyPokemon = game.field.getEnemyPokemon();
game.move.select(MoveId.ENCORE); game.move.select(MoveId.ENCORE);
await game.setTurnOrder(turnOrder); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(enemyPokemon.getTag(BattlerTagType.ENCORE)).toBeDefined(); expect(enemyPokemon.getTag(BattlerTagType.ENCORE)).toBeDefined();
await game.toNextTurn(); await game.toNextTurn();
game.move.select(MoveId.TORMENT); game.move.select(MoveId.TORMENT);
await game.setTurnOrder(turnOrder);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(enemyPokemon.getTag(BattlerTagType.TORMENT)).toBeDefined(); expect(enemyPokemon.getTag(BattlerTagType.TORMENT)).toBeDefined();
await game.toNextTurn(); await game.toNextTurn();
game.move.select(MoveId.SPLASH); game.move.select(MoveId.SPLASH);
await game.setTurnOrder(turnOrder);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
const lastMove = enemyPokemon.getLastXMoves()[0]; const lastMove = enemyPokemon.getLastXMoves()[0];
expect(lastMove?.move).toBe(MoveId.STRUGGLE); expect(lastMove?.move).toBe(MoveId.STRUGGLE);

View File

@ -109,14 +109,14 @@ describe("Move - Wish", () => {
vi.spyOn(karp1, "getNameToRender").mockReturnValue("Karp 1"); vi.spyOn(karp1, "getNameToRender").mockReturnValue("Karp 1");
vi.spyOn(karp2, "getNameToRender").mockReturnValue("Karp 2"); vi.spyOn(karp2, "getNameToRender").mockReturnValue("Karp 2");
const oldOrder = game.field.getSpeedOrder(); const oldOrder = game.field.getSpeedOrder(true);
game.move.use(MoveId.WISH, BattlerIndex.PLAYER); game.move.use(MoveId.WISH, BattlerIndex.PLAYER);
game.move.use(MoveId.WISH, BattlerIndex.PLAYER_2); game.move.use(MoveId.WISH, BattlerIndex.PLAYER_2);
await game.move.forceEnemyMove(MoveId.WISH); await game.move.forceEnemyMove(MoveId.WISH);
await game.move.forceEnemyMove(MoveId.WISH); await game.move.forceEnemyMove(MoveId.WISH);
// Ensure that the wishes are used deterministically in speed order (for speed ties) // Ensure that the wishes are used deterministically in speed order (for speed ties)
await game.setTurnOrder(oldOrder.map(p => p.getBattlerIndex())); await game.setTurnOrder(oldOrder);
await game.toNextTurn(); await game.toNextTurn();
expect(game).toHavePositionalTag(PositionalTagType.WISH, 4); expect(game).toHavePositionalTag(PositionalTagType.WISH, 4);
@ -137,7 +137,9 @@ describe("Move - Wish", () => {
const healPhases = game.scene.phaseManager["phaseQueue"].findAll("PokemonHealPhase"); const healPhases = game.scene.phaseManager["phaseQueue"].findAll("PokemonHealPhase");
expect(healPhases).toHaveLength(4); expect(healPhases).toHaveLength(4);
expect.soft(healPhases.map(php => php.getPokemon())).toEqual(oldOrder); expect
.soft(healPhases.map(php => php.getPokemon().getBattlerIndex(), "Wishes were not queued in correct order!"))
.toEqual(oldOrder);
await game.toEndOfTurn(); await game.toEndOfTurn();

View File

@ -68,7 +68,7 @@ export class FieldHelper extends GameManagerHelper {
* This does not account for Trick Room as it does not modify the _speed_ of Pokemon on the field, * This does not account for Trick Room as it does not modify the _speed_ of Pokemon on the field,
* only their turn order. * only their turn order.
*/ */
public getSpeedOrder(indices: true): BattlerIndex[]; public getSpeedOrder(indices: true): Exclude<BattlerIndex, BattlerIndex.ATTACKER>[];
public getSpeedOrder(indices = false): BattlerIndex[] | Pokemon[] { public getSpeedOrder(indices = false): BattlerIndex[] | Pokemon[] {
const ret = this.game.scene const ret = this.game.scene
.getField(true) .getField(true)