Round Manager
All round-related logic is managed by the RoundManager, which owns the lifecycle of RoundModel, RoundGenerator, and round state instances for a single play. It validates whether a round can start, requests round execution from the PlayerModel, and exposes a queue of features that the runtime consumes. Override the following methods to customize round behavior. These methods are called each time a new round starts:
createRound(details)– Creates a round model based on the provided round details.createGenerator(details)– Creates the initialRoundGeneratorbased on round details. The generator sequences features and transitions between phases.createState(details)– Creates the initial round state. The state is passed to the generator and persisted for the round.createDetails()– Provides default round details if none are specified.
Each of these objects should only handle a single round and must not be reused across multiple rounds.
Custom Round Manager Example
export class GameRoundManager extends RoundManager<GameRoundState> {
protected override createRound(details:IRoundDetails):RoundModel {
return new RoundModel(this._model, details);
}
protected override createGenerator(details:IRoundDetails):RoundGenerator<GameRoundState> {
return new GameRoundGenerator(this._round, this._model, this._state);
}
protected override createState(details:IRoundDetails):GameRoundState {
return { collectedScatters: 0 };
}
}
Round Details
To create a new round, you must provide an object that matches the IRoundDetails interface. Most properties are optional and are filled automatically from the current PlayerModel state when missing.
behavior– Defines how the round starts. Defaults toRoundBehavior.NORMAL.balance– Overrides the starting balance tracked by the round.roundTotalBet– Sets the actual currency cost of the round. Defaults to the player'scurrentBet.roundBet– Sets the base bet used for calculations such as win cap. Defaults to the player'scurrentBet.coinValue– Overrides the coin value for the round. Defaults to the player'scoinValue.
The RoundBehavior is the most important parameter because it defines how the manager and generator treat the incoming round:
RESTORE– Resumes a round that should play as fast as possible to catch up.RESTORE_NORMAL– Resumes a round but lets generators run at normal pace.NORMAL– Starts a regular round.REPLAY– Replays a finished round, typically for history views.
When requestRound() is called, the RoundManager creates a new RoundModel and RoundGenerator using these details.
Round Model
RoundModel is a per-round data object that records progress, timings, totals, and winnings. When values are missing in the details object, the model fetches them from the PlayerModel. The model instance is exposed through System.round and should be treated as read-only outside of managers. The RoundModel provides the following getters to read round information:
winCounter– Returns theWinCounterattached to this round.isInterrupted– Indicates whether an interrupt was triggered.isRoundActive– Indicates whether the round is currently running.roundDuration– Measures total elapsed time for the round.isPhaseActive– Indicates whether a phase timer is active.phaseDuration– Measures total elapsed time for the current phase.behavior– Gets or sets the activeRoundBehavior.startBalance– Returns the balance recorded at round start.finalBalance– Gets or sets the balance recorded after the round.roundWinCap– Calculates the maximum allowed win for the round.roundTotalBet– Returns the total currency spent on the round.roundTotalWin– Returns the accumulated winnings for the round.roundBet– Returns the base bet used for win and cap calculations.coinValue– Returns the coin value used during the round.
The round model creates a WinCounter per instance. The WinCounter accumulates currency winnings and dispatches model events when values change:
startCounter(value, duration?, easing?)– Adds winnings and optionally animates the increase.completeCounter()– Finishes the current tween and snaps to the target value.resetSpinCounter()– Clears the per-spin counter without affecting total wins.resetCounter()– Clears both counters.spinValue– Returns the current animated spin win.isWinCapReached– Indicates whether the configured win cap was hit.value– Returns the total win accumulated for the round.
Round State
Round state is a lightweight structure that tracks custom progress for your game. Each RoundManager defines its own shape, and a new state object is created for every round by createState().
The state instance is stored inside the RoundGenerator and must only be changed from the generator code. Round state is available via System.state property, which exposes the most recent read-only snapshot. Keep the state focused on gameplay-critical data such as active phase, remaining respins, or collected scatter count.
Round Generator
The RoundGenerator orchestrates backend calls and queues features for execution. Generators receive the round model, player model, and round state. Round generators can queue features at any time and return control to the runtime by resolving their promises. Four async hooks are available:
processRoundStart(queue)– Prepares the round before the first phase is processed.processRoundPhase(queue)– Adds features to the queue for the current phase and determines the next phase. Returntrueto schedule another phase, orfalseto transition toprocessRoundStop().processRoundStop(queue)– Finalizes the round and lets you dispatch outro features.processInterrupt(queue)– Adds features that gracefully stop the current phase when an interrupt is requested.
Generators typically queue backend-driven features that animate the spin, evaluate wins, and play outro content. You can swap generators at runtime by calling queue.changeGenerator(), but most games rely on a single generator per round.
Simple Round Generator Example
export class GameRoundGenerator extends RoundGenerator {
public override async processRoundPhase(queue:IFeatureQueue):Promise<boolean> {
queue.queueFeature(StartSpinFeature);
// Backend call is expected here
const response = await placeBet(this._round.roundBet);
queue.queueFeature(StopSpinFeature, {
symbolsList: response.symbolsList
});
queue.queueFeature(WinningFeature, {
paylinesList: response.paylinesList,
totalWin: response.totalWin
});
return false;
}
}