pixi-rainman-game-engine 0.3.29 → 0.3.30
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 +67 -9
- package/dist/controllers/AbstractController.d.ts +3 -1
- package/dist/controllers/AbstractController.js +41 -15
- 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,12 @@ 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();
|
|
100
104
|
this.resolveMysterySpeedUp();
|
|
101
|
-
this.skipScatterDelay = null;
|
|
102
105
|
if (this.currentColumn) {
|
|
103
106
|
this.currentColumn.skipHidingMysteryFx = true;
|
|
104
107
|
}
|
|
@@ -133,10 +136,15 @@ export class AbstractColumnsContainer extends Container {
|
|
|
133
136
|
// spin
|
|
134
137
|
return new Promise(async (resolve) => {
|
|
135
138
|
let index = 0;
|
|
139
|
+
this.clearPendingMysteryDelay();
|
|
140
|
+
this.mysteryFxGeneration = 0;
|
|
141
|
+
this.skipRemainingMysteryFxs = false;
|
|
136
142
|
const configuredBlindSpinsActions = this.prepareConfiguringReelsEnd(finalSymbolReels);
|
|
137
143
|
const frame = RainMan.componentRegistry.get(AbstractFrame.registryName);
|
|
138
144
|
while (configuredBlindSpinsActions.length !== 0) {
|
|
139
|
-
if (this.quickReelsStop ||
|
|
145
|
+
if (this.quickReelsStop ||
|
|
146
|
+
this.skipRemainingMysteryFxs ||
|
|
147
|
+
RainMan.settingsStore.currentSpeed === SPEED_LEVELS.fast) {
|
|
140
148
|
await Promise.all(configuredBlindSpinsActions.map(async (action) => await action()));
|
|
141
149
|
configuredBlindSpinsActions.length = 0;
|
|
142
150
|
SoundManager.play(SoundTracks.allRollStops);
|
|
@@ -150,16 +158,16 @@ export class AbstractColumnsContainer extends Container {
|
|
|
150
158
|
frame.invokeMysteryFx(this.currentColumn.x, this.currentColumn.y);
|
|
151
159
|
this.skipScatterDelay = configureSpinAction;
|
|
152
160
|
await this.currentColumn.speedUpForMysterySpin(100, 1500);
|
|
153
|
-
if (
|
|
161
|
+
if (this.quickReelsStop || this.skipRemainingMysteryFxs) {
|
|
162
|
+
await this.currentColumn.changeVelocity(Speed.STOP, 0, frame);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
154
165
|
if (!RainMan.settingsStore.isAutoplayEnabled ||
|
|
155
166
|
(RainMan.settingsStore.isAutoplayEnabled && !this.quickReelsStop)) {
|
|
156
|
-
|
|
157
|
-
this.skipScatterDelay?.();
|
|
158
|
-
this.skipScatterDelay = null;
|
|
159
|
-
}, RainMan.config.durationOfActions.scatterDelayerTime);
|
|
167
|
+
this.scheduleMysteryDelay(configureSpinAction, RainMan.config.durationOfActions.scatterDelayerTime);
|
|
160
168
|
}
|
|
169
|
+
await this.currentColumn.changeVelocity(Speed.STOP, RainMan.config.durationOfActions.scatterSpinningTime, frame);
|
|
161
170
|
}
|
|
162
|
-
await this.currentColumn.changeVelocity(Speed.STOP, RainMan.config.durationOfActions.scatterSpinningTime, frame);
|
|
163
171
|
frame.destroyMysteryFx();
|
|
164
172
|
}
|
|
165
173
|
if (!indexesOfReelsToExtendSpinningTime.includes(index)) {
|
|
@@ -170,10 +178,60 @@ export class AbstractColumnsContainer extends Container {
|
|
|
170
178
|
this.currentColumn = null;
|
|
171
179
|
}
|
|
172
180
|
await Promise.all(this.allColumns.map((column) => column.getStopPromise()));
|
|
181
|
+
this.clearPendingMysteryDelay();
|
|
182
|
+
this.mysteryFxGeneration = 0;
|
|
183
|
+
this.skipRemainingMysteryFxs = false;
|
|
173
184
|
afterSpinResolver();
|
|
174
185
|
resolve();
|
|
175
186
|
});
|
|
176
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* This cancels the timeout, removes the stored delayed action and invalidates
|
|
190
|
+
* any older timeout callback that might still try to execute later.
|
|
191
|
+
* @private
|
|
192
|
+
* @returns {void}
|
|
193
|
+
*/
|
|
194
|
+
clearPendingMysteryDelay() {
|
|
195
|
+
this.mysteryFxGeneration += 1;
|
|
196
|
+
if (this.mysteryDelayTimeout !== null) {
|
|
197
|
+
clearTimeout(this.mysteryDelayTimeout);
|
|
198
|
+
this.mysteryDelayTimeout = null;
|
|
199
|
+
}
|
|
200
|
+
this.skipScatterDelay = null;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Runs the pending mysteryFx immediately and clears its timeout.
|
|
204
|
+
* @private
|
|
205
|
+
* @returns {void}
|
|
206
|
+
*/
|
|
207
|
+
executePendingMysteryFx() {
|
|
208
|
+
const pendingMysteryDelay = this.skipScatterDelay;
|
|
209
|
+
this.clearPendingMysteryDelay();
|
|
210
|
+
pendingMysteryDelay?.();
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The callback is bound to the current generation so an old timeout from
|
|
214
|
+
* a previous spin cannot execute after a newer mystery delay was scheduled.
|
|
215
|
+
* @private
|
|
216
|
+
* @param {PlayableAction} action delayed reel configuration action
|
|
217
|
+
* @param {number} delay time in milliseconds before the action should run
|
|
218
|
+
* @returns {void}
|
|
219
|
+
*/
|
|
220
|
+
scheduleMysteryDelay(action, delay) {
|
|
221
|
+
this.clearPendingMysteryDelay();
|
|
222
|
+
// Store new mysteryFx action to be available in executePendingMysteryFx
|
|
223
|
+
this.skipScatterDelay = action;
|
|
224
|
+
const mysteryFxGeneration = this.mysteryFxGeneration;
|
|
225
|
+
this.mysteryDelayTimeout = setTimeout(() => {
|
|
226
|
+
if (mysteryFxGeneration !== this.mysteryFxGeneration) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
this.mysteryDelayTimeout = null;
|
|
230
|
+
this.skipScatterDelay = null;
|
|
231
|
+
this.mysteryFxGeneration += 1;
|
|
232
|
+
action();
|
|
233
|
+
}, delay);
|
|
234
|
+
}
|
|
177
235
|
/**
|
|
178
236
|
* Function for playing all streaks
|
|
179
237
|
* @public
|
|
@@ -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");
|
|
@@ -727,6 +729,9 @@ export class AbstractController {
|
|
|
727
729
|
this.mainContainer.freeSpinSummary.emit("pointerdown", new PIXI.FederatedPointerEvent("pointerdown"));
|
|
728
730
|
return;
|
|
729
731
|
}
|
|
732
|
+
if (this.gamePhase === gamePhases.HANDLING_ACTIONS) {
|
|
733
|
+
this.shouldPlayNextSpin = true;
|
|
734
|
+
}
|
|
730
735
|
if (this.mainContainer.mysteryWinVisibleFor) {
|
|
731
736
|
RainMan.componentRegistry.get(COMPONENTS.mysteryWin).stopUpdate();
|
|
732
737
|
}
|
|
@@ -786,12 +791,7 @@ export class AbstractController {
|
|
|
786
791
|
this.quickStopController.handleInvokingSpeedPopup();
|
|
787
792
|
return;
|
|
788
793
|
}
|
|
789
|
-
|
|
790
|
-
this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
|
|
791
|
-
RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
|
|
792
|
-
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
794
|
+
this.prepareBoughtFreeSpins();
|
|
795
795
|
if (RainMan.settingsStore.isAutoplayEnabled && !this.spinning) {
|
|
796
796
|
this.changeGamePhase(gamePhases.IDLE);
|
|
797
797
|
this.spin();
|
|
@@ -806,6 +806,14 @@ export class AbstractController {
|
|
|
806
806
|
}
|
|
807
807
|
this.spinThrottlerTimeout = setTimeout(() => (this.spinThrottlerTimeout = null), 100);
|
|
808
808
|
}
|
|
809
|
+
prepareBoughtFreeSpins() {
|
|
810
|
+
if (!RainMan.settingsStore.isFreeSpinsBought) {
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
|
|
814
|
+
RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
|
|
815
|
+
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
816
|
+
}
|
|
809
817
|
/**
|
|
810
818
|
* This function is responsible for getting the number of free spins bought
|
|
811
819
|
* @private
|
|
@@ -866,6 +874,12 @@ export class AbstractController {
|
|
|
866
874
|
logInfo("Take action can't be performed");
|
|
867
875
|
return;
|
|
868
876
|
}
|
|
877
|
+
if (this.currentlyPlayedAction !== undefined) {
|
|
878
|
+
this.changeGamePhase(gamePhases.STOPPING_HANDLING_ACTIONS);
|
|
879
|
+
this.stopPlayingSymbolsStreak();
|
|
880
|
+
await this.currentlyPlayedAction;
|
|
881
|
+
}
|
|
882
|
+
await Promise.all(this.uiController.promisesToSetBalances);
|
|
869
883
|
const takeData = await window.connectionWrapper.sendTakeAction(RainMan.settingsStore.roundNumber);
|
|
870
884
|
if (takeData.status.code === 200) {
|
|
871
885
|
RainMan.settingsStore.isTakeActionAvailable = false;
|
|
@@ -981,14 +995,10 @@ export class AbstractController {
|
|
|
981
995
|
*/
|
|
982
996
|
gambleGameEnabler(winAmount) {
|
|
983
997
|
if (RainMan.componentRegistry.has(BUTTONS.gamble) && RainMan.settingsStore.isGambleGameAvailable) {
|
|
984
|
-
RainMan.componentRegistry
|
|
985
|
-
.get(BUTTONS.gamble)
|
|
986
|
-
.flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || winAmount === 0);
|
|
998
|
+
RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(winAmount === 0);
|
|
987
999
|
}
|
|
988
1000
|
if (RainMan.componentRegistry.has(BUTTONS.take) && RainMan.settingsStore.isTakeActionAvailable) {
|
|
989
|
-
RainMan.componentRegistry
|
|
990
|
-
.get(BUTTONS.take)
|
|
991
|
-
.flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || winAmount === 0);
|
|
1001
|
+
RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(winAmount === 0);
|
|
992
1002
|
}
|
|
993
1003
|
}
|
|
994
1004
|
/**
|
|
@@ -1067,7 +1077,7 @@ export class AbstractController {
|
|
|
1067
1077
|
const availableFreeSpins = spinLogic.availableFreeSpins;
|
|
1068
1078
|
const availableFreeSpinsIncreased = availableFreeSpins > RainMan.settingsStore.howManyFreeSpinsLeft;
|
|
1069
1079
|
this.hideFreeSpinsMessageBox = availableFreeSpinsIncreased;
|
|
1070
|
-
if (this._lastWinAmount !== 0) {
|
|
1080
|
+
if (this._lastWinAmount !== 0 && !(availableFreeSpins > 0)) {
|
|
1071
1081
|
RainMan.settingsStore.isTakeActionAvailable = true;
|
|
1072
1082
|
RainMan.settingsStore.isGambleGameAvailable = true;
|
|
1073
1083
|
}
|
|
@@ -1206,6 +1216,24 @@ export class AbstractController {
|
|
|
1206
1216
|
}
|
|
1207
1217
|
RainMan.settingsStore.setIsPlayingAnyAction(false);
|
|
1208
1218
|
this.columnsContainer.setInteractivityForSymbols(true);
|
|
1219
|
+
const shouldStartNextSpin = this.shouldPlayNextSpin &&
|
|
1220
|
+
!RainMan.settingsStore.isAutoplayEnabled &&
|
|
1221
|
+
!RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
1222
|
+
!this.invokeFreeSpinPlateAfterWin &&
|
|
1223
|
+
!this.invokeFreeSpinSummaryPlateAfterWin &&
|
|
1224
|
+
!RainMan.globals.isSuperBonusGameEnabled;
|
|
1225
|
+
this.shouldPlayNextSpin = false;
|
|
1226
|
+
if (shouldStartNextSpin) {
|
|
1227
|
+
setTimeout(() => {
|
|
1228
|
+
if (!this.spinning &&
|
|
1229
|
+
this.gamePhase !== gamePhases.SPINNING &&
|
|
1230
|
+
this.gamePhase !== gamePhases.DATA_FETCH &&
|
|
1231
|
+
this.gamePhase !== gamePhases.CONFIGURING_SPIN &&
|
|
1232
|
+
!RainMan.settingsStore.isPlayingAnyAction) {
|
|
1233
|
+
this.throttledSpin();
|
|
1234
|
+
}
|
|
1235
|
+
}, 0);
|
|
1236
|
+
}
|
|
1209
1237
|
}
|
|
1210
1238
|
/**
|
|
1211
1239
|
* Function for invoking free spin plate, invoked in mainContainer
|
|
@@ -1234,7 +1262,6 @@ export class AbstractController {
|
|
|
1234
1262
|
*/
|
|
1235
1263
|
async handleFreeSpinSummaryPlateInvocation() {
|
|
1236
1264
|
await this.buttonsEventManager.disableButtonsForAction(async () => {
|
|
1237
|
-
this.uiController.updateDisplayedBalance(this.uiController.totalFreeSpinWinAmount);
|
|
1238
1265
|
this.uiController.messageBox.hideFreeSpinText();
|
|
1239
1266
|
this.uiController.messageBox.hideCurrentWinText();
|
|
1240
1267
|
await this.mainContainer.invokeFreeSpinSummary(this.uiController.totalNumberOfFreeSpins, this.uiController.totalFreeSpinWinAmount);
|
|
@@ -1242,7 +1269,6 @@ export class AbstractController {
|
|
|
1242
1269
|
this.uiController.resetTotalFreeSpinWinAmount();
|
|
1243
1270
|
this.changeGamePhase(gamePhases.IDLE);
|
|
1244
1271
|
});
|
|
1245
|
-
this.uiController.currentBalance = RainMan.settingsStore.balanceAfterSpin;
|
|
1246
1272
|
RainMan.settingsStore.resetTotalNumberOfFreeSpins();
|
|
1247
1273
|
RainMan.settingsStore.resetFreeSpinNumberBought();
|
|
1248
1274
|
this.changeGamePhase(gamePhases.IDLE);
|
package/package.json
CHANGED