SP slotplate
How-to

Add a phase

Adding a new FSM phase (anticipation, bonus, big-win).

The default FSM
idle waits for click spin debitBet + request stopSpin reels land on grid winShow spotlight + credit click response received allLanded win hold elapsed (or skip) no winlines → idle immediately skip() = forceStop skip() = forceStop skip() = cancel hold idle / resting phase active phase normal transition conditional shortcut
You're extending this. New phases go between existing transitions.

Short version

/add-phase AnticipationPhase

Long version

  1. Create the file. src/flow/phases/AnticipationPhase.ts:
    import type { Phase, PhaseContext } from '../Phase';
    
    export class AnticipationPhase implements Phase {
      readonly name = 'anticipation';
    
      async enter(ctx: PhaseContext) {
        const teasers = ctx.stores.data.teasingReels;
        ctx.reels.setAnticipation(teasers);
        // wait for the anticipation animation to settle, then advance
        await ctx.fsm.transition('stopSpin');
      }
    
      exit() { /* dispose anything this phase allocated */ }
    }
  2. Register. In src/composition.ts, add fsm.register(new AnticipationPhase()) alongside the others.
  3. Wire the transition in. Whichever phase precedes this one now transitions to it. For anticipation, that's probably SpinPhase — instead of going straight to stopSpin, it goes to anticipation when the server returns teasingReels.
  4. Test it. tests/flow/AnticipationPhase.test.ts — instantiate the phase, mock the context, call enter, assert the presenter was called and the FSM transitioned.
  5. Run: pnpm typecheck && pnpm test && pnpm lint.

Don't

  • Call setTimeout inside the phase. Use ctx.ticker.schedule.
  • Import pixi-reels. Talk to ctx.reels (the presenter).
  • Loop inside the phase. Transition out and back in (or split into two phases).
  • Call another phase's enter directly. Use ctx.fsm.transition.

The skip method

Implement skip() if the user should be able to short-circuit this phase (Turbo / SuperTurbo). Usually that means "cancel the pending ticker handle and transition immediately." See WinShowPhase.skip for the canonical shape.

The exit method

Implement exit() if the phase holds timers, event listeners, or transient state. Called before the next phase's enter — and also on FSM teardown. Make it idempotent.