@energy8platform/game-engine 0.20.0 → 0.22.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/README.md +121 -0
- package/dist/animation.cjs.js +18 -3
- package/dist/animation.cjs.js.map +1 -1
- package/dist/animation.esm.js +18 -3
- package/dist/animation.esm.js.map +1 -1
- package/dist/core.cjs.js +18 -3
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.esm.js +18 -3
- package/dist/core.esm.js.map +1 -1
- package/dist/host.cjs.js +18 -3
- package/dist/host.cjs.js.map +1 -1
- package/dist/host.d.ts +3 -5
- package/dist/host.esm.js +18 -3
- package/dist/host.esm.js.map +1 -1
- package/dist/index.cjs.js +18 -2535
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -1020
- package/dist/index.esm.js +20 -2525
- package/dist/index.esm.js.map +1 -1
- package/dist/slot.cjs.js +1872 -61
- package/dist/slot.cjs.js.map +1 -1
- package/dist/slot.d.ts +555 -28
- package/dist/slot.esm.js +1857 -62
- package/dist/slot.esm.js.map +1 -1
- package/dist/vite.cjs.js +0 -5
- package/dist/vite.cjs.js.map +1 -1
- package/dist/vite.esm.js +0 -5
- package/dist/vite.esm.js.map +1 -1
- package/package.json +2 -35
- package/src/animation/Tween.ts +14 -3
- package/src/host/index.ts +0 -1
- package/src/host/types.ts +0 -3
- package/src/index.ts +0 -28
- package/src/slot/anim/easing-map.ts +16 -2
- package/src/slot/cascade/TumbleController.ts +230 -0
- package/src/slot/config/ReelSystemConfig.ts +559 -0
- package/src/slot/config/presets.ts +222 -0
- package/src/slot/features/extra.ts +189 -0
- package/src/slot/features/index.ts +44 -0
- package/src/slot/features/symbols.ts +183 -0
- package/src/slot/features/types.ts +136 -0
- package/src/slot/features/wilds.ts +151 -0
- package/src/slot/grid/ReelGrid.ts +93 -24
- package/src/slot/grid/SymbolCell.ts +45 -11
- package/src/slot/index.ts +61 -2
- package/src/slot/motion/AnticipationController.ts +96 -0
- package/src/slot/motion/SpinEngine.ts +384 -0
- package/src/slot/system/ReelSystem.ts +295 -0
- package/src/vite/index.ts +0 -5
- package/dist/react-jsx.cjs.js +0 -3
- package/dist/react-jsx.cjs.js.map +0 -1
- package/dist/react-jsx.d.ts +0 -602
- package/dist/react-jsx.esm.js +0 -2
- package/dist/react-jsx.esm.js.map +0 -1
- package/dist/react.cjs.js +0 -3787
- package/dist/react.cjs.js.map +0 -1
- package/dist/react.d.ts +0 -1467
- package/dist/react.esm.js +0 -3771
- package/dist/react.esm.js.map +0 -1
- package/dist/ui.cjs.js +0 -2999
- package/dist/ui.cjs.js.map +0 -1
- package/dist/ui.d.ts +0 -1116
- package/dist/ui.esm.js +0 -2983
- package/dist/ui.esm.js.map +0 -1
- package/src/react/EngineContext.ts +0 -26
- package/src/react/ReactScene.ts +0 -88
- package/src/react/applyProps.ts +0 -271
- package/src/react/catalogue.ts +0 -17
- package/src/react/createPixiRoot.ts +0 -31
- package/src/react/extendAll.ts +0 -74
- package/src/react/hooks.ts +0 -46
- package/src/react/index.ts +0 -29
- package/src/react/jsx-runtime.ts +0 -346
- package/src/react/reconciler.ts +0 -338
- package/src/slot/freeSpins/FreeSpinsSession.ts +0 -40
- package/src/state/StateMachine.ts +0 -231
- package/src/state/index.ts +0 -1
- package/src/ui/BalanceDisplay.ts +0 -159
- package/src/ui/Button.ts +0 -304
- package/src/ui/FlexContainer.ts +0 -775
- package/src/ui/Label.ts +0 -124
- package/src/ui/LabelValue.ts +0 -122
- package/src/ui/Layout.ts +0 -291
- package/src/ui/Modal.ts +0 -170
- package/src/ui/Panel.ts +0 -204
- package/src/ui/ProgressBar.ts +0 -170
- package/src/ui/ScrollContainer.ts +0 -478
- package/src/ui/Slider.ts +0 -241
- package/src/ui/Toast.ts +0 -150
- package/src/ui/Toggle.ts +0 -201
- package/src/ui/WinDisplay.ts +0 -145
- package/src/ui/index.ts +0 -33
- package/src/ui/view.ts +0 -28
package/dist/slot.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Container, Texture, TextStyle } from 'pixi.js';
|
|
2
|
-
import { SlotSpinResultBase } from '@energy8platform/platform-core/slot-result';
|
|
3
2
|
|
|
4
3
|
/** A symbol's visual. Any Container; optionally implements the lifecycle the cell drives. */
|
|
5
4
|
interface SymbolView extends Container {
|
|
@@ -106,7 +105,10 @@ interface DecorationConfig {
|
|
|
106
105
|
}
|
|
107
106
|
interface ReelGridConfig {
|
|
108
107
|
cols: number;
|
|
108
|
+
/** Uniform row count. Ignored per-reel when `rowsPerReel` is provided. */
|
|
109
109
|
rows: number;
|
|
110
|
+
/** Per-reel row counts for Megaways / variable-height reels. Length must equal `cols`. */
|
|
111
|
+
rowsPerReel?: number[];
|
|
110
112
|
cellSize: number;
|
|
111
113
|
gap?: number;
|
|
112
114
|
resolve: SymbolResolver;
|
|
@@ -114,23 +116,40 @@ interface ReelGridConfig {
|
|
|
114
116
|
decoration?: DecorationConfig;
|
|
115
117
|
mask?: boolean;
|
|
116
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* A grid of `SymbolCell`s. Supports uniform grids and variable-height reels (Megaways):
|
|
121
|
+
* when `rowsPerReel` is set each reel is vertically centred inside the tallest reel's envelope.
|
|
122
|
+
*/
|
|
117
123
|
declare class ReelGrid extends Container {
|
|
118
124
|
readonly __uiComponent: true;
|
|
119
125
|
private _cols;
|
|
120
|
-
private
|
|
126
|
+
private _rowsPerReel;
|
|
127
|
+
private _maxRows;
|
|
121
128
|
private _cellSize;
|
|
122
129
|
private _gap;
|
|
123
130
|
private _cells;
|
|
124
131
|
private _cellLayer;
|
|
132
|
+
private _resolve;
|
|
133
|
+
private _frameStyle?;
|
|
134
|
+
private _mask;
|
|
125
135
|
constructor(config: ReelGridConfig);
|
|
136
|
+
private _buildCells;
|
|
137
|
+
private _applyMask;
|
|
126
138
|
get cols(): number;
|
|
139
|
+
/** Tallest reel's row count (the grid's visual height in rows). */
|
|
127
140
|
get rows(): number;
|
|
141
|
+
get cellSize(): number;
|
|
142
|
+
rowsOf(col: number): number;
|
|
143
|
+
get rowsPerReel(): number[];
|
|
144
|
+
/** Cell centre position. Variable-height reels are centred in the max-rows envelope. */
|
|
128
145
|
cellPosition(col: number, row: number): {
|
|
129
146
|
x: number;
|
|
130
147
|
y: number;
|
|
131
148
|
};
|
|
132
149
|
getCell(col: number, row: number): SymbolCell;
|
|
133
150
|
setGrid(cells: CellData[][]): void;
|
|
151
|
+
/** Rebuild the grid with new per-reel row counts (Megaways re-roll / dynamic rows). */
|
|
152
|
+
reshape(rowsPerReel: number[]): void;
|
|
134
153
|
resize(cellSize: number): void;
|
|
135
154
|
}
|
|
136
155
|
|
|
@@ -204,7 +223,7 @@ interface ReelSpinTimings {
|
|
|
204
223
|
stopStagger: number;
|
|
205
224
|
settle: number;
|
|
206
225
|
}
|
|
207
|
-
interface ReelStopPlan {
|
|
226
|
+
interface ReelStopPlan$1 {
|
|
208
227
|
reel: number;
|
|
209
228
|
stopTime: number;
|
|
210
229
|
landing: CellData[];
|
|
@@ -221,7 +240,7 @@ declare class ReelSpinController {
|
|
|
221
240
|
/** PURE: per-reel stop timing + landing window. No Pixi mutation. */
|
|
222
241
|
plan(data: ReelSpinData, opts?: {
|
|
223
242
|
turbo?: boolean;
|
|
224
|
-
}): ReelStopPlan[];
|
|
243
|
+
}): ReelStopPlan$1[];
|
|
225
244
|
/** Execute the spin: scroll each reel, decelerate, land on target, settle-bounce. Not unit-tested. */
|
|
226
245
|
run(data: ReelSpinData, opts?: {
|
|
227
246
|
turbo?: boolean;
|
|
@@ -230,6 +249,536 @@ declare class ReelSpinController {
|
|
|
230
249
|
skip(): void;
|
|
231
250
|
}
|
|
232
251
|
|
|
252
|
+
type EasingFunction = (t: number) => number;
|
|
253
|
+
|
|
254
|
+
/** Resolve a descriptor's string easing name to the engine's easing function. */
|
|
255
|
+
declare const EASING_BY_NAME: Record<string, EasingFunction>;
|
|
256
|
+
/** Resolve an easing name to a function, falling back to easeOutQuad. */
|
|
257
|
+
declare function easingByName(name?: string): EasingFunction;
|
|
258
|
+
|
|
259
|
+
/** Names of easing functions available in the engine's `Easing` map (see anim/easing-map.ts). */
|
|
260
|
+
type EasingName = 'linear' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack' | 'easeOutBounce' | 'easeInBounce' | 'easeOutElastic' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine';
|
|
261
|
+
/** Win-evaluation model. Purely presentational here (affects geometry + highlight), the math lives in Lua. */
|
|
262
|
+
type EvaluationMode = 'lines' | 'ways' | 'anywhere' | 'cluster' | 'megaways' | 'infinity';
|
|
263
|
+
interface GridConfig {
|
|
264
|
+
cols: number;
|
|
265
|
+
/** Uniform row count. Ignored when `rowsPerReel` is set. */
|
|
266
|
+
rows: number;
|
|
267
|
+
/** Per-reel row counts (Megaways / variable-height reels). Length should equal `cols`. */
|
|
268
|
+
rowsPerReel?: number[];
|
|
269
|
+
cellSize: number;
|
|
270
|
+
gap: number;
|
|
271
|
+
evaluation: EvaluationMode;
|
|
272
|
+
/** For Megaways: clamp per-reel rows to [minRows, maxRows]. */
|
|
273
|
+
minRows?: number;
|
|
274
|
+
maxRows?: number;
|
|
275
|
+
/** Megaways top horizontal reel (renders above the grid, adds to ways). */
|
|
276
|
+
topReel?: {
|
|
277
|
+
size: number;
|
|
278
|
+
} | null;
|
|
279
|
+
mask: boolean;
|
|
280
|
+
frameStyle?: CellFrameStyle;
|
|
281
|
+
decoration?: {
|
|
282
|
+
padding?: number;
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
type MotionStyle = 'swap' | 'strip' | 'cascade-drop';
|
|
286
|
+
type StopMode = 'sequential' | 'sync' | 'random';
|
|
287
|
+
type StopOrder = 'ltr' | 'rtl';
|
|
288
|
+
type Intensity = 'full' | 'reduced' | 'minimal';
|
|
289
|
+
interface SettleConfig {
|
|
290
|
+
/** Overshoot amplitude in px applied to the reel before it springs back. */
|
|
291
|
+
amp: number;
|
|
292
|
+
ms: number;
|
|
293
|
+
easing: EasingName;
|
|
294
|
+
}
|
|
295
|
+
/** Squash & stretch on landing impact (Stone-Rush / magnus style). */
|
|
296
|
+
interface SquashConfig {
|
|
297
|
+
enabled: boolean;
|
|
298
|
+
scaleX: number;
|
|
299
|
+
scaleY: number;
|
|
300
|
+
ms: number;
|
|
301
|
+
}
|
|
302
|
+
interface BlurConfig {
|
|
303
|
+
enabled: boolean;
|
|
304
|
+
/** Alpha applied to in-motion symbols (hot-ross uses 0.82). */
|
|
305
|
+
alpha: number;
|
|
306
|
+
/** Runtime BlurFilter strength factor (PixiJS slots demo uses ~8), 0 disables the filter. */
|
|
307
|
+
strength: number;
|
|
308
|
+
/** Draw vertical motion streaks behind moving symbols. */
|
|
309
|
+
streaks: boolean;
|
|
310
|
+
}
|
|
311
|
+
interface MotionConfig {
|
|
312
|
+
style: MotionStyle;
|
|
313
|
+
/** Base spin-up duration (ms) before the first reel can stop. */
|
|
314
|
+
spinUp: number;
|
|
315
|
+
/** Extra hold (ms) at full speed before deceleration. */
|
|
316
|
+
hold: number;
|
|
317
|
+
/** Delay (ms) between consecutive reel stops in sequential mode. */
|
|
318
|
+
stopStagger: number;
|
|
319
|
+
stopMode: StopMode;
|
|
320
|
+
stopOrder: StopOrder;
|
|
321
|
+
settle: SettleConfig;
|
|
322
|
+
squash: SquashConfig;
|
|
323
|
+
blur: BlurConfig;
|
|
324
|
+
/** Multiply all durations in turbo mode (0.5 = twice as fast). */
|
|
325
|
+
turboFactor: number;
|
|
326
|
+
/** Global animation-intensity scale (accessibility): full=1, reduced=0.7, minimal=0.4. */
|
|
327
|
+
intensity: Intensity;
|
|
328
|
+
/** Allow slam/quick-stop (snaps reels to target without changing outcome). */
|
|
329
|
+
slamStop: boolean;
|
|
330
|
+
/** Symbols visible on a reel tape while spinning (swap/strip). */
|
|
331
|
+
symbolsPerReel: number;
|
|
332
|
+
}
|
|
333
|
+
interface AnticipationConfig {
|
|
334
|
+
enabled: boolean;
|
|
335
|
+
/** Symbols that count toward the anticipation threshold (scatter/bonus). */
|
|
336
|
+
triggerSymbols: string[];
|
|
337
|
+
/** Number of trigger symbols already landed that arms anticipation (N−1, usually 2). */
|
|
338
|
+
threshold: number;
|
|
339
|
+
/** Which reels get the slow treatment: the still-spinning trailing reels, or explicit indices. */
|
|
340
|
+
reels: 'trailing' | number[];
|
|
341
|
+
/** Multiply the trailing reel's spin speed (lower = slower / longer). */
|
|
342
|
+
slowdownFactor: number;
|
|
343
|
+
/** Extra hold (ms) before the final anticipation reel lands (300–500 typical). */
|
|
344
|
+
holdMs: number;
|
|
345
|
+
/** Optional grid zoom while anticipating (magnum-opus uses 1.3×). */
|
|
346
|
+
zoom: {
|
|
347
|
+
enabled: boolean;
|
|
348
|
+
scale: number;
|
|
349
|
+
ms: number;
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
interface CascadeConfig {
|
|
353
|
+
enabled: boolean;
|
|
354
|
+
/** Animate surviving symbols sliding down into the gaps (true tumble). */
|
|
355
|
+
gravity: boolean;
|
|
356
|
+
timings: {
|
|
357
|
+
reveal: number;
|
|
358
|
+
highlight: number;
|
|
359
|
+
remove: number;
|
|
360
|
+
drop: number;
|
|
361
|
+
refill: number;
|
|
362
|
+
wait: number;
|
|
363
|
+
};
|
|
364
|
+
easings: {
|
|
365
|
+
highlight: EasingName;
|
|
366
|
+
remove: EasingName;
|
|
367
|
+
drop: EasingName;
|
|
368
|
+
};
|
|
369
|
+
/** Slow each successive cascade step to build tension: factor = 1 + step*perStepDecel (capped). */
|
|
370
|
+
perStepDecel: number;
|
|
371
|
+
perStepDecelCap: number;
|
|
372
|
+
/** Dim non-winning symbols during the highlight phase. */
|
|
373
|
+
dimNonWinners: boolean;
|
|
374
|
+
dimAlpha: number;
|
|
375
|
+
/** Running win multiplier that climbs per cascade (Pragmatic Tumble / Avalanche). */
|
|
376
|
+
multiplier: {
|
|
377
|
+
enabled: boolean;
|
|
378
|
+
start: number;
|
|
379
|
+
/** 'add' → +step each step; 'mul' → ×step each step. */
|
|
380
|
+
mode: 'add' | 'mul';
|
|
381
|
+
step: number;
|
|
382
|
+
cap: number | null;
|
|
383
|
+
/** Keep climbing across free-spins instead of resetting per spin. */
|
|
384
|
+
persistInFreeSpins: boolean;
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
interface WinConfig {
|
|
388
|
+
highlightScale: number;
|
|
389
|
+
glow: boolean;
|
|
390
|
+
/** Frame shake on landing/win. */
|
|
391
|
+
frameShake: {
|
|
392
|
+
enabled: boolean;
|
|
393
|
+
amp: number;
|
|
394
|
+
ms: number;
|
|
395
|
+
onlyOnSymbols: string[] | null;
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
interface ExpandingWildConfig {
|
|
399
|
+
enabled: boolean;
|
|
400
|
+
symbol: string;
|
|
401
|
+
/** Reels that may host an expanding wild (empty = all). */
|
|
402
|
+
reels: number[];
|
|
403
|
+
/** Expand to the full reel height. */
|
|
404
|
+
toFullReel: boolean;
|
|
405
|
+
ms: number;
|
|
406
|
+
easing: EasingName;
|
|
407
|
+
onlyInFreeSpins: boolean;
|
|
408
|
+
}
|
|
409
|
+
interface StickyConfig {
|
|
410
|
+
enabled: boolean;
|
|
411
|
+
symbols: string[];
|
|
412
|
+
/** How many spins a sticky symbol persists (0 = whole feature/bonus). */
|
|
413
|
+
durationSpins: number;
|
|
414
|
+
/** Ring colour drawn around sticky cells. */
|
|
415
|
+
ringColor: number;
|
|
416
|
+
}
|
|
417
|
+
interface WalkingWildConfig {
|
|
418
|
+
enabled: boolean;
|
|
419
|
+
symbol: string;
|
|
420
|
+
direction: 'left' | 'right';
|
|
421
|
+
stepPerSpin: number;
|
|
422
|
+
awardsRespin: boolean;
|
|
423
|
+
asStacked: boolean;
|
|
424
|
+
}
|
|
425
|
+
interface MultiplierConfig {
|
|
426
|
+
enabled: boolean;
|
|
427
|
+
/** Multiplier symbol id (carries a value), or null when multipliers are per-cell data. */
|
|
428
|
+
symbol: string | null;
|
|
429
|
+
scope: 'perSymbol' | 'perReel' | 'global';
|
|
430
|
+
combine: 'additive' | 'multiplicative';
|
|
431
|
+
attachedToWild: boolean;
|
|
432
|
+
max: number;
|
|
433
|
+
accumulateAcrossFreeSpins: boolean;
|
|
434
|
+
}
|
|
435
|
+
interface MysteryConfig {
|
|
436
|
+
enabled: boolean;
|
|
437
|
+
symbol: string;
|
|
438
|
+
/** Eligible reveal targets; all mystery tiles reveal the SAME single draw per spin. */
|
|
439
|
+
revealPool: string[];
|
|
440
|
+
canRevealWild: boolean;
|
|
441
|
+
ms: number;
|
|
442
|
+
}
|
|
443
|
+
interface TransformConfig {
|
|
444
|
+
enabled: boolean;
|
|
445
|
+
/** Trigger symbol whose landing fires the transform (null = data-driven). */
|
|
446
|
+
trigger: string | null;
|
|
447
|
+
/** 'randomLow' picks one low symbol at random; or pin a specific source. */
|
|
448
|
+
source: 'randomLow' | string;
|
|
449
|
+
target: string;
|
|
450
|
+
/** Convert every instance of the source symbol. */
|
|
451
|
+
allInstances: boolean;
|
|
452
|
+
/** Restrict to low→high (upgrade) direction. */
|
|
453
|
+
upgradeOnly: boolean;
|
|
454
|
+
ms: number;
|
|
455
|
+
}
|
|
456
|
+
interface GiantConfig {
|
|
457
|
+
enabled: boolean;
|
|
458
|
+
/** Footprint in cells. */
|
|
459
|
+
width: number;
|
|
460
|
+
height: number;
|
|
461
|
+
/** Symbols that may appear giant (empty = any). */
|
|
462
|
+
symbols: string[];
|
|
463
|
+
/** Pick one giant symbol type per spin. */
|
|
464
|
+
chosenPerSpin: boolean;
|
|
465
|
+
onlyInFreeSpins: boolean;
|
|
466
|
+
}
|
|
467
|
+
interface SplitConfig {
|
|
468
|
+
enabled: boolean;
|
|
469
|
+
symbol: string;
|
|
470
|
+
factor: number;
|
|
471
|
+
/** Reels that can host the split trigger (xSplit lands on the last reel). */
|
|
472
|
+
reels: number[];
|
|
473
|
+
/** Defer the split execution until all respins finish. */
|
|
474
|
+
deferUntilRespinsEnd: boolean;
|
|
475
|
+
}
|
|
476
|
+
interface StackedConfig {
|
|
477
|
+
enabled: boolean;
|
|
478
|
+
symbols: string[];
|
|
479
|
+
/** Max stack height (positions of the same symbol on one reel). */
|
|
480
|
+
height: number;
|
|
481
|
+
}
|
|
482
|
+
interface NudgeConfig {
|
|
483
|
+
enabled: boolean;
|
|
484
|
+
/** Reels eligible to nudge. */
|
|
485
|
+
reels: number[];
|
|
486
|
+
step: number;
|
|
487
|
+
/** xNudge: nudge a stacked wild into full view, +1 multiplier per nudge. */
|
|
488
|
+
toFullReel: boolean;
|
|
489
|
+
multiplierStart: number;
|
|
490
|
+
multiplierPerNudge: number;
|
|
491
|
+
}
|
|
492
|
+
interface ReelModifierConfig {
|
|
493
|
+
enabled: boolean;
|
|
494
|
+
/** Random pre-spin modifiers, each with a trigger weight. */
|
|
495
|
+
pool: {
|
|
496
|
+
effect: 'addRows' | 'addWilds' | 'setGiant' | 'guaranteedWilds';
|
|
497
|
+
magnitude: number;
|
|
498
|
+
weight: number;
|
|
499
|
+
}[];
|
|
500
|
+
appliesIn: 'base' | 'freeSpins' | 'both';
|
|
501
|
+
}
|
|
502
|
+
interface HoldAndSpinConfig {
|
|
503
|
+
enabled: boolean;
|
|
504
|
+
lockSymbols: string[];
|
|
505
|
+
triggerThreshold: number;
|
|
506
|
+
respinsAwarded: number;
|
|
507
|
+
/** Reset the respin counter to full whenever a new symbol locks. */
|
|
508
|
+
resetOnNewSymbol: boolean;
|
|
509
|
+
jackpotTiers: string[];
|
|
510
|
+
fullGridAwardsGrand: boolean;
|
|
511
|
+
}
|
|
512
|
+
interface RandomWildConfig {
|
|
513
|
+
enabled: boolean;
|
|
514
|
+
/** Fixed count, or [min,max] range. */
|
|
515
|
+
count: number | [number, number];
|
|
516
|
+
sticky: boolean;
|
|
517
|
+
multiplier: number;
|
|
518
|
+
trigger: 'randomBaseSpin' | 'onFreeSpins';
|
|
519
|
+
chance: number;
|
|
520
|
+
}
|
|
521
|
+
interface FeaturesConfig {
|
|
522
|
+
expandingWild: ExpandingWildConfig;
|
|
523
|
+
sticky: StickyConfig;
|
|
524
|
+
walkingWild: WalkingWildConfig;
|
|
525
|
+
multiplier: MultiplierConfig;
|
|
526
|
+
mystery: MysteryConfig;
|
|
527
|
+
transform: TransformConfig;
|
|
528
|
+
giant: GiantConfig;
|
|
529
|
+
split: SplitConfig;
|
|
530
|
+
stacked: StackedConfig;
|
|
531
|
+
nudge: NudgeConfig;
|
|
532
|
+
reelModifier: ReelModifierConfig;
|
|
533
|
+
holdAndSpin: HoldAndSpinConfig;
|
|
534
|
+
randomWild: RandomWildConfig;
|
|
535
|
+
}
|
|
536
|
+
/** Ordered list of feature keys (resolve order matters; see docs §3.4). */
|
|
537
|
+
type FeatureKey = keyof FeaturesConfig;
|
|
538
|
+
declare const FEATURE_KEYS: FeatureKey[];
|
|
539
|
+
interface ReelSystemConfig {
|
|
540
|
+
grid: GridConfig;
|
|
541
|
+
motion: MotionConfig;
|
|
542
|
+
anticipation: AnticipationConfig;
|
|
543
|
+
cascade: CascadeConfig;
|
|
544
|
+
win: WinConfig;
|
|
545
|
+
features: FeaturesConfig;
|
|
546
|
+
}
|
|
547
|
+
/** Deep-partial helper for overrides. */
|
|
548
|
+
type DeepPartial<T> = {
|
|
549
|
+
[K in keyof T]?: T[K] extends (infer U)[] ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
550
|
+
};
|
|
551
|
+
declare const DEFAULT_REEL_CONFIG: ReelSystemConfig;
|
|
552
|
+
/** Intensity → duration scale (accessibility). */
|
|
553
|
+
declare const INTENSITY_SCALE: Record<Intensity, number>;
|
|
554
|
+
/** Deep-merge `partial` onto `base` (arrays replace, objects merge). Returns a new object. */
|
|
555
|
+
declare function mergeReelConfig<T>(base: T, partial?: DeepPartial<T>): T;
|
|
556
|
+
/** Resolve a partial config to a fully-populated `ReelSystemConfig`. */
|
|
557
|
+
declare function resolveReelConfig(partial?: DeepPartial<ReelSystemConfig>): ReelSystemConfig;
|
|
558
|
+
/** Effective per-reel row counts (resolves Megaways `rowsPerReel`, else uniform `rows`). */
|
|
559
|
+
declare function effectiveRowsPerReel(grid: GridConfig): number[];
|
|
560
|
+
/** Total ways-to-win for a ways/megaways grid (product of per-reel heights). */
|
|
561
|
+
declare function waysCount(grid: GridConfig): number;
|
|
562
|
+
|
|
563
|
+
type PresetId = 'classic' | 'kitsune-wrath' | 'moon-spice' | 'stone-rush' | 'hot-ross' | 'magnus' | 'megaways';
|
|
564
|
+
interface ReelPreset {
|
|
565
|
+
id: PresetId;
|
|
566
|
+
name: string;
|
|
567
|
+
note: string;
|
|
568
|
+
config: DeepPartial<ReelSystemConfig>;
|
|
569
|
+
}
|
|
570
|
+
declare const PRESETS: Record<PresetId, ReelPreset>;
|
|
571
|
+
declare const PRESET_LIST: ReelPreset[];
|
|
572
|
+
|
|
573
|
+
interface SpinData {
|
|
574
|
+
/** Target board: targetGrid[col][row]. */
|
|
575
|
+
targetGrid: CellData[][];
|
|
576
|
+
/** Optional per-reel symbol tape for the spinning illusion (defaults to random of the landing symbols). */
|
|
577
|
+
strip?: (reel: number) => string[];
|
|
578
|
+
}
|
|
579
|
+
interface SpinRunOpts {
|
|
580
|
+
turbo?: boolean;
|
|
581
|
+
/** Reels to slow for anticipation (computed by the ReelSystem from config + targetGrid). */
|
|
582
|
+
anticipateReels?: number[];
|
|
583
|
+
anticipateSlowdown?: number;
|
|
584
|
+
anticipateHoldMs?: number;
|
|
585
|
+
}
|
|
586
|
+
interface ReelStopPlan {
|
|
587
|
+
reel: number;
|
|
588
|
+
/** Wall-clock time (ms) from spin start when this reel stops. */
|
|
589
|
+
stopTime: number;
|
|
590
|
+
landing: CellData[];
|
|
591
|
+
settle: {
|
|
592
|
+
amp: number;
|
|
593
|
+
ms: number;
|
|
594
|
+
};
|
|
595
|
+
anticipated: boolean;
|
|
596
|
+
}
|
|
597
|
+
declare class SpinEngine {
|
|
598
|
+
private _grid;
|
|
599
|
+
private _resolve;
|
|
600
|
+
private _cfg;
|
|
601
|
+
private _win;
|
|
602
|
+
private _killed;
|
|
603
|
+
private _shaking;
|
|
604
|
+
private _temp;
|
|
605
|
+
constructor(grid: ReelGrid, resolve: SymbolResolver, cfg: MotionConfig, win?: WinConfig);
|
|
606
|
+
setConfig(cfg: MotionConfig): void;
|
|
607
|
+
setWin(win: WinConfig): void;
|
|
608
|
+
/** Quick decaying frame shake when a landed reel carries a configured trigger symbol. */
|
|
609
|
+
private _frameShake;
|
|
610
|
+
private scale;
|
|
611
|
+
/** PURE: per-reel stop schedule. No Pixi mutation. */
|
|
612
|
+
plan(data: SpinData, opts?: SpinRunOpts): ReelStopPlan[];
|
|
613
|
+
/** Execute the spin for every reel concurrently. */
|
|
614
|
+
run(data: SpinData, opts?: SpinRunOpts): Promise<void>;
|
|
615
|
+
private _runReel;
|
|
616
|
+
/** Anticipation time-stretch factor for a reel (>=1, longer = slower). */
|
|
617
|
+
private slowOf;
|
|
618
|
+
private _runSwap;
|
|
619
|
+
private _runStrip;
|
|
620
|
+
private _runDrop;
|
|
621
|
+
private _settle;
|
|
622
|
+
private _squashCell;
|
|
623
|
+
/** Apply motion blur (alpha + optional BlurFilter) to targets; returns a disposer that clears it. */
|
|
624
|
+
private _applyBlur;
|
|
625
|
+
private _cleanupTemp;
|
|
626
|
+
/** Slam / quick stop: snap everything to the target and stop animating. */
|
|
627
|
+
skip(): void;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
interface AnticipationDecision {
|
|
631
|
+
active: boolean;
|
|
632
|
+
/** Reel indices that should spin slower / longer. */
|
|
633
|
+
reels: number[];
|
|
634
|
+
slowdown: number;
|
|
635
|
+
holdMs: number;
|
|
636
|
+
}
|
|
637
|
+
declare class AnticipationController {
|
|
638
|
+
private _cfg;
|
|
639
|
+
constructor(cfg: AnticipationConfig);
|
|
640
|
+
setConfig(cfg: AnticipationConfig): void;
|
|
641
|
+
/** Count how many trigger symbols land on a given reel. */
|
|
642
|
+
private countOnReel;
|
|
643
|
+
/**
|
|
644
|
+
* Decide anticipation from the landing grid. Trigger symbols are counted left→right;
|
|
645
|
+
* once the running total reaches `threshold`, every still-spinning reel after that point
|
|
646
|
+
* is flagged for the slow treatment (this mirrors "searching for the last scatter").
|
|
647
|
+
*/
|
|
648
|
+
decide(targetGrid: CellData[][]): AnticipationDecision;
|
|
649
|
+
/** Optionally zoom the grid in while anticipating, then settle back. Returns a reset fn. */
|
|
650
|
+
zoomIn(grid: ReelGrid): Promise<() => Promise<void>>;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
interface TumbleStep {
|
|
654
|
+
winningCells: {
|
|
655
|
+
col: number;
|
|
656
|
+
row: number;
|
|
657
|
+
}[];
|
|
658
|
+
removedCells: {
|
|
659
|
+
col: number;
|
|
660
|
+
row: number;
|
|
661
|
+
}[];
|
|
662
|
+
/** Optional explicit survivor slides (col, fromRow→toRow). When omitted, gravity is derived. */
|
|
663
|
+
drops?: {
|
|
664
|
+
col: number;
|
|
665
|
+
fromRow: number;
|
|
666
|
+
toRow: number;
|
|
667
|
+
}[];
|
|
668
|
+
newCells: {
|
|
669
|
+
col: number;
|
|
670
|
+
row: number;
|
|
671
|
+
symbol: string;
|
|
672
|
+
}[];
|
|
673
|
+
settledGrid: CellData[][];
|
|
674
|
+
}
|
|
675
|
+
declare class TumbleController {
|
|
676
|
+
private _grid;
|
|
677
|
+
private _cfg;
|
|
678
|
+
private _win;
|
|
679
|
+
private _killed;
|
|
680
|
+
private _mult;
|
|
681
|
+
constructor(grid: ReelGrid, cfg: CascadeConfig, win?: WinConfig);
|
|
682
|
+
setConfig(cfg: CascadeConfig): void;
|
|
683
|
+
setWin(win: WinConfig): void;
|
|
684
|
+
/** Killed, or the grid was torn down underneath us (rebuild during a cascade). */
|
|
685
|
+
private get _dead();
|
|
686
|
+
get multiplier(): number;
|
|
687
|
+
resetMultiplier(): void;
|
|
688
|
+
private advanceMultiplier;
|
|
689
|
+
/** Derive survivor slides for one column when explicit drops aren't supplied. */
|
|
690
|
+
private deriveDrops;
|
|
691
|
+
/** Run a single cascade step. `stepIndex` drives per-step deceleration. */
|
|
692
|
+
step(step: TumbleStep, stepIndex?: number, opts?: {
|
|
693
|
+
turbo?: boolean;
|
|
694
|
+
}): Promise<void>;
|
|
695
|
+
private _dim;
|
|
696
|
+
private _undim;
|
|
697
|
+
private _resetPositions;
|
|
698
|
+
skip(): void;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
interface FeatureContext {
|
|
702
|
+
grid: ReelGrid;
|
|
703
|
+
resolve: SymbolResolver;
|
|
704
|
+
cfg: ReelSystemConfig;
|
|
705
|
+
/** Overlay layer above the grid for rings/labels/sprites. */
|
|
706
|
+
fx: Container;
|
|
707
|
+
/** Mutable view of the current board (featureN may rewrite it). */
|
|
708
|
+
board: CellData[][];
|
|
709
|
+
/** Whether the current spin is a free-spin (gates onlyInFreeSpins features). */
|
|
710
|
+
freeSpins?: boolean;
|
|
711
|
+
/** Emit a human-readable note for the playground log. */
|
|
712
|
+
log?: (msg: string) => void;
|
|
713
|
+
}
|
|
714
|
+
interface ReelFeature {
|
|
715
|
+
/** Unique id. Built-ins use a `FeatureKey`; custom features may use any string. */
|
|
716
|
+
readonly key: FeatureKey | string;
|
|
717
|
+
readonly label: string;
|
|
718
|
+
/** Whether this feature is active for the given config. Custom features can just return `true`. */
|
|
719
|
+
enabled(cfg: ReelSystemConfig): boolean;
|
|
720
|
+
/** Run the feature presentation on the current board. */
|
|
721
|
+
demo(ctx: FeatureContext): Promise<void>;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/** All feature modules keyed by their FeatureKey. */
|
|
725
|
+
declare const FEATURES: Record<FeatureKey, ReelFeature>;
|
|
726
|
+
/** Features in canonical resolve order (see docs §3.4). */
|
|
727
|
+
declare const FEATURE_LIST: ReelFeature[];
|
|
728
|
+
|
|
729
|
+
interface CreateReelSystemOptions {
|
|
730
|
+
resolve: SymbolResolver;
|
|
731
|
+
config?: DeepPartial<ReelSystemConfig>;
|
|
732
|
+
/** Initial board (board[col][row]); defaults to empty cells. */
|
|
733
|
+
board?: CellData[][];
|
|
734
|
+
log?: (msg: string) => void;
|
|
735
|
+
/** Custom feature modules to register alongside the 13 built-ins. */
|
|
736
|
+
features?: ReelFeature[];
|
|
737
|
+
}
|
|
738
|
+
interface ReelSystem {
|
|
739
|
+
/** Root container — add this to your scene. */
|
|
740
|
+
readonly view: Container;
|
|
741
|
+
readonly grid: ReelGrid;
|
|
742
|
+
/** Overlay layer above the grid (masked off) — draw bespoke rings/labels/sprites here. */
|
|
743
|
+
readonly fx: Container;
|
|
744
|
+
readonly config: ReelSystemConfig;
|
|
745
|
+
/** Current board (board[col][row]). */
|
|
746
|
+
readonly board: CellData[][];
|
|
747
|
+
/** Ways-to-win for the current grid (ways/megaways evaluation). */
|
|
748
|
+
readonly ways: number;
|
|
749
|
+
setBoard(board: CellData[][]): void;
|
|
750
|
+
/** Merge a partial config; rebuilds the grid when geometry changes. */
|
|
751
|
+
update(partial: DeepPartial<ReelSystemConfig>): void;
|
|
752
|
+
/** Replace the whole config. */
|
|
753
|
+
setConfig(config: ReelSystemConfig): void;
|
|
754
|
+
spin(target: CellData[][], opts?: SpinRunOpts): Promise<void>;
|
|
755
|
+
/** Run a cascade chain. With `freeSpins` + `cascade.multiplier.persistInFreeSpins`, the multiplier carries over instead of resetting. */
|
|
756
|
+
cascade(steps: TumbleStep[], opts?: {
|
|
757
|
+
turbo?: boolean;
|
|
758
|
+
freeSpins?: boolean;
|
|
759
|
+
}): Promise<void>;
|
|
760
|
+
/** Current running cascade multiplier. */
|
|
761
|
+
readonly multiplier: number;
|
|
762
|
+
/** Register a custom feature (or override a built-in by reusing its key). */
|
|
763
|
+
registerFeature(feature: ReelFeature): void;
|
|
764
|
+
/** All registered features (built-ins + custom) in canonical order. */
|
|
765
|
+
features(): ReelFeature[];
|
|
766
|
+
/** Enabled feature modules (built-ins + custom). */
|
|
767
|
+
enabledFeatures(): ReelFeature[];
|
|
768
|
+
/** Run a feature by key — built-in `FeatureKey` or a custom feature's key. */
|
|
769
|
+
runFeature(key: FeatureKey | string, opts?: {
|
|
770
|
+
freeSpins?: boolean;
|
|
771
|
+
}): Promise<void>;
|
|
772
|
+
/** Build a FeatureContext for driving a feature/bespoke animation yourself. */
|
|
773
|
+
featureContext(opts?: {
|
|
774
|
+
freeSpins?: boolean;
|
|
775
|
+
}): FeatureContext;
|
|
776
|
+
resize(cellSize: number): void;
|
|
777
|
+
skip(): void;
|
|
778
|
+
destroy(): void;
|
|
779
|
+
}
|
|
780
|
+
declare function createReelSystem(opts: CreateReelSystemOptions): ReelSystem;
|
|
781
|
+
|
|
233
782
|
interface WinTier {
|
|
234
783
|
id: string;
|
|
235
784
|
minMultiplier: number;
|
|
@@ -287,28 +836,6 @@ declare class BigWinOverlay extends Container {
|
|
|
287
836
|
hide(): void;
|
|
288
837
|
}
|
|
289
838
|
|
|
290
|
-
interface FreeSpinsSessionConfig {
|
|
291
|
-
initialSpins: number;
|
|
292
|
-
/** Optional: extra spins to award from a result (retrigger). Default: none. */
|
|
293
|
-
retrigger?: (result: SlotSpinResultBase) => number;
|
|
294
|
-
/** Optional hard exit (e.g. max-win reached). */
|
|
295
|
-
isMaxWin?: () => boolean;
|
|
296
|
-
}
|
|
297
|
-
/** Headless free-spins state machine. The scene drives it; rendering/HUD reflect it. */
|
|
298
|
-
declare class FreeSpinsSession {
|
|
299
|
-
remaining: number;
|
|
300
|
-
total: number;
|
|
301
|
-
totalWin: number;
|
|
302
|
-
private readonly cfg;
|
|
303
|
-
constructor(cfg: FreeSpinsSessionConfig);
|
|
304
|
-
award(extra: number): void;
|
|
305
|
-
/** Convenience: award using the configured retrigger rule. */
|
|
306
|
-
applyRetrigger(result: SlotSpinResultBase): void;
|
|
307
|
-
addWin(amount: number): void;
|
|
308
|
-
consume(): void;
|
|
309
|
-
get isComplete(): boolean;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
839
|
/** The boundary at which a collected multiplier resets. */
|
|
313
840
|
type CarryPolicy = 'spin' | 'cascade' | 'session';
|
|
314
841
|
/**
|
|
@@ -329,5 +856,5 @@ declare class MultiplierAccumulator {
|
|
|
329
856
|
reset(boundary: CarryPolicy): void;
|
|
330
857
|
}
|
|
331
858
|
|
|
332
|
-
export { AnimatedSymbol, BigWinOverlay, CascadeController, CountUpDisplay,
|
|
333
|
-
export type { AnimatedSymbolConfig, BigWinOverlayConfig, CarryPolicy, CascadeAnim, CascadeStepData, CascadeTimings, CellData, CellFrameStyle, CellState, CountUpConfig, DecorationConfig,
|
|
859
|
+
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, SpinEngine, SymbolCell, TumbleController, createReelSystem, easingByName, effectiveRowsPerReel, mergeReelConfig, pickTier, resolveReelConfig, tierIndexAtValue, valueAt, waysCount };
|
|
860
|
+
export type { AnimatedSymbolConfig, AnticipationConfig, AnticipationDecision, BigWinOverlayConfig, BlurConfig, CarryPolicy, CascadeAnim, CascadeConfig, CascadeStepData, CascadeTimings, CellData, CellFrameStyle, CellState, CountUpConfig, CreateReelSystemOptions, DecorationConfig, DeepPartial, EasingName, EvaluationMode, ExpandingWildConfig, FeatureContext, FeatureKey, FeaturesConfig, GiantConfig, GridConfig, HoldAndSpinConfig, Intensity, MotionConfig, MotionStyle, MultiplierConfig, MysteryConfig, NudgeConfig, PresetId, RandomWildConfig, ReelFeature, ReelGridConfig, ReelModifierConfig, ReelPreset, ReelSpinData, ReelSpinTimings, ReelStopPlan$1 as ReelStopPlan, ReelSystem, ReelSystemConfig, SettleConfig, SpinData, SpinRunOpts, ReelStopPlan as SpinStopPlan, SplitConfig, SquashConfig, StackedConfig, StickyConfig, StopMode, StopOrder, SymbolCellConfig, SymbolResolver, SymbolTextures, SymbolView, TransformConfig, TumbleStep, WalkingWildConfig, WinConfig, WinTier };
|