@energy8platform/game-engine 0.38.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/slot.d.ts CHANGED
@@ -366,6 +366,14 @@ declare function easingByName(name?: string): EasingFunction;
366
366
 
367
367
  /** Names of easing functions available in the engine's `Easing` map (see anim/easing-map.ts). */
368
368
  type EasingName = 'linear' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack' | 'easeOutBounce' | 'easeInBounce' | 'easeOutElastic' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine';
369
+ /**
370
+ * A value that is either flat across the board, or per-reel: an array indexed by REEL INDEX
371
+ * (holes fall back to the scalar default). Used for anticipation timings so a game can make
372
+ * each successive reel slower than the last.
373
+ */
374
+ type PerReel<T> = T | (T | undefined)[];
375
+ /** Resolve a `PerReel<T>` for one reel. `undefined` (or a hole in the array) yields `fallback`. */
376
+ declare function perReelValue<T>(value: PerReel<T> | undefined, reel: number, fallback: T): T;
369
377
  /** Win-evaluation model. Purely presentational here (affects geometry + highlight), the math lives in Lua. */
370
378
  type EvaluationMode = 'lines' | 'ways' | 'anywhere' | 'cluster' | 'megaways' | 'infinity';
371
379
  interface GridConfig {
@@ -403,6 +411,10 @@ interface GridConfig {
403
411
  }
404
412
  type MotionStyle = 'swap' | 'strip' | 'cascade-drop';
405
413
  type StopMode = 'sequential' | 'sync' | 'random';
414
+ /** `cascade-drop` fill direction within one reel. */
415
+ type DropOrder = 'top-down' | 'bottom-up';
416
+ /** How `cascade-drop` spaces reels: by formula, or one strictly after the other. */
417
+ type DropSequence = 'parallel' | 'chained' | 'chained-when-anticipated';
406
418
  type StopOrder = 'ltr' | 'rtl';
407
419
  type Intensity = 'full' | 'reduced' | 'minimal';
408
420
  interface SettleConfig {
@@ -448,6 +460,40 @@ interface MotionConfig {
448
460
  slamStop: boolean;
449
461
  /** Symbols visible on a reel tape while spinning (swap/strip). */
450
462
  symbolsPerReel: number;
463
+ /** `cascade-drop`: ms between consecutive cells of ONE reel (top→bottom). Default 24. */
464
+ cellStagger: number;
465
+ /** `cascade-drop`: multiplier on `stopStagger` for the per-reel offset. Default 0.4. */
466
+ reelStaggerFactor: number;
467
+ /** `cascade-drop`: fall duration as a fraction of `spinUp`. Default 0.6. */
468
+ dropFallFactor: number;
469
+ /**
470
+ * `cascade-drop`: which cell of a reel lands first. `'top-down'` (default, the engine's original
471
+ * behaviour) deals the reel like cards from the top; `'bottom-up'` fills it the way gravity
472
+ * would — the lowest cell arrives first and the rest stack on top of it.
473
+ */
474
+ dropOrder: DropOrder;
475
+ /**
476
+ * `cascade-drop`: how reels are spaced.
477
+ * - `'parallel'` (default) starts every reel at its own formula offset —
478
+ * `reel * stopStagger * reelStaggerFactor` — so a reel can open while the previous one is
479
+ * still dropping. Fast, and what a normal spin wants.
480
+ * - `'chained'` starts a reel only once the previous one has seated its LAST cell, plus that
481
+ * same offset as the gap. One reel at a time, always — correct, but it makes every spin as
482
+ * long as the sum of its reels.
483
+ * - `'chained-when-anticipated'` runs the un-armed reels in parallel and switches to the chain
484
+ * from the first ANTICIPATED reel onwards. The base spin keeps its stop window; the hunt for
485
+ * the last scatter goes strictly reel by reel, each slower than the last.
486
+ */
487
+ dropSequence: DropSequence;
488
+ }
489
+ /** What a game-supplied `AnticipationConfig.decide` may return instead of a bare reel list. */
490
+ interface AnticipationOverride {
491
+ /** Reels to anticipate, in the order the progression should ramp. Empty = no anticipation. */
492
+ reels: number[];
493
+ /** Speed factor (lower = slower). Scalar, or per-reel indexed by reel index. */
494
+ slowdown?: PerReel<number>;
495
+ /** Extra hold before landing. Scalar, or per-reel indexed by reel index. */
496
+ holdMs?: PerReel<number>;
451
497
  }
452
498
  interface AnticipationConfig {
453
499
  enabled: boolean;
@@ -461,6 +507,21 @@ interface AnticipationConfig {
461
507
  slowdownFactor: number;
462
508
  /** Extra hold (ms) before the final anticipation reel lands (300–500 typical). */
463
509
  holdMs: number;
510
+ /**
511
+ * Game-supplied decision, REPLACING the built-in `triggerSymbols`/`threshold` counting.
512
+ * Return the reels to anticipate (or an `AnticipationOverride`); `null` / `[]` = no anticipation.
513
+ * Use this when the trigger is not expressible as "N of symbol X landed" — e.g. "the round is
514
+ * still alive on every reel so far", or "reel 3 missed its symbol, so let 4 and 5 stop normally".
515
+ */
516
+ decide?: ((targetGrid: CellData[][]) => number[] | AnticipationOverride | null) | null;
517
+ /**
518
+ * Ramp the slowdown across successive anticipated reels: reel #i of the decision gets
519
+ * `slowdownFactor * progressiveSlowdown ** i`. 1 = flat (default); < 1 = each reel slower
520
+ * than the last.
521
+ */
522
+ progressiveSlowdown: number;
523
+ /** Extra hold (ms) added per successive anticipated reel: reel #i gets `holdMs + i * this`. */
524
+ progressiveHoldMs: number;
464
525
  /** Optional grid zoom while anticipating (magnum-opus uses 1.3×). */
465
526
  zoom: {
466
527
  enabled: boolean;
@@ -701,8 +762,25 @@ interface SpinRunOpts {
701
762
  turbo?: boolean;
702
763
  /** Reels to slow for anticipation (computed by the ReelSystem from config + targetGrid). */
703
764
  anticipateReels?: number[];
704
- anticipateSlowdown?: number;
705
- anticipateHoldMs?: number;
765
+ /** Speed factor for anticipated reels (lower = slower). Scalar, or per-reel indexed by reel. */
766
+ anticipateSlowdown?: PerReel<number>;
767
+ /** Extra hold (ms) for anticipated reels. Scalar, or per-reel indexed by reel. */
768
+ anticipateHoldMs?: PerReel<number>;
769
+ /**
770
+ * Reels whose tape runs normally but whose landing is NOT handed back. The engine stops and
771
+ * disposes of the tape as usual and leaves the real cells hidden and unseated; the caller owns
772
+ * their data and visibility from that point (and `skip()` will not reveal them either).
773
+ */
774
+ deferReveal?: number[];
775
+ /** The resolved schedule, handed over before the first frame runs. Schedule against THESE
776
+ * numbers rather than re-deriving `plan()`'s formula. */
777
+ onPlan?: (plan: ReelStopPlan[]) => void;
778
+ /** Fires on the frame a reel lands — after its cells are seated, before settle/squash/shake.
779
+ * For a deferred reel it still fires (the reel DID stop); nothing was seated. */
780
+ onReelStop?: (reel: number, plan: ReelStopPlan) => void;
781
+ /** Fires as each cell takes its landing symbol. In `cascade-drop` this is the per-cell impact
782
+ * frame (after the fall, before the squash) — the hook for a per-cell sound or shake. */
783
+ onCellSeated?: (reel: number, row: number, data: CellData) => void;
706
784
  }
707
785
  interface ReelStopPlan {
708
786
  reel: number;
@@ -714,6 +792,17 @@ interface ReelStopPlan {
714
792
  ms: number;
715
793
  };
716
794
  anticipated: boolean;
795
+ /** Time-stretch applied to this reel's tape (>= 1, longer = slower). 1 when not anticipated. */
796
+ slowdown: number;
797
+ /** True when `deferReveal` withheld this reel's landing (see `SpinRunOpts.deferReveal`). */
798
+ deferred: boolean;
799
+ /**
800
+ * `cascade-drop` only: ms from spin start at which each cell of this reel seats, INDEXED BY ROW.
801
+ * The reel's fill direction lives in these numbers (`motion.dropOrder` decides which row is the
802
+ * smallest), as does its place in the chain (`motion.dropSequence`). `stopTime` is the largest
803
+ * of them — the frame the whole reel has landed.
804
+ */
805
+ cellStopTimes?: number[];
717
806
  }
718
807
  declare class SpinEngine {
719
808
  private _grid;
@@ -723,6 +812,7 @@ declare class SpinEngine {
723
812
  private _killed;
724
813
  private _shaking;
725
814
  private _temp;
815
+ private _deferred;
726
816
  constructor(grid: ReelGrid, resolve: SymbolResolver, cfg: MotionConfig, win?: WinConfig);
727
817
  setConfig(cfg: MotionConfig): void;
728
818
  setWin(win: WinConfig): void;
@@ -731,10 +821,17 @@ declare class SpinEngine {
731
821
  private scale;
732
822
  /** PURE: per-reel stop schedule. No Pixi mutation. */
733
823
  plan(data: SpinData, opts?: SpinRunOpts): ReelStopPlan[];
824
+ /**
825
+ * `cascade-drop` lays its reels out on a different clock from the tape styles: a reel is a
826
+ * sequence of per-cell arrivals, not one deceleration. Overwrite `stopTime` with the moment the
827
+ * reel has fully landed and fill in `cellStopTimes`, so `plan()` stays the single source of truth
828
+ * for WHEN anything happens — `_runDrop` below only executes these numbers.
829
+ */
830
+ private _planDrop;
734
831
  /** Execute the spin for every reel concurrently. */
735
832
  run(data: SpinData, opts?: SpinRunOpts): Promise<void>;
736
833
  private _runReel;
737
- /** Anticipation time-stretch factor for a reel (>=1, longer = slower). */
834
+ /** Anticipation time-stretch factor for a reel (>=1, longer = slower). Resolved in `plan()`. */
738
835
  private slowOf;
739
836
  private _runSwap;
740
837
  private _runStrip;
@@ -750,10 +847,13 @@ declare class SpinEngine {
750
847
 
751
848
  interface AnticipationDecision {
752
849
  active: boolean;
753
- /** Reel indices that should spin slower / longer. */
850
+ /** Reel indices that should spin slower / longer, in the order the ramp applies. */
754
851
  reels: number[];
755
- slowdown: number;
756
- holdMs: number;
852
+ /** Speed factor. A scalar when flat; a per-reel array when the decision ramps (see
853
+ * `progressiveSlowdown` / a game-supplied `decide`). Resolve with `perReelValue`. */
854
+ slowdown: PerReel<number>;
855
+ /** Extra hold before landing. Scalar or per-reel array, same as `slowdown`. */
856
+ holdMs: PerReel<number>;
757
857
  }
758
858
  declare class AnticipationController {
759
859
  private _cfg;
@@ -767,6 +867,13 @@ declare class AnticipationController {
767
867
  * is flagged for the slow treatment (this mirrors "searching for the last scatter").
768
868
  */
769
869
  decide(targetGrid: CellData[][]): AnticipationDecision;
870
+ /** Assemble a decision, applying the configured progression unless the caller pinned values. */
871
+ private build;
872
+ /**
873
+ * A flat scalar when the progression is a no-op, else an array INDEXED BY REEL so the engine can
874
+ * read a per-reel value straight out of `plan()`.
875
+ */
876
+ private ramp;
770
877
  /** Optionally zoom the grid in while anticipating, then settle back. Returns a reset fn. */
771
878
  zoomIn(grid: ReelGrid): Promise<() => Promise<void>>;
772
879
  }
@@ -947,6 +1054,14 @@ interface ReelSystem {
947
1054
  /** Replace the whole config. */
948
1055
  setConfig(config: ReelSystemConfig): void;
949
1056
  spin(target: CellData[][], opts?: SpinRunOpts): Promise<void>;
1057
+ /**
1058
+ * The schedule `spin(target, opts)` WOULD run, without running it — same anticipation decision,
1059
+ * same numbers. Schedule landing sounds / camera moves against this instead of re-deriving the
1060
+ * engine's formula. (`spin`'s `onPlan` hands you the same array once the spin is under way.)
1061
+ */
1062
+ planSpin(target: CellData[][], opts?: SpinRunOpts): ReelStopPlan[];
1063
+ /** The anticipation decision `spin(target, opts)` would use (run options override the config). */
1064
+ anticipationFor(target: CellData[][], opts?: SpinRunOpts): AnticipationDecision;
950
1065
  /** Run a cascade chain. With `freeSpins` + `cascade.multiplier.persistInFreeSpins`, the multiplier
951
1066
  * carries over instead of resetting. Generic in the step type, so `onStep` hands back the game's
952
1067
  * own step (with its per-step win) rather than the bare TumbleStep. */
@@ -1056,5 +1171,5 @@ declare class MultiplierAccumulator {
1056
1171
  reset(boundary: CarryPolicy): void;
1057
1172
  }
1058
1173
 
1059
- export { AnimatedSymbol, AnticipationController, BigWinOverlay, CascadeController, CountUpDisplay, DEFAULT_REEL_CONFIG, EASING_BY_NAME, FEATURES, FEATURE_KEYS, FEATURE_LIST, INTENSITY_SCALE, MultiplierAccumulator, PRESETS, PRESET_LIST, ReelGrid, ReelSpinController, ReelStepController, SpinEngine, SymbolCell, TumbleController, buildReelStepTape, cellPositionOf, createReelSystem, easingByName, effectiveRowsPerReel, mergeReelConfig, pickTier, resolveGeometry, resolveGridGeometry, resolveReelConfig, tierIndexAtValue, valueAt, waysCount };
1060
- export type { AnimatedSymbolConfig, AnticipationConfig, AnticipationDecision, BigWinOverlayConfig, BlurConfig, CarryPolicy, CascadeAnim, CascadeConfig, CascadeStepData, CascadeTimings, CellData, CellFrameStyle, CellSizeSpec, CellState, CountUpConfig, CreateReelSystemOptions, DecorationConfig, DeepPartial, EasingName, EvaluationMode, ExpandingWildConfig, FeatureContext, FeatureKey, FeaturesConfig, GeometryInput, GiantConfig, GridConfig, HoldAndSpinConfig, Intensity, MotionConfig, MotionStyle, MultiplierConfig, MysteryConfig, NudgeConfig, PresetId, RandomWildConfig, ReelFeature, ReelGridConfig, ReelModifierConfig, ReelPreset, ReelSpinData, ReelSpinTimings, ReelStepData, ReelStopPlan$1 as ReelStopPlan, ReelSystem, ReelSystemConfig, ResolvedGeometry, SettleConfig, SpinData, SpinRunOpts, ReelStopPlan as SpinStopPlan, SplitConfig, SquashConfig, StackedConfig, StepRunOpts, StickyConfig, StopMode, StopOrder, SymbolCellConfig, SymbolResolver, SymbolTextures, SymbolView, TransformConfig, TumbleStep, WalkingWildConfig, WinConfig, WinTier };
1174
+ export { AnimatedSymbol, AnticipationController, BigWinOverlay, CascadeController, CountUpDisplay, DEFAULT_REEL_CONFIG, EASING_BY_NAME, FEATURES, FEATURE_KEYS, FEATURE_LIST, INTENSITY_SCALE, MultiplierAccumulator, PRESETS, PRESET_LIST, ReelGrid, ReelSpinController, ReelStepController, SpinEngine, SymbolCell, TumbleController, buildReelStepTape, cellPositionOf, createReelSystem, easingByName, effectiveRowsPerReel, mergeReelConfig, perReelValue, pickTier, resolveGeometry, resolveGridGeometry, resolveReelConfig, tierIndexAtValue, valueAt, waysCount };
1175
+ export type { AnimatedSymbolConfig, AnticipationConfig, AnticipationDecision, AnticipationOverride, BigWinOverlayConfig, BlurConfig, CarryPolicy, CascadeAnim, CascadeConfig, CascadeStepData, CascadeTimings, CellData, CellFrameStyle, CellSizeSpec, CellState, CountUpConfig, CreateReelSystemOptions, DecorationConfig, DeepPartial, DropOrder, DropSequence, EasingName, EvaluationMode, ExpandingWildConfig, FeatureContext, FeatureKey, FeaturesConfig, GeometryInput, GiantConfig, GridConfig, HoldAndSpinConfig, Intensity, MotionConfig, MotionStyle, MultiplierConfig, MysteryConfig, NudgeConfig, PerReel, PresetId, RandomWildConfig, ReelFeature, ReelGridConfig, ReelModifierConfig, ReelPreset, ReelSpinData, ReelSpinTimings, ReelStepData, ReelStopPlan$1 as ReelStopPlan, ReelSystem, ReelSystemConfig, ResolvedGeometry, SettleConfig, SpinData, SpinRunOpts, ReelStopPlan as SpinStopPlan, SplitConfig, SquashConfig, StackedConfig, StepRunOpts, StickyConfig, StopMode, StopOrder, SymbolCellConfig, SymbolResolver, SymbolTextures, SymbolView, TransformConfig, TumbleStep, WalkingWildConfig, WinConfig, WinTier };