@energy8platform/game-engine 0.40.0 → 0.41.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 +18 -4
- package/dist/devtools.cjs.js +2 -0
- package/dist/devtools.cjs.js.map +1 -1
- package/dist/devtools.d.ts +12 -0
- package/dist/devtools.esm.js +2 -0
- package/dist/devtools.esm.js.map +1 -1
- package/dist/reel-panel-client.cjs.js +2 -0
- package/dist/reel-panel-client.cjs.js.map +1 -1
- package/dist/reel-panel-client.esm.js +2 -0
- package/dist/reel-panel-client.esm.js.map +1 -1
- package/dist/slot.cjs.js +24 -7
- package/dist/slot.cjs.js.map +1 -1
- package/dist/slot.d.ts +20 -0
- package/dist/slot.esm.js +24 -7
- package/dist/slot.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/slot/config/ReelSystemConfig.ts +13 -0
- package/src/slot/devtools/fieldSchema.ts +1 -0
- package/src/slot/motion/AnticipationController.ts +12 -2
- package/src/slot/motion/SpinEngine.ts +16 -2
- package/src/slot/system/ReelSystem.ts +5 -1
package/dist/slot.d.ts
CHANGED
|
@@ -494,6 +494,8 @@ interface AnticipationOverride {
|
|
|
494
494
|
slowdown?: PerReel<number>;
|
|
495
495
|
/** Extra hold before landing. Scalar, or per-reel indexed by reel index. */
|
|
496
496
|
holdMs?: PerReel<number>;
|
|
497
|
+
/** Growth of the gap between successive cells within a reel. Scalar, or per-reel. */
|
|
498
|
+
cellStaggerRamp?: PerReel<number>;
|
|
497
499
|
}
|
|
498
500
|
interface AnticipationConfig {
|
|
499
501
|
enabled: boolean;
|
|
@@ -522,6 +524,16 @@ interface AnticipationConfig {
|
|
|
522
524
|
progressiveSlowdown: number;
|
|
523
525
|
/** Extra hold (ms) added per successive anticipated reel: reel #i gets `holdMs + i * this`. */
|
|
524
526
|
progressiveHoldMs: number;
|
|
527
|
+
/**
|
|
528
|
+
* `cascade-drop`: how the gap between SUCCESSIVE CELLS grows inside an anticipated reel. The
|
|
529
|
+
* gap before cell #i is `cellStagger * <reel slowdown> * progressiveCellStagger ** i`, so 1
|
|
530
|
+
* (the default) keeps the reel's cells evenly spaced and > 1 makes each symbol land later than
|
|
531
|
+
* the last — the drip that turns a reel into a countdown.
|
|
532
|
+
*
|
|
533
|
+
* It compounds with `progressiveSlowdown`: that widens the base gap reel by reel, this widens
|
|
534
|
+
* it cell by cell, so a later reel drips both slower AND with a steeper ramp.
|
|
535
|
+
*/
|
|
536
|
+
progressiveCellStagger: number;
|
|
525
537
|
/** Optional grid zoom while anticipating (magnum-opus uses 1.3×). */
|
|
526
538
|
zoom: {
|
|
527
539
|
enabled: boolean;
|
|
@@ -766,6 +778,12 @@ interface SpinRunOpts {
|
|
|
766
778
|
anticipateSlowdown?: PerReel<number>;
|
|
767
779
|
/** Extra hold (ms) for anticipated reels. Scalar, or per-reel indexed by reel. */
|
|
768
780
|
anticipateHoldMs?: PerReel<number>;
|
|
781
|
+
/**
|
|
782
|
+
* `cascade-drop`: growth of the gap between successive cells inside an anticipated reel — the
|
|
783
|
+
* gap before cell #i is `cellStagger * <reel slowdown> * ramp ** i`. 1 keeps the reel evenly
|
|
784
|
+
* spaced. Scalar, or per-reel indexed by reel.
|
|
785
|
+
*/
|
|
786
|
+
anticipateCellStaggerRamp?: PerReel<number>;
|
|
769
787
|
/**
|
|
770
788
|
* Reels whose tape runs normally but whose landing is NOT handed back. The engine stops and
|
|
771
789
|
* disposes of the tape as usual and leaves the real cells hidden and unseated; the caller owns
|
|
@@ -854,6 +872,8 @@ interface AnticipationDecision {
|
|
|
854
872
|
slowdown: PerReel<number>;
|
|
855
873
|
/** Extra hold before landing. Scalar or per-reel array, same as `slowdown`. */
|
|
856
874
|
holdMs: PerReel<number>;
|
|
875
|
+
/** `cascade-drop`: growth of the gap between successive cells inside the reel (1 = even). */
|
|
876
|
+
cellStaggerRamp: PerReel<number>;
|
|
857
877
|
}
|
|
858
878
|
declare class AnticipationController {
|
|
859
879
|
private _cfg;
|
package/dist/slot.esm.js
CHANGED
|
@@ -1142,6 +1142,7 @@ const DEFAULT_REEL_CONFIG = {
|
|
|
1142
1142
|
decide: null,
|
|
1143
1143
|
progressiveSlowdown: 1,
|
|
1144
1144
|
progressiveHoldMs: 0,
|
|
1145
|
+
progressiveCellStagger: 1,
|
|
1145
1146
|
zoom: { enabled: false, scale: 1.15, ms: 600 },
|
|
1146
1147
|
},
|
|
1147
1148
|
cascade: {
|
|
@@ -1572,6 +1573,7 @@ class SpinEngine {
|
|
|
1572
1573
|
const anticipate = new Set(opts?.anticipateReels ?? []);
|
|
1573
1574
|
const defer = new Set(opts?.deferReveal ?? []);
|
|
1574
1575
|
const holds = [];
|
|
1576
|
+
const ramps = [];
|
|
1575
1577
|
const out = [];
|
|
1576
1578
|
for (let reel = 0; reel < cols; reel++) {
|
|
1577
1579
|
const idx = order(reel);
|
|
@@ -1590,6 +1592,7 @@ class SpinEngine {
|
|
|
1590
1592
|
const hold = isAnticipated ? perReelValue(opts?.anticipateHoldMs, reel, 0) * f : 0;
|
|
1591
1593
|
stopTime += hold;
|
|
1592
1594
|
holds[reel] = hold;
|
|
1595
|
+
ramps[reel] = isAnticipated ? perReelValue(opts?.anticipateCellStaggerRamp, reel, 1) : 1;
|
|
1593
1596
|
const speed = isAnticipated ? perReelValue(opts?.anticipateSlowdown, reel, 1) : 1;
|
|
1594
1597
|
out.push({
|
|
1595
1598
|
reel,
|
|
@@ -1602,7 +1605,7 @@ class SpinEngine {
|
|
|
1602
1605
|
});
|
|
1603
1606
|
}
|
|
1604
1607
|
if (this._cfg.style === 'cascade-drop')
|
|
1605
|
-
this._planDrop(out, holds, f, order);
|
|
1608
|
+
this._planDrop(out, holds, ramps, f, order);
|
|
1606
1609
|
return out;
|
|
1607
1610
|
}
|
|
1608
1611
|
/**
|
|
@@ -1611,7 +1614,7 @@ class SpinEngine {
|
|
|
1611
1614
|
* reel has fully landed and fill in `cellStopTimes`, so `plan()` stays the single source of truth
|
|
1612
1615
|
* for WHEN anything happens — `_runDrop` below only executes these numbers.
|
|
1613
1616
|
*/
|
|
1614
|
-
_planDrop(out, holds, f, order) {
|
|
1617
|
+
_planDrop(out, holds, ramps, f, order) {
|
|
1615
1618
|
const bottomUp = this._cfg.dropOrder === 'bottom-up';
|
|
1616
1619
|
// walk the reels in STOP order, so `stopOrder: 'rtl'` reverses the drop as well
|
|
1617
1620
|
const byPosition = [];
|
|
@@ -1633,10 +1636,15 @@ class SpinEngine {
|
|
|
1633
1636
|
// by formula while reels may overlap; queued behind the previous reel once the chain starts
|
|
1634
1637
|
const chained = chainFrom >= 0 && position > 0 && position >= chainFrom;
|
|
1635
1638
|
const start = (chained ? previousEnd + gap : position * gap) + (holds[p.reel] ?? 0);
|
|
1639
|
+
// The gap before cell #i is `cellStagger * scale * ramp**i` — accumulate rather than
|
|
1640
|
+
// multiply, so a ramp of 1 stays exactly the old evenly-spaced schedule.
|
|
1641
|
+
const ramp = ramps[p.reel] ?? 1;
|
|
1636
1642
|
const cells = [];
|
|
1643
|
+
let offset = 0;
|
|
1637
1644
|
for (let i = 0; i < rows; i++) {
|
|
1638
1645
|
const row = bottomUp ? rows - 1 - i : i;
|
|
1639
|
-
cells[row] = start +
|
|
1646
|
+
cells[row] = start + offset + fall;
|
|
1647
|
+
offset += this._cfg.cellStagger * scale * Math.pow(ramp, i);
|
|
1640
1648
|
}
|
|
1641
1649
|
p.cellStopTimes = cells;
|
|
1642
1650
|
p.stopTime = cells.length ? Math.max(...cells) : start;
|
|
@@ -1892,7 +1900,13 @@ class SpinEngine {
|
|
|
1892
1900
|
// Decides which trailing reels get the "anticipation" slow-down treatment, based purely on
|
|
1893
1901
|
// the already-resolved landing grid (presentation only — never a secondary outcome decision).
|
|
1894
1902
|
/** Fresh "nothing to anticipate" decision (fresh, so callers may mutate `reels` freely). */
|
|
1895
|
-
const none = () => ({
|
|
1903
|
+
const none = () => ({
|
|
1904
|
+
active: false,
|
|
1905
|
+
reels: [],
|
|
1906
|
+
slowdown: 1,
|
|
1907
|
+
holdMs: 0,
|
|
1908
|
+
cellStaggerRamp: 1,
|
|
1909
|
+
});
|
|
1896
1910
|
class AnticipationController {
|
|
1897
1911
|
_cfg;
|
|
1898
1912
|
constructor(cfg) {
|
|
@@ -1925,7 +1939,7 @@ class AnticipationController {
|
|
|
1925
1939
|
const o = Array.isArray(custom) ? { reels: custom } : custom;
|
|
1926
1940
|
if (!o.reels?.length)
|
|
1927
1941
|
return none();
|
|
1928
|
-
return this.build(o.reels.slice(), o.slowdown, o.holdMs);
|
|
1942
|
+
return this.build(o.reels.slice(), o.slowdown, o.holdMs, o.cellStaggerRamp);
|
|
1929
1943
|
}
|
|
1930
1944
|
if (Array.isArray(this._cfg.reels)) {
|
|
1931
1945
|
// explicit reel list — arm only if the threshold is met somewhere on the board
|
|
@@ -1954,10 +1968,11 @@ class AnticipationController {
|
|
|
1954
1968
|
return this.build(reels);
|
|
1955
1969
|
}
|
|
1956
1970
|
/** Assemble a decision, applying the configured progression unless the caller pinned values. */
|
|
1957
|
-
build(reels, slowdown, holdMs) {
|
|
1971
|
+
build(reels, slowdown, holdMs, cellStaggerRamp) {
|
|
1958
1972
|
return {
|
|
1959
1973
|
active: true,
|
|
1960
1974
|
reels,
|
|
1975
|
+
cellStaggerRamp: cellStaggerRamp ?? this._cfg.progressiveCellStagger,
|
|
1961
1976
|
slowdown: slowdown ??
|
|
1962
1977
|
this.ramp(reels, this._cfg.slowdownFactor, (base, i) => i === 0 ? base : base * Math.pow(this._cfg.progressiveSlowdown, i)),
|
|
1963
1978
|
holdMs: holdMs ??
|
|
@@ -3037,12 +3052,13 @@ function createReelSystem(opts) {
|
|
|
3037
3052
|
if (!explicit)
|
|
3038
3053
|
return anticipation.decide(target);
|
|
3039
3054
|
if (!explicit.length)
|
|
3040
|
-
return { active: false, reels: [], slowdown: 1, holdMs: 0 };
|
|
3055
|
+
return { active: false, reels: [], slowdown: 1, holdMs: 0, cellStaggerRamp: 1 };
|
|
3041
3056
|
return {
|
|
3042
3057
|
active: true,
|
|
3043
3058
|
reels: explicit.slice(),
|
|
3044
3059
|
slowdown: runOpts?.anticipateSlowdown ?? config.anticipation.slowdownFactor,
|
|
3045
3060
|
holdMs: runOpts?.anticipateHoldMs ?? config.anticipation.holdMs,
|
|
3061
|
+
cellStaggerRamp: runOpts?.anticipateCellStaggerRamp ?? config.anticipation.progressiveCellStagger,
|
|
3046
3062
|
};
|
|
3047
3063
|
}
|
|
3048
3064
|
/** Fold a resolved decision back onto the caller's run options (everything else passes through). */
|
|
@@ -3052,6 +3068,7 @@ function createReelSystem(opts) {
|
|
|
3052
3068
|
anticipateReels: decision.active ? decision.reels : undefined,
|
|
3053
3069
|
anticipateSlowdown: decision.slowdown,
|
|
3054
3070
|
anticipateHoldMs: decision.holdMs,
|
|
3071
|
+
anticipateCellStaggerRamp: decision.cellStaggerRamp,
|
|
3055
3072
|
};
|
|
3056
3073
|
}
|
|
3057
3074
|
buildGrid();
|