mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-06 08:22:16 +02:00
Compare commits
4 Commits
fb8cf781a5
...
4cca68b323
Author | SHA1 | Date | |
---|---|---|---|
|
4cca68b323 | ||
|
7fe5962d28 | ||
|
f57798fd1d | ||
|
6d1fbf92cc |
@ -168,6 +168,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
public sessionSlotId: integer;
|
public sessionSlotId: integer;
|
||||||
|
|
||||||
public phaseQueue: Phase[];
|
public phaseQueue: Phase[];
|
||||||
|
public conditionalQueue: Array<[() => boolean, Phase]>;
|
||||||
private phaseQueuePrepend: Phase[];
|
private phaseQueuePrepend: Phase[];
|
||||||
private phaseQueuePrependSpliceIndex: integer;
|
private phaseQueuePrependSpliceIndex: integer;
|
||||||
private nextCommandPhaseQueue: Phase[];
|
private nextCommandPhaseQueue: Phase[];
|
||||||
@ -252,6 +253,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
super("battle");
|
super("battle");
|
||||||
this.phaseQueue = [];
|
this.phaseQueue = [];
|
||||||
this.phaseQueuePrepend = [];
|
this.phaseQueuePrepend = [];
|
||||||
|
this.conditionalQueue = [];
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
this.phaseQueuePrependSpliceIndex = -1;
|
||||||
this.nextCommandPhaseQueue = [];
|
this.nextCommandPhaseQueue = [];
|
||||||
this.updateGameInfo();
|
this.updateGameInfo();
|
||||||
@ -1843,6 +1845,21 @@ export default class BattleScene extends SceneBase {
|
|||||||
return this.standbyPhase;
|
return this.standbyPhase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a phase to the conditional queue and ensures it is executed only when the specified condition is met.
|
||||||
|
*
|
||||||
|
* This method allows deferring the execution of a phase until certain conditions are met, which is useful for handling
|
||||||
|
* situations like abilities and entry hazards that depend on specific game states.
|
||||||
|
*
|
||||||
|
* @param {Phase} phase - The phase to be added to the conditional queue.
|
||||||
|
* @param {() => boolean} condition - A function that returns a boolean indicating whether the phase should be executed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
pushConditionalPhase(phase: Phase, condition: () => boolean): void {
|
||||||
|
this.conditionalQueue.push([condition, phase]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pushPhase(phase: Phase, defer: boolean = false): void {
|
pushPhase(phase: Phase, defer: boolean = false): void {
|
||||||
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
||||||
}
|
}
|
||||||
@ -1886,6 +1903,21 @@ export default class BattleScene extends SceneBase {
|
|||||||
this.populatePhaseQueue();
|
this.populatePhaseQueue();
|
||||||
}
|
}
|
||||||
this.currentPhase = this.phaseQueue.shift();
|
this.currentPhase = this.phaseQueue.shift();
|
||||||
|
|
||||||
|
// Check if there are any conditional phases queued
|
||||||
|
if (this.conditionalQueue?.length) {
|
||||||
|
// Retrieve the first conditional phase from the queue
|
||||||
|
const conditionalPhase = this.conditionalQueue.shift();
|
||||||
|
// Evaluate the condition associated with the phase
|
||||||
|
if (conditionalPhase[0]()) {
|
||||||
|
// If the condition is met, add the phase to the front of the phase queue
|
||||||
|
this.unshiftPhase(conditionalPhase[1]);
|
||||||
|
} else {
|
||||||
|
// If the condition is not met, re-add the phase back to the front of the conditional queue
|
||||||
|
this.conditionalQueue.unshift(conditionalPhase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.currentPhase.start();
|
this.currentPhase.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6517,8 +6517,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
|||||||
],
|
],
|
||||||
[Species.METAGROSS]: [
|
[Species.METAGROSS]: [
|
||||||
[ 0, Moves.HAMMER_ARM ],
|
[ 0, Moves.HAMMER_ARM ],
|
||||||
[ 0, Moves.CONFUSION ],
|
[ 1, Moves.CONFUSION ],
|
||||||
[ 0, Moves.METAL_CLAW ],
|
[ 1, Moves.METAL_CLAW ],
|
||||||
[ 1, Moves.BULLET_PUNCH ],
|
[ 1, Moves.BULLET_PUNCH ],
|
||||||
[ 1, Moves.TACKLE ],
|
[ 1, Moves.TACKLE ],
|
||||||
[ 1, Moves.EXPLOSION ],
|
[ 1, Moves.EXPLOSION ],
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "{{pokemonName}} (Gegner)",
|
"foePokemonWithAffix": "{{pokemonName}} (Gegner)",
|
||||||
"useMove": "{{pokemonNameWithAffix}} setzt {{moveName}} ein!",
|
"useMove": "{{pokemonNameWithAffix}} setzt {{moveName}} ein!",
|
||||||
"drainMessage": "{{pokemonName}} wurde Energie abgesaugt",
|
"drainMessage": "{{pokemonName}} wurde Energie abgesaugt",
|
||||||
"regainHealth": "KP von {{pokemonName}} wurden wieder aufgefrischt!"
|
"regainHealth": "KP von {{pokemonName}} wurden wieder aufgefrischt!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} wurde besiegt!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
||||||
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
||||||
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
||||||
"regainHealth": "{{pokemonName}} regained\nhealth!"
|
"regainHealth": "{{pokemonName}} regained\nhealth!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} fainted!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "El {{pokemonName}} enemigo",
|
"foePokemonWithAffix": "El {{pokemonName}} enemigo",
|
||||||
"useMove": "¡{{pokemonNameWithAffix}} usó {{moveName}}!",
|
"useMove": "¡{{pokemonNameWithAffix}} usó {{moveName}}!",
|
||||||
"drainMessage": "¡{{pokemonName}} tuvo su\nenergía absorbida!",
|
"drainMessage": "¡{{pokemonName}} tuvo su\nenergía absorbida!",
|
||||||
"regainHealth": "¡{{pokemonName}} recuperó\nPS!"
|
"regainHealth": "¡{{pokemonName}} recuperó\nPS!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} fainted!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "{{pokemonName}} ennemi",
|
"foePokemonWithAffix": "{{pokemonName}} ennemi",
|
||||||
"useMove": "{{pokemonNameWithAffix}} utilise\n{{moveName}} !",
|
"useMove": "{{pokemonNameWithAffix}} utilise\n{{moveName}} !",
|
||||||
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
||||||
"regainHealth": "{{pokemonName}} regained\nhealth!"
|
"regainHealth": "{{pokemonName}} regained\nhealth!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} fainted!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
||||||
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
||||||
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
||||||
"regainHealth": "{{pokemonName}} regained\nhealth!"
|
"regainHealth": "{{pokemonName}} regained\nhealth!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} fainted!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "상대 {{pokemonName}}",
|
"foePokemonWithAffix": "상대 {{pokemonName}}",
|
||||||
"useMove": "{{pokemonNameWithAffix}}의 {{moveName}}!",
|
"useMove": "{{pokemonNameWithAffix}}의 {{moveName}}!",
|
||||||
"drainMessage": "{{pokemonName}}[[로]]부터\n체력을 흡수했다!",
|
"drainMessage": "{{pokemonName}}[[로]]부터\n체력을 흡수했다!",
|
||||||
"regainHealth": "{{pokemonName}}[[는]]\n기력을 회복했다!"
|
"regainHealth": "{{pokemonName}}[[는]]\n기력을 회복했다!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}}[[는]] 쓰러졌다!",
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -2628,7 +2628,7 @@ export const PGMdoubleBattleDialogue: DialogueTranslationEntries = {
|
|||||||
},
|
},
|
||||||
"marnie_piers_double": {
|
"marnie_piers_double": {
|
||||||
"encounter": {
|
"encounter": {
|
||||||
1: `두송: 큰서트 즐길 준비 됐어?
|
1: `두송: 콘서트 즐길 준비 됐어?
|
||||||
$마리: 오빠... 얘들은 노래가 아니라 승부를 하러 왔어...`,
|
$마리: 오빠... 얘들은 노래가 아니라 승부를 하러 왔어...`,
|
||||||
},
|
},
|
||||||
"victory": {
|
"victory": {
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "{{pokemonName}} adversário",
|
"foePokemonWithAffix": "{{pokemonName}} adversário",
|
||||||
"useMove": "{{pokemonNameWithAffix}} usou {{moveName}}!",
|
"useMove": "{{pokemonNameWithAffix}} usou {{moveName}}!",
|
||||||
"drainMessage": "{{pokemonName}} teve sua\nenergia drenada!",
|
"drainMessage": "{{pokemonName}} teve sua\nenergia drenada!",
|
||||||
"regainHealth": "{{pokemonName}} recuperou\npontos de saúde!"
|
"regainHealth": "{{pokemonName}} recuperou\npontos de saúde!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} fainted!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -60,5 +60,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
||||||
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
||||||
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
||||||
"regainHealth": "{{pokemonName}} regained\nhealth!"
|
"regainHealth": "{{pokemonName}} regained\nhealth!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} fainted!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -57,5 +57,6 @@ export const battle: SimpleTranslationEntries = {
|
|||||||
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
"foePokemonWithAffix": "Foe {{pokemonName}}",
|
||||||
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
|
||||||
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
|
||||||
"regainHealth": "{{pokemonName}} regained\nhealth!"
|
"regainHealth": "{{pokemonName}} regained\nhealth!",
|
||||||
|
"fainted": "{{pokemonNameWithAffix}} fainted!"
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -1024,6 +1024,15 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (this.scene.currentBattle.battleType !== BattleType.TRAINER) {
|
if (this.scene.currentBattle.battleType !== BattleType.TRAINER) {
|
||||||
|
enemyField.map(p => this.scene.pushConditionalPhase(new PostSummonPhase(this.scene, p.getBattlerIndex()), () => {
|
||||||
|
// is the player party initialized ?
|
||||||
|
const a = !!this.scene.getParty()?.length;
|
||||||
|
// how many player pokemon are on the field ?
|
||||||
|
const amountOnTheField = this.scene.getParty().filter(p => p.isOnField()).length;
|
||||||
|
// if it's a double, there should be 2, otherwise 1
|
||||||
|
const b = this.scene.currentBattle.double ? amountOnTheField === 2 : amountOnTheField === 1;
|
||||||
|
return a && b;
|
||||||
|
}));
|
||||||
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
enemyField.map(p => this.scene.pushPhase(new ScanIvsPhase(this.scene, p.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6))));
|
enemyField.map(p => this.scene.pushPhase(new ScanIvsPhase(this.scene, p.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6))));
|
||||||
@ -1479,10 +1488,6 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||||||
|
|
||||||
if (!this.loaded || this.scene.currentBattle.battleType === BattleType.TRAINER || (this.scene.currentBattle.waveIndex % 10) === 1) {
|
if (!this.loaded || this.scene.currentBattle.battleType === BattleType.TRAINER || (this.scene.currentBattle.waveIndex % 10) === 1) {
|
||||||
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
||||||
}
|
|
||||||
if (pokemon.isPlayer()) {
|
|
||||||
// postSummon for player only here, since we want the postSummon from opponent to be call in the turnInitPhase
|
|
||||||
// covering both wild & trainer battles
|
|
||||||
this.queuePostSummon();
|
this.queuePostSummon();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1797,13 +1802,6 @@ export class TurnInitPhase extends FieldPhase {
|
|||||||
|
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
const enemyField = this.scene.getEnemyField().filter(p => p.isActive()) as Pokemon[];
|
|
||||||
enemyField.map(p => {
|
|
||||||
if (p.battleSummonData.turnCount !== 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return this.scene.unshiftPhase(new PostSummonPhase(this.scene, p.getBattlerIndex()));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.scene.getPlayerField().forEach(p => {
|
this.scene.getPlayerField().forEach(p => {
|
||||||
// If this pokemon is in play and evolved into something illegal under the current challenge, force a switch
|
// If this pokemon is in play and evolved into something illegal under the current challenge, force a switch
|
||||||
@ -3641,7 +3639,7 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
this.scene.currentBattle.enemyFaints += 1;
|
this.scene.currentBattle.enemyFaints += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scene.queueMessage(getPokemonMessage(pokemon, " fainted!"), null, true);
|
this.scene.queueMessage(i18next.t("battle:fainted", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), null, true);
|
||||||
|
|
||||||
if (pokemon.turnData?.attacksReceived?.length) {
|
if (pokemon.turnData?.attacksReceived?.length) {
|
||||||
const lastAttack = pokemon.turnData.attacksReceived[0];
|
const lastAttack = pokemon.turnData.attacksReceived[0];
|
||||||
|
128
src/test/moves/spikes.test.ts
Normal file
128
src/test/moves/spikes.test.ts
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
|
import * as overrides from "#app/overrides";
|
||||||
|
import {Abilities} from "#app/data/enums/abilities";
|
||||||
|
import {Species} from "#app/data/enums/species";
|
||||||
|
import {
|
||||||
|
CommandPhase
|
||||||
|
} from "#app/phases";
|
||||||
|
import {Moves} from "#app/data/enums/moves";
|
||||||
|
|
||||||
|
|
||||||
|
describe("Moves - Spikes", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.scene.battleStyle = 1;
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]);
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIKES,Moves.SPLASH, Moves.ROAR]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("single - wild - stay on field - no damage", async() => {
|
||||||
|
// player set spikes on the field and do splash for 3 turns
|
||||||
|
// opponent do splash for 4 turns
|
||||||
|
// nobody should take damage
|
||||||
|
await game.runToSummon([
|
||||||
|
Species.MIGHTYENA,
|
||||||
|
Species.POOCHYENA,
|
||||||
|
]);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, true);
|
||||||
|
const initialHp = game.scene.getParty()[0].hp;
|
||||||
|
expect(game.scene.getParty()[0].hp).toBe(initialHp);
|
||||||
|
game.doAttack(0);
|
||||||
|
await game.toNextTurn();
|
||||||
|
game.doAttack(1);
|
||||||
|
await game.toNextTurn();
|
||||||
|
game.doAttack(1);
|
||||||
|
await game.toNextTurn();
|
||||||
|
game.doAttack(1);
|
||||||
|
await game.toNextTurn();
|
||||||
|
game.doAttack(1);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(game.scene.getParty()[0].hp).toBe(initialHp);
|
||||||
|
console.log(game.textInterceptor.logs);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("single - wild - take some damage", async() => {
|
||||||
|
// player set spikes on the field and switch back to back
|
||||||
|
// opponent do splash for 2 turns
|
||||||
|
// nobody should take damage
|
||||||
|
await game.runToSummon([
|
||||||
|
Species.MIGHTYENA,
|
||||||
|
Species.POOCHYENA,
|
||||||
|
]);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, false);
|
||||||
|
|
||||||
|
const initialHp = game.scene.getParty()[0].hp;
|
||||||
|
await game.switchPokemon(1, false);
|
||||||
|
await game.phaseInterceptor.run(CommandPhase);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, false);
|
||||||
|
|
||||||
|
await game.switchPokemon(1, false);
|
||||||
|
await game.phaseInterceptor.run(CommandPhase);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, false);
|
||||||
|
|
||||||
|
expect(game.scene.getParty()[0].hp).toBe(initialHp);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("trainer - wild - force switch opponent - should take damage", async() => {
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
|
||||||
|
// player set spikes on the field and do splash for 3 turns
|
||||||
|
// opponent do splash for 4 turns
|
||||||
|
// nobody should take damage
|
||||||
|
await game.runToSummon([
|
||||||
|
Species.MIGHTYENA,
|
||||||
|
Species.POOCHYENA,
|
||||||
|
]);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, true);
|
||||||
|
const initialHpOpponent = game.scene.currentBattle.enemyParty[1].hp;
|
||||||
|
game.doAttack(0);
|
||||||
|
await game.toNextTurn();
|
||||||
|
game.doAttack(2);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(game.scene.currentBattle.enemyParty[0].hp).toBeLessThan(initialHpOpponent);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("trainer - wild - force switch by himself opponent - should take damage", async() => {
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
|
||||||
|
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5000);
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(0);
|
||||||
|
// turn 1: player set spikes, opponent do splash
|
||||||
|
// turn 2: player do splash, opponent switch pokemon
|
||||||
|
// opponent pokemon should trigger spikes and lose HP
|
||||||
|
await game.runToSummon([
|
||||||
|
Species.MIGHTYENA,
|
||||||
|
Species.POOCHYENA,
|
||||||
|
]);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, true);
|
||||||
|
const initialHpOpponent = game.scene.currentBattle.enemyParty[1].hp;
|
||||||
|
game.doAttack(0);
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
game.forceOpponentToSwitch();
|
||||||
|
game.doAttack(1);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(game.scene.currentBattle.enemyParty[0].hp).toBeLessThan(initialHpOpponent);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
});
|
@ -7,6 +7,7 @@ export default class TextInterceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void {
|
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void {
|
||||||
|
console.log(text);
|
||||||
this.logs.push(text);
|
this.logs.push(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import {Command} from "#app/ui/command-ui-handler";
|
|||||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||||
import {Button} from "#app/enums/buttons";
|
import {Button} from "#app/enums/buttons";
|
||||||
import PartyUiHandler, {PartyUiMode} from "#app/ui/party-ui-handler";
|
import PartyUiHandler, {PartyUiMode} from "#app/ui/party-ui-handler";
|
||||||
|
import Trainer from "#app/field/trainer";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage the game state and transitions between phases.
|
* Class to manage the game state and transitions between phases.
|
||||||
@ -192,6 +193,14 @@ export default class GameManager {
|
|||||||
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(NewBattlePhase));
|
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(NewBattlePhase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forceOpponentToSwitch() {
|
||||||
|
const originalMatchupScore = Trainer.prototype.getPartyMemberMatchupScores;
|
||||||
|
Trainer.prototype.getPartyMemberMatchupScores = () => {
|
||||||
|
Trainer.prototype.getPartyMemberMatchupScores = originalMatchupScore;
|
||||||
|
return [[1, 100], [1, 100]];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** Transition to the next upcoming {@linkcode CommandPhase} */
|
/** Transition to the next upcoming {@linkcode CommandPhase} */
|
||||||
async toNextTurn() {
|
async toNextTurn() {
|
||||||
await this.phaseInterceptor.to(CommandPhase);
|
await this.phaseInterceptor.to(CommandPhase);
|
||||||
@ -281,14 +290,16 @@ export default class GameManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async switchPokemon(pokemonIndex: number) {
|
async switchPokemon(pokemonIndex: number, toNext: boolean = true) {
|
||||||
this.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
this.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
this.scene.ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted);
|
this.scene.ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted);
|
||||||
});
|
});
|
||||||
this.onNextPrompt("CommandPhase", Mode.PARTY, () => {
|
this.onNextPrompt("CommandPhase", Mode.PARTY, () => {
|
||||||
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, pokemonIndex, false);
|
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, pokemonIndex, false);
|
||||||
});
|
});
|
||||||
await this.phaseInterceptor.run(CommandPhase);
|
if (toNext) {
|
||||||
await this.phaseInterceptor.to(CommandPhase);
|
await this.phaseInterceptor.run(CommandPhase);
|
||||||
|
await this.phaseInterceptor.to(CommandPhase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user