mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-14 11:29:28 +02:00
Fixed intimidate bugs fr fr
This commit is contained in:
parent
2d6267b668
commit
018a0091f3
@ -44,6 +44,30 @@ export abstract class PhasePriorityQueue {
|
||||
public clear(): void {
|
||||
this.queue.splice(0, this.queue.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to remove one or more Phases from the current queue.
|
||||
* @param phaseFilter - The function to select phases for removal
|
||||
* @param removeCount - The maximum number of phases to remove, or `all` to remove all matching phases;
|
||||
* default `1`
|
||||
* @returns The number of successfully removed phases
|
||||
* @todo Remove this eventually once the patchwork bug this is used for is fixed
|
||||
*/
|
||||
public tryRemovePhase(phaseFilter: (phase: Phase) => boolean, removeCount: number | "all" = 1): number {
|
||||
if (typeof removeCount === "string") {
|
||||
removeCount = Number.MAX_SAFE_INTEGER; // For the lulz
|
||||
}
|
||||
let numRemoved = 0;
|
||||
let phaseIndex = this.queue.findIndex(phaseFilter);
|
||||
if (phaseIndex === -1) {
|
||||
return 0;
|
||||
}
|
||||
do {
|
||||
this.queue.splice(phaseIndex, 1);
|
||||
numRemoved++;
|
||||
} while (numRemoved < removeCount || (phaseIndex = this.queue.findIndex(phaseFilter)) !== -1);
|
||||
return removeCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,6 +103,7 @@ export class PostSummonPhasePriorityQueue extends PhasePriorityQueue {
|
||||
private queueAbilityPhase(phase: PostSummonPhase): void {
|
||||
const phasePokemon = phase.getPokemon();
|
||||
|
||||
console.log(phasePokemon.getNameToRender());
|
||||
phasePokemon.getAbilityPriorities().forEach((priority, idx) => {
|
||||
this.queue.push(new PostSummonActivateAbilityPhase(phasePokemon.getBattlerIndex(), priority, !!idx));
|
||||
globalScene.phaseManager.appendToPhase(
|
||||
|
@ -355,14 +355,23 @@ export class PhaseManager {
|
||||
if (this.phaseQueuePrependSpliceIndex > -1) {
|
||||
this.clearPhaseQueueSplice();
|
||||
}
|
||||
if (this.phaseQueuePrepend.length) {
|
||||
while (this.phaseQueuePrepend.length) {
|
||||
const poppedPhase = this.phaseQueuePrepend.pop();
|
||||
if (poppedPhase) {
|
||||
this.phaseQueue.unshift(poppedPhase);
|
||||
}
|
||||
this.phaseQueue.unshift(...this.phaseQueuePrepend);
|
||||
this.phaseQueuePrepend.splice(0);
|
||||
|
||||
const unactivatedConditionalPhases: [() => boolean, Phase][] = [];
|
||||
// Check if there are any conditional phases queued
|
||||
for (const [condition, phase] of this.conditionalQueue) {
|
||||
// Evaluate the condition associated with the phase
|
||||
if (condition()) {
|
||||
// If the condition is met, add the phase to the phase queue
|
||||
this.pushPhase(phase);
|
||||
} else {
|
||||
// If the condition is not met, re-add the phase back to the end of the conditional queue
|
||||
unactivatedConditionalPhases.push([condition, phase]);
|
||||
}
|
||||
}
|
||||
this.conditionalQueue = unactivatedConditionalPhases;
|
||||
|
||||
if (!this.phaseQueue.length) {
|
||||
this.populatePhaseQueue();
|
||||
// Clear the conditionalQueue if there are no phases left in the phaseQueue
|
||||
@ -371,24 +380,6 @@ export class PhaseManager {
|
||||
|
||||
this.currentPhase = this.phaseQueue.shift() ?? null;
|
||||
|
||||
const unactivatedConditionalPhases: [() => boolean, Phase][] = [];
|
||||
// Check if there are any conditional phases queued
|
||||
while (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 phase queue
|
||||
this.pushPhase(conditionalPhase[1]);
|
||||
} else if (conditionalPhase) {
|
||||
// If the condition is not met, re-add the phase back to the front of the conditional queue
|
||||
unactivatedConditionalPhases.push(conditionalPhase);
|
||||
} else {
|
||||
console.warn("condition phase is undefined/null!", conditionalPhase);
|
||||
}
|
||||
}
|
||||
this.conditionalQueue.push(...unactivatedConditionalPhases);
|
||||
|
||||
if (this.currentPhase) {
|
||||
console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;");
|
||||
this.currentPhase.start();
|
||||
@ -520,6 +511,25 @@ export class PhaseManager {
|
||||
this.dynamicPhaseQueues[type].push(phase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to remove one or more Phases from the given DynamicPhaseQueue, removing the equivalent amount of {@linkcode ActivatePriorityQueuePhase}s from the queue.
|
||||
* @param type - The {@linkcode DynamicPhaseType} to check
|
||||
* @param phaseFilter - The function to select phases for removal
|
||||
* @param removeCount - The maximum number of phases to remove, or `all` to remove all matching phases;
|
||||
* default `1`
|
||||
* @todo Remove this eventually once the patchwork bug this is used for is fixed
|
||||
*/
|
||||
public tryRemoveDynamicPhase(
|
||||
type: DynamicPhaseType,
|
||||
phaseFilter: (phase: Phase) => boolean,
|
||||
removeCount: number | "all" = 1,
|
||||
): void {
|
||||
const numRemoved = this.dynamicPhaseQueues[type].tryRemovePhase(phaseFilter, removeCount);
|
||||
for (let x = 0; x < numRemoved; x++) {
|
||||
this.tryRemovePhase(p => p.is("ActivatePriorityQueuePhase"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unshifts the top phase from the corresponding dynamic queue onto {@linkcode phaseQueue}
|
||||
* @param type {@linkcode DynamicPhaseType} The type of dynamic phase to start
|
||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { BattleStyle } from "#enums/battle-style";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { DynamicPhaseType } from "#enums/dynamic-phase-type";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import { BattlePhase } from "#phases/battle-phase";
|
||||
@ -66,6 +67,17 @@ export class CheckSwitchPhase extends BattlePhase {
|
||||
UiMode.CONFIRM,
|
||||
() => {
|
||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||
/*
|
||||
Remove any pending `ActivatePriorityQueuePhase`s for the currently leaving Pokemon produced by the prior `SwitchSummonPhase`.
|
||||
This is required to avoid triggering on-switch abilities twice on initial entrance.
|
||||
TODO: Separate the animations from `SwitchSummonPhase` to another phase and call that on initial switch - this is a band-aid fix
|
||||
TODO: Confirm with @emdeann what the maximum number of these things that gets unshifted can be
|
||||
*/
|
||||
globalScene.phaseManager.tryRemoveDynamicPhase(
|
||||
DynamicPhaseType.POST_SUMMON,
|
||||
p => p.is("PostSummonPhase") && p.getPokemon() === pokemon,
|
||||
4,
|
||||
);
|
||||
globalScene.phaseManager.unshiftNew("SwitchPhase", SwitchType.INITIAL_SWITCH, this.fieldIndex, false, true);
|
||||
this.end();
|
||||
},
|
||||
|
@ -35,31 +35,45 @@ describe("Abilities - Intimidate", () => {
|
||||
it("should lower all opponents' ATK by 1 stage on entry and switch", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]);
|
||||
|
||||
const [mightyena, poochyena] = game.scene.getPlayerParty();
|
||||
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
expect(enemy.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(mightyena).toHaveAbilityApplied(AbilityId.INTIMIDATE);
|
||||
|
||||
game.doSwitchPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(poochyena.isActive()).toBe(true);
|
||||
expect(enemy.getStatStage(Stat.ATK)).toBe(-2);
|
||||
expect(poochyena).toHaveAbilityApplied(AbilityId.INTIMIDATE);
|
||||
});
|
||||
|
||||
// TODO: This fails due to a limitation in our switching logic - the animations and field entry occur concurrently
|
||||
// inside `SummonPhase`, unshifting 2 `PostSummmonPhase`s and proccing intimidate twice
|
||||
it.todo("should lower all opponents' ATK by 1 stage on initial switch prompt", async () => {
|
||||
it("should trigger once on initial switch prompt without cancelling opposing abilities", async () => {
|
||||
await game.classicMode.runToSummon([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]);
|
||||
await game.classicMode.startBattleWithSwitch(1);
|
||||
|
||||
const [poochyena, mightyena] = game.scene.getPlayerField();
|
||||
const [poochyena, mightyena] = game.scene.getPlayerParty();
|
||||
expect(poochyena.species.speciesId).toBe(SpeciesId.POOCHYENA);
|
||||
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
expect(enemy).toHaveStatStage(Stat.ATK, -1);
|
||||
expect(poochyena).toHaveStatStage(Stat.ATK, -1);
|
||||
|
||||
expect(poochyena).toHaveAbilityApplied(AbilityId.INTIMIDATE);
|
||||
expect(mightyena).not.toHaveAbilityApplied(AbilityId.INTIMIDATE);
|
||||
});
|
||||
|
||||
it("should activate on reload with single party", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MIGHTYENA]);
|
||||
|
||||
expect(game.field.getEnemyPokemon()).toHaveStatStage(Stat.ATK, -1);
|
||||
|
||||
await game.reload.reloadSession();
|
||||
|
||||
expect(game.field.getEnemyPokemon()).toHaveStatStage(Stat.ATK, -1);
|
||||
});
|
||||
|
||||
it("should lower ATK of all opponents in a double battle", async () => {
|
||||
game.override.battleStyle("double");
|
||||
await game.classicMode.startBattle([SpeciesId.MIGHTYENA]);
|
||||
|
Loading…
Reference in New Issue
Block a user