pixi-rainman-game-engine 0.3.29 → 0.3.31-b
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/Rainman/types.d.ts +1 -0
- package/dist/components/AbstractBuyFreeSpins/AbstractBuyFreeSpinsPlate.js +5 -2
- package/dist/components/AbstractIntroScreen/AbstractIntroScreen.d.ts +7 -1
- package/dist/components/AbstractIntroScreen/AbstractIntroScreen.js +34 -6
- package/dist/components/AbstractIntroScreen/IntroPageData.d.ts +8 -0
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +2 -2
- package/dist/components/GambleGame/GambleGame.js +1 -0
- package/dist/components/frame/AbstractColumnsContainer.d.ts +25 -0
- package/dist/components/frame/AbstractColumnsContainer.js +75 -13
- package/dist/components/symbols/AbstractSymbolsColumn.d.ts +6 -0
- package/dist/components/symbols/AbstractSymbolsColumn.js +12 -4
- package/dist/controllers/AbstractController.d.ts +3 -1
- package/dist/controllers/AbstractController.js +79 -34
- package/package.json +1 -1
package/dist/Rainman/types.d.ts
CHANGED
|
@@ -81,6 +81,7 @@ export interface Globals {
|
|
|
81
81
|
disableSpeedPopup?: (value: boolean) => void;
|
|
82
82
|
handleDisablingButtons?: (value?: boolean) => void;
|
|
83
83
|
throttledSpin?: () => void;
|
|
84
|
+
prepareBoughtFreeSpins?: () => void;
|
|
84
85
|
updateFreeSpinShown?: (value: number) => void;
|
|
85
86
|
backendSymbolMap?: Map<number, never>;
|
|
86
87
|
betTable?: number[];
|
|
@@ -145,9 +145,12 @@ export class AbstractBuyFreeSpinsPlate extends Container {
|
|
|
145
145
|
RainMan.settingsStore.setRoundNumber(roundNumber);
|
|
146
146
|
this.cleanup();
|
|
147
147
|
this.onContinueCallback();
|
|
148
|
-
RainMan.settingsStore.
|
|
149
|
-
RainMan.settingsStore.handleInvokeFreeSpinPlate?.(option.amount, false);
|
|
148
|
+
await RainMan.settingsStore.handleInvokeFreeSpinPlate?.(option.amount, false);
|
|
150
149
|
RainMan.settingsStore.disableKeyboardShortcuts = false;
|
|
150
|
+
RainMan.globals.prepareBoughtFreeSpins?.();
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
RainMan.globals.throttledSpin?.();
|
|
153
|
+
}, 500);
|
|
151
154
|
}
|
|
152
155
|
catch (err) {
|
|
153
156
|
console.error(err);
|
|
@@ -2,7 +2,7 @@ import { Container, Sprite, Text, TextStyle, Texture } from "pixi.js";
|
|
|
2
2
|
import { IntroLogo } from "../common";
|
|
3
3
|
import { IntroContinueButton } from "./IntroContinueButton";
|
|
4
4
|
import { IntroDotButton } from "./IntroDotButton";
|
|
5
|
-
import { IntroPageData } from "./IntroPageData";
|
|
5
|
+
import { IntroPageData, IntroPageInnerTextBlock } from "./IntroPageData";
|
|
6
6
|
/**
|
|
7
7
|
* Abstract intro screen shown between loading and gameplay.
|
|
8
8
|
* Each game subclasses this and provides assets + page definitions as properties.
|
|
@@ -38,6 +38,7 @@ export declare abstract class AbstractIntroScreen extends Container {
|
|
|
38
38
|
protected dotShadow?: Sprite;
|
|
39
39
|
protected frameImage: Sprite;
|
|
40
40
|
protected pageImage: Sprite;
|
|
41
|
+
protected pageInnerTextBlocks: Text[];
|
|
41
42
|
protected pageText: Text;
|
|
42
43
|
private currentPage;
|
|
43
44
|
private isChecked;
|
|
@@ -54,14 +55,19 @@ export declare abstract class AbstractIntroScreen extends Container {
|
|
|
54
55
|
protected abstract positionText(): void;
|
|
55
56
|
protected abstract positionCheckbox(): void;
|
|
56
57
|
protected abstract positionLogo(): void;
|
|
58
|
+
protected positionPageInnerText(): void;
|
|
57
59
|
protected abstract getPageImageScale(): {
|
|
58
60
|
vertical: number;
|
|
59
61
|
horizontal: number;
|
|
60
62
|
};
|
|
61
63
|
protected abstract positionPageImage(): void;
|
|
64
|
+
protected createPageInnerTextBlocks(blocks: IntroPageInnerTextBlock[]): Text[];
|
|
62
65
|
protected showPage(index: number): void;
|
|
63
66
|
private updateFade;
|
|
64
67
|
private cleanup;
|
|
68
|
+
private refreshPageInnerText;
|
|
69
|
+
private setInnerTextAlpha;
|
|
70
|
+
private setPageContentAlpha;
|
|
65
71
|
/**
|
|
66
72
|
* Resizes dot shadow width to match all dots and centers it on them.
|
|
67
73
|
* Call this in positionDots() after positioning the dots.
|
|
@@ -32,6 +32,7 @@ export class AbstractIntroScreen extends Container {
|
|
|
32
32
|
dotShadow;
|
|
33
33
|
frameImage;
|
|
34
34
|
pageImage;
|
|
35
|
+
pageInnerTextBlocks = [];
|
|
35
36
|
pageText;
|
|
36
37
|
currentPage = 0;
|
|
37
38
|
isChecked = false;
|
|
@@ -91,8 +92,7 @@ export class AbstractIntroScreen extends Container {
|
|
|
91
92
|
this.addChild(bg);
|
|
92
93
|
this.frameImage.texture = getTexture(isPortrait ? "intro-frame-mobile.png" : "intro-frame.png");
|
|
93
94
|
this.showPage(this.currentPage);
|
|
94
|
-
this.
|
|
95
|
-
this.pageText.alpha = 1;
|
|
95
|
+
this.setPageContentAlpha(1);
|
|
96
96
|
const pageImageScale = this.getPageImageScale();
|
|
97
97
|
const dimensions = scaleToParent(this.pageImage.texture.width, this.pageImage.texture.height, RainMan.app.screen.width * pageImageScale.horizontal, RainMan.app.screen.height * pageImageScale.vertical);
|
|
98
98
|
this.pageImage.width = dimensions.width;
|
|
@@ -109,6 +109,7 @@ export class AbstractIntroScreen extends Container {
|
|
|
109
109
|
this.addChild(this.frameImage);
|
|
110
110
|
this.addChild(this.frameImage);
|
|
111
111
|
this.addChild(this.pageImage);
|
|
112
|
+
this.pageInnerTextBlocks.forEach((block) => this.addChild(block));
|
|
112
113
|
this.addChild(this.pageText);
|
|
113
114
|
this.addChild(this.continueButton);
|
|
114
115
|
this.addChild(this.checkboxSprite);
|
|
@@ -123,6 +124,7 @@ export class AbstractIntroScreen extends Container {
|
|
|
123
124
|
this.positionCheckbox();
|
|
124
125
|
this.positionContinueButton();
|
|
125
126
|
this.positionText();
|
|
127
|
+
this.positionPageInnerText();
|
|
126
128
|
this.positionDotShadow();
|
|
127
129
|
this.frameImage.x = this.pageImage.x;
|
|
128
130
|
this.frameImage.y = this.pageImage.y;
|
|
@@ -133,6 +135,10 @@ export class AbstractIntroScreen extends Container {
|
|
|
133
135
|
this.frameImage.width = this.pageImage.width;
|
|
134
136
|
this.frameImage.height = this.pageImage.height;
|
|
135
137
|
}
|
|
138
|
+
positionPageInnerText() { }
|
|
139
|
+
createPageInnerTextBlocks(blocks) {
|
|
140
|
+
return blocks.map((block) => new Text(block.text));
|
|
141
|
+
}
|
|
136
142
|
showPage(index) {
|
|
137
143
|
if (index < 0 || index >= this.pages.length)
|
|
138
144
|
return;
|
|
@@ -141,6 +147,8 @@ export class AbstractIntroScreen extends Container {
|
|
|
141
147
|
const isPortrait = getDeviceOrientation() === "mobile-portrait";
|
|
142
148
|
this.pageImage.texture = Texture.from(isPortrait ? page.imageMobile : page.imageDesktop);
|
|
143
149
|
this.pageText.text = page.text;
|
|
150
|
+
this.refreshPageInnerText(page);
|
|
151
|
+
this.setInnerTextAlpha(this.pageImage.alpha);
|
|
144
152
|
for (let i = 0; i < this.dots.length; i++) {
|
|
145
153
|
this.dots[i].setActive(i === index);
|
|
146
154
|
}
|
|
@@ -153,6 +161,28 @@ export class AbstractIntroScreen extends Container {
|
|
|
153
161
|
RainMan.app.renderer.off("resize", this.resizeHandler);
|
|
154
162
|
this.destroy({ children: true });
|
|
155
163
|
}
|
|
164
|
+
refreshPageInnerText(page) {
|
|
165
|
+
this.pageInnerTextBlocks.forEach((block) => {
|
|
166
|
+
this.removeChild(block);
|
|
167
|
+
block.destroy();
|
|
168
|
+
});
|
|
169
|
+
this.pageInnerTextBlocks = [];
|
|
170
|
+
if (!page.pageInnerText?.length)
|
|
171
|
+
return;
|
|
172
|
+
this.pageInnerTextBlocks = this.createPageInnerTextBlocks(page.pageInnerText);
|
|
173
|
+
this.pageInnerTextBlocks.forEach((block) => this.addChild(block));
|
|
174
|
+
this.positionPageInnerText();
|
|
175
|
+
}
|
|
176
|
+
setInnerTextAlpha(alpha) {
|
|
177
|
+
this.pageInnerTextBlocks.forEach((block) => {
|
|
178
|
+
block.alpha = alpha;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
setPageContentAlpha(alpha) {
|
|
182
|
+
this.pageImage.alpha = alpha;
|
|
183
|
+
this.pageText.alpha = alpha;
|
|
184
|
+
this.setInnerTextAlpha(alpha);
|
|
185
|
+
}
|
|
156
186
|
/**
|
|
157
187
|
* Resizes dot shadow width to match all dots and centers it on them.
|
|
158
188
|
* Call this in positionDots() after positioning the dots.
|
|
@@ -195,16 +225,14 @@ export class AbstractIntroScreen extends Container {
|
|
|
195
225
|
this.fadeTween = new TWEEN.Tween({ alpha: this.pageImage.alpha })
|
|
196
226
|
.to({ alpha: 0 }, this.FADE_DURATION)
|
|
197
227
|
.onUpdate((obj) => {
|
|
198
|
-
this.
|
|
199
|
-
this.pageText.alpha = obj.alpha;
|
|
228
|
+
this.setPageContentAlpha(obj.alpha);
|
|
200
229
|
})
|
|
201
230
|
.onComplete(() => {
|
|
202
231
|
this.showPage(index);
|
|
203
232
|
this.fadeTween = new TWEEN.Tween({ alpha: 0 })
|
|
204
233
|
.to({ alpha: 1 }, this.FADE_DURATION)
|
|
205
234
|
.onUpdate((obj) => {
|
|
206
|
-
this.
|
|
207
|
-
this.pageText.alpha = obj.alpha;
|
|
235
|
+
this.setPageContentAlpha(obj.alpha);
|
|
208
236
|
})
|
|
209
237
|
.onComplete(() => {
|
|
210
238
|
this.isAnimating = false;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data for a single inner text block rendered inside an intro page image.
|
|
3
|
+
*/
|
|
4
|
+
export type IntroPageInnerTextBlock = {
|
|
5
|
+
id?: string;
|
|
6
|
+
text: string;
|
|
7
|
+
};
|
|
1
8
|
/**
|
|
2
9
|
* Data for a single page in the intro screen.
|
|
3
10
|
*/
|
|
@@ -5,4 +12,5 @@ export type IntroPageData = {
|
|
|
5
12
|
imageDesktop: string;
|
|
6
13
|
imageMobile: string;
|
|
7
14
|
text: string;
|
|
15
|
+
pageInnerText?: IntroPageInnerTextBlock[];
|
|
8
16
|
};
|
|
@@ -549,7 +549,7 @@ export class AbstractMainContainer extends Container {
|
|
|
549
549
|
async invokeGambleGame() {
|
|
550
550
|
if (!this.gambleGameSpineName)
|
|
551
551
|
return;
|
|
552
|
-
|
|
552
|
+
await new Promise((resolve) => {
|
|
553
553
|
this.gambleGame = new GambleGame(this.gambleGameSpineName, resolve, this._controller.lastWinAmount, this._controller.balance);
|
|
554
554
|
RainMan.settingsStore.isGambleGameActive = true;
|
|
555
555
|
this.showOverlay();
|
|
@@ -561,7 +561,7 @@ export class AbstractMainContainer extends Container {
|
|
|
561
561
|
this._controller.updateGambleValues(RainMan.settingsStore.gambleGameWin);
|
|
562
562
|
this.gambleGame = null;
|
|
563
563
|
}
|
|
564
|
-
this._controller
|
|
564
|
+
this._controller?.updateBalance();
|
|
565
565
|
this.hideOverlay();
|
|
566
566
|
}
|
|
567
567
|
/**
|
|
@@ -126,6 +126,7 @@ export class GambleGame extends Container {
|
|
|
126
126
|
this.card.state.addAnimation(0, "wait", true, 0);
|
|
127
127
|
const gambleData = await window.connectionWrapper.fetchGambleData(RainMan.settingsStore.roundNumber, this.lastWinAmount, choice);
|
|
128
128
|
this.balanceValue = gambleData.balance + gambleData.win_amount;
|
|
129
|
+
this.balanceValue = gambleData.balanceAfterSpin;
|
|
129
130
|
await new Promise((resolve) => {
|
|
130
131
|
this.card.state.clearTracks();
|
|
131
132
|
this.card.state.clearListeners();
|
|
@@ -18,6 +18,9 @@ export declare abstract class AbstractColumnsContainer extends Container impleme
|
|
|
18
18
|
protected allColumns: AbstractSymbolsColumn[];
|
|
19
19
|
private velocityMultiplier;
|
|
20
20
|
private skipScatterDelay;
|
|
21
|
+
private mysteryDelayTimeout;
|
|
22
|
+
private mysteryFxGeneration;
|
|
23
|
+
private skipRemainingMysteryFxs;
|
|
21
24
|
currentColumn: Nullable<AbstractSymbolsColumn>;
|
|
22
25
|
private playedSounds;
|
|
23
26
|
quickReelsStop: boolean;
|
|
@@ -92,6 +95,28 @@ export declare abstract class AbstractColumnsContainer extends Container impleme
|
|
|
92
95
|
* @returns {Promise<void>}
|
|
93
96
|
*/
|
|
94
97
|
configBlindSpin(finalSymbolReels: SymbolReels, afterSpinResolver: (value: void | PromiseLike<void>) => void, indexesOfReelsToExtendSpinningTime: number[]): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* This cancels the timeout, removes the stored delayed action and invalidates
|
|
100
|
+
* any older timeout callback that might still try to execute later.
|
|
101
|
+
* @private
|
|
102
|
+
* @returns {void}
|
|
103
|
+
*/
|
|
104
|
+
private clearPendingMysteryDelay;
|
|
105
|
+
/**
|
|
106
|
+
* Runs the pending mysteryFx immediately and clears its timeout.
|
|
107
|
+
* @private
|
|
108
|
+
* @returns {void}
|
|
109
|
+
*/
|
|
110
|
+
private executePendingMysteryFx;
|
|
111
|
+
/**
|
|
112
|
+
* The callback is bound to the current generation so an old timeout from
|
|
113
|
+
* a previous spin cannot execute after a newer mystery delay was scheduled.
|
|
114
|
+
* @private
|
|
115
|
+
* @param {PlayableAction} action delayed reel configuration action
|
|
116
|
+
* @param {number} delay time in milliseconds before the action should run
|
|
117
|
+
* @returns {void}
|
|
118
|
+
*/
|
|
119
|
+
private scheduleMysteryDelay;
|
|
95
120
|
/**
|
|
96
121
|
* Function for playing all streaks
|
|
97
122
|
* @public
|
|
@@ -20,6 +20,9 @@ export class AbstractColumnsContainer extends Container {
|
|
|
20
20
|
allColumns = [];
|
|
21
21
|
velocityMultiplier = defaultSpeedConfig.symbolsColumnsSpeed;
|
|
22
22
|
skipScatterDelay = null;
|
|
23
|
+
mysteryDelayTimeout = null;
|
|
24
|
+
mysteryFxGeneration = 0;
|
|
25
|
+
skipRemainingMysteryFxs = false;
|
|
23
26
|
currentColumn = null;
|
|
24
27
|
playedSounds = [];
|
|
25
28
|
quickReelsStop = false;
|
|
@@ -93,12 +96,13 @@ export class AbstractColumnsContainer extends Container {
|
|
|
93
96
|
*/
|
|
94
97
|
enableQuickReelsStop() {
|
|
95
98
|
this.quickReelsStop = true;
|
|
99
|
+
this.skipRemainingMysteryFxs = true;
|
|
96
100
|
RainMan.settingsStore.isQuickSpinsActive = true;
|
|
97
101
|
RainMan.settingsStore.setIsTemporarySpeed(true);
|
|
98
102
|
RainMan.componentRegistry.setTemporarySpeedLevel(SPEED_LEVELS.fast);
|
|
99
|
-
this.
|
|
103
|
+
this.executePendingMysteryFx();
|
|
104
|
+
this.currentColumn?.releaseNextColumnTrigger();
|
|
100
105
|
this.resolveMysterySpeedUp();
|
|
101
|
-
this.skipScatterDelay = null;
|
|
102
106
|
if (this.currentColumn) {
|
|
103
107
|
this.currentColumn.skipHidingMysteryFx = true;
|
|
104
108
|
}
|
|
@@ -133,10 +137,15 @@ export class AbstractColumnsContainer extends Container {
|
|
|
133
137
|
// spin
|
|
134
138
|
return new Promise(async (resolve) => {
|
|
135
139
|
let index = 0;
|
|
140
|
+
this.clearPendingMysteryDelay();
|
|
141
|
+
this.mysteryFxGeneration = 0;
|
|
142
|
+
this.skipRemainingMysteryFxs = false;
|
|
136
143
|
const configuredBlindSpinsActions = this.prepareConfiguringReelsEnd(finalSymbolReels);
|
|
137
144
|
const frame = RainMan.componentRegistry.get(AbstractFrame.registryName);
|
|
138
145
|
while (configuredBlindSpinsActions.length !== 0) {
|
|
139
|
-
if (this.quickReelsStop ||
|
|
146
|
+
if (this.quickReelsStop ||
|
|
147
|
+
this.skipRemainingMysteryFxs ||
|
|
148
|
+
RainMan.settingsStore.currentSpeed === SPEED_LEVELS.fast) {
|
|
140
149
|
await Promise.all(configuredBlindSpinsActions.map(async (action) => await action()));
|
|
141
150
|
configuredBlindSpinsActions.length = 0;
|
|
142
151
|
SoundManager.play(SoundTracks.allRollStops);
|
|
@@ -145,21 +154,22 @@ export class AbstractColumnsContainer extends Container {
|
|
|
145
154
|
const configureSpinAction = configuredBlindSpinsActions.shift();
|
|
146
155
|
if (configureSpinAction !== undefined) {
|
|
147
156
|
if (indexesOfReelsToExtendSpinningTime.includes(index)) {
|
|
148
|
-
|
|
149
|
-
this.currentColumn
|
|
150
|
-
|
|
157
|
+
const mysteryColumn = this.allColumns[index];
|
|
158
|
+
this.currentColumn = mysteryColumn;
|
|
159
|
+
mysteryColumn.adaptToSpeed(RainMan.settingsStore.currentSpeed);
|
|
160
|
+
frame.invokeMysteryFx(mysteryColumn.x, mysteryColumn.y);
|
|
151
161
|
this.skipScatterDelay = configureSpinAction;
|
|
152
|
-
await
|
|
153
|
-
if (
|
|
162
|
+
await mysteryColumn.speedUpForMysterySpin(100, 1500);
|
|
163
|
+
if (this.quickReelsStop || this.skipRemainingMysteryFxs) {
|
|
164
|
+
await mysteryColumn.changeVelocity(Speed.STOP, 0, frame);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
154
167
|
if (!RainMan.settingsStore.isAutoplayEnabled ||
|
|
155
168
|
(RainMan.settingsStore.isAutoplayEnabled && !this.quickReelsStop)) {
|
|
156
|
-
|
|
157
|
-
this.skipScatterDelay?.();
|
|
158
|
-
this.skipScatterDelay = null;
|
|
159
|
-
}, RainMan.config.durationOfActions.scatterDelayerTime);
|
|
169
|
+
this.scheduleMysteryDelay(configureSpinAction, RainMan.config.durationOfActions.scatterDelayerTime);
|
|
160
170
|
}
|
|
171
|
+
await mysteryColumn.changeVelocity(Speed.STOP, RainMan.config.durationOfActions.scatterSpinningTime, frame);
|
|
161
172
|
}
|
|
162
|
-
await this.currentColumn.changeVelocity(Speed.STOP, RainMan.config.durationOfActions.scatterSpinningTime, frame);
|
|
163
173
|
frame.destroyMysteryFx();
|
|
164
174
|
}
|
|
165
175
|
if (!indexesOfReelsToExtendSpinningTime.includes(index)) {
|
|
@@ -170,10 +180,60 @@ export class AbstractColumnsContainer extends Container {
|
|
|
170
180
|
this.currentColumn = null;
|
|
171
181
|
}
|
|
172
182
|
await Promise.all(this.allColumns.map((column) => column.getStopPromise()));
|
|
183
|
+
this.clearPendingMysteryDelay();
|
|
184
|
+
this.mysteryFxGeneration = 0;
|
|
185
|
+
this.skipRemainingMysteryFxs = false;
|
|
173
186
|
afterSpinResolver();
|
|
174
187
|
resolve();
|
|
175
188
|
});
|
|
176
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* This cancels the timeout, removes the stored delayed action and invalidates
|
|
192
|
+
* any older timeout callback that might still try to execute later.
|
|
193
|
+
* @private
|
|
194
|
+
* @returns {void}
|
|
195
|
+
*/
|
|
196
|
+
clearPendingMysteryDelay() {
|
|
197
|
+
this.mysteryFxGeneration += 1;
|
|
198
|
+
if (this.mysteryDelayTimeout !== null) {
|
|
199
|
+
clearTimeout(this.mysteryDelayTimeout);
|
|
200
|
+
this.mysteryDelayTimeout = null;
|
|
201
|
+
}
|
|
202
|
+
this.skipScatterDelay = null;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Runs the pending mysteryFx immediately and clears its timeout.
|
|
206
|
+
* @private
|
|
207
|
+
* @returns {void}
|
|
208
|
+
*/
|
|
209
|
+
executePendingMysteryFx() {
|
|
210
|
+
const pendingMysteryDelay = this.skipScatterDelay;
|
|
211
|
+
this.clearPendingMysteryDelay();
|
|
212
|
+
pendingMysteryDelay?.();
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* The callback is bound to the current generation so an old timeout from
|
|
216
|
+
* a previous spin cannot execute after a newer mystery delay was scheduled.
|
|
217
|
+
* @private
|
|
218
|
+
* @param {PlayableAction} action delayed reel configuration action
|
|
219
|
+
* @param {number} delay time in milliseconds before the action should run
|
|
220
|
+
* @returns {void}
|
|
221
|
+
*/
|
|
222
|
+
scheduleMysteryDelay(action, delay) {
|
|
223
|
+
this.clearPendingMysteryDelay();
|
|
224
|
+
// Store new mysteryFx action to be available in executePendingMysteryFx
|
|
225
|
+
this.skipScatterDelay = action;
|
|
226
|
+
const mysteryFxGeneration = this.mysteryFxGeneration;
|
|
227
|
+
this.mysteryDelayTimeout = setTimeout(() => {
|
|
228
|
+
if (mysteryFxGeneration !== this.mysteryFxGeneration) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.mysteryDelayTimeout = null;
|
|
232
|
+
this.skipScatterDelay = null;
|
|
233
|
+
this.mysteryFxGeneration += 1;
|
|
234
|
+
action();
|
|
235
|
+
}, delay);
|
|
236
|
+
}
|
|
177
237
|
/**
|
|
178
238
|
* Function for playing all streaks
|
|
179
239
|
* @public
|
|
@@ -373,8 +433,10 @@ export class AbstractColumnsContainer extends Container {
|
|
|
373
433
|
*/
|
|
374
434
|
prepareConfiguringReelsEnd(finalSymbolReels) {
|
|
375
435
|
return this.allColumns.map((column, index) => async () => {
|
|
436
|
+
this.currentColumn = column;
|
|
376
437
|
column.configBlindSpin(finalSymbolReels[index]);
|
|
377
438
|
await column.getTriggersPromise();
|
|
439
|
+
this.currentColumn = null;
|
|
378
440
|
});
|
|
379
441
|
}
|
|
380
442
|
}
|
|
@@ -167,6 +167,12 @@ export declare abstract class AbstractSymbolsColumn extends Container implements
|
|
|
167
167
|
* @returns {Promise<void>} stop promise
|
|
168
168
|
*/
|
|
169
169
|
getStopPromise(): Promise<void>;
|
|
170
|
+
/**
|
|
171
|
+
* Function for releasing trigger to next column
|
|
172
|
+
* @public
|
|
173
|
+
* @returns {void}
|
|
174
|
+
*/
|
|
175
|
+
releaseNextColumnTrigger(): void;
|
|
170
176
|
/**
|
|
171
177
|
* Function for stopping all playing animations of symbols
|
|
172
178
|
* @public
|
|
@@ -298,6 +298,17 @@ export class AbstractSymbolsColumn extends Container {
|
|
|
298
298
|
}
|
|
299
299
|
throw new Error("No promise to return");
|
|
300
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Function for releasing trigger to next column
|
|
303
|
+
* @public
|
|
304
|
+
* @returns {void}
|
|
305
|
+
*/
|
|
306
|
+
releaseNextColumnTrigger() {
|
|
307
|
+
if (this.triggerNextColumn !== null) {
|
|
308
|
+
this.triggerNextColumn();
|
|
309
|
+
this.triggerNextColumn = null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
301
312
|
/**
|
|
302
313
|
* Function for stopping all playing animations of symbols
|
|
303
314
|
* @public
|
|
@@ -618,12 +629,9 @@ export class AbstractSymbolsColumn extends Container {
|
|
|
618
629
|
if (element) {
|
|
619
630
|
// swap symbol with chosen element
|
|
620
631
|
symbol.swapSymbol(element);
|
|
621
|
-
// symbol.setSpineMode(MOVE3);
|
|
622
632
|
}
|
|
623
633
|
if (this.ending.length === 1) {
|
|
624
|
-
|
|
625
|
-
this.triggerNextColumn();
|
|
626
|
-
}
|
|
634
|
+
this.releaseNextColumnTrigger();
|
|
627
635
|
}
|
|
628
636
|
if (this.ending.length === 0) {
|
|
629
637
|
this.shouldMoveToTop = false;
|
|
@@ -64,6 +64,7 @@ export declare abstract class AbstractController<T> {
|
|
|
64
64
|
protected resolveSuperBonusWin?: () => void;
|
|
65
65
|
clearMobileSpinTimeout: (() => void) | undefined;
|
|
66
66
|
protected initData: InitDataInterface;
|
|
67
|
+
protected shouldPlayNextSpin: boolean;
|
|
67
68
|
protected _lastWinAmount: number;
|
|
68
69
|
protected constructor(buttonsEventManager: ButtonsEventManager, mainContainer: AbstractMainContainer, connection: SubscribableConnectionWrapper);
|
|
69
70
|
/**
|
|
@@ -262,6 +263,7 @@ export declare abstract class AbstractController<T> {
|
|
|
262
263
|
* @returns {void}
|
|
263
264
|
*/
|
|
264
265
|
protected throttledSpin(): void;
|
|
266
|
+
protected prepareBoughtFreeSpins(): void;
|
|
265
267
|
/**
|
|
266
268
|
* This function is responsible for getting the number of free spins bought
|
|
267
269
|
* @private
|
|
@@ -366,7 +368,7 @@ export declare abstract class AbstractController<T> {
|
|
|
366
368
|
* @param {number} winAmount amount from gamble game
|
|
367
369
|
* @returns {void}
|
|
368
370
|
*/
|
|
369
|
-
|
|
371
|
+
gambleGameEnabler(winAmount: number): void;
|
|
370
372
|
/**
|
|
371
373
|
* Function for spin logic of the game
|
|
372
374
|
* This function is responsible for:
|
|
@@ -64,6 +64,7 @@ export class AbstractController {
|
|
|
64
64
|
resolveSuperBonusWin;
|
|
65
65
|
clearMobileSpinTimeout;
|
|
66
66
|
initData;
|
|
67
|
+
shouldPlayNextSpin = false;
|
|
67
68
|
_lastWinAmount = 0;
|
|
68
69
|
constructor(buttonsEventManager, mainContainer, connection) {
|
|
69
70
|
this.buttonsEventManager = buttonsEventManager;
|
|
@@ -102,6 +103,7 @@ export class AbstractController {
|
|
|
102
103
|
RainMan.settingsStore.setRoundNumber(this.roundNumber);
|
|
103
104
|
RainMan.settingsStore.initPaytableMap(initData);
|
|
104
105
|
RainMan.globals.throttledSpin = this.throttledSpin.bind(this);
|
|
106
|
+
RainMan.globals.prepareBoughtFreeSpins = this.prepareBoughtFreeSpins.bind(this);
|
|
105
107
|
RainMan.settingsStore.useTakeAction = this.useTakeAction.bind(this);
|
|
106
108
|
this.connection.subscribeForConfigChanges(this.reinitializeUserBalanceData.bind(this));
|
|
107
109
|
this.uiController.updateBet("first");
|
|
@@ -480,30 +482,47 @@ export class AbstractController {
|
|
|
480
482
|
this.clearMobileSpinTimeout();
|
|
481
483
|
});
|
|
482
484
|
refreshButton.on("touchstart", () => {
|
|
485
|
+
if (this.mobileSpinTimeout) {
|
|
486
|
+
clearInterval(this.mobileSpinTimeout);
|
|
487
|
+
this.mobileSpinTimeout = null;
|
|
488
|
+
}
|
|
489
|
+
if (this.mobileSpinDelay) {
|
|
490
|
+
clearTimeout(this.mobileSpinDelay);
|
|
491
|
+
this.mobileSpinDelay = null;
|
|
492
|
+
}
|
|
483
493
|
if (this.buttonHeldSince === 0) {
|
|
484
494
|
this.buttonHeldSince = Date.now();
|
|
485
495
|
}
|
|
486
|
-
this.
|
|
487
|
-
|
|
488
|
-
if (
|
|
489
|
-
this.columnsContainer.enableQuickReelsStop();
|
|
490
|
-
}
|
|
491
|
-
this.handleDisablingButtons(true);
|
|
492
|
-
this.quickStopController.setQuickStopCounterLock(true);
|
|
493
|
-
this.summaryStop = this.skipFreeSpinSummary ? false : this.invokeFreeSpinSummaryPlateAfterWin;
|
|
494
|
-
if (this.invokeFreeSpinPlateAfterWin ||
|
|
495
|
-
this.summaryStop ||
|
|
496
|
-
this.shouldStopMobileSpin ||
|
|
497
|
-
this.resolveBigWin !== undefined ||
|
|
498
|
-
this.resolveSuperBonusWin !== undefined ||
|
|
499
|
-
this.resolveMysteryWin !== undefined) {
|
|
500
|
-
if (this.clearMobileSpinTimeout) {
|
|
501
|
-
this.clearMobileSpinTimeout();
|
|
502
|
-
}
|
|
496
|
+
this.mobileSpinDelay = setTimeout(() => {
|
|
497
|
+
this.mobileSpinDelay = null;
|
|
498
|
+
if (this.buttonHeldSince === 0) {
|
|
503
499
|
return;
|
|
504
500
|
}
|
|
505
|
-
this.
|
|
506
|
-
|
|
501
|
+
this.mobileSpinTimeout = setInterval(() => {
|
|
502
|
+
if (this.buttonHeldSince === 0) {
|
|
503
|
+
if (this.clearMobileSpinTimeout) {
|
|
504
|
+
this.clearMobileSpinTimeout();
|
|
505
|
+
}
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
this.columnsContainer.enableQuickReelsStop();
|
|
509
|
+
this.handleDisablingButtons(true);
|
|
510
|
+
this.quickStopController.setQuickStopCounterLock(true);
|
|
511
|
+
this.summaryStop = this.skipFreeSpinSummary ? false : this.invokeFreeSpinSummaryPlateAfterWin;
|
|
512
|
+
if (this.invokeFreeSpinPlateAfterWin ||
|
|
513
|
+
this.summaryStop ||
|
|
514
|
+
this.shouldStopMobileSpin ||
|
|
515
|
+
this.resolveBigWin !== undefined ||
|
|
516
|
+
this.resolveSuperBonusWin !== undefined ||
|
|
517
|
+
this.resolveMysteryWin !== undefined) {
|
|
518
|
+
if (this.clearMobileSpinTimeout) {
|
|
519
|
+
this.clearMobileSpinTimeout();
|
|
520
|
+
}
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
this.handleSpinLogic();
|
|
524
|
+
}, RainMan.config.durationOfActions.mobileSpinTimeout);
|
|
525
|
+
}, 250);
|
|
507
526
|
});
|
|
508
527
|
}
|
|
509
528
|
/**
|
|
@@ -727,6 +746,9 @@ export class AbstractController {
|
|
|
727
746
|
this.mainContainer.freeSpinSummary.emit("pointerdown", new PIXI.FederatedPointerEvent("pointerdown"));
|
|
728
747
|
return;
|
|
729
748
|
}
|
|
749
|
+
if (this.gamePhase === gamePhases.HANDLING_ACTIONS) {
|
|
750
|
+
this.shouldPlayNextSpin = true;
|
|
751
|
+
}
|
|
730
752
|
if (this.mainContainer.mysteryWinVisibleFor) {
|
|
731
753
|
RainMan.componentRegistry.get(COMPONENTS.mysteryWin).stopUpdate();
|
|
732
754
|
}
|
|
@@ -786,12 +808,7 @@ export class AbstractController {
|
|
|
786
808
|
this.quickStopController.handleInvokingSpeedPopup();
|
|
787
809
|
return;
|
|
788
810
|
}
|
|
789
|
-
|
|
790
|
-
this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
|
|
791
|
-
RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
|
|
792
|
-
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
811
|
+
this.prepareBoughtFreeSpins();
|
|
795
812
|
if (RainMan.settingsStore.isAutoplayEnabled && !this.spinning) {
|
|
796
813
|
this.changeGamePhase(gamePhases.IDLE);
|
|
797
814
|
this.spin();
|
|
@@ -806,6 +823,14 @@ export class AbstractController {
|
|
|
806
823
|
}
|
|
807
824
|
this.spinThrottlerTimeout = setTimeout(() => (this.spinThrottlerTimeout = null), 100);
|
|
808
825
|
}
|
|
826
|
+
prepareBoughtFreeSpins() {
|
|
827
|
+
if (!RainMan.settingsStore.isFreeSpinsBought) {
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
|
|
831
|
+
RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
|
|
832
|
+
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
833
|
+
}
|
|
809
834
|
/**
|
|
810
835
|
* This function is responsible for getting the number of free spins bought
|
|
811
836
|
* @private
|
|
@@ -866,6 +891,12 @@ export class AbstractController {
|
|
|
866
891
|
logInfo("Take action can't be performed");
|
|
867
892
|
return;
|
|
868
893
|
}
|
|
894
|
+
if (this.currentlyPlayedAction !== undefined) {
|
|
895
|
+
this.changeGamePhase(gamePhases.STOPPING_HANDLING_ACTIONS);
|
|
896
|
+
this.stopPlayingSymbolsStreak();
|
|
897
|
+
await this.currentlyPlayedAction;
|
|
898
|
+
}
|
|
899
|
+
await Promise.all(this.uiController.promisesToSetBalances);
|
|
869
900
|
const takeData = await window.connectionWrapper.sendTakeAction(RainMan.settingsStore.roundNumber);
|
|
870
901
|
if (takeData.status.code === 200) {
|
|
871
902
|
RainMan.settingsStore.isTakeActionAvailable = false;
|
|
@@ -981,14 +1012,10 @@ export class AbstractController {
|
|
|
981
1012
|
*/
|
|
982
1013
|
gambleGameEnabler(winAmount) {
|
|
983
1014
|
if (RainMan.componentRegistry.has(BUTTONS.gamble) && RainMan.settingsStore.isGambleGameAvailable) {
|
|
984
|
-
RainMan.componentRegistry
|
|
985
|
-
.get(BUTTONS.gamble)
|
|
986
|
-
.flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || winAmount === 0);
|
|
1015
|
+
RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(winAmount === 0);
|
|
987
1016
|
}
|
|
988
1017
|
if (RainMan.componentRegistry.has(BUTTONS.take) && RainMan.settingsStore.isTakeActionAvailable) {
|
|
989
|
-
RainMan.componentRegistry
|
|
990
|
-
.get(BUTTONS.take)
|
|
991
|
-
.flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || winAmount === 0);
|
|
1018
|
+
RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(winAmount === 0);
|
|
992
1019
|
}
|
|
993
1020
|
}
|
|
994
1021
|
/**
|
|
@@ -1067,7 +1094,7 @@ export class AbstractController {
|
|
|
1067
1094
|
const availableFreeSpins = spinLogic.availableFreeSpins;
|
|
1068
1095
|
const availableFreeSpinsIncreased = availableFreeSpins > RainMan.settingsStore.howManyFreeSpinsLeft;
|
|
1069
1096
|
this.hideFreeSpinsMessageBox = availableFreeSpinsIncreased;
|
|
1070
|
-
if (this._lastWinAmount !== 0) {
|
|
1097
|
+
if (this._lastWinAmount !== 0 && !(availableFreeSpins > 0)) {
|
|
1071
1098
|
RainMan.settingsStore.isTakeActionAvailable = true;
|
|
1072
1099
|
RainMan.settingsStore.isGambleGameAvailable = true;
|
|
1073
1100
|
}
|
|
@@ -1206,6 +1233,24 @@ export class AbstractController {
|
|
|
1206
1233
|
}
|
|
1207
1234
|
RainMan.settingsStore.setIsPlayingAnyAction(false);
|
|
1208
1235
|
this.columnsContainer.setInteractivityForSymbols(true);
|
|
1236
|
+
const shouldStartNextSpin = this.shouldPlayNextSpin &&
|
|
1237
|
+
!RainMan.settingsStore.isAutoplayEnabled &&
|
|
1238
|
+
!RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
1239
|
+
!this.invokeFreeSpinPlateAfterWin &&
|
|
1240
|
+
!this.invokeFreeSpinSummaryPlateAfterWin &&
|
|
1241
|
+
!RainMan.globals.isSuperBonusGameEnabled;
|
|
1242
|
+
this.shouldPlayNextSpin = false;
|
|
1243
|
+
if (shouldStartNextSpin) {
|
|
1244
|
+
setTimeout(() => {
|
|
1245
|
+
if (!this.spinning &&
|
|
1246
|
+
this.gamePhase !== gamePhases.SPINNING &&
|
|
1247
|
+
this.gamePhase !== gamePhases.DATA_FETCH &&
|
|
1248
|
+
this.gamePhase !== gamePhases.CONFIGURING_SPIN &&
|
|
1249
|
+
!RainMan.settingsStore.isPlayingAnyAction) {
|
|
1250
|
+
this.throttledSpin();
|
|
1251
|
+
}
|
|
1252
|
+
}, 0);
|
|
1253
|
+
}
|
|
1209
1254
|
}
|
|
1210
1255
|
/**
|
|
1211
1256
|
* Function for invoking free spin plate, invoked in mainContainer
|
|
@@ -1234,7 +1279,6 @@ export class AbstractController {
|
|
|
1234
1279
|
*/
|
|
1235
1280
|
async handleFreeSpinSummaryPlateInvocation() {
|
|
1236
1281
|
await this.buttonsEventManager.disableButtonsForAction(async () => {
|
|
1237
|
-
this.uiController.updateDisplayedBalance(this.uiController.totalFreeSpinWinAmount);
|
|
1238
1282
|
this.uiController.messageBox.hideFreeSpinText();
|
|
1239
1283
|
this.uiController.messageBox.hideCurrentWinText();
|
|
1240
1284
|
await this.mainContainer.invokeFreeSpinSummary(this.uiController.totalNumberOfFreeSpins, this.uiController.totalFreeSpinWinAmount);
|
|
@@ -1242,7 +1286,6 @@ export class AbstractController {
|
|
|
1242
1286
|
this.uiController.resetTotalFreeSpinWinAmount();
|
|
1243
1287
|
this.changeGamePhase(gamePhases.IDLE);
|
|
1244
1288
|
});
|
|
1245
|
-
this.uiController.currentBalance = RainMan.settingsStore.balanceAfterSpin;
|
|
1246
1289
|
RainMan.settingsStore.resetTotalNumberOfFreeSpins();
|
|
1247
1290
|
RainMan.settingsStore.resetFreeSpinNumberBought();
|
|
1248
1291
|
this.changeGamePhase(gamePhases.IDLE);
|
|
@@ -1314,6 +1357,8 @@ export class AbstractController {
|
|
|
1314
1357
|
stopPlayingSymbolsStreak() {
|
|
1315
1358
|
this.columnsContainer.stopPlayingSymbolsInColumns();
|
|
1316
1359
|
this.frame.stopPlayingWinLineAnimations();
|
|
1360
|
+
this.frame.hideMysteryFx();
|
|
1361
|
+
this.frame.destroyMysteryFx();
|
|
1317
1362
|
}
|
|
1318
1363
|
/**
|
|
1319
1364
|
* Function for stopping playing symbols transformation
|
package/package.json
CHANGED