2024-08-06 07:06:25 -07:00
import { Phase } from "#app/phase" ;
2025-02-22 22:52:07 -06:00
import ErrorInterceptor from "#test/testUtils/errorInterceptor" ;
2024-09-05 15:29:39 +10:00
import { AttemptRunPhase } from "#app/phases/attempt-run-phase" ;
2024-08-22 06:49:33 -07:00
import { BattleEndPhase } from "#app/phases/battle-end-phase" ;
import { BerryPhase } from "#app/phases/berry-phase" ;
import { CheckSwitchPhase } from "#app/phases/check-switch-phase" ;
import { CommandPhase } from "#app/phases/command-phase" ;
2024-11-25 14:15:39 -08:00
import { DamageAnimPhase } from "#app/phases/damage-anim-phase" ;
2024-08-22 06:49:33 -07:00
import { EggLapsePhase } from "#app/phases/egg-lapse-phase" ;
import { EncounterPhase } from "#app/phases/encounter-phase" ;
2024-08-30 20:21:56 -07:00
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase" ;
2024-08-22 06:49:33 -07:00
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase" ;
2024-08-30 20:21:56 -07:00
import { EvolutionPhase } from "#app/phases/evolution-phase" ;
2024-08-22 06:49:33 -07:00
import { FaintPhase } from "#app/phases/faint-phase" ;
2024-11-05 09:19:20 -05:00
import { FormChangePhase } from "#app/phases/form-change-phase" ;
2024-09-09 09:11:46 -07:00
import { LearnMovePhase } from "#app/phases/learn-move-phase" ;
2024-09-03 09:14:45 -04:00
import { LevelCapPhase } from "#app/phases/level-cap-phase" ;
2024-08-22 06:49:33 -07:00
import { LoginPhase } from "#app/phases/login-phase" ;
import { MessagePhase } from "#app/phases/message-phase" ;
import { MoveEffectPhase } from "#app/phases/move-effect-phase" ;
import { MoveEndPhase } from "#app/phases/move-end-phase" ;
import { MovePhase } from "#app/phases/move-phase" ;
import { NewBattlePhase } from "#app/phases/new-battle-phase" ;
2024-09-03 09:14:45 -04:00
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase" ;
2024-08-22 06:49:33 -07:00
import { NextEncounterPhase } from "#app/phases/next-encounter-phase" ;
import { PostSummonPhase } from "#app/phases/post-summon-phase" ;
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase" ;
import { SelectGenderPhase } from "#app/phases/select-gender-phase" ;
import { SelectModifierPhase } from "#app/phases/select-modifier-phase" ;
import { SelectStarterPhase } from "#app/phases/select-starter-phase" ;
import { SelectTargetPhase } from "#app/phases/select-target-phase" ;
import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase" ;
import { ShowAbilityPhase } from "#app/phases/show-ability-phase" ;
2024-09-02 22:12:34 -04:00
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase" ;
2024-08-22 06:49:33 -07:00
import { SummonPhase } from "#app/phases/summon-phase" ;
import { SwitchPhase } from "#app/phases/switch-phase" ;
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase" ;
import { TitlePhase } from "#app/phases/title-phase" ;
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase" ;
import { TurnEndPhase } from "#app/phases/turn-end-phase" ;
import { TurnInitPhase } from "#app/phases/turn-init-phase" ;
import { TurnStartPhase } from "#app/phases/turn-start-phase" ;
import { UnavailablePhase } from "#app/phases/unavailable-phase" ;
import { VictoryPhase } from "#app/phases/victory-phase" ;
2024-09-02 22:12:34 -04:00
import { PartyHealPhase } from "#app/phases/party-heal-phase" ;
2024-08-22 06:49:33 -07:00
import UI , { Mode } from "#app/ui/ui" ;
2024-09-26 04:39:59 -04:00
import { SelectBiomePhase } from "#app/phases/select-biome-phase" ;
2024-09-13 22:05:58 -04:00
import {
MysteryEncounterBattlePhase ,
MysteryEncounterOptionSelectedPhase ,
MysteryEncounterPhase ,
MysteryEncounterRewardsPhase ,
PostMysteryEncounterPhase
} from "#app/phases/mystery-encounter-phases" ;
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase" ;
import { PartyExpPhase } from "#app/phases/party-exp-phase" ;
2024-10-10 23:54:43 +08:00
import { ExpPhase } from "#app/phases/exp-phase" ;
2024-11-11 18:22:27 -05:00
import { GameOverPhase } from "#app/phases/game-over-phase" ;
import { RibbonModifierRewardPhase } from "#app/phases/ribbon-modifier-reward-phase" ;
import { GameOverModifierRewardPhase } from "#app/phases/game-over-modifier-reward-phase" ;
import { UnlockPhase } from "#app/phases/unlock-phase" ;
import { PostGameOverPhase } from "#app/phases/post-game-over-phase" ;
2025-02-21 02:34:39 -06:00
import { RevivalBlessingPhase } from "#app/phases/revival-blessing-phase" ;
2024-09-13 22:05:58 -04:00
export interface PromptHandler {
phaseTarget? : string ;
mode? : Mode ;
callback ? : ( ) = > void ;
expireFn ? : ( ) = > void ;
awaitingActionInput? : boolean ;
}
2024-10-10 23:54:43 +08:00
type PhaseClass =
| typeof LoginPhase
| typeof TitlePhase
| typeof SelectGenderPhase
| typeof NewBiomeEncounterPhase
| typeof SelectStarterPhase
| typeof PostSummonPhase
| typeof SummonPhase
| typeof ToggleDoublePositionPhase
| typeof CheckSwitchPhase
| typeof ShowAbilityPhase
| typeof MessagePhase
| typeof TurnInitPhase
| typeof CommandPhase
| typeof EnemyCommandPhase
| typeof TurnStartPhase
| typeof MovePhase
| typeof MoveEffectPhase
2024-11-25 14:15:39 -08:00
| typeof DamageAnimPhase
2024-10-10 23:54:43 +08:00
| typeof FaintPhase
| typeof BerryPhase
| typeof TurnEndPhase
| typeof BattleEndPhase
| typeof EggLapsePhase
| typeof SelectModifierPhase
| typeof NextEncounterPhase
| typeof NewBattlePhase
| typeof VictoryPhase
| typeof LearnMovePhase
| typeof MoveEndPhase
| typeof StatStageChangePhase
| typeof ShinySparklePhase
| typeof SelectTargetPhase
| typeof UnavailablePhase
| typeof QuietFormChangePhase
| typeof SwitchPhase
| typeof SwitchSummonPhase
| typeof PartyHealPhase
2024-11-05 09:19:20 -05:00
| typeof FormChangePhase
2024-10-10 23:54:43 +08:00
| typeof EvolutionPhase
| typeof EndEvolutionPhase
| typeof LevelCapPhase
| typeof AttemptRunPhase
| typeof SelectBiomePhase
| typeof MysteryEncounterPhase
| typeof MysteryEncounterOptionSelectedPhase
| typeof MysteryEncounterBattlePhase
| typeof MysteryEncounterRewardsPhase
| typeof PostMysteryEncounterPhase
2024-11-11 18:22:27 -05:00
| typeof RibbonModifierRewardPhase
| typeof GameOverModifierRewardPhase
2024-10-10 23:54:43 +08:00
| typeof ModifierRewardPhase
| typeof PartyExpPhase
2024-11-05 09:19:20 -05:00
| typeof ExpPhase
2024-11-11 18:22:27 -05:00
| typeof EncounterPhase
| typeof GameOverPhase
| typeof UnlockPhase
2025-02-21 02:34:39 -06:00
| typeof PostGameOverPhase
| typeof RevivalBlessingPhase ;
2024-10-10 23:54:43 +08:00
type PhaseString =
| "LoginPhase"
| "TitlePhase"
| "SelectGenderPhase"
| "NewBiomeEncounterPhase"
| "SelectStarterPhase"
| "PostSummonPhase"
| "SummonPhase"
| "ToggleDoublePositionPhase"
| "CheckSwitchPhase"
| "ShowAbilityPhase"
| "MessagePhase"
| "TurnInitPhase"
| "CommandPhase"
| "EnemyCommandPhase"
| "TurnStartPhase"
| "MovePhase"
| "MoveEffectPhase"
2024-11-25 14:15:39 -08:00
| "DamageAnimPhase"
2024-10-10 23:54:43 +08:00
| "FaintPhase"
| "BerryPhase"
| "TurnEndPhase"
| "BattleEndPhase"
| "EggLapsePhase"
| "SelectModifierPhase"
| "NextEncounterPhase"
| "NewBattlePhase"
| "VictoryPhase"
| "LearnMovePhase"
| "MoveEndPhase"
| "StatStageChangePhase"
| "ShinySparklePhase"
| "SelectTargetPhase"
| "UnavailablePhase"
| "QuietFormChangePhase"
| "SwitchPhase"
| "SwitchSummonPhase"
| "PartyHealPhase"
2024-11-05 09:19:20 -05:00
| "FormChangePhase"
2024-10-10 23:54:43 +08:00
| "EvolutionPhase"
| "EndEvolutionPhase"
| "LevelCapPhase"
| "AttemptRunPhase"
| "SelectBiomePhase"
| "MysteryEncounterPhase"
| "MysteryEncounterOptionSelectedPhase"
| "MysteryEncounterBattlePhase"
| "MysteryEncounterRewardsPhase"
| "PostMysteryEncounterPhase"
2024-11-11 18:22:27 -05:00
| "RibbonModifierRewardPhase"
| "GameOverModifierRewardPhase"
2024-10-10 23:54:43 +08:00
| "ModifierRewardPhase"
| "PartyExpPhase"
2024-11-05 09:19:20 -05:00
| "ExpPhase"
2024-11-11 18:22:27 -05:00
| "EncounterPhase"
| "GameOverPhase"
| "UnlockPhase"
2025-02-21 02:34:39 -06:00
| "PostGameOverPhase"
| "RevivalBlessingPhase" ;
2024-10-10 23:54:43 +08:00
type PhaseInterceptorPhase = PhaseClass | PhaseString ;
2024-06-08 00:33:45 +02:00
export default class PhaseInterceptor {
public scene ;
public phases = { } ;
2024-08-06 23:29:51 -07:00
public log : string [ ] ;
2024-06-08 00:33:45 +02:00
private onHold ;
private interval ;
private promptInterval ;
private intervalRun ;
2024-09-13 22:05:58 -04:00
private prompts : PromptHandler [ ] ;
2024-06-08 00:33:45 +02:00
private phaseFrom ;
2024-06-08 21:54:20 +02:00
private inProgress ;
private originalSetMode ;
private originalSuperEnd ;
2024-06-08 00:33:45 +02:00
/ * *
* List of phases with their corresponding start methods .
2024-11-05 09:19:20 -05:00
*
* CAUTION : If a phase and its subclasses ( if any ) both appear in this list ,
* make sure that this list contains said phase AFTER all of its subclasses .
* This way , the phase ' s ` prototype.start ` is properly preserved during
* ` initPhases() ` so that its subclasses can use ` super.start() ` properly .
2024-06-08 00:33:45 +02:00
* /
private PHASES = [
2024-10-04 13:08:31 +08:00
[ LoginPhase , this . startPhase ] ,
[ TitlePhase , this . startPhase ] ,
[ SelectGenderPhase , this . startPhase ] ,
[ NewBiomeEncounterPhase , this . startPhase ] ,
[ SelectStarterPhase , this . startPhase ] ,
[ PostSummonPhase , this . startPhase ] ,
[ SummonPhase , this . startPhase ] ,
[ ToggleDoublePositionPhase , this . startPhase ] ,
[ CheckSwitchPhase , this . startPhase ] ,
[ ShowAbilityPhase , this . startPhase ] ,
[ MessagePhase , this . startPhase ] ,
[ TurnInitPhase , this . startPhase ] ,
[ CommandPhase , this . startPhase ] ,
[ EnemyCommandPhase , this . startPhase ] ,
[ TurnStartPhase , this . startPhase ] ,
[ MovePhase , this . startPhase ] ,
[ MoveEffectPhase , this . startPhase ] ,
2024-11-25 14:15:39 -08:00
[ DamageAnimPhase , this . startPhase ] ,
2024-10-04 13:08:31 +08:00
[ FaintPhase , this . startPhase ] ,
[ BerryPhase , this . startPhase ] ,
[ TurnEndPhase , this . startPhase ] ,
[ BattleEndPhase , this . startPhase ] ,
[ EggLapsePhase , this . startPhase ] ,
[ SelectModifierPhase , this . startPhase ] ,
[ NextEncounterPhase , this . startPhase ] ,
[ NewBattlePhase , this . startPhase ] ,
[ VictoryPhase , this . startPhase ] ,
[ LearnMovePhase , this . startPhase ] ,
[ MoveEndPhase , this . startPhase ] ,
[ StatStageChangePhase , this . startPhase ] ,
[ ShinySparklePhase , this . startPhase ] ,
[ SelectTargetPhase , this . startPhase ] ,
[ UnavailablePhase , this . startPhase ] ,
[ QuietFormChangePhase , this . startPhase ] ,
[ SwitchPhase , this . startPhase ] ,
[ SwitchSummonPhase , this . startPhase ] ,
[ PartyHealPhase , this . startPhase ] ,
2024-11-05 09:19:20 -05:00
[ FormChangePhase , this . startPhase ] ,
2024-10-04 13:08:31 +08:00
[ EvolutionPhase , this . startPhase ] ,
[ EndEvolutionPhase , this . startPhase ] ,
[ LevelCapPhase , this . startPhase ] ,
[ AttemptRunPhase , this . startPhase ] ,
[ SelectBiomePhase , this . startPhase ] ,
[ MysteryEncounterPhase , this . startPhase ] ,
[ MysteryEncounterOptionSelectedPhase , this . startPhase ] ,
[ MysteryEncounterBattlePhase , this . startPhase ] ,
[ MysteryEncounterRewardsPhase , this . startPhase ] ,
[ PostMysteryEncounterPhase , this . startPhase ] ,
2024-11-11 18:22:27 -05:00
[ RibbonModifierRewardPhase , this . startPhase ] ,
[ GameOverModifierRewardPhase , this . startPhase ] ,
2024-10-04 13:08:31 +08:00
[ ModifierRewardPhase , this . startPhase ] ,
[ PartyExpPhase , this . startPhase ] ,
[ ExpPhase , this . startPhase ] ,
2024-11-05 09:19:20 -05:00
[ EncounterPhase , this . startPhase ] ,
2024-11-11 18:22:27 -05:00
[ GameOverPhase , this . startPhase ] ,
[ UnlockPhase , this . startPhase ] ,
[ PostGameOverPhase , this . startPhase ] ,
2025-02-21 02:34:39 -06:00
[ RevivalBlessingPhase , this . startPhase ] ,
2024-06-08 21:54:20 +02:00
] ;
private endBySetMode = [
2024-09-13 22:05:58 -04:00
TitlePhase , SelectGenderPhase , CommandPhase , SelectModifierPhase , MysteryEncounterPhase , PostMysteryEncounterPhase
2024-06-08 00:33:45 +02:00
] ;
/ * *
* Constructor to initialize the scene and properties , and to start the phase handling .
* @param scene - The scene to be managed .
* /
constructor ( scene ) {
this . scene = scene ;
this . onHold = [ ] ;
this . prompts = [ ] ;
2024-08-06 23:29:51 -07:00
this . clearLogs ( ) ;
2024-06-10 16:10:23 +02:00
this . startPromptHandler ( ) ;
2024-06-08 00:33:45 +02:00
this . initPhases ( ) ;
}
2024-08-06 23:29:51 -07:00
/ * *
* Clears phase logs
* /
clearLogs() {
this . log = [ ] ;
}
2024-06-08 21:54:20 +02:00
rejectAll ( error ) {
if ( this . inProgress ) {
clearInterval ( this . promptInterval ) ;
clearInterval ( this . interval ) ;
clearInterval ( this . intervalRun ) ;
this . inProgress . onError ( error ) ;
}
}
2024-06-08 00:33:45 +02:00
/ * *
* Method to set the starting phase .
* @param phaseFrom - The phase to start from .
* @returns The instance of the PhaseInterceptor .
* /
2024-10-10 23:54:43 +08:00
runFrom ( phaseFrom : PhaseInterceptorPhase ) : PhaseInterceptor {
2024-06-08 00:33:45 +02:00
this . phaseFrom = phaseFrom ;
return this ;
}
/ * *
* Method to transition to a target phase .
* @param phaseTo - The phase to transition to .
2024-10-10 23:54:43 +08:00
* @param runTarget - Whether or not to run the target phase .
2024-06-08 00:33:45 +02:00
* @returns A promise that resolves when the transition is complete .
* /
2024-10-10 23:54:43 +08:00
async to ( phaseTo : PhaseInterceptorPhase , runTarget : boolean = true ) : Promise < void > {
2024-06-08 21:54:20 +02:00
return new Promise ( async ( resolve , reject ) = > {
ErrorInterceptor . getInstance ( ) . add ( this ) ;
2024-06-10 16:10:23 +02:00
if ( this . phaseFrom ) {
await this . run ( this . phaseFrom ) . catch ( ( e ) = > reject ( e ) ) ;
this . phaseFrom = null ;
}
2024-06-08 00:33:45 +02:00
const targetName = typeof phaseTo === "string" ? phaseTo : phaseTo.name ;
2024-06-08 21:54:20 +02:00
this . intervalRun = setInterval ( async ( ) = > {
2024-06-08 00:33:45 +02:00
const currentPhase = this . onHold ? . length && this . onHold [ 0 ] ;
2024-06-08 21:54:20 +02:00
if ( currentPhase && currentPhase . name === targetName ) {
2024-06-08 00:33:45 +02:00
clearInterval ( this . intervalRun ) ;
2024-06-08 21:54:20 +02:00
if ( ! runTarget ) {
return resolve ( ) ;
}
await this . run ( currentPhase ) . catch ( ( e ) = > {
clearInterval ( this . intervalRun ) ;
return reject ( e ) ;
} ) ;
2024-06-08 00:33:45 +02:00
return resolve ( ) ;
}
2024-06-08 21:54:20 +02:00
if ( currentPhase && currentPhase . name !== targetName ) {
await this . run ( currentPhase ) . catch ( ( e ) = > {
clearInterval ( this . intervalRun ) ;
return reject ( e ) ;
} ) ;
}
2024-06-08 00:33:45 +02:00
} ) ;
} ) ;
}
/ * *
* Method to run a phase with an optional skip function .
* @param phaseTarget - The phase to run .
* @param skipFn - Optional skip function .
* @returns A promise that resolves when the phase is run .
* /
2024-10-10 23:54:43 +08:00
run ( phaseTarget : PhaseInterceptorPhase , skipFn ? : ( className : PhaseClass ) = > boolean ) : Promise < void > {
2024-06-08 00:33:45 +02:00
const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name ;
this . scene . moveAnimations = null ; // Mandatory to avoid crash
return new Promise ( async ( resolve , reject ) = > {
2024-06-08 21:54:20 +02:00
ErrorInterceptor . getInstance ( ) . add ( this ) ;
2024-06-08 00:33:45 +02:00
const interval = setInterval ( async ( ) = > {
2024-06-08 21:54:20 +02:00
const currentPhase = this . onHold . shift ( ) ;
if ( currentPhase ) {
if ( currentPhase . name !== targetName ) {
clearInterval ( interval ) ;
const skip = skipFn && skipFn ( currentPhase . name ) ;
if ( skip ) {
this . onHold . unshift ( currentPhase ) ;
ErrorInterceptor . getInstance ( ) . remove ( this ) ;
return resolve ( ) ;
}
clearInterval ( interval ) ;
return reject ( ` Wrong phase: this is ${ currentPhase . name } and not ${ targetName } ` ) ;
}
2024-06-08 00:33:45 +02:00
clearInterval ( interval ) ;
2024-06-08 21:54:20 +02:00
this . inProgress = {
name : currentPhase.name ,
callback : ( ) = > {
ErrorInterceptor . getInstance ( ) . remove ( this ) ;
resolve ( ) ;
} ,
onError : ( error ) = > reject ( error ) ,
} ;
currentPhase . call ( ) ;
2024-06-08 00:33:45 +02:00
}
} ) ;
} ) ;
}
2024-10-10 23:54:43 +08:00
whenAboutToRun ( phaseTarget : PhaseInterceptorPhase , skipFn ? : ( className : PhaseClass ) = > boolean ) : Promise < void > {
2024-06-08 00:33:45 +02:00
const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name ;
2024-06-08 21:54:20 +02:00
this . scene . moveAnimations = null ; // Mandatory to avoid crash
return new Promise ( async ( resolve , reject ) = > {
ErrorInterceptor . getInstance ( ) . add ( this ) ;
const interval = setInterval ( async ( ) = > {
2024-06-13 14:42:25 +02:00
const currentPhase = this . onHold [ 0 ] ;
if ( currentPhase ? . name === targetName ) {
clearInterval ( interval ) ;
resolve ( ) ;
2024-06-08 00:33:45 +02:00
}
} ) ;
} ) ;
2024-06-13 14:42:25 +02:00
}
pop() {
this . onHold . pop ( ) ;
this . scene . shiftPhase ( ) ;
2024-06-08 00:33:45 +02:00
}
2024-09-03 09:14:45 -04:00
/ * *
* Remove the current phase from the phase interceptor .
*
* Do not call this unless absolutely necessary . This function is intended
* for cleaning up the phase interceptor when , for whatever reason , a phase
* is manually ended without using the phase interceptor .
*
* @param shouldRun Whether or not the current scene should also be run .
* /
shift ( shouldRun : boolean = false ) : void {
this . onHold . shift ( ) ;
if ( shouldRun ) {
this . scene . shiftPhase ( ) ;
}
}
2024-06-08 00:33:45 +02:00
/ * *
* Method to initialize phases and their corresponding methods .
* /
initPhases() {
2024-06-08 21:54:20 +02:00
this . originalSetMode = UI . prototype . setMode ;
this . originalSuperEnd = Phase . prototype . end ;
UI . prototype . setMode = ( mode , . . . args ) = > this . setMode . call ( this , mode , . . . args ) ;
Phase . prototype . end = ( ) = > this . superEndPhase . call ( this ) ;
2024-10-04 13:08:31 +08:00
for ( const [ phase , methodStart ] of this . PHASES ) {
2024-06-08 00:33:45 +02:00
const originalStart = phase . prototype . start ;
2024-06-08 21:54:20 +02:00
this . phases [ phase . name ] = {
start : originalStart ,
endBySetMode : this.endBySetMode.some ( ( elm ) = > elm . name === phase . name ) ,
} ;
phase . prototype . start = ( ) = > methodStart . call ( this , phase ) ;
2024-06-08 00:33:45 +02:00
}
}
/ * *
* Method to start a phase and log it .
* @param phase - The phase to start .
* /
2024-10-10 23:54:43 +08:00
startPhase ( phase : PhaseClass ) {
2024-06-08 00:33:45 +02:00
this . log . push ( phase . name ) ;
const instance = this . scene . getCurrentPhase ( ) ;
this . onHold . push ( {
name : phase.name ,
call : ( ) = > {
2024-06-08 21:54:20 +02:00
this . phases [ phase . name ] . start . apply ( instance ) ;
2024-06-08 00:33:45 +02:00
}
} ) ;
}
2024-06-08 21:54:20 +02:00
unlock() {
this . inProgress ? . callback ( ) ;
this . inProgress = undefined ;
}
/ * *
* Method to end a phase and log it .
* @param phase - The phase to start .
* /
superEndPhase() {
const instance = this . scene . getCurrentPhase ( ) ;
this . originalSuperEnd . apply ( instance ) ;
this . inProgress ? . callback ( ) ;
this . inProgress = undefined ;
}
/ * *
* m2m to set mode .
2024-10-10 23:54:43 +08:00
* @param mode - The { @linkcode Mode } to set .
* @param args - Additional arguments to pass to the original method .
2024-06-08 21:54:20 +02:00
* /
2024-10-10 23:54:43 +08:00
setMode ( mode : Mode , . . . args : unknown [ ] ) : Promise < void > {
2024-06-08 21:54:20 +02:00
const currentPhase = this . scene . getCurrentPhase ( ) ;
const instance = this . scene . ui ;
2024-08-07 09:23:12 -07:00
console . log ( "setMode" , ` ${ Mode [ mode ] } (= ${ mode } ) ` , args ) ;
2024-10-04 13:08:31 +08:00
const ret = this . originalSetMode . apply ( instance , [ mode , . . . args ] ) ;
2024-06-10 16:10:23 +02:00
if ( ! this . phases [ currentPhase . constructor . name ] ) {
2024-09-26 04:39:59 -04:00
throw new Error ( ` missing ${ currentPhase . constructor . name } in phaseInterceptor PHASES list --- Add it to PHASES inside of /test/utils/phaseInterceptor.ts ` ) ;
2024-06-10 16:10:23 +02:00
}
2024-06-08 21:54:20 +02:00
if ( this . phases [ currentPhase . constructor . name ] . endBySetMode ) {
this . inProgress ? . callback ( ) ;
this . inProgress = undefined ;
}
return ret ;
}
2024-06-08 00:33:45 +02:00
/ * *
* Method to start the prompt handler .
* /
2024-06-10 16:10:23 +02:00
startPromptHandler() {
2024-06-08 00:33:45 +02:00
this . promptInterval = setInterval ( ( ) = > {
if ( this . prompts . length ) {
const actionForNextPrompt = this . prompts [ 0 ] ;
const expireFn = actionForNextPrompt . expireFn && actionForNextPrompt . expireFn ( ) ;
const currentMode = this . scene . ui . getMode ( ) ;
2024-09-13 22:05:58 -04:00
const currentPhase = this . scene . getCurrentPhase ( ) ? . constructor . name ;
2024-06-10 16:10:23 +02:00
const currentHandler = this . scene . ui . getHandler ( ) ;
2024-06-08 00:33:45 +02:00
if ( expireFn ) {
this . prompts . shift ( ) ;
2025-01-12 15:33:05 -08:00
} else if (
2025-02-21 02:34:39 -06:00
currentMode === actionForNextPrompt . mode &&
currentPhase === actionForNextPrompt . phaseTarget &&
currentHandler . active &&
( ! actionForNextPrompt . awaitingActionInput ||
( actionForNextPrompt . awaitingActionInput && currentHandler . awaitingActionInput ) )
2025-01-12 15:33:05 -08:00
) {
2024-09-13 22:05:58 -04:00
const prompt = this . prompts . shift ( ) ;
if ( prompt ? . callback ) {
prompt . callback ( ) ;
}
2024-06-08 00:33:45 +02:00
}
}
} ) ;
}
/ * *
* Method to add an action to the next prompt .
* @param phaseTarget - The target phase for the prompt .
* @param mode - The mode of the UI .
* @param callback - The callback function to execute .
* @param expireFn - The function to determine if the prompt has expired .
2024-09-13 22:05:58 -04:00
* @param awaitingActionInput
2024-06-08 00:33:45 +02:00
* /
2024-08-07 09:23:12 -07:00
addToNextPrompt ( phaseTarget : string , mode : Mode , callback : ( ) = > void , expireFn ? : ( ) = > void , awaitingActionInput : boolean = false ) {
2024-06-08 00:33:45 +02:00
this . prompts . push ( {
phaseTarget ,
mode ,
callback ,
2024-06-10 16:10:23 +02:00
expireFn ,
awaitingActionInput
2024-06-08 00:33:45 +02:00
} ) ;
}
/ * *
* Restores the original state of phases and clears intervals .
*
* This function iterates through all phases and resets their ` start ` method to the original
* function stored in ` this.phases ` . Additionally , it clears the ` promptInterval ` and ` interval ` .
* /
restoreOg() {
2024-10-04 13:08:31 +08:00
for ( const [ phase ] of this . PHASES ) {
2024-06-08 21:54:20 +02:00
phase . prototype . start = this . phases [ phase . name ] . start ;
2024-06-08 00:33:45 +02:00
}
2024-06-08 21:54:20 +02:00
UI . prototype . setMode = this . originalSetMode ;
Phase . prototype . end = this . originalSuperEnd ;
2024-06-08 00:33:45 +02:00
clearInterval ( this . promptInterval ) ;
clearInterval ( this . interval ) ;
2024-06-08 21:54:20 +02:00
clearInterval ( this . intervalRun ) ;
2024-06-08 00:33:45 +02:00
}
}