pixi-rainman-game-engine 0.3.43 → 0.3.44-beta
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/ComponentRegistry/ComponentRegistry.js +5 -3
- package/dist/ComponentRegistry/types.d.ts +2 -1
- package/dist/ComponentRegistry/types.js +1 -1
- package/dist/DescribedPlayableAction/DescribedPlayableAction.d.ts +3 -0
- package/dist/DescribedPlayableAction/DescribedPlayableAction.js +1 -0
- package/dist/application/ButtonsEventManager/ButtonsEventManager.d.ts +1 -0
- package/dist/application/ButtonsEventManager/ButtonsEventManager.js +9 -0
- package/dist/application/SoundManager/SoundManager.d.ts +1 -10
- package/dist/application/SoundManager/SoundManager.js +17 -56
- package/dist/components/AbstractMainContainer/AbstractMainContainer.d.ts +4 -1
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +29 -8
- package/dist/components/buttons/buttonGroups/MiddleButtons.d.ts +3 -2
- package/dist/components/buttons/buttonGroups/MiddleButtons.js +18 -4
- package/dist/components/buttons/buttonGroups/RightButtonsMobile.d.ts +3 -3
- package/dist/components/buttons/buttonGroups/RightButtonsMobile.js +10 -7
- package/dist/components/buttons/default/SpeedControlButtonMobile.d.ts +22 -0
- package/dist/components/buttons/default/SpeedControlButtonMobile.js +51 -0
- package/dist/components/buttons/default/index.d.ts +1 -0
- package/dist/components/buttons/default/index.js +1 -0
- package/dist/components/common/AnimatedNumber.js +10 -1
- package/dist/components/symbols/AbstractSymbolBase.d.ts +2 -0
- package/dist/components/symbols/AbstractSymbolBase.js +35 -8
- package/dist/controllers/AbstractController.d.ts +3 -0
- package/dist/controllers/AbstractController.js +31 -14
- package/dist/controllers/UiController.d.ts +0 -1
- package/dist/controllers/UiController.js +7 -4
- package/dist/stores/SettingsStore.d.ts +1 -0
- package/dist/stores/SettingsStore.js +1 -0
- package/dist/utils/common/sound.js +8 -9
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isIncentiveComponentInterface, isSpeedAdapterInterface, SpeedLevelHandler, TimedIncentiveController } from "../application";
|
|
2
|
-
import { AbstractSymbolsColumn, SpeedControlButton } from "../components";
|
|
2
|
+
import { AbstractSymbolsColumn, SpeedControlButton, SpeedControlButtonMobile } from "../components";
|
|
3
3
|
import { RainMan } from "../Rainman";
|
|
4
4
|
import { openFullscreen } from "../utils";
|
|
5
5
|
/**
|
|
@@ -49,7 +49,8 @@ export class ComponentRegistry {
|
|
|
49
49
|
this.speedLevelHandler.setSpeed(newSpeedLevel);
|
|
50
50
|
RainMan.settingsStore.setSpeedLevel(this.speedLevelHandler.currentSpeed);
|
|
51
51
|
this.updateAllSpeedAdaptable(RainMan.settingsStore.currentSpeed);
|
|
52
|
-
this.
|
|
52
|
+
this.getIfExists(SpeedControlButton.registryName)?.forceTextureUpdate();
|
|
53
|
+
this.getIfExists(SpeedControlButtonMobile.registryName)?.forceTextureUpdate();
|
|
53
54
|
}
|
|
54
55
|
/**
|
|
55
56
|
* Setting the next available speed level
|
|
@@ -60,7 +61,8 @@ export class ComponentRegistry {
|
|
|
60
61
|
this.speedLevelHandler.nextSpeed();
|
|
61
62
|
RainMan.settingsStore.setSpeedLevel(this.speedLevelHandler.currentSpeed);
|
|
62
63
|
this.updateAllSpeedAdaptable(RainMan.settingsStore.currentSpeed);
|
|
63
|
-
this.
|
|
64
|
+
this.getIfExists(SpeedControlButton.registryName)?.forceTextureUpdate();
|
|
65
|
+
this.getIfExists(SpeedControlButtonMobile.registryName)?.forceTextureUpdate();
|
|
64
66
|
}
|
|
65
67
|
/**
|
|
66
68
|
* Getter for current speed level
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, GambleButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, StylefulUpdatableText, TakeButton, UpdatableTextComponent, UpdatableValueComponent, VolumeButton } from "../components";
|
|
1
|
+
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, GambleButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, SpeedControlButtonMobile, StylefulUpdatableText, TakeButton, UpdatableTextComponent, UpdatableValueComponent, VolumeButton } from "../components";
|
|
2
2
|
/**
|
|
3
3
|
* RegistryMap is a map of all components that are registered in the ComponentRegistry.
|
|
4
4
|
* It is used to type-check the components that are registered in the ComponentRegistry.
|
|
@@ -11,6 +11,7 @@ export interface RegistryMap {
|
|
|
11
11
|
[MessageBox.gamePaysTextRegistryName]: UpdatableTextComponent;
|
|
12
12
|
[MessageBox.registryName]: MessageBox;
|
|
13
13
|
[SpeedControlButton.registryName]: SpeedControlButton;
|
|
14
|
+
[SpeedControlButtonMobile.registryName]: SpeedControlButtonMobile;
|
|
14
15
|
[Background.registryName]: Background;
|
|
15
16
|
[VolumeButton.registryName]: VolumeButton;
|
|
16
17
|
[AutoplayButton.registryName]: AutoplayButton;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, VolumeButton } from "../components";
|
|
1
|
+
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, SpeedControlButtonMobile, VolumeButton } from "../components";
|
|
@@ -10,5 +10,8 @@ export declare class DescribedPlayableAction<T> {
|
|
|
10
10
|
winAmount: Nullable<number>;
|
|
11
11
|
skipLooping: boolean;
|
|
12
12
|
isFirstStreak: boolean;
|
|
13
|
+
animationTarget: {
|
|
14
|
+
isCurrentAnimationPastProgressThreshold?: () => boolean;
|
|
15
|
+
} | null;
|
|
13
16
|
constructor(type: T, action: PlayableAction, winAmount?: Nullable<number>, skipLooping?: boolean);
|
|
14
17
|
}
|
|
@@ -154,6 +154,7 @@ export declare class ButtonsEventManager {
|
|
|
154
154
|
* @returns {void}
|
|
155
155
|
*/
|
|
156
156
|
private handleModalInvocation;
|
|
157
|
+
private closeAllModals;
|
|
157
158
|
/**
|
|
158
159
|
* Function for closing all other modals except the one with given name
|
|
159
160
|
* @param {string} activeLayerName - name of the layer that should remain open
|
|
@@ -62,6 +62,7 @@ export class ButtonsEventManager {
|
|
|
62
62
|
RainMan.settingsStore.handleModalInvocation = this.handleModalInvocation.bind(this);
|
|
63
63
|
RainMan.settingsStore.enableButtons = this.enableButtons.bind(this);
|
|
64
64
|
RainMan.settingsStore.closeOtherModals = this.closeOtherModals.bind(this);
|
|
65
|
+
RainMan.settingsStore.closeAllModals = this.closeAllModals.bind(this);
|
|
65
66
|
RainMan.settingsStore.closeCurrentlyOpenModal = this.closeCurrentlyOpenModal.bind(this);
|
|
66
67
|
}
|
|
67
68
|
/**
|
|
@@ -359,6 +360,14 @@ export class ButtonsEventManager {
|
|
|
359
360
|
}
|
|
360
361
|
}
|
|
361
362
|
}
|
|
363
|
+
closeAllModals() {
|
|
364
|
+
for (const itemId of allUiItems) {
|
|
365
|
+
const layer = window.document.getElementById(itemId);
|
|
366
|
+
if (layer !== null && layer.style.display === "flex") {
|
|
367
|
+
layer.style.display = "none";
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
362
371
|
/**
|
|
363
372
|
* Function for closing all other modals except the one with given name
|
|
364
373
|
* @param {string} activeLayerName - name of the layer that should remain open
|
|
@@ -16,7 +16,6 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
16
16
|
readonly speedLevelMapper: SpeedLevelDirectory<SoundOverrides>;
|
|
17
17
|
private musicCatalogue;
|
|
18
18
|
private currentAmbientTrack;
|
|
19
|
-
private currentAmbientOffset;
|
|
20
19
|
private loadedSoundAssets;
|
|
21
20
|
private audioContextRecoveryPromise;
|
|
22
21
|
constructor();
|
|
@@ -41,7 +40,7 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
41
40
|
* @returns {void}
|
|
42
41
|
*/
|
|
43
42
|
stopPlayingFxSounds(): void;
|
|
44
|
-
|
|
43
|
+
stopSoundsForPageHide(): void;
|
|
45
44
|
/**
|
|
46
45
|
* Function for resuming and pausing sound in game
|
|
47
46
|
* @public
|
|
@@ -67,14 +66,6 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
67
66
|
private getOppositeAmbientTrack;
|
|
68
67
|
private getCurrentAmbientTrack;
|
|
69
68
|
private getSound;
|
|
70
|
-
private getAmbientPlaybackOffset;
|
|
71
|
-
private trackAmbientPlaybackProgress;
|
|
72
|
-
/**
|
|
73
|
-
* Saves active ambient position before the browser interrupts WebAudio playback.
|
|
74
|
-
* @public
|
|
75
|
-
* @returns {void}
|
|
76
|
-
*/
|
|
77
|
-
captureAmbientPlaybackPositionForPageHide(): void;
|
|
78
69
|
private isIOSWebAudioRuntime;
|
|
79
70
|
private recreatePixiSoundContext;
|
|
80
71
|
private recreatePixiSoundContextOnce;
|
|
@@ -31,7 +31,6 @@ export class SoundManagerInstance {
|
|
|
31
31
|
};
|
|
32
32
|
musicCatalogue = new Map();
|
|
33
33
|
currentAmbientTrack = null;
|
|
34
|
-
currentAmbientOffset = 0;
|
|
35
34
|
loadedSoundAssets = {};
|
|
36
35
|
audioContextRecoveryPromise = null;
|
|
37
36
|
constructor() {
|
|
@@ -101,16 +100,19 @@ export class SoundManagerInstance {
|
|
|
101
100
|
sound.stop();
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
|
-
|
|
105
|
-
this.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
103
|
+
stopSoundsForPageHide() {
|
|
104
|
+
const music = this.getSound(SoundTracks.music);
|
|
105
|
+
const freeSpinsMusic = this.getSound(SoundTracks.freeSpinsMusic);
|
|
106
|
+
const isMusicPlaying = Boolean(music?.isPlaying && !music.paused);
|
|
107
|
+
const isFreeSpinsMusicPlaying = Boolean(freeSpinsMusic?.isPlaying && !freeSpinsMusic.paused);
|
|
108
|
+
if (isFreeSpinsMusicPlaying) {
|
|
109
|
+
this.currentAmbientTrack = SoundTracks.freeSpinsMusic;
|
|
110
|
+
}
|
|
111
|
+
else if (isMusicPlaying) {
|
|
112
|
+
this.currentAmbientTrack = SoundTracks.music;
|
|
113
|
+
}
|
|
114
|
+
this.stopAmbientMusic();
|
|
115
|
+
this.stopPlayingFxSounds();
|
|
114
116
|
}
|
|
115
117
|
/**
|
|
116
118
|
* Function for resuming and pausing sound in game
|
|
@@ -154,15 +156,12 @@ export class SoundManagerInstance {
|
|
|
154
156
|
return;
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
|
-
|
|
159
|
+
sound.play({
|
|
158
160
|
singleInstance: true,
|
|
159
161
|
loop: soundsToLoop.includes(soundName),
|
|
160
162
|
volume: this.getVolumeLevel(soundName),
|
|
161
163
|
speed: soundName === "cardDrawing" ? 0.8 : 1
|
|
162
164
|
});
|
|
163
|
-
if (this.isAmbientTrack(soundName) && !(instance instanceof Promise)) {
|
|
164
|
-
this.trackAmbientPlaybackProgress(soundName, sound, instance);
|
|
165
|
-
}
|
|
166
165
|
}
|
|
167
166
|
/**
|
|
168
167
|
* Returns the volume level for a given sound track.
|
|
@@ -193,41 +192,6 @@ export class SoundManagerInstance {
|
|
|
193
192
|
const overrideSoundName = this.overrides[soundName];
|
|
194
193
|
return this.musicCatalogue.get(overrideSoundName ?? soundName);
|
|
195
194
|
}
|
|
196
|
-
getAmbientPlaybackOffset(sound) {
|
|
197
|
-
if (!sound.isPlayable || !Number.isFinite(sound.duration) || sound.duration <= 0) {
|
|
198
|
-
return 0;
|
|
199
|
-
}
|
|
200
|
-
return this.currentAmbientOffset % sound.duration;
|
|
201
|
-
}
|
|
202
|
-
trackAmbientPlaybackProgress(soundName, sound, instance) {
|
|
203
|
-
if (!sound.isPlayable || sound.duration <= 0) {
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
instance.on("progress", (progress) => {
|
|
207
|
-
if (this.currentAmbientTrack !== soundName || !Number.isFinite(progress)) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
this.currentAmbientOffset = (progress * sound.duration) % sound.duration;
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Saves active ambient position before the browser interrupts WebAudio playback.
|
|
215
|
-
* @public
|
|
216
|
-
* @returns {void}
|
|
217
|
-
*/
|
|
218
|
-
captureAmbientPlaybackPositionForPageHide() {
|
|
219
|
-
if (!RainMan.settingsStore.isSoundStarted || !RainMan.settingsStore.shouldPlayAmbientMusic) {
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
const ambientTrack = this.getCurrentAmbientTrack();
|
|
223
|
-
const ambientSound = this.getSound(ambientTrack);
|
|
224
|
-
const ambientInstance = ambientSound?.instances.find((instance) => Number.isFinite(instance.progress) && instance.progress > 0);
|
|
225
|
-
if (!ambientSound || !ambientInstance || !ambientSound.isPlayable || ambientSound.duration <= 0) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
this.currentAmbientTrack = ambientTrack;
|
|
229
|
-
this.currentAmbientOffset = (ambientInstance.progress * ambientSound.duration) % ambientSound.duration;
|
|
230
|
-
}
|
|
231
195
|
isIOSWebAudioRuntime() {
|
|
232
196
|
const userAgent = navigator.userAgent;
|
|
233
197
|
const platform = navigator.platform;
|
|
@@ -320,16 +284,12 @@ export class SoundManagerInstance {
|
|
|
320
284
|
this.stop(this.getOppositeAmbientTrack(ambientTrack));
|
|
321
285
|
ambientSound.stop();
|
|
322
286
|
this.currentAmbientTrack = ambientTrack;
|
|
323
|
-
|
|
287
|
+
ambientSound.play({
|
|
324
288
|
singleInstance: true,
|
|
325
289
|
loop: soundsToLoop.includes(ambientTrack),
|
|
326
|
-
start: this.getAmbientPlaybackOffset(ambientSound),
|
|
327
290
|
volume: this.getVolumeLevel(ambientTrack),
|
|
328
291
|
speed: 1
|
|
329
292
|
});
|
|
330
|
-
if (!(instance instanceof Promise)) {
|
|
331
|
-
this.trackAmbientPlaybackProgress(ambientTrack, ambientSound, instance);
|
|
332
|
-
}
|
|
333
293
|
}
|
|
334
294
|
/**
|
|
335
295
|
* Restores ambient playback after page visibility change or iOS app interruption.
|
|
@@ -437,7 +397,8 @@ export class SoundManagerInstance {
|
|
|
437
397
|
if (!isAudioContextRunning) {
|
|
438
398
|
return false;
|
|
439
399
|
}
|
|
440
|
-
|
|
400
|
+
this.restoreAmbientPlayback();
|
|
401
|
+
return true;
|
|
441
402
|
}
|
|
442
403
|
/**
|
|
443
404
|
* Returns information if audio context is ready to play sounds.
|
|
@@ -6,7 +6,7 @@ import { RainMan } from "../../Rainman";
|
|
|
6
6
|
import { Nullable, PromiseResolverType } from "../../utils";
|
|
7
7
|
import { BigWinContainer, MysteryWinContainer, UpdatableSpineContainer } from "../../winComponents";
|
|
8
8
|
import { AbstractFreeSpinContainer } from "../AbstractFreeSpinContainer";
|
|
9
|
-
import { LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RightButtons, RightButtonsLandscape, RightButtonsMobile } from "../buttons";
|
|
9
|
+
import { LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RightButtons, RightButtonsLandscape, RightButtonsMobile, SpeedControlButtonMobile } from "../buttons";
|
|
10
10
|
import { FreeSpinButton, Logo, ResponsiveContainer } from "../common";
|
|
11
11
|
import { IResizableContainer } from "../common/IResizableContainer";
|
|
12
12
|
import { AbstractFrame } from "../frame";
|
|
@@ -34,6 +34,7 @@ export declare abstract class AbstractMainContainer extends Container {
|
|
|
34
34
|
static readonly registryName = "mainContainer";
|
|
35
35
|
messageBox: MessageBox;
|
|
36
36
|
protected bigWinContainer: Nullable<UpdatableSpineContainer> | BigWinContainer;
|
|
37
|
+
protected readonly mobileSpeedButton: SpeedControlButtonMobile;
|
|
37
38
|
protected mysteryWinContainer: Nullable<UpdatableSpineContainer> | MysteryWinContainer;
|
|
38
39
|
protected bonusWinContainer: Nullable<UpdatableSpineContainer>;
|
|
39
40
|
protected superBonusWinContainer: Nullable<UpdatableSpineContainer>;
|
|
@@ -75,6 +76,7 @@ export declare abstract class AbstractMainContainer extends Container {
|
|
|
75
76
|
* @returns {Promise<void>} - A promise that resolves when the animation is complete.
|
|
76
77
|
*/
|
|
77
78
|
invokeMysteryWinPlate(_animationName: string, _popupAnimation: string, _winType: WinTypeId, _amount: number, _isAdditionalFreeSpins: boolean): Promise<void>;
|
|
79
|
+
protected attachMobileSpeedButton(parent: Container): void;
|
|
78
80
|
/**
|
|
79
81
|
* This function initializes the spines that should be paused when the battery saver is on
|
|
80
82
|
* @protected
|
|
@@ -318,6 +320,7 @@ export declare abstract class AbstractMainContainer extends Container {
|
|
|
318
320
|
* @returns {Promise<void>} - A promise that resolves when the gamble game is finished.
|
|
319
321
|
*/
|
|
320
322
|
invokeGambleGame(): Promise<void>;
|
|
323
|
+
private destroyDisplayContainer;
|
|
321
324
|
/**
|
|
322
325
|
* Function for creating the under frame panel.
|
|
323
326
|
* This panel is used in mobile portrait mode to display additional information.
|
|
@@ -3,7 +3,7 @@ import { ButtonsEventManager, SoundManager, SoundTracks } from "../../applicatio
|
|
|
3
3
|
import { AnimationLayer, BackgroundLayer, FrameLayer, UXLayer } from "../../layers";
|
|
4
4
|
import { RainMan } from "../../Rainman";
|
|
5
5
|
import { getDeviceOrientation, globalMinRatio } from "../../utils";
|
|
6
|
-
import { BUTTONS, LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RefreshButton, RightButtons, RightButtonsLandscape, RightButtonsMobile } from "../buttons";
|
|
6
|
+
import { BUTTONS, LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RefreshButton, RightButtons, RightButtonsLandscape, RightButtonsMobile, SpeedControlButtonMobile } from "../buttons";
|
|
7
7
|
import { GambleGame } from "../GambleGame";
|
|
8
8
|
import { MessageBox } from "../messageBox";
|
|
9
9
|
/**
|
|
@@ -29,6 +29,7 @@ export class AbstractMainContainer extends Container {
|
|
|
29
29
|
static registryName = "mainContainer";
|
|
30
30
|
messageBox;
|
|
31
31
|
bigWinContainer = null;
|
|
32
|
+
mobileSpeedButton = new SpeedControlButtonMobile();
|
|
32
33
|
mysteryWinContainer = null;
|
|
33
34
|
bonusWinContainer = null;
|
|
34
35
|
superBonusWinContainer = null;
|
|
@@ -59,6 +60,9 @@ export class AbstractMainContainer extends Container {
|
|
|
59
60
|
this.name = AbstractMainContainer.registryName;
|
|
60
61
|
this.buttonsEventManager = new ButtonsEventManager();
|
|
61
62
|
this.messageBox = new MessageBox();
|
|
63
|
+
if (!RainMan.componentRegistry.has(SpeedControlButtonMobile.registryName)) {
|
|
64
|
+
RainMan.componentRegistry.add(this.mobileSpeedButton);
|
|
65
|
+
}
|
|
62
66
|
SoundManager.setPlayStatus(SoundTracks.music, RainMan.settingsStore.shouldPlayAmbientMusic);
|
|
63
67
|
RainMan.settingsStore.setHandleInvokeFreeSpinPlate(this.invokeFreeSpinPlate.bind(this));
|
|
64
68
|
RainMan.settingsStore.setHandleBuyFreeSpinPopupActivatio(this.invokeBuyFreeSpinPlate.bind(this));
|
|
@@ -75,6 +79,13 @@ export class AbstractMainContainer extends Container {
|
|
|
75
79
|
* @returns {Promise<void>} - A promise that resolves when the animation is complete.
|
|
76
80
|
*/
|
|
77
81
|
async invokeMysteryWinPlate(_animationName, _popupAnimation, _winType, _amount, _isAdditionalFreeSpins) { }
|
|
82
|
+
attachMobileSpeedButton(parent) {
|
|
83
|
+
if (this.mobileSpeedButton.parent) {
|
|
84
|
+
this.mobileSpeedButton.parent.removeChild(this.mobileSpeedButton);
|
|
85
|
+
}
|
|
86
|
+
parent.addChild(this.mobileSpeedButton);
|
|
87
|
+
this.mobileSpeedButton.adaptToSpeed(RainMan.componentRegistry.getSpeedLevel());
|
|
88
|
+
}
|
|
78
89
|
/**
|
|
79
90
|
* This function initializes the spines that should be paused when the battery saver is on
|
|
80
91
|
* @protected
|
|
@@ -232,7 +243,7 @@ export class AbstractMainContainer extends Container {
|
|
|
232
243
|
await this._freeSpinPlate.onStart();
|
|
233
244
|
});
|
|
234
245
|
if (this._freeSpinPlate !== null) {
|
|
235
|
-
this.
|
|
246
|
+
this.destroyDisplayContainer(this._freeSpinPlate);
|
|
236
247
|
this._freeSpinPlate = null;
|
|
237
248
|
}
|
|
238
249
|
this.hideOverlay();
|
|
@@ -241,6 +252,7 @@ export class AbstractMainContainer extends Container {
|
|
|
241
252
|
invokeBuyFreeSpinPlate() {
|
|
242
253
|
const refreshButton = RainMan.componentRegistry.get(RefreshButton.registryName);
|
|
243
254
|
refreshButton.flipDisabledFlag(true);
|
|
255
|
+
RainMan.settingsStore.closeAllModals?.();
|
|
244
256
|
this._buyFreeSpinsPlate = this.createBuyFreeSpinPlate();
|
|
245
257
|
if (!this._buyFreeSpinsPlate) {
|
|
246
258
|
refreshButton.flipDisabledFlag(false);
|
|
@@ -292,7 +304,7 @@ export class AbstractMainContainer extends Container {
|
|
|
292
304
|
this.addChild(this._freeSpinSummary);
|
|
293
305
|
});
|
|
294
306
|
if (this._freeSpinSummary !== null) {
|
|
295
|
-
this.
|
|
307
|
+
this.destroyDisplayContainer(this._freeSpinSummary);
|
|
296
308
|
this._freeSpinSummary = null;
|
|
297
309
|
}
|
|
298
310
|
this.hideOverlay();
|
|
@@ -309,7 +321,7 @@ export class AbstractMainContainer extends Container {
|
|
|
309
321
|
return;
|
|
310
322
|
}
|
|
311
323
|
this.freeSpinSummary.onClick();
|
|
312
|
-
this.
|
|
324
|
+
this.destroyDisplayContainer(this.freeSpinSummary);
|
|
313
325
|
this._freeSpinSummary = null;
|
|
314
326
|
this.hideOverlay();
|
|
315
327
|
}
|
|
@@ -559,7 +571,7 @@ export class AbstractMainContainer extends Container {
|
|
|
559
571
|
this.addChild(this.gambleGame);
|
|
560
572
|
});
|
|
561
573
|
if (this.gambleGame) {
|
|
562
|
-
this.
|
|
574
|
+
this.destroyDisplayContainer(this.gambleGame);
|
|
563
575
|
this.messageBox.visible = true;
|
|
564
576
|
RainMan.settingsStore.isGambleGameActive = false;
|
|
565
577
|
this._controller.updateGambleValues(RainMan.settingsStore.gambleGameWin);
|
|
@@ -571,6 +583,15 @@ export class AbstractMainContainer extends Container {
|
|
|
571
583
|
}
|
|
572
584
|
this.hideOverlay();
|
|
573
585
|
}
|
|
586
|
+
destroyDisplayContainer(container) {
|
|
587
|
+
if (container.destroyed) {
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
if (container.parent) {
|
|
591
|
+
container.parent.removeChild(container);
|
|
592
|
+
}
|
|
593
|
+
container.destroy({ children: true });
|
|
594
|
+
}
|
|
574
595
|
/**
|
|
575
596
|
* Function for creating the under frame panel.
|
|
576
597
|
* This panel is used in mobile portrait mode to display additional information.
|
|
@@ -771,7 +792,7 @@ export class AbstractMainContainer extends Container {
|
|
|
771
792
|
* @returns {RightButtonsMobile} - Returns a new instance of RightButtonsMobile for mobile portrait orientation.
|
|
772
793
|
*/
|
|
773
794
|
createRightButtonsMobile() {
|
|
774
|
-
return new RightButtonsMobile();
|
|
795
|
+
return new RightButtonsMobile(this.mobileSpeedButton);
|
|
775
796
|
}
|
|
776
797
|
/**
|
|
777
798
|
* Function for creating the left buttons for landscape orientation
|
|
@@ -795,7 +816,7 @@ export class AbstractMainContainer extends Container {
|
|
|
795
816
|
* @returns {MiddleButtons} - Returns a new instance of MiddleButtons for portrait orientation.
|
|
796
817
|
*/
|
|
797
818
|
createPortraitPlayButtons() {
|
|
798
|
-
return new MiddleButtons();
|
|
819
|
+
return new MiddleButtons(false);
|
|
799
820
|
}
|
|
800
821
|
/**
|
|
801
822
|
* Function for creating the landscape play buttons
|
|
@@ -803,7 +824,7 @@ export class AbstractMainContainer extends Container {
|
|
|
803
824
|
* @returns {MiddleButtons} - Returns a new instance of MiddleButtons for landscape orientation.
|
|
804
825
|
*/
|
|
805
826
|
createLandscapePlayButtons() {
|
|
806
|
-
return new MiddleButtons(true);
|
|
827
|
+
return new MiddleButtons(true, this.mobileSpeedButton);
|
|
807
828
|
}
|
|
808
829
|
/**
|
|
809
830
|
* This method initializes the components for the current screen ratio.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Graphics } from "pixi.js";
|
|
2
2
|
import { ResponsiveContainer } from "../../common";
|
|
3
|
-
import { AutoplayButton, GambleButton, PlusButton, RefreshButton, TakeButton } from "../default";
|
|
3
|
+
import { AutoplayButton, GambleButton, PlusButton, RefreshButton, SpeedControlButtonMobile, TakeButton } from "../default";
|
|
4
4
|
/**
|
|
5
5
|
* Class for managing middle buttons in game (MOBILE ONLY).
|
|
6
6
|
* The class uses {@link AutoplayButton}, {@link PlusButton}, {@link RefreshButton}.
|
|
@@ -8,13 +8,14 @@ import { AutoplayButton, GambleButton, PlusButton, RefreshButton, TakeButton } f
|
|
|
8
8
|
*/
|
|
9
9
|
export declare class MiddleButtons extends ResponsiveContainer {
|
|
10
10
|
private landscape;
|
|
11
|
+
private readonly speedButtonMobile?;
|
|
11
12
|
protected readonly autoplayButton: AutoplayButton;
|
|
12
13
|
protected readonly betButton: PlusButton;
|
|
13
14
|
protected readonly refreshButton: RefreshButton;
|
|
14
15
|
protected readonly positioningFrame: Graphics;
|
|
15
16
|
protected readonly gambleButton: GambleButton;
|
|
16
17
|
protected readonly takeButton: TakeButton;
|
|
17
|
-
constructor(landscape?: boolean);
|
|
18
|
+
constructor(landscape?: boolean, speedButtonMobile?: SpeedControlButtonMobile | undefined);
|
|
18
19
|
/**
|
|
19
20
|
* Function for removing children from the registry
|
|
20
21
|
* @public
|
|
@@ -11,26 +11,37 @@ import { REGISTRY } from "../registrynames";
|
|
|
11
11
|
*/
|
|
12
12
|
export class MiddleButtons extends ResponsiveContainer {
|
|
13
13
|
landscape;
|
|
14
|
+
speedButtonMobile;
|
|
14
15
|
autoplayButton = new AutoplayButton(true);
|
|
15
16
|
betButton = new PlusButton(true);
|
|
16
17
|
refreshButton = new RefreshButton(true);
|
|
17
18
|
positioningFrame = new Graphics();
|
|
18
19
|
gambleButton = new GambleButton(true);
|
|
19
20
|
takeButton = new TakeButton(true);
|
|
20
|
-
constructor(landscape = false) {
|
|
21
|
+
constructor(landscape = false, speedButtonMobile) {
|
|
21
22
|
super();
|
|
22
23
|
this.landscape = landscape;
|
|
24
|
+
this.speedButtonMobile = speedButtonMobile;
|
|
23
25
|
this.name = REGISTRY.middleButtons;
|
|
24
26
|
this.parentLayer = UXLayer;
|
|
25
27
|
const buttons = [this.autoplayButton, this.betButton, this.refreshButton];
|
|
26
28
|
this.addChild(...buttons);
|
|
27
29
|
RainMan.componentRegistry.addMany(buttons);
|
|
30
|
+
if (this.speedButtonMobile) {
|
|
31
|
+
this.speedButtonMobile.visible = true;
|
|
32
|
+
this.speedButtonMobile.scale.set(1);
|
|
33
|
+
this.speedButtonMobile.adaptToSpeed(RainMan.componentRegistry.getSpeedLevel());
|
|
34
|
+
this.addChild(this.speedButtonMobile);
|
|
35
|
+
}
|
|
28
36
|
this.addGambleAndTakeButtons();
|
|
29
37
|
this.positioningFrame.beginFill(0x000000, 0);
|
|
30
38
|
this.positioningFrame.drawRect(0, 0, 800, 250);
|
|
31
39
|
this.addChild(this.positioningFrame);
|
|
32
40
|
this.refreshButton.scale.set(0.75);
|
|
33
41
|
this.autoplayButton.scale.set(0.75);
|
|
42
|
+
if (this.speedButtonMobile) {
|
|
43
|
+
this.speedButtonMobile.scale.set(1);
|
|
44
|
+
}
|
|
34
45
|
this.betButton.scale.set(0.75);
|
|
35
46
|
this.takeButton.scale.set(0.75);
|
|
36
47
|
this.gambleButton.scale.set(0.75);
|
|
@@ -63,7 +74,6 @@ export class MiddleButtons extends ResponsiveContainer {
|
|
|
63
74
|
this.refreshButton,
|
|
64
75
|
this.autoplayButton,
|
|
65
76
|
this.betButton,
|
|
66
|
-
this.positioningFrame,
|
|
67
77
|
...(this.gambleButton && RainMan.config.gambleGameEnabled ? [this.gambleButton] : []),
|
|
68
78
|
...(this.takeButton ? [this.takeButton] : [])
|
|
69
79
|
]);
|
|
@@ -92,11 +102,15 @@ export class MiddleButtons extends ResponsiveContainer {
|
|
|
92
102
|
const { width, height } = this.positioningFrame;
|
|
93
103
|
this.refreshButton.x = width / 2;
|
|
94
104
|
this.refreshButton.y = height / 2;
|
|
105
|
+
if (this.speedButtonMobile) {
|
|
106
|
+
this.speedButtonMobile.x = width / 2;
|
|
107
|
+
this.speedButtonMobile.y = 150;
|
|
108
|
+
}
|
|
95
109
|
if (this.landscape) {
|
|
96
110
|
this.betButton.x = width / 2;
|
|
97
|
-
this.betButton.y =
|
|
111
|
+
this.betButton.y = -25;
|
|
98
112
|
this.autoplayButton.x = width / 2;
|
|
99
|
-
this.autoplayButton.y = height;
|
|
113
|
+
this.autoplayButton.y = height + 35;
|
|
100
114
|
}
|
|
101
115
|
else {
|
|
102
116
|
this.autoplayButton.x = -width;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ITextStyle } from "pixi.js";
|
|
2
2
|
import { ResponsiveContainer } from "../../common";
|
|
3
3
|
import { UpdatableTextComponent } from "../../updatable";
|
|
4
|
-
import { InfoButton, NegButton,
|
|
4
|
+
import { InfoButton, NegButton, SpeedControlButtonMobile } from "../default";
|
|
5
5
|
/**
|
|
6
6
|
* Buttons for mobile version. It has a current bet and game information button.
|
|
7
7
|
* @augments {ResponsiveContainer}
|
|
8
8
|
*/
|
|
9
9
|
export declare class RightButtonsMobile extends ResponsiveContainer {
|
|
10
|
+
private readonly speedButtonMobile;
|
|
10
11
|
protected readonly infoButton: InfoButton;
|
|
11
12
|
protected readonly negButton: NegButton;
|
|
12
|
-
protected readonly speedControlButton: SpeedControlButton;
|
|
13
13
|
protected bet: UpdatableTextComponent;
|
|
14
|
-
constructor();
|
|
14
|
+
constructor(speedButtonMobile: SpeedControlButtonMobile);
|
|
15
15
|
/**
|
|
16
16
|
* Function for removing children from the registry.
|
|
17
17
|
* @public
|
|
@@ -3,7 +3,7 @@ import { UXLayer } from "../../../layers";
|
|
|
3
3
|
import { RainMan } from "../../../Rainman";
|
|
4
4
|
import { ResponsiveContainer } from "../../common";
|
|
5
5
|
import { UPDATABLE_MODES, UpdatableTextComponent } from "../../updatable";
|
|
6
|
-
import { InfoButton, NegButton
|
|
6
|
+
import { InfoButton, NegButton } from "../default";
|
|
7
7
|
import { COMPONENTS, REGISTRY } from "../registrynames";
|
|
8
8
|
import { MOBILE_BUTTONS_GAP, MOBILE_PANEL_BUTTON_SCALE, MOBILE_X_OFFSET, MOBILE_Y_BOTTOM_OFFSET } from "./constants";
|
|
9
9
|
/**
|
|
@@ -11,22 +11,25 @@ import { MOBILE_BUTTONS_GAP, MOBILE_PANEL_BUTTON_SCALE, MOBILE_X_OFFSET, MOBILE_
|
|
|
11
11
|
* @augments {ResponsiveContainer}
|
|
12
12
|
*/
|
|
13
13
|
export class RightButtonsMobile extends ResponsiveContainer {
|
|
14
|
+
speedButtonMobile;
|
|
14
15
|
infoButton = new InfoButton(true);
|
|
15
16
|
negButton = new NegButton();
|
|
16
|
-
speedControlButton = new SpeedControlButton();
|
|
17
17
|
bet = new UpdatableTextComponent(COMPONENTS.betText, i18next.t("bet"), UPDATABLE_MODES.money, RainMan.config.mobileFontSize);
|
|
18
|
-
constructor() {
|
|
18
|
+
constructor(speedButtonMobile) {
|
|
19
19
|
super(-1);
|
|
20
|
+
this.speedButtonMobile = speedButtonMobile;
|
|
20
21
|
this.name = REGISTRY.rightButtons;
|
|
21
22
|
this.parentLayer = UXLayer;
|
|
22
23
|
this.negButton.visible = false;
|
|
23
|
-
this.speedControlButton.visible = false;
|
|
24
24
|
this.infoButton.anchor.set(1, 0.5);
|
|
25
25
|
this.infoButton.scale.set(-MOBILE_PANEL_BUTTON_SCALE);
|
|
26
26
|
this.bet.pivot.set(this.bet.width, this.bet.height / 2);
|
|
27
27
|
this.bet.scale.set(-1);
|
|
28
|
-
this.
|
|
29
|
-
|
|
28
|
+
this.speedButtonMobile.scale.set(-1);
|
|
29
|
+
this.speedButtonMobile.x = 100;
|
|
30
|
+
this.speedButtonMobile.y = 200;
|
|
31
|
+
this.addChild(this.infoButton, this.bet, this.speedButtonMobile);
|
|
32
|
+
RainMan.componentRegistry.addMany([this.infoButton, this.bet, this.negButton]);
|
|
30
33
|
this.resize();
|
|
31
34
|
}
|
|
32
35
|
/**
|
|
@@ -35,7 +38,7 @@ export class RightButtonsMobile extends ResponsiveContainer {
|
|
|
35
38
|
* @returns {void}
|
|
36
39
|
*/
|
|
37
40
|
removeChildrenFromRegistry() {
|
|
38
|
-
RainMan.componentRegistry.removeMany([this.infoButton, this.bet, this.negButton
|
|
41
|
+
RainMan.componentRegistry.removeMany([this.infoButton, this.bet, this.negButton]);
|
|
39
42
|
}
|
|
40
43
|
/**
|
|
41
44
|
* Function for repositioning components on mobile screens.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SpeedAdapterInterface, SpeedLevel, SpeedLevelDirectory } from "../../../application";
|
|
2
|
+
import { BaseButton, TextureMap } from "../BaseButton";
|
|
3
|
+
/**
|
|
4
|
+
* Button for speed control {@link SpeedLevel}
|
|
5
|
+
* It needs following textures:
|
|
6
|
+
* - turtle - `speed-turtle.png`
|
|
7
|
+
* - rabbit - `speed-rabbit.png`
|
|
8
|
+
* - cheetah - `speed-cheetah.png`
|
|
9
|
+
* @class
|
|
10
|
+
*/
|
|
11
|
+
export declare class SpeedControlButtonMobile extends BaseButton implements SpeedAdapterInterface<TextureMap> {
|
|
12
|
+
static readonly registryName = "speedControlButtonMobile";
|
|
13
|
+
readonly speedLevelMapper: SpeedLevelDirectory<TextureMap>;
|
|
14
|
+
constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Change button's texture according to speed level
|
|
17
|
+
* @public
|
|
18
|
+
* @param {SpeedLevel} speedLevel - new speed level
|
|
19
|
+
* @returns {void}
|
|
20
|
+
*/
|
|
21
|
+
adaptToSpeed(speedLevel: SpeedLevel): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { RainMan } from "../../../Rainman";
|
|
2
|
+
import { getTexture } from "../../../utils";
|
|
3
|
+
import { BaseButton, ButtonStates } from "../BaseButton";
|
|
4
|
+
const createTextureMap = (speedLevel) => {
|
|
5
|
+
return {
|
|
6
|
+
[ButtonStates.NORMAL]: getTexture(`${speedLevel}.png`),
|
|
7
|
+
[ButtonStates.CLICKED]: getTexture(`${speedLevel}-c.png`)
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
const createTextureMapForSpeed = (speedLevel) => {
|
|
11
|
+
const speedLevelMapper = {
|
|
12
|
+
slow: createTextureMap("turtle"),
|
|
13
|
+
normal: createTextureMap("rabbit"),
|
|
14
|
+
fast: createTextureMap("cheetah")
|
|
15
|
+
};
|
|
16
|
+
return speedLevelMapper[speedLevel];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Button for speed control {@link SpeedLevel}
|
|
20
|
+
* It needs following textures:
|
|
21
|
+
* - turtle - `speed-turtle.png`
|
|
22
|
+
* - rabbit - `speed-rabbit.png`
|
|
23
|
+
* - cheetah - `speed-cheetah.png`
|
|
24
|
+
* @class
|
|
25
|
+
*/
|
|
26
|
+
export class SpeedControlButtonMobile extends BaseButton {
|
|
27
|
+
static registryName = "speedControlButtonMobile";
|
|
28
|
+
speedLevelMapper;
|
|
29
|
+
constructor() {
|
|
30
|
+
super(SpeedControlButtonMobile.registryName, createTextureMapForSpeed(RainMan.settingsStore.currentSpeed));
|
|
31
|
+
this.speedLevelMapper = {
|
|
32
|
+
slow: createTextureMap("turtle"),
|
|
33
|
+
normal: createTextureMap("rabbit"),
|
|
34
|
+
fast: createTextureMap("cheetah")
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Change button's texture according to speed level
|
|
39
|
+
* @public
|
|
40
|
+
* @param {SpeedLevel} speedLevel - new speed level
|
|
41
|
+
* @returns {void}
|
|
42
|
+
*/
|
|
43
|
+
adaptToSpeed(speedLevel) {
|
|
44
|
+
if (RainMan.settingsStore.isTemporarySpeed) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const textureMap = this.speedLevelMapper[speedLevel];
|
|
48
|
+
this.setTextureMap(textureMap);
|
|
49
|
+
this.texture = textureMap[ButtonStates.NORMAL];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -9,6 +9,7 @@ export * from "./PlusButton";
|
|
|
9
9
|
export * from "./RedButton";
|
|
10
10
|
export * from "./RefreshButton";
|
|
11
11
|
export * from "./SpeedControlButton";
|
|
12
|
+
export * from "./SpeedControlButtonMobile";
|
|
12
13
|
export * from "./SpinConfirmationButton";
|
|
13
14
|
export * from "./TakeButton";
|
|
14
15
|
export * from "./VolumeButton";
|
|
@@ -9,6 +9,7 @@ export * from "./PlusButton";
|
|
|
9
9
|
export * from "./RedButton";
|
|
10
10
|
export * from "./RefreshButton";
|
|
11
11
|
export * from "./SpeedControlButton";
|
|
12
|
+
export * from "./SpeedControlButtonMobile";
|
|
12
13
|
export * from "./SpinConfirmationButton";
|
|
13
14
|
export * from "./TakeButton";
|
|
14
15
|
export * from "./VolumeButton";
|
|
@@ -68,7 +68,16 @@ export class AnimatedNumber extends Container {
|
|
|
68
68
|
* @returns {void}
|
|
69
69
|
*/
|
|
70
70
|
removeDigits() {
|
|
71
|
-
this.digits.forEach((digit) =>
|
|
71
|
+
this.digits.forEach((digit) => {
|
|
72
|
+
if (digit.destroyed) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
digit.state.clearListeners();
|
|
76
|
+
if (digit.parent) {
|
|
77
|
+
digit.parent.removeChild(digit);
|
|
78
|
+
}
|
|
79
|
+
digit.destroy({ children: true });
|
|
80
|
+
});
|
|
72
81
|
this.digits = [];
|
|
73
82
|
}
|
|
74
83
|
/**
|
|
@@ -91,6 +91,7 @@ export declare abstract class AbstractSymbolBase extends Container implements Sp
|
|
|
91
91
|
* @returns {Promise<void>}
|
|
92
92
|
*/
|
|
93
93
|
handleMultiplierAnimation(multiplier: number): Promise<void>;
|
|
94
|
+
private destroySpine;
|
|
94
95
|
/**
|
|
95
96
|
* Function for playing the symbol animation
|
|
96
97
|
* @public
|
|
@@ -98,6 +99,7 @@ export declare abstract class AbstractSymbolBase extends Container implements Sp
|
|
|
98
99
|
* @returns {Promise<void>} - A promise that resolves when the animation is complete
|
|
99
100
|
*/
|
|
100
101
|
play(suffix?: string): Promise<void>;
|
|
102
|
+
isCurrentAnimationPastProgressThreshold(): boolean;
|
|
101
103
|
/**
|
|
102
104
|
* Function for stopping the symbol animation.
|
|
103
105
|
* @public
|
|
@@ -31,10 +31,10 @@ export class AbstractSymbolBase extends Container {
|
|
|
31
31
|
this._id = symbolId;
|
|
32
32
|
this.spine = new Spine(this.getResourceForSymbolId(this._id));
|
|
33
33
|
this.spine.parentLayer = AnimationLayer;
|
|
34
|
-
this.symbolImage = new Sprite(getTexture(this.getImage(this._id)));
|
|
35
|
-
this.setSymbol(symbolId);
|
|
36
34
|
this.spine.x = 0;
|
|
37
35
|
this.spine.y = 0;
|
|
36
|
+
this.symbolImage = new Sprite(getTexture(this.getImage(this._id)));
|
|
37
|
+
this.setSymbol(symbolId);
|
|
38
38
|
this.eventMode = "static";
|
|
39
39
|
const symbolRadius = 150;
|
|
40
40
|
this.hitArea = new Rectangle(-symbolRadius, -symbolRadius, 2 * symbolRadius, 2 * symbolRadius);
|
|
@@ -109,6 +109,7 @@ export class AbstractSymbolBase extends Container {
|
|
|
109
109
|
return () => {
|
|
110
110
|
this.swapSymbol(symbolId);
|
|
111
111
|
return new Promise((resolve) => {
|
|
112
|
+
this.destroySpine(this.spine);
|
|
112
113
|
this.spine = new Spine(getSpineData(specialResourceName));
|
|
113
114
|
this.endOfSwapAnimationPromise = resolve;
|
|
114
115
|
switch (this.animationSpeedMultiplier) {
|
|
@@ -143,10 +144,11 @@ export class AbstractSymbolBase extends Container {
|
|
|
143
144
|
*/
|
|
144
145
|
switchSymbolBaseDisplayedObject(option, suffix = "") {
|
|
145
146
|
if (option === "spine") {
|
|
146
|
-
this.
|
|
147
|
-
this.
|
|
148
|
-
this.spine.y = this.symbolImage.y;
|
|
147
|
+
const { x, y } = this.symbolImage;
|
|
148
|
+
this.destroySpine(this.spine);
|
|
149
149
|
this.spine = new Spine(this.getResourceForSymbolId(this._id));
|
|
150
|
+
this.spine.x = x;
|
|
151
|
+
this.spine.y = y;
|
|
150
152
|
const animationName = this.getAnimationNameForSymbol(this._id, suffix);
|
|
151
153
|
this.spine.parentLayer = AnimationLayer;
|
|
152
154
|
this.spine.state.setAnimation(0, animationName, false);
|
|
@@ -156,14 +158,15 @@ export class AbstractSymbolBase extends Container {
|
|
|
156
158
|
this.removeChild(this.symbolImage);
|
|
157
159
|
return;
|
|
158
160
|
}
|
|
161
|
+
const { x, y } = this.symbolImage;
|
|
159
162
|
this.removeChild(this.symbolImage);
|
|
160
163
|
this.symbolImage.destroy({ children: true });
|
|
161
164
|
this.symbolImage = new Sprite(getTexture(this.getImage(this._id, suffix)));
|
|
162
165
|
this.symbolImage.anchor.set(0.5, 0.5);
|
|
163
|
-
this.symbolImage.x = this.spine.x;
|
|
164
|
-
this.symbolImage.y = this.spine.y;
|
|
166
|
+
this.symbolImage.x = this.spine.destroyed ? x : this.spine.x;
|
|
167
|
+
this.symbolImage.y = this.spine.destroyed ? y : this.spine.y;
|
|
165
168
|
this.addChild(this.symbolImage);
|
|
166
|
-
this.
|
|
169
|
+
this.destroySpine(this.spine);
|
|
167
170
|
return;
|
|
168
171
|
}
|
|
169
172
|
/**
|
|
@@ -182,6 +185,7 @@ export class AbstractSymbolBase extends Container {
|
|
|
182
185
|
}
|
|
183
186
|
else {
|
|
184
187
|
logError(`$ Multiplier animation 'x${multiplier}' does not exist for symbol ID: ${this._id}`);
|
|
188
|
+
symbolMultiplier.destroy({ children: true });
|
|
185
189
|
return;
|
|
186
190
|
}
|
|
187
191
|
this.addChild(symbolMultiplier);
|
|
@@ -194,6 +198,17 @@ export class AbstractSymbolBase extends Container {
|
|
|
194
198
|
});
|
|
195
199
|
});
|
|
196
200
|
this.removeChild(symbolMultiplier);
|
|
201
|
+
symbolMultiplier.destroy({ children: true });
|
|
202
|
+
}
|
|
203
|
+
destroySpine(spine) {
|
|
204
|
+
if (spine.destroyed) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
spine.state.clearListeners();
|
|
208
|
+
if (spine.parent) {
|
|
209
|
+
spine.parent.removeChild(spine);
|
|
210
|
+
}
|
|
211
|
+
spine.destroy({ children: true });
|
|
197
212
|
}
|
|
198
213
|
/**
|
|
199
214
|
* Function for playing the symbol animation
|
|
@@ -214,6 +229,18 @@ export class AbstractSymbolBase extends Container {
|
|
|
214
229
|
});
|
|
215
230
|
});
|
|
216
231
|
}
|
|
232
|
+
isCurrentAnimationPastProgressThreshold() {
|
|
233
|
+
const entry = this.spine.state.tracks[0];
|
|
234
|
+
if (!entry) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
const trackTime = entry.trackTime ?? 0;
|
|
238
|
+
const animationEnd = entry.animationEnd ?? 0;
|
|
239
|
+
if (animationEnd <= 0) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
return trackTime >= animationEnd / 3;
|
|
243
|
+
}
|
|
217
244
|
/**
|
|
218
245
|
* Function for stopping the symbol animation.
|
|
219
246
|
* @public
|
|
@@ -57,6 +57,9 @@ export declare abstract class AbstractController<T> {
|
|
|
57
57
|
shouldStopMobileSpin: boolean;
|
|
58
58
|
disableMessageBoxChange: boolean;
|
|
59
59
|
shouldClearQuickReelsStopAfterSpin: boolean;
|
|
60
|
+
protected firstAnimationTarget: {
|
|
61
|
+
isCurrentAnimationPastProgressThreshold?: () => boolean;
|
|
62
|
+
} | null;
|
|
60
63
|
freeSpinsWin: Nullable<number>;
|
|
61
64
|
protected resolveBigWin?: () => void;
|
|
62
65
|
protected resolveMysteryWin?: () => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import i18next from "i18next";
|
|
2
2
|
import { sample } from "lodash";
|
|
3
3
|
import { ApiConfig, SoundManager, SoundTracks, SPEED_LEVELS } from "../application";
|
|
4
|
-
import { AbstractFrame, AutoplayButton, BUTTONS, COMPONENTS, FreeSpinButton, MessageBox, RefreshButton, SpeedControlButton } from "../components";
|
|
4
|
+
import { AbstractFrame, AutoplayButton, BUTTONS, COMPONENTS, FreeSpinButton, MessageBox, RefreshButton, SpeedControlButton, SpeedControlButtonMobile } from "../components";
|
|
5
5
|
import { SpinData } from "../connectivity";
|
|
6
6
|
import { gamePhases, PossibleWins } from "../constants";
|
|
7
7
|
import { RainMan } from "../Rainman";
|
|
@@ -57,6 +57,7 @@ export class AbstractController {
|
|
|
57
57
|
shouldStopMobileSpin = false;
|
|
58
58
|
disableMessageBoxChange = false;
|
|
59
59
|
shouldClearQuickReelsStopAfterSpin = false;
|
|
60
|
+
firstAnimationTarget = null;
|
|
60
61
|
freeSpinsWin = null;
|
|
61
62
|
resolveBigWin;
|
|
62
63
|
resolveMysteryWin;
|
|
@@ -256,7 +257,10 @@ export class AbstractController {
|
|
|
256
257
|
* @returns {void}
|
|
257
258
|
*/
|
|
258
259
|
disableSpeedButton(shouldBeDisabled) {
|
|
259
|
-
RainMan.componentRegistry.
|
|
260
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName)?.flipDisabledFlag(shouldBeDisabled);
|
|
261
|
+
RainMan.componentRegistry
|
|
262
|
+
.getIfExists(SpeedControlButtonMobile.registryName)
|
|
263
|
+
?.flipDisabledFlag(shouldBeDisabled);
|
|
260
264
|
}
|
|
261
265
|
/**
|
|
262
266
|
* Function for disabling information buttons
|
|
@@ -289,14 +293,11 @@ export class AbstractController {
|
|
|
289
293
|
*/
|
|
290
294
|
handleDisablingButtons(disabled) {
|
|
291
295
|
this.disableBetButtons(disabled ?? this.shouldBetButtonsBeDisabled);
|
|
292
|
-
|
|
293
|
-
RainMan.globals.isSuperBonusGameEnabled
|
|
294
|
-
RainMan.settingsStore.isAutoplayEnabled
|
|
295
|
-
this.
|
|
296
|
-
|
|
297
|
-
else {
|
|
298
|
-
this.disableSpeedButton(disabled ?? this.shouldButtonsBeDisabled);
|
|
299
|
-
}
|
|
296
|
+
const shouldSpeedBeDisabled = !RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
297
|
+
!RainMan.globals.isSuperBonusGameEnabled &&
|
|
298
|
+
!RainMan.settingsStore.isAutoplayEnabled &&
|
|
299
|
+
this.shouldButtonsBeDisabled;
|
|
300
|
+
this.disableSpeedButton(shouldSpeedBeDisabled);
|
|
300
301
|
}
|
|
301
302
|
/**
|
|
302
303
|
* Function for initializing buttons
|
|
@@ -339,10 +340,12 @@ export class AbstractController {
|
|
|
339
340
|
this.gamePhase === gamePhases.SPINNING ||
|
|
340
341
|
this.gamePhase === gamePhases.GAME_SUMMARY);
|
|
341
342
|
}
|
|
342
|
-
RainMan.componentRegistry.
|
|
343
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName)?.setOnClick(() => {
|
|
343
344
|
RainMan.settingsStore.closeCurrentlyOpenModal?.();
|
|
344
345
|
RainMan.componentRegistry.nextSpeedLevel();
|
|
345
|
-
|
|
346
|
+
const speedLevel = RainMan.componentRegistry.getSpeedLevel();
|
|
347
|
+
this.uiController.updateShownSpeedLevel(speedLevel);
|
|
348
|
+
this.uiController.messageBox.updateIncentiveText(sample(i18next.t("idleMessages", { returnObjects: true })[speedLevel]));
|
|
346
349
|
});
|
|
347
350
|
}
|
|
348
351
|
/**
|
|
@@ -365,6 +368,13 @@ export class AbstractController {
|
|
|
365
368
|
}
|
|
366
369
|
RainMan.settingsStore.handleModalInvocation?.(UI_ITEMS.bet);
|
|
367
370
|
});
|
|
371
|
+
if (RainMan.componentRegistry.has(SpeedControlButtonMobile.registryName)) {
|
|
372
|
+
RainMan.componentRegistry.get(SpeedControlButtonMobile.registryName).setOnClick(() => {
|
|
373
|
+
RainMan.settingsStore.closeCurrentlyOpenModal?.();
|
|
374
|
+
RainMan.componentRegistry.nextSpeedLevel();
|
|
375
|
+
this.uiController.messageBox.updateIncentiveText(sample(i18next.t("idleMessages", { returnObjects: true })[RainMan.componentRegistry.getSpeedLevel()]));
|
|
376
|
+
});
|
|
377
|
+
}
|
|
368
378
|
return;
|
|
369
379
|
}
|
|
370
380
|
RainMan.componentRegistry.get(BUTTONS.plus).setOnClick(() => {
|
|
@@ -760,7 +770,7 @@ export class AbstractController {
|
|
|
760
770
|
return;
|
|
761
771
|
}
|
|
762
772
|
if (this.gamePhase === gamePhases.HANDLING_ACTIONS) {
|
|
763
|
-
this.shouldPlayNextSpin =
|
|
773
|
+
this.shouldPlayNextSpin = !RainMan.settingsStore.isFreeSpinsPlayEnabled;
|
|
764
774
|
}
|
|
765
775
|
if (this.mainContainer.mysteryWinVisibleFor) {
|
|
766
776
|
RainMan.componentRegistry.get(COMPONENTS.mysteryWin).stopUpdate();
|
|
@@ -907,7 +917,7 @@ export class AbstractController {
|
|
|
907
917
|
async useTakeAction() {
|
|
908
918
|
if (!RainMan.settingsStore.isTakeActionAvailable ||
|
|
909
919
|
RainMan.settingsStore.roundNumber === 0 ||
|
|
910
|
-
this._lastWinAmount === 0) {
|
|
920
|
+
(this._lastWinAmount === 0 && !RainMan.settingsStore.isAfterFreeSpinsSummary)) {
|
|
911
921
|
logInfo("Take action can't be performed");
|
|
912
922
|
return;
|
|
913
923
|
}
|
|
@@ -1159,6 +1169,8 @@ export class AbstractController {
|
|
|
1159
1169
|
this.uiController.limitWinAmount(spinLogic.winTotalAmount);
|
|
1160
1170
|
}
|
|
1161
1171
|
this.composeWinActionsQueue(spinLogic);
|
|
1172
|
+
this.firstAnimationTarget =
|
|
1173
|
+
this.winActionsQueue.find((action) => action.animationTarget)?.animationTarget ?? null;
|
|
1162
1174
|
if (spinLogic.winTotalAmount === 0 && this.invokeFreeSpinPlateAfterWin) {
|
|
1163
1175
|
this.uiController.messageBox.hideCurrentWinText();
|
|
1164
1176
|
}
|
|
@@ -1312,6 +1324,8 @@ export class AbstractController {
|
|
|
1312
1324
|
* @returns {Promise<void>} - promise that resolves when free spin plate is invoked
|
|
1313
1325
|
*/
|
|
1314
1326
|
async handleFreeSpinPlateInvocation(numberOfFreeSpins, isAdditionalFreeSpin = false) {
|
|
1327
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButtonMobile.registryName)?.flipDisabledFlag(true);
|
|
1328
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName)?.flipDisabledFlag(true);
|
|
1315
1329
|
await this.buttonsEventManager.disableButtonsForAction(async () => {
|
|
1316
1330
|
await this.mainContainer.invokeFreeSpinPlate(numberOfFreeSpins ?? RainMan.settingsStore.totalNumberOfFreeSpins, isAdditionalFreeSpin);
|
|
1317
1331
|
});
|
|
@@ -1328,9 +1342,12 @@ export class AbstractController {
|
|
|
1328
1342
|
* @returns {Promise<void>} - promise that resolves when free spin summary plate is invoked
|
|
1329
1343
|
*/
|
|
1330
1344
|
async handleFreeSpinSummaryPlateInvocation() {
|
|
1345
|
+
this.shouldPlayNextSpin = false;
|
|
1331
1346
|
await this.buttonsEventManager.disableButtonsForAction(async () => {
|
|
1332
1347
|
this.uiController.messageBox.hideFreeSpinText();
|
|
1333
1348
|
this.uiController.messageBox.hideCurrentWinText();
|
|
1349
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButtonMobile.registryName)?.flipDisabledFlag(true);
|
|
1350
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName)?.flipDisabledFlag(true);
|
|
1334
1351
|
await this.mainContainer.invokeFreeSpinSummary(this.uiController.totalNumberOfFreeSpins, this.uiController.totalFreeSpinWinAmount);
|
|
1335
1352
|
this.uiController.totalNumberOfFreeSpins = 0;
|
|
1336
1353
|
this.uiController.resetTotalFreeSpinWinAmount();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { round } from "lodash";
|
|
2
|
-
import { COMPONENTS, MessageBox, SpeedControlButton } from "../components";
|
|
2
|
+
import { COMPONENTS, MessageBox, SpeedControlButton, SpeedControlButtonMobile } from "../components";
|
|
3
3
|
import { RainMan } from "../Rainman";
|
|
4
4
|
import { ceilToDecimal } from "../utils";
|
|
5
5
|
/**
|
|
@@ -181,8 +181,12 @@ export class UiController {
|
|
|
181
181
|
* @returns {void}
|
|
182
182
|
*/
|
|
183
183
|
updateShownSpeedLevel(currentSpeed) {
|
|
184
|
-
RainMan.componentRegistry.
|
|
185
|
-
RainMan.componentRegistry.
|
|
184
|
+
const speedButton = RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName);
|
|
185
|
+
const mobileSpeedButton = RainMan.componentRegistry.getIfExists(SpeedControlButtonMobile.registryName);
|
|
186
|
+
speedButton?.adaptToSpeed(currentSpeed);
|
|
187
|
+
speedButton?.forceTextureUpdate();
|
|
188
|
+
mobileSpeedButton?.adaptToSpeed(currentSpeed);
|
|
189
|
+
mobileSpeedButton?.forceTextureUpdate();
|
|
186
190
|
}
|
|
187
191
|
/**
|
|
188
192
|
* Function for updating shown balance
|
|
@@ -216,7 +220,6 @@ export class UiController {
|
|
|
216
220
|
}
|
|
217
221
|
/**
|
|
218
222
|
* Shows game pays in a bottom panel, if exists
|
|
219
|
-
* @param amount
|
|
220
223
|
* @public
|
|
221
224
|
* @returns {void}
|
|
222
225
|
*/
|
|
@@ -63,6 +63,7 @@ export declare class SettingsStore {
|
|
|
63
63
|
updateVolumeButtonTexture?: () => void;
|
|
64
64
|
handleModalInvocation?: (layerId: string) => void;
|
|
65
65
|
closeOtherModals?: (layerId: string) => void;
|
|
66
|
+
closeAllModals?: () => void;
|
|
66
67
|
closeCurrentlyOpenModal?: () => void;
|
|
67
68
|
handleInvokeFreeSpinPlate?: (freeSpinAmount: number, isAdditionalFreeSpin: boolean) => Promise<void>;
|
|
68
69
|
handleBuyFreeSpinPopupActivation?: () => void;
|
|
@@ -16,16 +16,15 @@ const interruptedAudioResume = () => {
|
|
|
16
16
|
window.addEventListener("touchend", resumeAudioOnInterruption, { once: true, passive: true });
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
* Pixi handles the actual pause state through its WebAudio auto-pause flow.
|
|
19
|
+
* Pauses audio when the page goes to the background.
|
|
21
20
|
* @returns {void}
|
|
22
21
|
*/
|
|
23
|
-
const
|
|
22
|
+
const pauseAudio = () => {
|
|
24
23
|
isResumingAudio = false;
|
|
25
24
|
shouldResumeAudioOnInterruption = false;
|
|
26
25
|
removeInterruptedAudioResumeListeners();
|
|
27
26
|
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
28
|
-
SoundManager.
|
|
27
|
+
SoundManager.stopSoundsForPageHide();
|
|
29
28
|
}
|
|
30
29
|
};
|
|
31
30
|
/**
|
|
@@ -72,10 +71,10 @@ function resumeAudioOnInterruption() {
|
|
|
72
71
|
*/
|
|
73
72
|
const handleVisibilityChange = () => {
|
|
74
73
|
if (document.hidden) {
|
|
75
|
-
|
|
74
|
+
pauseAudio();
|
|
76
75
|
return;
|
|
77
76
|
}
|
|
78
|
-
|
|
77
|
+
interruptedAudioResume();
|
|
79
78
|
};
|
|
80
79
|
/**
|
|
81
80
|
* Sets up audio states for tab switches and iOS app interruptions.
|
|
@@ -84,7 +83,7 @@ const handleVisibilityChange = () => {
|
|
|
84
83
|
export const loadSoundsOnTabChange = () => {
|
|
85
84
|
sound.disableAutoPause = false;
|
|
86
85
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
87
|
-
window.addEventListener("pagehide", () =>
|
|
88
|
-
window.addEventListener("pageshow", () =>
|
|
89
|
-
window.addEventListener("focus", () =>
|
|
86
|
+
window.addEventListener("pagehide", () => pauseAudio());
|
|
87
|
+
window.addEventListener("pageshow", () => interruptedAudioResume());
|
|
88
|
+
window.addEventListener("focus", () => interruptedAudioResume());
|
|
90
89
|
};
|
package/package.json
CHANGED