mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-03 23:12:20 +02:00
Automatically queue consecutive Pokemon phases as dynamic
This commit is contained in:
parent
6e762ad80a
commit
301e12e92a
@ -1,3 +1,5 @@
|
|||||||
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import type { Phase } from "#app/phase";
|
||||||
import type { PhaseConstructorMap } from "#app/phase-manager";
|
import type { PhaseConstructorMap } from "#app/phase-manager";
|
||||||
|
|
||||||
// Intentionally export the types of everything in phase-manager, as this file is meant to be
|
// Intentionally export the types of everything in phase-manager, as this file is meant to be
|
||||||
@ -27,3 +29,7 @@ export type PhaseString = keyof PhaseMap;
|
|||||||
export type DynamicPhaseString = "PostSummonPhase" | "SwitchSummonPhase" | "MovePhase" | "MoveHeaderPhase";
|
export type DynamicPhaseString = "PostSummonPhase" | "SwitchSummonPhase" | "MovePhase" | "MoveHeaderPhase";
|
||||||
|
|
||||||
export type StaticPhaseString = Exclude<PhaseString, DynamicPhaseString>;
|
export type StaticPhaseString = Exclude<PhaseString, DynamicPhaseString>;
|
||||||
|
|
||||||
|
export interface DynamicPhase extends Phase {
|
||||||
|
getPokemon(): Pokemon;
|
||||||
|
}
|
||||||
|
@ -83,7 +83,7 @@ import type { Localizable } from "#app/@types/locales";
|
|||||||
import { applyAbAttrs } from "./apply-ab-attrs";
|
import { applyAbAttrs } from "./apply-ab-attrs";
|
||||||
import { MovePriorityModifier } from "#enums/move-priority-modifier";
|
import { MovePriorityModifier } from "#enums/move-priority-modifier";
|
||||||
import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
import type { MovePhase } from "#app/phases/move-phase";
|
||||||
|
|
||||||
export class Ability implements Localizable {
|
export class Ability implements Localizable {
|
||||||
public id: AbilityId;
|
public id: AbilityId;
|
||||||
@ -6102,7 +6102,14 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
|||||||
// If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance
|
// If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance
|
||||||
if (move.getMove().is("AttackMove") || move.getMove().is("StatusMove")) {
|
if (move.getMove().is("AttackMove") || move.getMove().is("StatusMove")) {
|
||||||
const target = this.getTarget(dancer, source, targets);
|
const target = this.getTarget(dancer, source, targets);
|
||||||
globalScene.phaseManager.pushNew("MovePhase", dancer, target, move, MoveUseMode.INDIRECT, MovePhaseTimingModifier.FIRST);
|
globalScene.phaseManager.pushNew(
|
||||||
|
"MovePhase",
|
||||||
|
dancer,
|
||||||
|
target,
|
||||||
|
move,
|
||||||
|
MoveUseMode.INDIRECT,
|
||||||
|
MovePhaseTimingModifier.FIRST,
|
||||||
|
);
|
||||||
} else if (move.getMove().is("SelfStatusMove")) {
|
} else if (move.getMove().is("SelfStatusMove")) {
|
||||||
// If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself
|
// If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself
|
||||||
globalScene.phaseManager.pushNew(
|
globalScene.phaseManager.pushNew(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { Phase } from "#app/phase";
|
import type { Phase } from "#app/phase";
|
||||||
import type { default as Pokemon } from "#app/field/pokemon";
|
import type { default as Pokemon } from "#app/field/pokemon";
|
||||||
import type { DynamicPhaseString, PhaseMap, PhaseString, StaticPhaseString } from "./@types/phase-types";
|
import type { PhaseMap, PhaseString, DynamicPhase, StaticPhaseString } from "./@types/phase-types";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { AddEnemyBuffModifierPhase } from "#app/phases/add-enemy-buff-modifier-phase";
|
import { AddEnemyBuffModifierPhase } from "#app/phases/add-enemy-buff-modifier-phase";
|
||||||
import { AttemptCapturePhase } from "#app/phases/attempt-capture-phase";
|
import { AttemptCapturePhase } from "#app/phases/attempt-capture-phase";
|
||||||
@ -214,6 +214,12 @@ const PHASES = Object.freeze({
|
|||||||
/** Maps Phase strings to their constructors */
|
/** Maps Phase strings to their constructors */
|
||||||
export type PhaseConstructorMap = typeof PHASES;
|
export type PhaseConstructorMap = typeof PHASES;
|
||||||
|
|
||||||
|
const turnEndPhases: PhaseString[] = ["WeatherEffectPhase", "BerryPhase", "CheckStatusEffectPhase", "TurnEndPhase"];
|
||||||
|
|
||||||
|
const ignorablePhases: PhaseString[] = ["ShowAbilityPhase", "HideAbilityPhase"];
|
||||||
|
// TODO might be easier to define which phases should be dynamic instead
|
||||||
|
const nonDynamicPokemonPhases: PhaseString[] = ["SummonPhase", "CommandPhase"];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PhaseManager is responsible for managing the phases in the battle scene
|
* PhaseManager is responsible for managing the phases in the battle scene
|
||||||
*/
|
*/
|
||||||
@ -232,6 +238,8 @@ export class PhaseManager {
|
|||||||
private currentPhase: Phase | null = null;
|
private currentPhase: Phase | null = null;
|
||||||
private standbyPhase: Phase | null = null;
|
private standbyPhase: Phase | null = null;
|
||||||
|
|
||||||
|
public turnEnded = false;
|
||||||
|
|
||||||
/* Phase Functions */
|
/* Phase Functions */
|
||||||
getCurrentPhase(): Phase | null {
|
getCurrentPhase(): Phase | null {
|
||||||
return this.currentPhase;
|
return this.currentPhase;
|
||||||
@ -247,11 +255,11 @@ export class PhaseManager {
|
|||||||
* @param defer boolean on which queue to add to, defaults to false, and adds to phaseQueue
|
* @param defer boolean on which queue to add to, defaults to false, and adds to phaseQueue
|
||||||
*/
|
*/
|
||||||
pushPhase(phase: Phase, defer = false): void {
|
pushPhase(phase: Phase, defer = false): void {
|
||||||
if (this.dynamicQueueManager.isDynamicPhase(phase.phaseName)) {
|
if (this.isDynamicPhase(phase) && this.dynamicQueueManager.activeQueueExists(phase.phaseName)) {
|
||||||
this.dynamicQueueManager.queueDynamicPhase(phase);
|
this.dynamicQueueManager.queueDynamicPhase(phase);
|
||||||
} else {
|
return;
|
||||||
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
|
||||||
}
|
}
|
||||||
|
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -259,6 +267,10 @@ export class PhaseManager {
|
|||||||
* @param phases {@linkcode Phase} the phase(s) to add
|
* @param phases {@linkcode Phase} the phase(s) to add
|
||||||
*/
|
*/
|
||||||
unshiftPhase(...phases: Phase[]): void {
|
unshiftPhase(...phases: Phase[]): void {
|
||||||
|
if (this.isDynamicPhase(phases[0]) && this.dynamicQueueManager.activeQueueExists(phases[0].phaseName)) {
|
||||||
|
phases.forEach((p: DynamicPhase) => this.dynamicQueueManager.queueDynamicPhase(p));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.phaseQueuePrependSpliceIndex === -1) {
|
if (this.phaseQueuePrependSpliceIndex === -1) {
|
||||||
this.phaseQueuePrepend.push(...phases);
|
this.phaseQueuePrepend.push(...phases);
|
||||||
} else {
|
} else {
|
||||||
@ -283,6 +295,7 @@ export class PhaseManager {
|
|||||||
this.dynamicQueueManager.clearQueues();
|
this.dynamicQueueManager.clearQueues();
|
||||||
this.currentPhase = null;
|
this.currentPhase = null;
|
||||||
this.standbyPhase = null;
|
this.standbyPhase = null;
|
||||||
|
this.turnEnded = false;
|
||||||
this.clearPhaseQueueSplice();
|
this.clearPhaseQueueSplice();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,14 +336,16 @@ export class PhaseManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.phaseQueue.length) {
|
|
||||||
this.populatePhaseQueue();
|
this.queueDynamicPhasesAtFront();
|
||||||
|
|
||||||
|
if (this.phaseQueue.every(p => ignorablePhases.includes(p.phaseName))) {
|
||||||
|
this.startNextDynamicPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.phaseQueue[0].is("WeatherEffectPhase")) {
|
if (!this.turnEnded && (!this.phaseQueue.length || this.phaseQueue[0].is("BattleEndPhase"))) {
|
||||||
const dynamicPhase = this.dynamicQueueManager.popNextPhase();
|
if (!this.startNextDynamicPhase()) {
|
||||||
if (dynamicPhase) {
|
this.turnEndSequence();
|
||||||
this.phaseQueue.unshift(dynamicPhase);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,8 +371,8 @@ export class PhaseManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public hasPhaseOfType(type: PhaseString, condition?: PhaseConditionFunc): boolean {
|
public hasPhaseOfType(type: PhaseString, condition?: PhaseConditionFunc): boolean {
|
||||||
if (this.dynamicQueueManager.isDynamicPhase(type)) {
|
if (this.dynamicQueueManager.exists(type, condition)) {
|
||||||
return this.dynamicQueueManager.exists(type, condition);
|
return true;
|
||||||
}
|
}
|
||||||
return [this.phaseQueue, this.phaseQueuePrepend].some((queue: Phase[]) =>
|
return [this.phaseQueue, this.phaseQueuePrepend].some((queue: Phase[]) =>
|
||||||
queue.find(phase => phase.is(type) && (!condition || condition(phase))),
|
queue.find(phase => phase.is(type) && (!condition || condition(phase))),
|
||||||
@ -374,7 +389,7 @@ export class PhaseManager {
|
|||||||
phaseType: P,
|
phaseType: P,
|
||||||
phaseFilter?: (phase: PhaseMap[P]) => boolean,
|
phaseFilter?: (phase: PhaseMap[P]) => boolean,
|
||||||
): PhaseMap[P] | undefined {
|
): PhaseMap[P] | undefined {
|
||||||
if (this.dynamicQueueManager.isDynamicPhase(phaseType)) {
|
if (this.dynamicQueueManager.exists(phaseType, phaseFilter)) {
|
||||||
return this.dynamicQueueManager.findPhaseOfType(phaseType, phaseFilter) as PhaseMap[P];
|
return this.dynamicQueueManager.findPhaseOfType(phaseType, phaseFilter) as PhaseMap[P];
|
||||||
}
|
}
|
||||||
return this.phaseQueue.find(phase => phase.is(phaseType) && (!phaseFilter || phaseFilter(phase))) as PhaseMap[P];
|
return this.phaseQueue.find(phase => phase.is(phaseType) && (!phaseFilter || phaseFilter(phase))) as PhaseMap[P];
|
||||||
@ -457,17 +472,6 @@ export class PhaseManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unshifts the top phase from the corresponding dynamic queue onto {@linkcode phaseQueue}
|
|
||||||
* @param type {@linkcode DynamicPhaseString} The type of dynamic phase to start
|
|
||||||
*/
|
|
||||||
public startNextDynamicPhase(type?: DynamicPhaseString): void {
|
|
||||||
const phase = this.dynamicQueueManager.popNextPhase(type);
|
|
||||||
if (phase) {
|
|
||||||
this.unshiftPhase(phase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a MessagePhase, either to PhaseQueuePrepend or nextCommandPhaseQueue
|
* Adds a MessagePhase, either to PhaseQueuePrepend or nextCommandPhaseQueue
|
||||||
* @param message - string for MessagePhase
|
* @param message - string for MessagePhase
|
||||||
@ -518,12 +522,10 @@ export class PhaseManager {
|
|||||||
/**
|
/**
|
||||||
* Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order)
|
* Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order)
|
||||||
*/
|
*/
|
||||||
private populatePhaseQueue(): void {
|
private turnEndSequence(): void {
|
||||||
const dynamicPhase = this.dynamicQueueManager.popNextPhase();
|
this.turnEnded = true;
|
||||||
if (dynamicPhase) {
|
this.dynamicQueueManager.clearQueues();
|
||||||
this.phaseQueue.unshift(dynamicPhase);
|
this.queueTurnEndPhases();
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.nextCommandPhaseQueue.length) {
|
if (this.nextCommandPhaseQueue.length) {
|
||||||
this.phaseQueue.push(...this.nextCommandPhaseQueue);
|
this.phaseQueue.push(...this.nextCommandPhaseQueue);
|
||||||
this.nextCommandPhaseQueue.splice(0, this.nextCommandPhaseQueue.length);
|
this.nextCommandPhaseQueue.splice(0, this.nextCommandPhaseQueue.length);
|
||||||
@ -565,10 +567,7 @@ export class PhaseManager {
|
|||||||
* @param phase - The name of the phase to create
|
* @param phase - The name of the phase to create
|
||||||
* @param args - The arguments to pass to the phase constructor
|
* @param args - The arguments to pass to the phase constructor
|
||||||
*/
|
*/
|
||||||
public unshiftNew<T extends StaticPhaseString>(
|
public unshiftNew<T extends PhaseString>(phase: T, ...args: ConstructorParameters<PhaseConstructorMap[T]>): void {
|
||||||
phase: T,
|
|
||||||
...args: ConstructorParameters<PhaseConstructorMap[T]>
|
|
||||||
): void {
|
|
||||||
this.unshiftPhase(this.create(phase, ...args));
|
this.unshiftPhase(this.create(phase, ...args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,4 +614,44 @@ export class PhaseManager {
|
|||||||
public changePhaseMove(phaseCondition: PhaseConditionFunc, move: PokemonMove) {
|
public changePhaseMove(phaseCondition: PhaseConditionFunc, move: PokemonMove) {
|
||||||
this.dynamicQueueManager.setMoveForPhase(phaseCondition, move);
|
this.dynamicQueueManager.setMoveForPhase(phaseCondition, move);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public queueTurnEndPhases(): void {
|
||||||
|
turnEndPhases
|
||||||
|
.slice()
|
||||||
|
.reverse()
|
||||||
|
.forEach(p => this.phaseQueue.unshift(this.create(p)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private consecutivePokemonPhases(): DynamicPhase[] | undefined {
|
||||||
|
if (this.phaseQueue.length < 1 || !this.isDynamicPhase(this.phaseQueue[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let spliceLength = this.phaseQueue.findIndex(p => !p.is(this.phaseQueue[0].phaseName));
|
||||||
|
spliceLength = spliceLength !== -1 ? spliceLength : this.phaseQueue.length;
|
||||||
|
if (spliceLength > 1) {
|
||||||
|
return this.phaseQueue.splice(0, spliceLength) as DynamicPhase[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private queueDynamicPhasesAtFront(): void {
|
||||||
|
const dynamicPhases = this.consecutivePokemonPhases();
|
||||||
|
if (dynamicPhases) {
|
||||||
|
dynamicPhases.forEach((p: DynamicPhase) => {
|
||||||
|
globalScene.phaseManager.dynamicQueueManager.queueDynamicPhase(p);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public startNextDynamicPhase(): boolean {
|
||||||
|
const dynamicPhase = this.dynamicQueueManager.popNextPhase();
|
||||||
|
if (dynamicPhase) {
|
||||||
|
this.phaseQueue.unshift(dynamicPhase);
|
||||||
|
}
|
||||||
|
return !!dynamicPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
private isDynamicPhase(phase: Phase): phase is DynamicPhase {
|
||||||
|
return typeof (phase as any).getPokemon === "function" && !nonDynamicPokemonPhases.includes(phase.phaseName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
import type { BattlerIndex } from "#enums/battler-index";
|
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
|
||||||
export class CheckStatusEffectPhase extends Phase {
|
export class CheckStatusEffectPhase extends Phase {
|
||||||
public readonly phaseName = "CheckStatusEffectPhase";
|
public readonly phaseName = "CheckStatusEffectPhase";
|
||||||
private order: BattlerIndex[];
|
|
||||||
constructor(order: BattlerIndex[]) {
|
|
||||||
super();
|
|
||||||
this.order = order;
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
const field = globalScene.getField();
|
const field = globalScene.getField();
|
||||||
for (const o of this.order) {
|
for (const p of field) {
|
||||||
if (field[o].status?.isPostTurn()) {
|
if (p?.status?.isPostTurn()) {
|
||||||
globalScene.phaseManager.unshiftNew("PostTurnStatusEffectPhase", o);
|
globalScene.phaseManager.unshiftNew("PostTurnStatusEffectPhase", p.getBattlerIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.end();
|
this.end();
|
||||||
|
@ -562,7 +562,6 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (![BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
if (![BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
||||||
enemyField.map(p => globalScene.phaseManager.pushNew("PostSummonPhase", p.getBattlerIndex()));
|
|
||||||
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
enemyField.map(p => globalScene.phaseManager.pushNew("ScanIvsPhase", p.getBattlerIndex()));
|
enemyField.map(p => globalScene.phaseManager.pushNew("ScanIvsPhase", p.getBattlerIndex()));
|
||||||
@ -603,6 +602,9 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (![BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
||||||
|
enemyField.map(p => globalScene.phaseManager.pushNew("PostSummonPhase", p.getBattlerIndex()));
|
||||||
|
}
|
||||||
handleTutorial(Tutorial.Access_Menu).then(() => super.end());
|
handleTutorial(Tutorial.Access_Menu).then(() => super.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +36,6 @@ export class PostSummonPhase extends PokemonPhase {
|
|||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
override end() {
|
|
||||||
globalScene.phaseManager.startNextDynamicPhase("PostSummonPhase");
|
|
||||||
super.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getPriority() {
|
public getPriority() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ export class TurnInitPhase extends FieldPhase {
|
|||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
globalScene.phaseManager.turnEnded = false;
|
||||||
globalScene.getPlayerField().forEach(p => {
|
globalScene.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
|
||||||
if (p.isOnField() && !p.isAllowedInBattle()) {
|
if (p.isOnField() && !p.isAllowedInBattle()) {
|
||||||
|
@ -163,14 +163,6 @@ export class TurnStartPhase extends FieldPhase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
phaseManager.pushNew("WeatherEffectPhase");
|
|
||||||
phaseManager.pushNew("BerryPhase");
|
|
||||||
|
|
||||||
/** Add a new phase to check who should be taking status damage */
|
|
||||||
phaseManager.pushNew("CheckStatusEffectPhase", moveOrder);
|
|
||||||
|
|
||||||
phaseManager.pushNew("TurnEndPhase");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this.end() will call shiftPhase(), which dumps everything from PrependQueue (aka everything that is unshifted()) to the front
|
* this.end() will call shiftPhase(), which dumps everything from PrependQueue (aka everything that is unshifted()) to the front
|
||||||
* of the queue and dequeues to start the next phase
|
* of the queue and dequeues to start the next phase
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import type { PhaseConditionFunc } from "#app/@types/phase-condition";
|
import type { PhaseConditionFunc } from "#app/@types/phase-condition";
|
||||||
import type { DynamicPhaseString, PhaseString } from "#app/@types/phase-types";
|
import type { PhaseString, DynamicPhase } from "#app/@types/phase-types";
|
||||||
import type { PokemonMove } from "#app/data/moves/pokemon-move";
|
import type { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import type { Phase } from "#app/phase";
|
import type { Phase } from "#app/phase";
|
||||||
import type { MoveHeaderPhase } from "#app/phases/move-header-phase";
|
|
||||||
import { MovePhasePriorityQueue } from "#app/queues/move-phase-priority-queue";
|
import { MovePhasePriorityQueue } from "#app/queues/move-phase-priority-queue";
|
||||||
import type { PhasePriorityQueue } from "#app/queues/phase-priority-queue";
|
import type { PhasePriorityQueue } from "#app/queues/phase-priority-queue";
|
||||||
import { PokemonPhasePriorityQueue } from "#app/queues/pokemon-phase-priority-queue";
|
import { PokemonPhasePriorityQueue } from "#app/queues/pokemon-phase-priority-queue";
|
||||||
@ -14,11 +13,12 @@ import type { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"
|
|||||||
|
|
||||||
export class DynamicQueueManager {
|
export class DynamicQueueManager {
|
||||||
private dynamicPhaseMap: Map<PhaseString, PhasePriorityQueue<Phase>>;
|
private dynamicPhaseMap: Map<PhaseString, PhasePriorityQueue<Phase>>;
|
||||||
|
private alwaysDynamic: PhaseString[] = ["SwitchSummonPhase", "PostSummonPhase", "MovePhase"];
|
||||||
|
private popOrder: PhaseString[] = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.dynamicPhaseMap = new Map();
|
this.dynamicPhaseMap = new Map();
|
||||||
this.dynamicPhaseMap.set("SwitchSummonPhase", new SwitchSummonPhasePriorityQueue());
|
this.dynamicPhaseMap.set("SwitchSummonPhase", new SwitchSummonPhasePriorityQueue());
|
||||||
this.dynamicPhaseMap.set("MoveHeaderPhase", new PokemonPhasePriorityQueue<MoveHeaderPhase>());
|
|
||||||
this.dynamicPhaseMap.set("PostSummonPhase", new PostSummonPhasePriorityQueue());
|
this.dynamicPhaseMap.set("PostSummonPhase", new PostSummonPhasePriorityQueue());
|
||||||
this.dynamicPhaseMap.set("MovePhase", new MovePhasePriorityQueue());
|
this.dynamicPhaseMap.set("MovePhase", new MovePhasePriorityQueue());
|
||||||
}
|
}
|
||||||
@ -27,27 +27,39 @@ export class DynamicQueueManager {
|
|||||||
for (const queue of this.dynamicPhaseMap.values()) {
|
for (const queue of this.dynamicPhaseMap.values()) {
|
||||||
queue.clear();
|
queue.clear();
|
||||||
}
|
}
|
||||||
|
this.popOrder.splice(0, this.popOrder.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public queueDynamicPhase(phase: Phase): void {
|
public queueDynamicPhase<T extends DynamicPhase>(phase: T): void {
|
||||||
|
if (!this.dynamicPhaseMap.has(phase.phaseName)) {
|
||||||
|
this.dynamicPhaseMap.set(phase.phaseName, new PokemonPhasePriorityQueue<T>());
|
||||||
|
}
|
||||||
this.dynamicPhaseMap.get(phase.phaseName)?.push(phase);
|
this.dynamicPhaseMap.get(phase.phaseName)?.push(phase);
|
||||||
|
this.popOrder.push(phase.phaseName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public popNextPhase(type?: DynamicPhaseString): Phase | undefined {
|
public popNextPhase(): Phase | undefined {
|
||||||
const queue = type
|
const type = this.popOrder.pop();
|
||||||
? this.dynamicPhaseMap.get(type)
|
if (!type) {
|
||||||
: [...this.dynamicPhaseMap.values()].find(queue => !queue.isEmpty());
|
return;
|
||||||
return queue?.pop();
|
}
|
||||||
}
|
if (!this.alwaysDynamic.includes(type)) {
|
||||||
|
return this.dynamicPhaseMap.get(type)?.pop();
|
||||||
public isDynamicPhase(type: PhaseString): boolean {
|
}
|
||||||
return this.dynamicPhaseMap.has(type);
|
return this.alwaysDynamic
|
||||||
|
.map((p: PhaseString) => this.dynamicPhaseMap.get(p))
|
||||||
|
.find(q => q && !q.isEmpty())
|
||||||
|
?.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public findPhaseOfType(type: PhaseString, condition?: PhaseConditionFunc): Phase | undefined {
|
public findPhaseOfType(type: PhaseString, condition?: PhaseConditionFunc): Phase | undefined {
|
||||||
return this.dynamicPhaseMap.get(type)?.findPhase(condition);
|
return this.dynamicPhaseMap.get(type)?.findPhase(condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public activeQueueExists(type: PhaseString) {
|
||||||
|
return this.alwaysDynamic.includes(type) || this.dynamicPhaseMap.get(type)?.isEmpty() === false;
|
||||||
|
}
|
||||||
|
|
||||||
public exists(type: PhaseString, condition?: PhaseConditionFunc): boolean {
|
public exists(type: PhaseString, condition?: PhaseConditionFunc): boolean {
|
||||||
return !!this.dynamicPhaseMap.get(type)?.hasPhaseWithCondition(condition);
|
return !!this.dynamicPhaseMap.get(type)?.hasPhaseWithCondition(condition);
|
||||||
}
|
}
|
||||||
@ -84,4 +96,8 @@ export class DynamicQueueManager {
|
|||||||
private getMovePhaseQueue(): MovePhasePriorityQueue {
|
private getMovePhaseQueue(): MovePhasePriorityQueue {
|
||||||
return this.dynamicPhaseMap.get("MovePhase") as MovePhasePriorityQueue;
|
return this.dynamicPhaseMap.get("MovePhase") as MovePhasePriorityQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addPopType(type: PhaseString): void {
|
||||||
|
this.popOrder.push(type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import type { PartyMemberPokemonPhase } from "#app/phases/party-member-pokemon-phase";
|
import type { DynamicPhase } from "#app/@types/phase-types";
|
||||||
import type { PokemonPhase } from "#app/phases/pokemon-phase";
|
|
||||||
import { PhasePriorityQueue } from "#app/queues/phase-priority-queue";
|
import { PhasePriorityQueue } from "#app/queues/phase-priority-queue";
|
||||||
import { sortInSpeedOrder } from "#app/utils/speed-order";
|
import { sortInSpeedOrder } from "#app/utils/speed-order";
|
||||||
import type { BattlerIndex } from "#enums/battler-index";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
|
|
||||||
export class PokemonPhasePriorityQueue<T extends PokemonPhase | PartyMemberPokemonPhase> extends PhasePriorityQueue<T> {
|
export class PokemonPhasePriorityQueue<T extends DynamicPhase> extends PhasePriorityQueue<T> {
|
||||||
protected setOrder: BattlerIndex[] | undefined;
|
protected setOrder: BattlerIndex[] | undefined;
|
||||||
public override reorder(): void {
|
public override reorder(): void {
|
||||||
|
this.queue = this.queue.filter(phase => phase.getPokemon()?.isActive(true));
|
||||||
if (this.setOrder) {
|
if (this.setOrder) {
|
||||||
this.queue.sort(
|
this.queue.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
import { PostSummonActivateAbilityPhase } from "#app/phases/post-summon-activate-ability-phase";
|
import { PostSummonActivateAbilityPhase } from "#app/phases/post-summon-activate-ability-phase";
|
||||||
import type { PostSummonPhase } from "#app/phases/post-summon-phase";
|
import type { PostSummonPhase } from "#app/phases/post-summon-phase";
|
||||||
import { PokemonPhasePriorityQueue } from "#app/queues/pokemon-phase-priority-queue";
|
import { PokemonPhasePriorityQueue } from "#app/queues/pokemon-phase-priority-queue";
|
||||||
@ -29,10 +30,9 @@ export class PostSummonPhasePriorityQueue extends PokemonPhasePriorityQueue<Post
|
|||||||
private queueAbilityPhase(phase: PostSummonPhase): void {
|
private queueAbilityPhase(phase: PostSummonPhase): void {
|
||||||
const phasePokemon = phase.getPokemon();
|
const phasePokemon = phase.getPokemon();
|
||||||
|
|
||||||
phasePokemon
|
phasePokemon.getAbilityPriorities().forEach((priority, idx) => {
|
||||||
.getAbilityPriorities()
|
this.queue.push(new PostSummonActivateAbilityPhase(phasePokemon.getBattlerIndex(), priority, !!idx));
|
||||||
.forEach((priority, idx) =>
|
globalScene.phaseManager.dynamicQueueManager.addPopType("PostSummonPhase");
|
||||||
this.queue.push(new PostSummonActivateAbilityPhase(phasePokemon.getBattlerIndex(), priority, !!idx)),
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user