mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-03 23:12:20 +02:00
Modify existing phase manager methods to check dyanmic queues
This commit is contained in:
parent
30ab803df9
commit
70edead47e
@ -23,3 +23,7 @@ export type PhaseClass = PhaseConstructorMap[keyof PhaseConstructorMap];
|
||||
* Union type of all phase names as strings.
|
||||
*/
|
||||
export type PhaseString = keyof PhaseMap;
|
||||
|
||||
export type DynamicPhaseString = "PostSummonPhase" | "SwitchSummonPhase" | "MovePhase";
|
||||
|
||||
export type StaticPhaseString = Exclude<PhaseString, DynamicPhaseString>;
|
||||
|
@ -1151,16 +1151,9 @@ export class EncoreTag extends MoveRestrictionBattlerTag {
|
||||
}),
|
||||
);
|
||||
|
||||
const movePhase = globalScene.phaseManager.findPhase("MovePhase", (m: MovePhase) => m.pokemon === pokemon);
|
||||
if (movePhase) {
|
||||
const movesetMove = pokemon.getMoveset().find(m => m.moveId === this.moveId);
|
||||
if (movesetMove) {
|
||||
const lastMove = pokemon.getLastXMoves(1)[0];
|
||||
globalScene.phaseManager.tryReplacePhase(
|
||||
m => m.is("MovePhase") && m.pokemon === pokemon,
|
||||
globalScene.phaseManager.create("MovePhase", pokemon, lastMove.targets ?? [], movesetMove),
|
||||
);
|
||||
}
|
||||
globalScene.phaseManager.changePhaseMove((phase: MovePhase) => phase.pokemon === pokemon, movesetMove);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,7 @@ import { ChargingMove, MoveAttrMap, MoveAttrString, MoveKindString, MoveClassMap
|
||||
import { applyMoveAttrs } from "./apply-attrs";
|
||||
import { frenzyMissFunc, getMoveTargets } from "./move-utils";
|
||||
import { MovePriorityModifier } from "#enums/move-priority-modifier";
|
||||
import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
||||
|
||||
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
|
||||
export type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean;
|
||||
@ -6212,8 +6213,6 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
|
||||
if (globalScene.currentBattle.double && globalScene.getEnemyParty().length > 1 && !isNullOrUndefined(allyPokemon)) {
|
||||
// Handle cases where revived pokemon needs to get switched in on same turn
|
||||
if (allyPokemon.isFainted() || allyPokemon === pokemon) {
|
||||
// Enemy switch phase should be removed and replaced with the revived pkmn switching in
|
||||
globalScene.phaseManager.tryRemovePhase((phase: SwitchSummonPhase) => phase.is("SwitchSummonPhase") && phase.getPokemon() === pokemon);
|
||||
// If the pokemon being revived was alive earlier in the turn, cancel its move
|
||||
// (revived pokemon can't move in the turn they're brought back)
|
||||
globalScene.phaseManager.findPhase("MovePhase", (phase: MovePhase) => phase.pokemon === pokemon)?.cancel();
|
||||
@ -7086,7 +7085,7 @@ export class RepeatMoveAttr extends MoveEffectAttr {
|
||||
}));
|
||||
target.getMoveQueue().unshift({ move: lastMove.move, targets: moveTargets, ignorePP: false });
|
||||
target.turnData.extraTurns++;
|
||||
globalScene.phaseManager.appendNewToPhase("MoveEndPhase", "MovePhase", target, moveTargets, movesetMove);
|
||||
globalScene.phaseManager.appendNewToPhase("MoveEndPhase", "MovePhase", target, moveTargets, movesetMove, false, false, false, MovePhaseTimingModifier.FIRST);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7884,12 +7883,7 @@ export class AfterYouAttr extends MoveEffectAttr {
|
||||
*/
|
||||
override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean {
|
||||
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:afterYou", { targetName: getPokemonNameWithAffix(target) }));
|
||||
|
||||
//Will find next acting phase of the targeted pokémon, delete it and queue it next on successful delete.
|
||||
const nextAttackPhase = globalScene.phaseManager.findPhase("MovePhase", (phase) => phase.pokemon === target);
|
||||
if (nextAttackPhase && globalScene.phaseManager.tryRemovePhase((phase: MovePhase) => phase.pokemon === target)) {
|
||||
globalScene.phaseManager.prependNewToPhase("MovePhase", "MovePhase", target, [ ...nextAttackPhase.targets ], nextAttackPhase.move);
|
||||
}
|
||||
globalScene.phaseManager.forceMoveNext((phase: MovePhase) => phase.pokemon === target);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
/**
|
||||
* Enum representation of the phase types held by implementations of {@linkcode PhasePriorityQueue}
|
||||
*/
|
||||
export enum DynamicPhaseType {
|
||||
POST_SUMMON
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import type { Phase } from "#app/phase";
|
||||
import type { default as Pokemon } from "#app/field/pokemon";
|
||||
import type { PhaseMap, PhaseString } from "./@types/phase-types";
|
||||
import type { DynamicPhaseString, PhaseMap, PhaseString, StaticPhaseString } from "./@types/phase-types";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { ActivatePriorityQueuePhase } from "#app/phases/activate-priority-queue-phase";
|
||||
import { AddEnemyBuffModifierPhase } from "#app/phases/add-enemy-buff-modifier-phase";
|
||||
@ -12,7 +12,6 @@ import { CheckStatusEffectPhase } from "#app/phases/check-status-effect-phase";
|
||||
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
||||
import { coerceArray } from "#app/utils/common";
|
||||
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
|
||||
import { EggHatchPhase } from "#app/phases/egg-hatch-phase";
|
||||
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
||||
@ -100,6 +99,7 @@ import { WeatherEffectPhase } from "#app/phases/weather-effect-phase";
|
||||
import { DynamicQueueManager } from "#app/queues/dynamic-queue-manager";
|
||||
import type { PhaseConditionFunc } from "#app/@types/phase-condition";
|
||||
import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
||||
import type { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||
|
||||
/**
|
||||
* Manager for phases used by battle scene.
|
||||
@ -423,7 +423,7 @@ export class PhaseManager {
|
||||
this.phaseQueue.splice(phaseIndex, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return this.dynamicQueueManager.removePhase(phaseFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -450,16 +450,23 @@ export class PhaseManager {
|
||||
* @param targetPhase - The phase to search for in phaseQueue
|
||||
* @returns boolean if a targetPhase was found and added
|
||||
*/
|
||||
prependToPhase(phase: Phase | Phase[], targetPhase: PhaseString): boolean {
|
||||
phase = coerceArray(phase);
|
||||
prependToPhase(phase: Phase, targetPhase: PhaseString): boolean {
|
||||
const insertPhase = this.dynamicQueueManager.isDynamicPhase(phase.phaseName)
|
||||
? new ActivatePriorityQueuePhase(phase.phaseName)
|
||||
: phase;
|
||||
const target = PHASES[targetPhase];
|
||||
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof target);
|
||||
|
||||
if (this.dynamicQueueManager.isDynamicPhase(phase.phaseName)) {
|
||||
this.dynamicQueueManager.queueDynamicPhase(phase);
|
||||
}
|
||||
|
||||
if (targetIndex !== -1) {
|
||||
this.phaseQueue.splice(targetIndex, 0, ...phase);
|
||||
this.phaseQueue.splice(targetIndex, 0, insertPhase);
|
||||
return true;
|
||||
}
|
||||
this.unshiftPhase(...phase);
|
||||
this.unshiftPhase(insertPhase);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -470,16 +477,22 @@ export class PhaseManager {
|
||||
* @param condition Condition the target phase must meet to be appended to
|
||||
* @returns `true` if a `targetPhase` was found to append to
|
||||
*/
|
||||
appendToPhase(phase: Phase | Phase[], targetPhase: PhaseString, condition?: PhaseConditionFunc): boolean {
|
||||
phase = coerceArray(phase);
|
||||
appendToPhase(phase: Phase, targetPhase: StaticPhaseString, condition?: PhaseConditionFunc): boolean {
|
||||
const insertPhase = this.dynamicQueueManager.isDynamicPhase(phase.phaseName)
|
||||
? new ActivatePriorityQueuePhase(phase.phaseName)
|
||||
: phase;
|
||||
const target = PHASES[targetPhase];
|
||||
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof target && (!condition || condition(ph)));
|
||||
|
||||
if (this.dynamicQueueManager.isDynamicPhase(phase.phaseName)) {
|
||||
this.dynamicQueueManager.queueDynamicPhase(phase);
|
||||
}
|
||||
|
||||
if (targetIndex !== -1 && this.phaseQueue.length > targetIndex) {
|
||||
this.phaseQueue.splice(targetIndex + 1, 0, ...phase);
|
||||
this.phaseQueue.splice(targetIndex + 1, 0, insertPhase);
|
||||
return true;
|
||||
}
|
||||
this.unshiftPhase(...phase);
|
||||
this.unshiftPhase(insertPhase);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -496,10 +509,10 @@ export class PhaseManager {
|
||||
|
||||
/**
|
||||
* Unshifts the top phase from the corresponding dynamic queue onto {@linkcode phaseQueue}
|
||||
* @param type {@linkcode DynamicPhaseType} The type of dynamic phase to start
|
||||
* @param type {@linkcode DynamicPhaseString} The type of dynamic phase to start
|
||||
*/
|
||||
public startNextDynamicPhaseOfType(type: PhaseString): void {
|
||||
const phase = this.dynamicQueueManager.popNextPhaseOfType(type);
|
||||
public startNextDynamicPhase(): void {
|
||||
const phase = this.dynamicQueueManager.popNextPhase();
|
||||
if (phase) {
|
||||
this.unshiftPhase(phase);
|
||||
}
|
||||
@ -640,14 +653,14 @@ export class PhaseManager {
|
||||
* @returns `true` if a `targetPhase` was found to append to
|
||||
*/
|
||||
public appendNewToPhase<T extends PhaseString>(
|
||||
targetPhase: PhaseString,
|
||||
targetPhase: StaticPhaseString,
|
||||
phase: T,
|
||||
...args: ConstructorParameters<PhaseConstructorMap[T]>
|
||||
): boolean {
|
||||
return this.appendToPhase(this.create(phase, ...args), targetPhase);
|
||||
}
|
||||
|
||||
public startNewDynamicPhase<T extends PhaseString>(
|
||||
public startNewDynamicPhase<T extends DynamicPhaseString>(
|
||||
phase: T,
|
||||
...args: ConstructorParameters<PhaseConstructorMap[T]>
|
||||
): void {
|
||||
@ -661,4 +674,8 @@ export class PhaseManager {
|
||||
public forceMoveLast(phaseCondition: PhaseConditionFunc) {
|
||||
this.dynamicQueueManager.setMoveTimingModifier(phaseCondition, MovePhaseTimingModifier.LAST);
|
||||
}
|
||||
|
||||
public changePhaseMove(phaseCondition: PhaseConditionFunc, move: PokemonMove) {
|
||||
this.dynamicQueueManager.setMoveForPhase(phaseCondition, move);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export class ActivatePriorityQueuePhase extends Phase {
|
||||
|
||||
override start() {
|
||||
super.start();
|
||||
globalScene.phaseManager.startNextDynamicPhaseOfType(this.type);
|
||||
globalScene.phaseManager.startNextDynamicPhase();
|
||||
this.end();
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ export class MovePhase extends PokemonPhase {
|
||||
return this._move;
|
||||
}
|
||||
|
||||
protected set move(move: PokemonMove) {
|
||||
public set move(move: PokemonMove) {
|
||||
this._move = move;
|
||||
}
|
||||
|
||||
@ -88,6 +88,7 @@ export class MovePhase extends PokemonPhase {
|
||||
followUp = false,
|
||||
ignorePp = false,
|
||||
reflected = false,
|
||||
timingModifier = MovePhaseTimingModifier.NORMAL,
|
||||
) {
|
||||
super(pokemon.getBattlerIndex());
|
||||
|
||||
@ -97,7 +98,7 @@ export class MovePhase extends PokemonPhase {
|
||||
this.followUp = followUp;
|
||||
this.ignorePp = ignorePp;
|
||||
this.reflected = reflected;
|
||||
this.timingModifier = MovePhaseTimingModifier.NORMAL;
|
||||
this.timingModifier = timingModifier;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,4 +22,8 @@ export abstract class PartyMemberPokemonPhase extends FieldPhase {
|
||||
getPokemon(): Pokemon {
|
||||
return this.getParty()[this.partyMemberIndex];
|
||||
}
|
||||
|
||||
isPlayer(): boolean {
|
||||
return this.player;
|
||||
}
|
||||
}
|
||||
|
@ -296,4 +296,8 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
||||
|
||||
super.end();
|
||||
}
|
||||
|
||||
public getFieldIndex(): number {
|
||||
return this.fieldIndex;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
import type { PhaseConditionFunc } from "#app/@types/phase-condition";
|
||||
import type { PhaseString } from "#app/@types/phase-types";
|
||||
import type { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||
import type { Phase } from "#app/phase";
|
||||
import type { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { MovePhasePriorityQueue } from "#app/queues/move-phase-priority-queue";
|
||||
import type { PhasePriorityQueue } from "#app/queues/phase-priority-queue";
|
||||
import { PokemonPhasePriorityQueue } from "#app/queues/pokemon-phase-priority-queue";
|
||||
import { PostSummonPhasePriorityQueue } from "#app/queues/post-summon-phase-priority-queue";
|
||||
import { SwitchSummonPhasePriorityQueue } from "#app/queues/switch-summon-phase-priority-queue";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import type { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
||||
|
||||
export class DynamicQueueManager {
|
||||
private dynamicPhaseMap: Map<PhaseString, PhasePriorityQueue<Phase>>;
|
||||
|
||||
constructor() {
|
||||
this.dynamicPhaseMap = new Map();
|
||||
this.dynamicPhaseMap.set("SwitchSummonPhase", new PokemonPhasePriorityQueue<SwitchSummonPhase>());
|
||||
this.dynamicPhaseMap.set("SwitchSummonPhase", new SwitchSummonPhasePriorityQueue());
|
||||
this.dynamicPhaseMap.set("PostSummonPhase", new PostSummonPhasePriorityQueue());
|
||||
this.dynamicPhaseMap.set("MovePhase", new MovePhasePriorityQueue());
|
||||
}
|
||||
@ -28,8 +29,8 @@ export class DynamicQueueManager {
|
||||
this.dynamicPhaseMap.get(phase.phaseName)?.push(phase);
|
||||
}
|
||||
|
||||
public popNextPhaseOfType(type: PhaseString): Phase | undefined {
|
||||
return this.dynamicPhaseMap.get(type)?.pop();
|
||||
public popNextPhase(): Phase | undefined {
|
||||
return [...this.dynamicPhaseMap.values()].find(queue => !queue.isEmpty())?.pop();
|
||||
}
|
||||
|
||||
public isDynamicPhase(type: PhaseString): boolean {
|
||||
@ -44,11 +45,24 @@ export class DynamicQueueManager {
|
||||
return !!this.dynamicPhaseMap.get(type)?.hasPhaseWithCondition(condition);
|
||||
}
|
||||
|
||||
public removePhase(condition: PhaseConditionFunc) {
|
||||
for (const queue of this.dynamicPhaseMap.values()) {
|
||||
if (queue.remove(condition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public setMoveTimingModifier(condition: PhaseConditionFunc, modifier: MovePhaseTimingModifier) {
|
||||
const movePhaseQueue: MovePhasePriorityQueue = this.dynamicPhaseMap.get("MovePhase") as MovePhasePriorityQueue;
|
||||
movePhaseQueue.setTimingModifier(condition, modifier);
|
||||
}
|
||||
|
||||
public setMoveForPhase(condition: PhaseConditionFunc, move: PokemonMove) {
|
||||
(this.dynamicPhaseMap.get("MovePhase") as MovePhasePriorityQueue).setMoveForPhase(condition, move);
|
||||
}
|
||||
|
||||
public setMoveOrder(order: BattlerIndex[]) {
|
||||
(this.dynamicPhaseMap.get("MovePhase") as MovePhasePriorityQueue).setMoveOrder(order);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { PhaseConditionFunc } from "#app/@types/phase-condition";
|
||||
import type { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||
import type { MovePhase } from "#app/phases/move-phase";
|
||||
import { PokemonPhasePriorityQueue } from "#app/queues/pokemon-phase-priority-queue";
|
||||
import { isNullOrUndefined } from "#app/utils/common";
|
||||
@ -18,6 +19,13 @@ export class MovePhasePriorityQueue extends PokemonPhasePriorityQueue<MovePhase>
|
||||
}
|
||||
}
|
||||
|
||||
public setMoveForPhase(condition: PhaseConditionFunc, move: PokemonMove) {
|
||||
const phase = this.queue.find(phase => condition(phase));
|
||||
if (!isNullOrUndefined(phase)) {
|
||||
phase.move = move;
|
||||
}
|
||||
}
|
||||
|
||||
public setMoveOrder(order: BattlerIndex[]) {
|
||||
this.setOrder = order;
|
||||
}
|
||||
|
@ -42,6 +42,15 @@ export abstract class PhasePriorityQueue<T extends Phase> {
|
||||
return !this.queue.length;
|
||||
}
|
||||
|
||||
public remove(condition: PhaseConditionFunc): boolean {
|
||||
const phaseIndex = this.queue.findIndex(condition);
|
||||
if (phaseIndex > -1) {
|
||||
this.queue.splice(phaseIndex, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public findPhase(condition?: PhaseConditionFunc): Phase | undefined {
|
||||
return this.queue.find(phase => !condition || condition(phase));
|
||||
}
|
||||
|
14
src/queues/switch-summon-phase-priority-queue.ts
Normal file
14
src/queues/switch-summon-phase-priority-queue.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import type { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { PokemonPhasePriorityQueue } from "#app/queues/pokemon-phase-priority-queue";
|
||||
|
||||
export class SwitchSummonPhasePriorityQueue extends PokemonPhasePriorityQueue<SwitchSummonPhase> {
|
||||
public override push(phase: SwitchSummonPhase): void {
|
||||
// The same pokemon or slot cannot be switched into at the same time
|
||||
this.queue.filter(
|
||||
old =>
|
||||
old.getPokemon() !== phase.getPokemon() &&
|
||||
!(old.isPlayer() === phase.isPlayer() && old.getFieldIndex() === phase.getFieldIndex()),
|
||||
);
|
||||
super.push(phase);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user