pixi-rainman-game-engine 0.3.40 → 0.3.42
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/appConfig.js +1 -0
- package/dist/Rainman/types.d.ts +1 -0
- package/dist/SettingsUI/components/AutoplaySettings/index.jsx +14 -1
- package/dist/SettingsUI/components/SpeedSwitchButton/index.jsx +2 -2
- package/dist/SettingsUI/components/VolumeSettings/volume.css +1 -1
- package/dist/application/SoundManager/SoundManager.d.ts +8 -1
- package/dist/application/SoundManager/SoundManager.js +48 -16
- package/dist/application/SoundManager/types.d.ts +4 -0
- package/dist/application/SoundManager/types.js +5 -1
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +4 -0
- package/dist/components/GambleGame/GambleGame.js +18 -1
- package/dist/components/frame/AbstractColumnsContainer.d.ts +18 -0
- package/dist/components/frame/AbstractColumnsContainer.js +73 -0
- package/dist/components/messageBox/MessageBox.d.ts +11 -0
- package/dist/components/messageBox/MessageBox.js +20 -0
- package/dist/connectivity/serverData.d.ts +1 -0
- package/dist/controllers/AbstractController.js +14 -2
- package/dist/controllers/UiController.d.ts +7 -0
- package/dist/controllers/UiController.js +17 -0
- package/dist/loading/AbstractLoadingContainer.js +1 -1
- package/dist/stores/SettingsStore.d.ts +13 -0
- package/dist/stores/SettingsStore.js +26 -0
- package/dist/utils/common/sound.js +3 -3
- package/dist/winComponents/TexturedText.d.ts +2 -0
- package/dist/winComponents/TexturedText.js +13 -0
- package/package.json +1 -1
package/dist/Rainman/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import i18next from "i18next";
|
|
|
4
4
|
import { observer } from "mobx-react-lite";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { COMPONENTS } from "../../../components";
|
|
7
|
+
import { RainMan } from "../../../Rainman";
|
|
7
8
|
import { UI_ITEMS } from "../../../utils";
|
|
8
9
|
import { useStores } from "../../hooks";
|
|
9
10
|
import { CloseModalButton } from "../CloseModalButton";
|
|
@@ -11,11 +12,18 @@ import { RichLimitingSlider } from "../RichLimitingSlider";
|
|
|
11
12
|
import { SpeedButtonWithHeader, SwitchWithHeader } from "../SwitchWithHeader";
|
|
12
13
|
const initialAutoSpinCount = 10;
|
|
13
14
|
const availableAutoSpinLimits = [10, 20, 50, 70, 100];
|
|
15
|
+
const infiniteAutoSpinCount = 1000000;
|
|
14
16
|
export const AutoplaySettings = observer(() => {
|
|
15
17
|
const { settingStore } = useStores();
|
|
18
|
+
const infinityAutoplayEnabled = RainMan.config.enableInfinityAutoplay;
|
|
16
19
|
const updateLimitsBounds = (newLimit) => {
|
|
20
|
+
settingStore.setInfinitySpinsEnabled(false);
|
|
17
21
|
setAutoSpinsCount(newLimit);
|
|
18
22
|
};
|
|
23
|
+
const enableInfinityAutoplay = () => {
|
|
24
|
+
settingStore.setInfinitySpinsEnabled(true);
|
|
25
|
+
setAutoSpinsCount(infiniteAutoSpinCount);
|
|
26
|
+
};
|
|
19
27
|
const { singleWinExceeds, balancedIncreased, balancedDecreased, howManyAutoSpinsLeft, infinitySpinsEnabled, setSingleWinExceeds, setBalancedIncreased, setBalancedDecreased, setAutoSpinsCount, resetAutoplaySettings } = settingStore;
|
|
20
28
|
return (<div className="autoplay-settings">
|
|
21
29
|
<CloseModalButton layerId={UI_ITEMS.autoplay}/>
|
|
@@ -23,9 +31,14 @@ export const AutoplaySettings = observer(() => {
|
|
|
23
31
|
<h2>{i18next.t("autoPlay")}</h2>
|
|
24
32
|
</div>
|
|
25
33
|
<div className="autoplay-settings__stop-limits">
|
|
26
|
-
{availableAutoSpinLimits.map((limiter, index) => (<button key={`${limiter}${index}`} value={limiter} className={`autoplay-settings__limit ${limiter === howManyAutoSpinsLeft
|
|
34
|
+
{availableAutoSpinLimits.map((limiter, index) => (<button key={`${limiter}${index}`} value={limiter} className={`autoplay-settings__limit ${!infinitySpinsEnabled && limiter === howManyAutoSpinsLeft
|
|
35
|
+
? "autoplay-settings__limit--active"
|
|
36
|
+
: ""} middle`} onClick={(event) => updateLimitsBounds(Number(event.currentTarget.value))}>
|
|
27
37
|
<p>{limiter}</p>
|
|
28
38
|
</button>))}
|
|
39
|
+
{infinityAutoplayEnabled && (<button value="infinity" className={`autoplay-settings__limit ${infinitySpinsEnabled ? "autoplay-settings__limit--active" : ""} right`} onClick={enableInfinityAutoplay}>
|
|
40
|
+
<p>∞</p>
|
|
41
|
+
</button>)}
|
|
29
42
|
</div>
|
|
30
43
|
<div className="separator"/>
|
|
31
44
|
<div className="autoplay-settings__title">
|
|
@@ -5,13 +5,13 @@ export const SpeedButtonSwitch = observer(() => {
|
|
|
5
5
|
const speedLevelMapper = {
|
|
6
6
|
slow: "turtle",
|
|
7
7
|
normal: "rabbit",
|
|
8
|
-
fast: "cheetah"
|
|
8
|
+
fast: "cheetah"
|
|
9
9
|
};
|
|
10
10
|
const { settingStore } = useStores();
|
|
11
11
|
const { currentSpeed } = settingStore;
|
|
12
12
|
return (<label className="switch turtle-switch speed-level-id">
|
|
13
13
|
<span className="turtle-switch-round-box"/>
|
|
14
|
-
<img className="turtle-switch__icon" src={`assets/settings/speed-${speedLevelMapper[currentSpeed]}.
|
|
14
|
+
<img className="turtle-switch__icon" src={`assets/settings/speed-${speedLevelMapper[currentSpeed]}.webp`}/>
|
|
15
15
|
<div className="dot-container">
|
|
16
16
|
{Array.from({ length: 3 }).map((_, i) => (<div key={i} className={`white-dot ${i < settingStore.indexOfSpeedLevel ? "white-dot--active" : ""}`}/>))}
|
|
17
17
|
</div>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
bottom: 5px;
|
|
37
37
|
width: 30px;
|
|
38
38
|
height: 30px;
|
|
39
|
-
background-image: url("/assets/settings/sound-icon.
|
|
39
|
+
background-image: url("/assets/settings/sound-icon.webp");
|
|
40
40
|
background-position: center;
|
|
41
41
|
background-size: contain;
|
|
42
42
|
background-repeat: no-repeat;
|
|
@@ -16,6 +16,7 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
16
16
|
readonly speedLevelMapper: SpeedLevelDirectory<SoundOverrides>;
|
|
17
17
|
private musicCatalogue;
|
|
18
18
|
private currentAmbientTrack;
|
|
19
|
+
private pausedSoundsForPageHide;
|
|
19
20
|
constructor();
|
|
20
21
|
/**
|
|
21
22
|
* Function for loading sounds into pixi
|
|
@@ -37,7 +38,7 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
37
38
|
* @returns {void}
|
|
38
39
|
*/
|
|
39
40
|
stopPlayingFxSounds(): void;
|
|
40
|
-
|
|
41
|
+
pauseSoundsForPageHide(): void;
|
|
41
42
|
/**
|
|
42
43
|
* Function for resuming and pausing sound in game
|
|
43
44
|
* @public
|
|
@@ -76,6 +77,12 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
76
77
|
* @returns {void}
|
|
77
78
|
*/
|
|
78
79
|
restoreAmbientPlayback(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Restores sounds paused because of page visibility change.
|
|
82
|
+
* @public
|
|
83
|
+
* @returns {void}
|
|
84
|
+
*/
|
|
85
|
+
restorePlaybackAfterPageHide(): void;
|
|
79
86
|
/**
|
|
80
87
|
* Function for pausing all sounds in game
|
|
81
88
|
* If sound is not playing, it will be skipped
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Sound, sound } from "@pixi/sound";
|
|
2
2
|
import { RainMan } from "../../Rainman";
|
|
3
3
|
import { SoundTracks } from "./types";
|
|
4
|
-
const soundsToLoop = [
|
|
4
|
+
const soundsToLoop = [
|
|
5
|
+
SoundTracks.mysteryFxLoop,
|
|
6
|
+
SoundTracks.music,
|
|
7
|
+
SoundTracks.freeSpinsMusic,
|
|
8
|
+
SoundTracks.cardDrawing
|
|
9
|
+
];
|
|
5
10
|
export const pixiSoundContext = sound.context;
|
|
6
11
|
/**
|
|
7
12
|
* Class for managing sound in game, uses the pixi sound library
|
|
@@ -26,6 +31,7 @@ export class SoundManagerInstance {
|
|
|
26
31
|
};
|
|
27
32
|
musicCatalogue = new Map();
|
|
28
33
|
currentAmbientTrack = null;
|
|
34
|
+
pausedSoundsForPageHide = new Set();
|
|
29
35
|
constructor() {
|
|
30
36
|
this.overrides = this.speedLevelMapper.slow;
|
|
31
37
|
}
|
|
@@ -89,19 +95,18 @@ export class SoundManagerInstance {
|
|
|
89
95
|
sound.stop();
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
this.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this.stopPlayingFxSounds();
|
|
98
|
+
pauseSoundsForPageHide() {
|
|
99
|
+
this.pausedSoundsForPageHide.clear();
|
|
100
|
+
this.musicCatalogue.forEach((sound, soundName) => {
|
|
101
|
+
if (!sound.isPlaying || sound.paused) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (soundName === SoundTracks.freeSpinsMusic || soundName === SoundTracks.music) {
|
|
105
|
+
this.currentAmbientTrack = soundName;
|
|
106
|
+
}
|
|
107
|
+
this.pausedSoundsForPageHide.add(soundName);
|
|
108
|
+
sound.pause();
|
|
109
|
+
});
|
|
105
110
|
}
|
|
106
111
|
/**
|
|
107
112
|
* Function for resuming and pausing sound in game
|
|
@@ -148,7 +153,8 @@ export class SoundManagerInstance {
|
|
|
148
153
|
sound.play({
|
|
149
154
|
singleInstance: true,
|
|
150
155
|
loop: soundsToLoop.includes(soundName),
|
|
151
|
-
volume: this.getVolumeLevel(soundName)
|
|
156
|
+
volume: this.getVolumeLevel(soundName),
|
|
157
|
+
speed: soundName === "cardDrawing" ? 0.8 : 1
|
|
152
158
|
});
|
|
153
159
|
}
|
|
154
160
|
/**
|
|
@@ -225,6 +231,32 @@ export class SoundManagerInstance {
|
|
|
225
231
|
(RainMan.settingsStore.isFreeSpinsStarted ? SoundTracks.freeSpinsMusic : SoundTracks.music);
|
|
226
232
|
this.play(ambientTrack);
|
|
227
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Restores sounds paused because of page visibility change.
|
|
236
|
+
* @public
|
|
237
|
+
* @returns {void}
|
|
238
|
+
*/
|
|
239
|
+
restorePlaybackAfterPageHide() {
|
|
240
|
+
if (!RainMan.settingsStore.isSoundStarted) {
|
|
241
|
+
this.pausedSoundsForPageHide.clear();
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (!this.pausedSoundsForPageHide.size) {
|
|
245
|
+
this.restoreAmbientPlayback();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const pausedSounds = [...this.pausedSoundsForPageHide];
|
|
249
|
+
this.pausedSoundsForPageHide.clear();
|
|
250
|
+
pausedSounds.forEach((soundName) => {
|
|
251
|
+
if (this.isAmbientTrack(soundName) && !RainMan.settingsStore.shouldPlayAmbientMusic) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (!this.isAmbientTrack(soundName) && !RainMan.settingsStore.shouldPlayFxSounds) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this.resume(soundName);
|
|
258
|
+
});
|
|
259
|
+
}
|
|
228
260
|
/**
|
|
229
261
|
* Function for pausing all sounds in game
|
|
230
262
|
* If sound is not playing, it will be skipped
|
|
@@ -311,7 +343,7 @@ export class SoundManagerInstance {
|
|
|
311
343
|
if (!isAudioContextRunning) {
|
|
312
344
|
return false;
|
|
313
345
|
}
|
|
314
|
-
this.
|
|
346
|
+
this.restorePlaybackAfterPageHide();
|
|
315
347
|
return true;
|
|
316
348
|
}
|
|
317
349
|
/**
|
|
@@ -64,6 +64,10 @@ export interface SoundTracks {
|
|
|
64
64
|
rouletteStop: "rouletteStop";
|
|
65
65
|
mysterySymbol: "mysterySymbol";
|
|
66
66
|
jackpotWin: "jackpotWin";
|
|
67
|
+
cardWin: "cardWin";
|
|
68
|
+
cardLose: "cardLose";
|
|
69
|
+
cardDrawing: "cardDrawing";
|
|
70
|
+
cardCollect: "cardCollect";
|
|
67
71
|
}
|
|
68
72
|
export type SoundTrack = SoundTracks[keyof SoundTracks];
|
|
69
73
|
/**
|
|
@@ -61,5 +61,9 @@ export const SoundTracks = {
|
|
|
61
61
|
rouletteStart: "rouletteStart",
|
|
62
62
|
rouletteLoop: "rouletteLoop",
|
|
63
63
|
rouletteStop: "rouletteStop",
|
|
64
|
-
jackpotWin: "jackpotWin"
|
|
64
|
+
jackpotWin: "jackpotWin",
|
|
65
|
+
cardWin: "cardWin",
|
|
66
|
+
cardLose: "cardLose",
|
|
67
|
+
cardDrawing: "cardDrawing",
|
|
68
|
+
cardCollect: "cardCollect"
|
|
65
69
|
};
|
|
@@ -563,6 +563,10 @@ export class AbstractMainContainer extends Container {
|
|
|
563
563
|
this.messageBox.visible = true;
|
|
564
564
|
RainMan.settingsStore.isGambleGameActive = false;
|
|
565
565
|
this._controller.updateGambleValues(RainMan.settingsStore.gambleGameWin);
|
|
566
|
+
if (RainMan.settingsStore.gambleGameWin > 0) {
|
|
567
|
+
RainMan.settingsStore.useTakeAction?.();
|
|
568
|
+
}
|
|
569
|
+
RainMan.settingsStore.disableSpecialButtons();
|
|
566
570
|
this.gambleGame = null;
|
|
567
571
|
}
|
|
568
572
|
this.hideOverlay();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import i18next from "i18next";
|
|
2
2
|
import { Container, Sprite, Text, Texture } from "pixi.js";
|
|
3
3
|
import { Spine } from "pixi-spine";
|
|
4
|
+
import { SoundManager } from "../../application";
|
|
4
5
|
import { COLOR_BUTTONS_CENTER_OFFSET, COLOR_BUTTONS_SCALE_X, gamblesTextStyle } from "../../constants";
|
|
5
6
|
import { RainMan } from "../../Rainman";
|
|
6
7
|
import { getDeviceOrientation, getSpineData, globalMinRatio } from "../../utils";
|
|
@@ -60,6 +61,7 @@ export class GambleGame extends Container {
|
|
|
60
61
|
this.addChildrenOnce();
|
|
61
62
|
this.bindButtonsOnce();
|
|
62
63
|
this.resize();
|
|
64
|
+
SoundManager.play("cardDrawing");
|
|
63
65
|
}
|
|
64
66
|
configureButtons() {
|
|
65
67
|
this.collectButton.eventMode = "static";
|
|
@@ -86,8 +88,11 @@ export class GambleGame extends Container {
|
|
|
86
88
|
this.redButton.setOnClick(() => this.handleGamblePlay("red"));
|
|
87
89
|
this.blackButton.setOnClick(() => this.handleGamblePlay("black"));
|
|
88
90
|
this.collectButton.setOnClick(() => {
|
|
91
|
+
SoundManager.stop("cardDrawing");
|
|
92
|
+
SoundManager.play("music");
|
|
89
93
|
RainMan.settingsStore.gambleGameWin = this.lastWinAmount;
|
|
90
94
|
RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(true);
|
|
95
|
+
SoundManager.play("cardCollect");
|
|
91
96
|
this.resolver(this.balanceValue);
|
|
92
97
|
});
|
|
93
98
|
}
|
|
@@ -170,6 +175,8 @@ export class GambleGame extends Container {
|
|
|
170
175
|
if (this.lastWinAmount === 0) {
|
|
171
176
|
return;
|
|
172
177
|
}
|
|
178
|
+
SoundManager.stop("cardDrawing");
|
|
179
|
+
this.collectButton.flipDisabledFlag(true);
|
|
173
180
|
this.redButton.flipDisabledFlag(true);
|
|
174
181
|
this.blackButton.flipDisabledFlag(true);
|
|
175
182
|
this.card.state.addAnimation(0, "wait", true, 0);
|
|
@@ -178,6 +185,12 @@ export class GambleGame extends Container {
|
|
|
178
185
|
this.card.state.clearTracks();
|
|
179
186
|
this.card.state.clearListeners();
|
|
180
187
|
this.card.state.addAnimation(0, gambleData.winning_card, false, 0);
|
|
188
|
+
if (gambleData.win_amount > 0) {
|
|
189
|
+
SoundManager.play("cardWin");
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
SoundManager.play("cardLose");
|
|
193
|
+
}
|
|
181
194
|
this.card.state.addListener({ complete: () => resolve() });
|
|
182
195
|
});
|
|
183
196
|
if (gambleData.win_amount > 0) {
|
|
@@ -186,6 +199,8 @@ export class GambleGame extends Container {
|
|
|
186
199
|
this.blackButton.flipDisabledFlag(false);
|
|
187
200
|
this.redButton.eventMode = "static";
|
|
188
201
|
this.blackButton.eventMode = "static";
|
|
202
|
+
SoundManager.play("cardDrawing");
|
|
203
|
+
this.collectButton.flipDisabledFlag(false);
|
|
189
204
|
}
|
|
190
205
|
this.card.state.addAnimation(0, "wait2", true, 0);
|
|
191
206
|
this.lastWinAmount = gambleData.win_amount;
|
|
@@ -197,8 +212,10 @@ export class GambleGame extends Container {
|
|
|
197
212
|
this.card.state.addAnimation(0, "idle", true, 0);
|
|
198
213
|
await this.loseDoubleAndWinFields();
|
|
199
214
|
window.setTimeout(() => {
|
|
215
|
+
SoundManager.stop("cardDrawing");
|
|
216
|
+
SoundManager.play("music");
|
|
200
217
|
this.closeGame();
|
|
201
|
-
},
|
|
218
|
+
}, 500);
|
|
202
219
|
}
|
|
203
220
|
}
|
|
204
221
|
/**
|
|
@@ -95,6 +95,16 @@ export declare abstract class AbstractColumnsContainer extends Container impleme
|
|
|
95
95
|
* @returns {Promise<void>}
|
|
96
96
|
*/
|
|
97
97
|
configBlindSpin(finalSymbolReels: SymbolReels, afterSpinResolver: (value: void | PromiseLike<void>) => void, indexesOfReelsToExtendSpinningTime: number[]): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* This function is responsible for setting symbols in single column
|
|
100
|
+
* @public
|
|
101
|
+
* @param {SymbolReels} finalSymbolReels final symbols in columns
|
|
102
|
+
* @param {(value: void | PromiseLike<void>) => void} afterSpinResolver resolver for after spin
|
|
103
|
+
* @param {number} columnIndex index of column to configure
|
|
104
|
+
* @param {boolean} shouldExtendSpinningTime determines whether to extend spinning time for the column
|
|
105
|
+
* @returns {Promise<void>}
|
|
106
|
+
*/
|
|
107
|
+
configBlindSpinForColumn(finalSymbolReels: SymbolReels, afterSpinResolver: (value: void | PromiseLike<void>) => void, columnIndex: number, shouldExtendSpinningTime?: boolean): Promise<void>;
|
|
98
108
|
/**
|
|
99
109
|
* This cancels the timeout, removes the stored delayed action and invalidates
|
|
100
110
|
* any older timeout callback that might still try to execute later.
|
|
@@ -227,4 +237,12 @@ export declare abstract class AbstractColumnsContainer extends Container impleme
|
|
|
227
237
|
* @returns {PlayableAction[]} - array of playable actions
|
|
228
238
|
*/
|
|
229
239
|
protected prepareConfiguringReelsEnd(finalSymbolReels: SymbolReels): PlayableAction[];
|
|
240
|
+
/**
|
|
241
|
+
* Function for preparing configuring for single reel
|
|
242
|
+
* @protected
|
|
243
|
+
* @param {SymbolReels} finalSymbolReels - final symbol reels
|
|
244
|
+
* @param {number} columnIndex - column index
|
|
245
|
+
* @returns {PlayableAction} - playable action
|
|
246
|
+
*/
|
|
247
|
+
protected prepareConfiguringReelsEndForIndex(finalSymbolReels: SymbolReels, columnIndex: number): PlayableAction;
|
|
230
248
|
}
|
|
@@ -187,6 +187,63 @@ export class AbstractColumnsContainer extends Container {
|
|
|
187
187
|
resolve();
|
|
188
188
|
});
|
|
189
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* This function is responsible for setting symbols in single column
|
|
192
|
+
* @public
|
|
193
|
+
* @param {SymbolReels} finalSymbolReels final symbols in columns
|
|
194
|
+
* @param {(value: void | PromiseLike<void>) => void} afterSpinResolver resolver for after spin
|
|
195
|
+
* @param {number} columnIndex index of column to configure
|
|
196
|
+
* @param {boolean} shouldExtendSpinningTime determines whether to extend spinning time for the column
|
|
197
|
+
* @returns {Promise<void>}
|
|
198
|
+
*/
|
|
199
|
+
async configBlindSpinForColumn(finalSymbolReels, afterSpinResolver, columnIndex, shouldExtendSpinningTime = false) {
|
|
200
|
+
return new Promise(async (resolve) => {
|
|
201
|
+
this.clearPendingMysteryDelay();
|
|
202
|
+
this.mysteryFxGeneration = 0;
|
|
203
|
+
this.skipRemainingMysteryFxs = false;
|
|
204
|
+
const frame = RainMan.componentRegistry.get(AbstractFrame.registryName);
|
|
205
|
+
const column = this.allColumns[columnIndex];
|
|
206
|
+
if (column === undefined) {
|
|
207
|
+
afterSpinResolver();
|
|
208
|
+
resolve();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const configureSpinAction = this.prepareConfiguringReelsEndForIndex(finalSymbolReels, columnIndex);
|
|
212
|
+
if (this.quickReelsStop ||
|
|
213
|
+
this.skipRemainingMysteryFxs ||
|
|
214
|
+
RainMan.settingsStore.currentSpeed === SPEED_LEVELS.fast) {
|
|
215
|
+
await configureSpinAction();
|
|
216
|
+
SoundManager.play(SoundTracks.allRollStops);
|
|
217
|
+
}
|
|
218
|
+
else if (shouldExtendSpinningTime) {
|
|
219
|
+
this.currentColumn = column;
|
|
220
|
+
column.adaptToSpeed(RainMan.settingsStore.currentSpeed);
|
|
221
|
+
frame.invokeMysteryFx(column.x, column.y);
|
|
222
|
+
this.skipScatterDelay = configureSpinAction;
|
|
223
|
+
await column.speedUpForMysterySpin(100, 1500);
|
|
224
|
+
if (this.quickReelsStop || this.skipRemainingMysteryFxs) {
|
|
225
|
+
await column.changeVelocity(Speed.STOP, 0, frame);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
if (!RainMan.settingsStore.isAutoplayEnabled ||
|
|
229
|
+
(RainMan.settingsStore.isAutoplayEnabled && !this.quickReelsStop)) {
|
|
230
|
+
this.scheduleMysteryDelay(configureSpinAction, RainMan.config.durationOfActions.scatterDelayerTime);
|
|
231
|
+
}
|
|
232
|
+
await column.changeVelocity(Speed.STOP, RainMan.config.durationOfActions.scatterSpinningTime, frame);
|
|
233
|
+
}
|
|
234
|
+
frame.destroyMysteryFx();
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
await configureSpinAction();
|
|
238
|
+
}
|
|
239
|
+
await column.getStopPromise();
|
|
240
|
+
this.clearPendingMysteryDelay();
|
|
241
|
+
this.mysteryFxGeneration = 0;
|
|
242
|
+
this.skipRemainingMysteryFxs = false;
|
|
243
|
+
afterSpinResolver();
|
|
244
|
+
resolve();
|
|
245
|
+
});
|
|
246
|
+
}
|
|
190
247
|
/**
|
|
191
248
|
* This cancels the timeout, removes the stored delayed action and invalidates
|
|
192
249
|
* any older timeout callback that might still try to execute later.
|
|
@@ -441,4 +498,20 @@ export class AbstractColumnsContainer extends Container {
|
|
|
441
498
|
this.currentColumn = null;
|
|
442
499
|
});
|
|
443
500
|
}
|
|
501
|
+
/**
|
|
502
|
+
* Function for preparing configuring for single reel
|
|
503
|
+
* @protected
|
|
504
|
+
* @param {SymbolReels} finalSymbolReels - final symbol reels
|
|
505
|
+
* @param {number} columnIndex - column index
|
|
506
|
+
* @returns {PlayableAction} - playable action
|
|
507
|
+
*/
|
|
508
|
+
prepareConfiguringReelsEndForIndex(finalSymbolReels, columnIndex) {
|
|
509
|
+
const column = this.allColumns[columnIndex];
|
|
510
|
+
return async () => {
|
|
511
|
+
this.currentColumn = column;
|
|
512
|
+
column.configBlindSpin(finalSymbolReels[columnIndex]);
|
|
513
|
+
await column.getTriggersPromise();
|
|
514
|
+
this.currentColumn = null;
|
|
515
|
+
};
|
|
516
|
+
}
|
|
444
517
|
}
|
|
@@ -34,6 +34,8 @@ export declare class MessageBox extends Container {
|
|
|
34
34
|
private possibleWinShown;
|
|
35
35
|
private incentiveMessageShown;
|
|
36
36
|
private winLineIndicatorShown;
|
|
37
|
+
private winLineIndicatorXOffset;
|
|
38
|
+
private winLineIndicatorYOffset;
|
|
37
39
|
constructor();
|
|
38
40
|
/**
|
|
39
41
|
* Updates the incentive text displayed in the message box.
|
|
@@ -84,6 +86,15 @@ export declare class MessageBox extends Container {
|
|
|
84
86
|
* @returns {void}
|
|
85
87
|
*/
|
|
86
88
|
hideWinLineIndicator(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Sets the offset of the win line indicator along the x and y axes. Each time winLineIndicator is shown,
|
|
91
|
+
* the indicator is positioned at the current offset.
|
|
92
|
+
* @public
|
|
93
|
+
* @param {number} xOffset - The amount to move the win line indicator along the x-axis.
|
|
94
|
+
* @param {number} yOffset - The amount to move the win line indicator along the y-axis.
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
setWinWinLineIndicatorOffset(xOffset?: number, yOffset?: number): void;
|
|
87
98
|
/**
|
|
88
99
|
* Function for resizing message box
|
|
89
100
|
* It sets the scale of the message box to the global minimum ratio.
|
|
@@ -39,6 +39,8 @@ export class MessageBox extends Container {
|
|
|
39
39
|
possibleWinShown = false;
|
|
40
40
|
incentiveMessageShown = false;
|
|
41
41
|
winLineIndicatorShown = false;
|
|
42
|
+
winLineIndicatorXOffset = 0;
|
|
43
|
+
winLineIndicatorYOffset = 0;
|
|
42
44
|
constructor() {
|
|
43
45
|
super();
|
|
44
46
|
this.name = MessageBox.registryName;
|
|
@@ -165,6 +167,18 @@ export class MessageBox extends Container {
|
|
|
165
167
|
this.winLineIndicator = undefined;
|
|
166
168
|
}
|
|
167
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Sets the offset of the win line indicator along the x and y axes. Each time winLineIndicator is shown,
|
|
172
|
+
* the indicator is positioned at the current offset.
|
|
173
|
+
* @public
|
|
174
|
+
* @param {number} xOffset - The amount to move the win line indicator along the x-axis.
|
|
175
|
+
* @param {number} yOffset - The amount to move the win line indicator along the y-axis.
|
|
176
|
+
* @returns {void}
|
|
177
|
+
*/
|
|
178
|
+
setWinWinLineIndicatorOffset(xOffset, yOffset) {
|
|
179
|
+
this.winLineIndicatorXOffset += xOffset ?? 0;
|
|
180
|
+
this.winLineIndicatorYOffset += yOffset ?? 0;
|
|
181
|
+
}
|
|
168
182
|
/**
|
|
169
183
|
* Function for resizing message box
|
|
170
184
|
* It sets the scale of the message box to the global minimum ratio.
|
|
@@ -334,6 +348,12 @@ export class MessageBox extends Container {
|
|
|
334
348
|
};
|
|
335
349
|
this.winLineIndicator = new WinLineIndicator(winLineTextStyle, getImageForSymbolId, message, symbolIds);
|
|
336
350
|
this.winLineIndicator.y = 50;
|
|
351
|
+
if (this.winLineIndicatorXOffset) {
|
|
352
|
+
this.winLineIndicator.x = this.winLineIndicatorXOffset;
|
|
353
|
+
}
|
|
354
|
+
if (this.winLineIndicatorYOffset) {
|
|
355
|
+
this.winLineIndicator.y = this.winLineIndicatorYOffset;
|
|
356
|
+
}
|
|
337
357
|
this.winLineIndicatorShown = true;
|
|
338
358
|
this.centerTextOnX(this.winLineIndicator);
|
|
339
359
|
this.addChild(this.winLineIndicator);
|
|
@@ -311,6 +311,7 @@ export class AbstractController {
|
|
|
311
311
|
if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
|
|
312
312
|
this.buttonsEventManager.initGambleButton(() => {
|
|
313
313
|
RainMan.settingsStore.isGambleGameAvailable = false;
|
|
314
|
+
SoundManager.stopAll();
|
|
314
315
|
this.mainContainer.invokeGambleGame();
|
|
315
316
|
}, !RainMan.settingsStore.isGambleGameAvailable ||
|
|
316
317
|
RainMan.settingsStore.isPlayingAnyAction ||
|
|
@@ -322,7 +323,6 @@ export class AbstractController {
|
|
|
322
323
|
if (RainMan.componentRegistry.has(BUTTONS.take)) {
|
|
323
324
|
this.buttonsEventManager.initTakeButton(() => {
|
|
324
325
|
RainMan.settingsStore.useTakeAction?.();
|
|
325
|
-
this.uiController.currentBalance = RainMan.settingsStore.balanceAfterSpin;
|
|
326
326
|
RainMan.settingsStore.isTakeActionAvailable = false;
|
|
327
327
|
RainMan.settingsStore.isGambleGameAvailable = false;
|
|
328
328
|
if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
|
|
@@ -842,6 +842,13 @@ export class AbstractController {
|
|
|
842
842
|
this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
|
|
843
843
|
RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
|
|
844
844
|
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
845
|
+
if (this.speedLevelBeforeFreeSpins === null) {
|
|
846
|
+
this.speedLevelBeforeFreeSpins = RainMan.settingsStore.currentSpeed;
|
|
847
|
+
}
|
|
848
|
+
RainMan.settingsStore.setIsTemporarySpeed(false);
|
|
849
|
+
RainMan.componentRegistry.setSpeedLevel(SPEED_LEVELS.slow);
|
|
850
|
+
this.uiController.updateShownSpeedLevel(SPEED_LEVELS.slow);
|
|
851
|
+
this.disableSpeedButton(false);
|
|
845
852
|
}
|
|
846
853
|
/**
|
|
847
854
|
* This function is responsible for getting the number of free spins bought
|
|
@@ -904,6 +911,7 @@ export class AbstractController {
|
|
|
904
911
|
logInfo("Take action can't be performed");
|
|
905
912
|
return;
|
|
906
913
|
}
|
|
914
|
+
this.shouldPlayNextSpin = false;
|
|
907
915
|
if (this.currentlyPlayedAction !== undefined) {
|
|
908
916
|
this.changeGamePhase(gamePhases.STOPPING_HANDLING_ACTIONS);
|
|
909
917
|
this.stopPlayingSymbolsStreak();
|
|
@@ -914,6 +922,7 @@ export class AbstractController {
|
|
|
914
922
|
if (takeData.status.code === 200) {
|
|
915
923
|
RainMan.settingsStore.isTakeActionAvailable = false;
|
|
916
924
|
logInfo(`💰 Round ${takeData.round_number} ended with balance:`, takeData.balance);
|
|
925
|
+
await this.uiController.animateCurrentBalance(takeData.balance);
|
|
917
926
|
}
|
|
918
927
|
else {
|
|
919
928
|
RainMan.settingsStore.isTakeActionAvailable = true;
|
|
@@ -1219,7 +1228,9 @@ export class AbstractController {
|
|
|
1219
1228
|
}
|
|
1220
1229
|
await this.performActionsAfterSpin();
|
|
1221
1230
|
this.freeSpinsWin = gambleWinAmount > 0 ? gambleWinAmount : null;
|
|
1222
|
-
|
|
1231
|
+
if (!RainMan.globals.isSuperBonusGameEnabled) {
|
|
1232
|
+
this.gambleGameEnabler(gambleWinAmount);
|
|
1233
|
+
}
|
|
1223
1234
|
if (RainMan.settingsStore.isAutoplayEnabled ||
|
|
1224
1235
|
(RainMan.settingsStore.howManyFreeSpinsLeft !== 0 && this.shouldAutoplayFreeSpins)) {
|
|
1225
1236
|
this.handleAutoplayLogic();
|
|
@@ -1237,6 +1248,7 @@ export class AbstractController {
|
|
|
1237
1248
|
if (this.speedLevelBeforeFreeSpins !== null &&
|
|
1238
1249
|
!RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
1239
1250
|
!RainMan.globals.isSuperBonusGameEnabled) {
|
|
1251
|
+
RainMan.settingsStore.setIsTemporarySpeed(false);
|
|
1240
1252
|
RainMan.componentRegistry.setSpeedLevel(this.speedLevelBeforeFreeSpins);
|
|
1241
1253
|
this.uiController.updateShownSpeedLevel(this.speedLevelBeforeFreeSpins);
|
|
1242
1254
|
this.speedLevelBeforeFreeSpins = null;
|
|
@@ -189,6 +189,13 @@ export declare class UiController {
|
|
|
189
189
|
* @returns {Promise<void>}
|
|
190
190
|
*/
|
|
191
191
|
updateDisplayedBalance(amount: number): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Function for animating current balance to a final value.
|
|
194
|
+
* @public
|
|
195
|
+
* @param {number} finalBalance - final balance to display
|
|
196
|
+
* @returns {Promise<void>}
|
|
197
|
+
*/
|
|
198
|
+
animateCurrentBalance(finalBalance: number): Promise<void>;
|
|
192
199
|
/**
|
|
193
200
|
* Function for resetting win amount
|
|
194
201
|
* @public
|
|
@@ -282,6 +282,23 @@ export class UiController {
|
|
|
282
282
|
async updateDisplayedBalance(amount) {
|
|
283
283
|
this.promisesToSetBalances.push(RainMan.componentRegistry.get(COMPONENTS.creditText).update(amount));
|
|
284
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Function for animating current balance to a final value.
|
|
287
|
+
* @public
|
|
288
|
+
* @param {number} finalBalance - final balance to display
|
|
289
|
+
* @returns {Promise<void>}
|
|
290
|
+
*/
|
|
291
|
+
async animateCurrentBalance(finalBalance) {
|
|
292
|
+
const balanceDiff = ceilToDecimal(finalBalance - this._currentBalance);
|
|
293
|
+
this._currentBalance = finalBalance;
|
|
294
|
+
if (balanceDiff === 0) {
|
|
295
|
+
this.setDisplayedBalance();
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const animationPromise = RainMan.componentRegistry.get(COMPONENTS.creditText).update(balanceDiff);
|
|
299
|
+
this.promisesToSetBalances.push(animationPromise);
|
|
300
|
+
await animationPromise;
|
|
301
|
+
}
|
|
285
302
|
/**
|
|
286
303
|
* Function for resetting win amount
|
|
287
304
|
* @public
|
|
@@ -24,7 +24,7 @@ export class AbstractLoadingContainer extends Container {
|
|
|
24
24
|
this.name = "loadingContainer";
|
|
25
25
|
this.x = 0;
|
|
26
26
|
this.y = 0;
|
|
27
|
-
this.loaderContainer = new SpriteLoadingContainer("./assets/images/materials/texture.
|
|
27
|
+
this.loaderContainer = new SpriteLoadingContainer("./assets/images/materials/texture.webp");
|
|
28
28
|
this.presentationFinishedPromise = new Promise((resolve) => {
|
|
29
29
|
this.resolvePresentationFinished = resolve;
|
|
30
30
|
});
|
|
@@ -113,6 +113,12 @@ export declare class SettingsStore {
|
|
|
113
113
|
* @returns {void}
|
|
114
114
|
*/
|
|
115
115
|
disableSpecialButtons(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Enables special buttons like gamble and take.
|
|
118
|
+
* @public
|
|
119
|
+
* @returns {void}
|
|
120
|
+
*/
|
|
121
|
+
enableSpecialButtons(): void;
|
|
116
122
|
/**
|
|
117
123
|
* Swaps the bet change disabled flag.
|
|
118
124
|
* @public
|
|
@@ -338,6 +344,13 @@ export declare class SettingsStore {
|
|
|
338
344
|
* @returns {void}
|
|
339
345
|
*/
|
|
340
346
|
setAutoSpinsCount(count: number): void;
|
|
347
|
+
/**
|
|
348
|
+
* Setter for the infinite autoplay flag
|
|
349
|
+
* @public
|
|
350
|
+
* @param {boolean} newState new state for infinite autoplay
|
|
351
|
+
* @returns {void}
|
|
352
|
+
*/
|
|
353
|
+
setInfinitySpinsEnabled(newState: boolean): void;
|
|
341
354
|
/**
|
|
342
355
|
* Setter for the autoplay enabled flag
|
|
343
356
|
* @public
|
|
@@ -79,6 +79,7 @@ export class SettingsStore {
|
|
|
79
79
|
initialAutoplaySettingsState = {
|
|
80
80
|
onAnyWin: false,
|
|
81
81
|
howManyAutoSpinsLeft: INITIAL_AUTO_SPIN_COUNT,
|
|
82
|
+
infinitySpinsEnabled: false,
|
|
82
83
|
singleWinExceeds: 0,
|
|
83
84
|
balancedIncreased: 0,
|
|
84
85
|
balancedDecreased: 0,
|
|
@@ -185,6 +186,21 @@ export class SettingsStore {
|
|
|
185
186
|
RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(true);
|
|
186
187
|
}
|
|
187
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Enables special buttons like gamble and take.
|
|
191
|
+
* @public
|
|
192
|
+
* @returns {void}
|
|
193
|
+
*/
|
|
194
|
+
enableSpecialButtons() {
|
|
195
|
+
if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
|
|
196
|
+
RainMan.settingsStore.isGambleGameAvailable = true;
|
|
197
|
+
RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(false);
|
|
198
|
+
}
|
|
199
|
+
if (RainMan.componentRegistry.has(BUTTONS.take)) {
|
|
200
|
+
RainMan.settingsStore.isTakeActionAvailable = true;
|
|
201
|
+
RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(false);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
188
204
|
/**
|
|
189
205
|
* Swaps the bet change disabled flag.
|
|
190
206
|
* @public
|
|
@@ -576,6 +592,15 @@ export class SettingsStore {
|
|
|
576
592
|
setAutoSpinsCount(count) {
|
|
577
593
|
this.howManyAutoSpinsLeft = count;
|
|
578
594
|
}
|
|
595
|
+
/**
|
|
596
|
+
* Setter for the infinite autoplay flag
|
|
597
|
+
* @public
|
|
598
|
+
* @param {boolean} newState new state for infinite autoplay
|
|
599
|
+
* @returns {void}
|
|
600
|
+
*/
|
|
601
|
+
setInfinitySpinsEnabled(newState) {
|
|
602
|
+
this.infinitySpinsEnabled = newState;
|
|
603
|
+
}
|
|
579
604
|
/**
|
|
580
605
|
* Setter for the autoplay enabled flag
|
|
581
606
|
* @public
|
|
@@ -713,6 +738,7 @@ export class SettingsStore {
|
|
|
713
738
|
resetAutoplaySettings() {
|
|
714
739
|
this.onAnyWin = this.initialAutoplaySettingsState.onAnyWin;
|
|
715
740
|
this.howManyAutoSpinsLeft = this.initialAutoplaySettingsState.howManyAutoSpinsLeft;
|
|
741
|
+
this.infinitySpinsEnabled = this.initialAutoplaySettingsState.infinitySpinsEnabled;
|
|
716
742
|
this.singleWinExceeds = this.initialAutoplaySettingsState.singleWinExceeds;
|
|
717
743
|
this.balancedIncreased = this.initialAutoplaySettingsState.balancedIncreased;
|
|
718
744
|
this.balancedDecreased = this.initialAutoplaySettingsState.balancedDecreased;
|
|
@@ -24,7 +24,7 @@ const pauseAudio = () => {
|
|
|
24
24
|
shouldResumeAudioOnInterruption = false;
|
|
25
25
|
removeInterruptedAudioResumeListeners();
|
|
26
26
|
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
27
|
-
SoundManager.
|
|
27
|
+
SoundManager.pauseSoundsForPageHide();
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
@@ -84,6 +84,6 @@ export const loadSoundsOnTabChange = () => {
|
|
|
84
84
|
sound.disableAutoPause = true;
|
|
85
85
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
86
86
|
window.addEventListener("pagehide", () => pauseAudio());
|
|
87
|
-
window.addEventListener("pageshow", () =>
|
|
88
|
-
window.addEventListener("focus", () =>
|
|
87
|
+
window.addEventListener("pageshow", () => resumeAudio());
|
|
88
|
+
window.addEventListener("focus", () => resumeAudio());
|
|
89
89
|
};
|
|
@@ -25,6 +25,8 @@ export declare class TexturedText extends UpdatableValueComponent {
|
|
|
25
25
|
* @returns {void}
|
|
26
26
|
*/
|
|
27
27
|
randomizeSet(value: number, _possibleValues: number[]): void;
|
|
28
|
+
adjustTextureSpriteLength(): void;
|
|
29
|
+
set(newValue: number): void;
|
|
28
30
|
/**
|
|
29
31
|
* Plays the animation for the text element
|
|
30
32
|
* @public
|
|
@@ -18,6 +18,7 @@ export class TexturedText extends UpdatableValueComponent {
|
|
|
18
18
|
this.registryName = registryName;
|
|
19
19
|
this.valueTextComponent.style = { ...this.valueTextComponent.style, fontSize: 120, padding: 50 };
|
|
20
20
|
this.valueTextComponent.anchor.set(0.5, 0.5);
|
|
21
|
+
this.updateFontSize();
|
|
21
22
|
if (textureName) {
|
|
22
23
|
this.textureSprite = new TilingSprite(getTexture(textureName), this.valueTextComponent.width, this.valueTextComponent.height);
|
|
23
24
|
this.textureSprite.scale.set(1.1);
|
|
@@ -48,6 +49,17 @@ export class TexturedText extends UpdatableValueComponent {
|
|
|
48
49
|
this.valueTextComponent.style.fontSize = -10 * new MoneyText(value).toString().length + this.baseFontSize;
|
|
49
50
|
super.update(value, 1);
|
|
50
51
|
}
|
|
52
|
+
adjustTextureSpriteLength() {
|
|
53
|
+
if (!this.textureSprite) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.textureSprite.width = this.valueTextComponent.width;
|
|
57
|
+
this.textureSprite.height = this.valueTextComponent.height;
|
|
58
|
+
}
|
|
59
|
+
set(newValue) {
|
|
60
|
+
super.set(newValue);
|
|
61
|
+
this.adjustTextureSpriteLength();
|
|
62
|
+
}
|
|
51
63
|
/**
|
|
52
64
|
* Plays the animation for the text element
|
|
53
65
|
* @public
|
|
@@ -89,5 +101,6 @@ export class TexturedText extends UpdatableValueComponent {
|
|
|
89
101
|
*/
|
|
90
102
|
updateFontSize() {
|
|
91
103
|
this.valueTextComponent.style.fontSize = -10 * super.value.length + this.baseFontSize;
|
|
104
|
+
this.adjustTextureSpriteLength();
|
|
92
105
|
}
|
|
93
106
|
}
|
package/package.json
CHANGED