pixi-rainman-game-engine 0.3.34 → 0.3.36-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DescribedPlayableAction/DescribedPlayableAction.d.ts +3 -0
- package/dist/DescribedPlayableAction/DescribedPlayableAction.js +1 -0
- package/dist/SettingsUI/components/CloseModalButton/index.jsx +1 -1
- package/dist/application/SoundManager/SoundManager.d.ts +1 -1
- package/dist/application/SoundManager/SoundManager.js +7 -5
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +4 -3
- package/dist/components/GambleGame/GambleGame.d.ts +8 -0
- package/dist/components/GambleGame/GambleGame.js +159 -57
- package/dist/components/symbols/AbstractSymbolBase.d.ts +1 -0
- package/dist/components/symbols/AbstractSymbolBase.js +12 -0
- package/dist/components/updatable/UpdatableValueComponent.d.ts +1 -0
- package/dist/components/updatable/UpdatableValueComponent.js +8 -6
- package/dist/connectivity/wins.d.ts +4 -1
- package/dist/constants/wins.d.ts +1 -0
- package/dist/constants/wins.js +2 -1
- package/dist/controllers/AbstractController.d.ts +3 -0
- package/dist/controllers/AbstractController.js +20 -4
- package/dist/controllers/UiController.d.ts +0 -1
- package/dist/controllers/UiController.js +0 -1
- package/dist/stores/SettingsStore.d.ts +0 -2
- package/dist/stores/SettingsStore.js +0 -2
- package/dist/utils/common/sound.js +29 -13
- package/package.json +1 -1
|
@@ -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
|
+
isCurrentAnimationPastHalf?: () => boolean;
|
|
15
|
+
} | null;
|
|
13
16
|
constructor(type: T, action: PlayableAction, winAmount?: Nullable<number>, skipLooping?: boolean);
|
|
14
17
|
}
|
|
@@ -13,7 +13,7 @@ export const CloseModalButton = observer(({ layerId, afterClose }) => {
|
|
|
13
13
|
settingStore.setSpeedPopupVisibility?.("none");
|
|
14
14
|
settingStore.isSpeedModalShown = false;
|
|
15
15
|
}
|
|
16
|
-
if (isBetDisabled) {
|
|
16
|
+
if (!isBetDisabled) {
|
|
17
17
|
settingStore.enableButtons?.();
|
|
18
18
|
}
|
|
19
19
|
afterClose?.();
|
|
@@ -117,7 +117,7 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
117
117
|
* @public
|
|
118
118
|
* @returns {void}
|
|
119
119
|
*/
|
|
120
|
-
resumeOnFocus(): Promise<
|
|
120
|
+
resumeOnFocus(): Promise<boolean>;
|
|
121
121
|
/**
|
|
122
122
|
* Returns information if audio context is ready to play sounds.
|
|
123
123
|
* @public
|
|
@@ -186,10 +186,7 @@ export class SoundManagerInstance {
|
|
|
186
186
|
if (!ambientMusic || ambientMusic.isPlaying) {
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
|
-
|
|
190
|
-
ambientMusic.resume();
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
189
|
+
ambientMusic.stop();
|
|
193
190
|
this.play(ambientTrack);
|
|
194
191
|
}
|
|
195
192
|
/**
|
|
@@ -260,10 +257,15 @@ export class SoundManagerInstance {
|
|
|
260
257
|
await sound.context.audioContext.resume();
|
|
261
258
|
}
|
|
262
259
|
catch (error) {
|
|
263
|
-
console.error("Could not resume audio");
|
|
260
|
+
console.error("Could not resume audio", error);
|
|
264
261
|
}
|
|
265
262
|
}
|
|
263
|
+
if (!this.isAudioContextRunning()) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
sound.resumeAll();
|
|
266
267
|
this.restoreAmbientPlayback();
|
|
268
|
+
return true;
|
|
267
269
|
}
|
|
268
270
|
/**
|
|
269
271
|
* Returns information if audio context is ready to play sounds.
|
|
@@ -893,9 +893,6 @@ export class AbstractMainContainer extends Container {
|
|
|
893
893
|
this.mysteryBonusContainer.resize();
|
|
894
894
|
this.addChild(this.mysteryBonusContainer);
|
|
895
895
|
}
|
|
896
|
-
if (this.gambleGame) {
|
|
897
|
-
this.gambleGame.resize();
|
|
898
|
-
}
|
|
899
896
|
if (this.bottomPanel) {
|
|
900
897
|
this.bottomPanel.scale.set(resizingHelper);
|
|
901
898
|
this.bottomPanel.width = RainMan.app.screen.width;
|
|
@@ -915,6 +912,10 @@ export class AbstractMainContainer extends Container {
|
|
|
915
912
|
this.addChild(this._buyFreeSpinsPlate);
|
|
916
913
|
this._buyFreeSpinsPlate.resize();
|
|
917
914
|
}
|
|
915
|
+
if (this.gambleGame) {
|
|
916
|
+
this.gambleGame.resize();
|
|
917
|
+
this.addChild(this.gambleGame);
|
|
918
|
+
}
|
|
918
919
|
RainMan.settingsStore.popupPaytableRepositionCallback?.();
|
|
919
920
|
}
|
|
920
921
|
/**
|
|
@@ -26,6 +26,11 @@ export declare class GambleGame extends Container {
|
|
|
26
26
|
private readonly previousGamblesContainer;
|
|
27
27
|
private previousGambles;
|
|
28
28
|
constructor(cardSpineName: string, resolver: (newBalance: number) => void, lastWinAmount: number, balanceValue: number);
|
|
29
|
+
private configureButtons;
|
|
30
|
+
private addChildrenOnce;
|
|
31
|
+
private bindButtonsOnce;
|
|
32
|
+
private bringButtonsToFront;
|
|
33
|
+
private restoreButtonEventModes;
|
|
29
34
|
/**
|
|
30
35
|
* Function for showing previous gamble
|
|
31
36
|
* @private
|
|
@@ -72,4 +77,7 @@ export declare class GambleGame extends Container {
|
|
|
72
77
|
* @returns {void}
|
|
73
78
|
*/
|
|
74
79
|
private initChildPositions;
|
|
80
|
+
private layoutPc;
|
|
81
|
+
private layoutMobilePortrait;
|
|
82
|
+
private layoutMobileLandscape;
|
|
75
83
|
}
|
|
@@ -3,7 +3,7 @@ import { Container, Sprite, Text, Texture } from "pixi.js";
|
|
|
3
3
|
import { Spine } from "pixi-spine";
|
|
4
4
|
import { COLOR_BUTTONS_CENTER_OFFSET, COLOR_BUTTONS_SCALE_X, gamblesTextStyle } from "../../constants";
|
|
5
5
|
import { RainMan } from "../../Rainman";
|
|
6
|
-
import { getSpineData, globalMinRatio } from "../../utils";
|
|
6
|
+
import { getDeviceOrientation, getSpineData, globalMinRatio } from "../../utils";
|
|
7
7
|
import { BlackButton, BUTTONS, CollectButton, RedButton } from "../buttons";
|
|
8
8
|
import { GambleUpdatableText } from "../updatable";
|
|
9
9
|
/**
|
|
@@ -37,7 +37,10 @@ export class GambleGame extends Container {
|
|
|
37
37
|
this.resolver = resolver;
|
|
38
38
|
this.lastWinAmount = lastWinAmount;
|
|
39
39
|
this.balanceValue = balanceValue;
|
|
40
|
+
this.x = 0;
|
|
41
|
+
this.y = 0;
|
|
40
42
|
this.eventMode = "static";
|
|
43
|
+
this.interactiveChildren = true;
|
|
41
44
|
this.background = new Sprite(Texture.from("black-bg.png"));
|
|
42
45
|
this.frame = new Sprite(Texture.from("frame-v2.png"));
|
|
43
46
|
this.previousGamblesText = new Text(i18next.t("previousCards"), gamblesTextStyle());
|
|
@@ -53,6 +56,33 @@ export class GambleGame extends Container {
|
|
|
53
56
|
this.card.state.addAnimation(0, "wait2", true, 0);
|
|
54
57
|
this.currentWin = new GambleUpdatableText(GambleGame.gambleCurrentWinRegistryName, i18next.t("currentWinGamble"), this.lastWinAmount, 1);
|
|
55
58
|
this.gambleWin = new GambleUpdatableText(GambleGame.gambleWinRegistryName, i18next.t("gambleToWin"), this.lastWinAmount * 2, 2);
|
|
59
|
+
this.configureButtons();
|
|
60
|
+
this.addChildrenOnce();
|
|
61
|
+
this.bindButtonsOnce();
|
|
62
|
+
this.resize();
|
|
63
|
+
}
|
|
64
|
+
configureButtons() {
|
|
65
|
+
this.collectButton.eventMode = "static";
|
|
66
|
+
this.redButton.eventMode = "static";
|
|
67
|
+
this.blackButton.eventMode = "static";
|
|
68
|
+
this.collectButton.cursor = "pointer";
|
|
69
|
+
this.redButton.cursor = "pointer";
|
|
70
|
+
this.blackButton.cursor = "pointer";
|
|
71
|
+
}
|
|
72
|
+
addChildrenOnce() {
|
|
73
|
+
this.addChild(this.background);
|
|
74
|
+
this.addChild(this.frame);
|
|
75
|
+
this.addChild(this.card);
|
|
76
|
+
this.addChild(this.previousGamblesText);
|
|
77
|
+
this.addChild(this.previousGamblesContainer);
|
|
78
|
+
this.addChild(this.currentWin);
|
|
79
|
+
this.addChild(this.gambleWin);
|
|
80
|
+
this.addChild(this.collectText);
|
|
81
|
+
this.addChild(this.collectButton);
|
|
82
|
+
this.addChild(this.redButton);
|
|
83
|
+
this.addChild(this.blackButton);
|
|
84
|
+
}
|
|
85
|
+
bindButtonsOnce() {
|
|
56
86
|
this.redButton.setOnClick(() => this.handleGamblePlay("red"));
|
|
57
87
|
this.blackButton.setOnClick(() => this.handleGamblePlay("black"));
|
|
58
88
|
this.collectButton.setOnClick(() => {
|
|
@@ -60,7 +90,22 @@ export class GambleGame extends Container {
|
|
|
60
90
|
RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(true);
|
|
61
91
|
this.resolver(this.balanceValue);
|
|
62
92
|
});
|
|
63
|
-
|
|
93
|
+
}
|
|
94
|
+
bringButtonsToFront() {
|
|
95
|
+
this.addChild(this.collectButton);
|
|
96
|
+
this.addChild(this.redButton);
|
|
97
|
+
this.addChild(this.blackButton);
|
|
98
|
+
}
|
|
99
|
+
restoreButtonEventModes() {
|
|
100
|
+
if (!this.collectButton.disabled) {
|
|
101
|
+
this.collectButton.eventMode = "static";
|
|
102
|
+
}
|
|
103
|
+
if (!this.redButton.disabled) {
|
|
104
|
+
this.redButton.eventMode = "static";
|
|
105
|
+
}
|
|
106
|
+
if (!this.blackButton.disabled) {
|
|
107
|
+
this.blackButton.eventMode = "static";
|
|
108
|
+
}
|
|
64
109
|
}
|
|
65
110
|
/**
|
|
66
111
|
* Function for showing previous gamble
|
|
@@ -70,11 +115,15 @@ export class GambleGame extends Container {
|
|
|
70
115
|
*/
|
|
71
116
|
showPreviousGambles(previousGambles) {
|
|
72
117
|
const { width } = RainMan.app.screen;
|
|
73
|
-
this.previousGambles.forEach((gambleCard) =>
|
|
118
|
+
this.previousGambles.forEach((gambleCard) => {
|
|
119
|
+
this.previousGamblesContainer.removeChild(gambleCard);
|
|
120
|
+
gambleCard.destroy();
|
|
121
|
+
});
|
|
74
122
|
this.previousGambles = previousGambles.map((gambleCard, index) => {
|
|
75
123
|
const card = new Sprite(Texture.from(`${gambleCard}-small.png`));
|
|
76
|
-
card.scale.set(0.45);
|
|
124
|
+
getDeviceOrientation() === "mobile-landscape" ? card.scale.set(0.3) : card.scale.set(0.45);
|
|
77
125
|
card.x = index * (card.width + 10);
|
|
126
|
+
card.y = 0;
|
|
78
127
|
this.previousGamblesContainer.addChild(card);
|
|
79
128
|
return card;
|
|
80
129
|
});
|
|
@@ -125,7 +174,6 @@ export class GambleGame extends Container {
|
|
|
125
174
|
this.blackButton.flipDisabledFlag(true);
|
|
126
175
|
this.card.state.addAnimation(0, "wait", true, 0);
|
|
127
176
|
const gambleData = await window.connectionWrapper.fetchGambleData(RainMan.settingsStore.roundNumber, this.lastWinAmount, choice);
|
|
128
|
-
this.balanceValue = gambleData.balance + gambleData.win_amount;
|
|
129
177
|
this.balanceValue = gambleData.balanceAfterSpin;
|
|
130
178
|
await new Promise((resolve) => {
|
|
131
179
|
this.card.state.clearTracks();
|
|
@@ -137,20 +185,21 @@ export class GambleGame extends Container {
|
|
|
137
185
|
await this.updateDoubleAndWinFields(Math.max(gambleData.win_amount, 0));
|
|
138
186
|
this.redButton.flipDisabledFlag(false);
|
|
139
187
|
this.blackButton.flipDisabledFlag(false);
|
|
188
|
+
this.redButton.eventMode = "static";
|
|
189
|
+
this.blackButton.eventMode = "static";
|
|
140
190
|
}
|
|
141
191
|
this.card.state.addAnimation(0, "wait2", true, 0);
|
|
142
192
|
this.lastWinAmount = gambleData.win_amount;
|
|
143
193
|
this.showPreviousGambles(gambleData.previous_gambles);
|
|
194
|
+
this.bringButtonsToFront();
|
|
144
195
|
if (gambleData.win_amount === 0) {
|
|
145
196
|
this.redButton.flipDisabledFlag(true);
|
|
146
197
|
this.blackButton.flipDisabledFlag(true);
|
|
147
198
|
this.card.state.addAnimation(0, "idle", true, 0);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}, 2000)
|
|
153
|
-
]);
|
|
199
|
+
await this.loseDoubleAndWinFields();
|
|
200
|
+
window.setTimeout(() => {
|
|
201
|
+
this.closeGame();
|
|
202
|
+
}, 2000);
|
|
154
203
|
}
|
|
155
204
|
}
|
|
156
205
|
/**
|
|
@@ -162,68 +211,121 @@ export class GambleGame extends Container {
|
|
|
162
211
|
const { width, height } = RainMan.app.screen;
|
|
163
212
|
this.x = 0;
|
|
164
213
|
this.y = 0;
|
|
165
|
-
this.
|
|
166
|
-
this.
|
|
167
|
-
this.
|
|
214
|
+
this.scale.set(1);
|
|
215
|
+
this.initChildPositions(width, height);
|
|
216
|
+
this.restoreButtonEventModes();
|
|
217
|
+
this.bringButtonsToFront();
|
|
168
218
|
}
|
|
169
219
|
/**
|
|
170
220
|
* Function for initializing child positions
|
|
171
221
|
* @private
|
|
172
222
|
* @returns {void}
|
|
173
223
|
*/
|
|
174
|
-
initChildPositions() {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
this.
|
|
179
|
-
this.
|
|
180
|
-
this.removeChild(this.redButton);
|
|
181
|
-
this.removeChild(this.blackButton);
|
|
182
|
-
this.removeChild(this.card);
|
|
183
|
-
this.removeChild(this.currentWin);
|
|
184
|
-
this.removeChild(this.gambleWin);
|
|
185
|
-
this.removeChild(this.previousGamblesContainer);
|
|
186
|
-
const { width, height } = RainMan.app.screen;
|
|
224
|
+
initChildPositions(width, height) {
|
|
225
|
+
const ratio = globalMinRatio();
|
|
226
|
+
const deviceOrientation = getDeviceOrientation();
|
|
227
|
+
const centerX = width / 2;
|
|
228
|
+
this.background.x = 0;
|
|
229
|
+
this.background.y = 0;
|
|
187
230
|
this.background.width = width;
|
|
188
231
|
this.background.height = height;
|
|
232
|
+
this.frame.x = 0;
|
|
233
|
+
this.frame.y = 0;
|
|
189
234
|
this.frame.width = width;
|
|
190
235
|
this.frame.height = height;
|
|
191
|
-
const CENTER = RainMan.app.screen.width / 2;
|
|
192
236
|
const previousGambles = window.connectionWrapper.getLastGambleResponse()?.previous_gambles || [];
|
|
193
|
-
this.previousGamblesText.x =
|
|
237
|
+
this.previousGamblesText.x = centerX - this.previousGamblesText.width / 2;
|
|
194
238
|
this.previousGamblesText.y = 20;
|
|
239
|
+
if (deviceOrientation === "mobile-landscape") {
|
|
240
|
+
this.previousGamblesText.scale.set(0.38);
|
|
241
|
+
this.previousGamblesText.y = 6;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
this.previousGamblesText.scale.set(1);
|
|
245
|
+
this.previousGamblesText.y = 20;
|
|
246
|
+
}
|
|
247
|
+
this.previousGamblesText.x = centerX - this.previousGamblesText.width / 2;
|
|
195
248
|
this.showPreviousGambles(previousGambles);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
249
|
+
if (deviceOrientation === "pc") {
|
|
250
|
+
this.layoutPc(width, height, ratio);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (deviceOrientation === "mobile-portrait") {
|
|
254
|
+
this.layoutMobilePortrait(width, height, ratio);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this.layoutMobileLandscape(width, height, ratio);
|
|
258
|
+
}
|
|
259
|
+
layoutPc(width, height, ratio) {
|
|
260
|
+
const centerX = width / 2;
|
|
261
|
+
const centerY = height / 2;
|
|
262
|
+
this.card.scale.set(ratio * 0.8);
|
|
263
|
+
this.card.x = centerX;
|
|
264
|
+
this.card.y = centerY;
|
|
265
|
+
this.collectText.x = centerX;
|
|
200
266
|
this.collectText.y = height - this.collectText.height;
|
|
201
|
-
this.collectButton.scale.set(
|
|
202
|
-
this.collectButton.x =
|
|
267
|
+
this.collectButton.scale.set(ratio * 0.6);
|
|
268
|
+
this.collectButton.x = centerX;
|
|
203
269
|
this.collectButton.y = this.collectText.y - this.collectButton.height - 30;
|
|
204
|
-
this.redButton.scale.set(
|
|
205
|
-
|
|
206
|
-
this.redButton.x =
|
|
207
|
-
this.redButton.y =
|
|
208
|
-
this.blackButton.
|
|
209
|
-
this.blackButton.
|
|
210
|
-
this.
|
|
211
|
-
this.
|
|
212
|
-
this.currentWin.y = height - this.currentWin.height;
|
|
270
|
+
this.redButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X);
|
|
271
|
+
this.blackButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X);
|
|
272
|
+
this.redButton.x = centerX - COLOR_BUTTONS_CENTER_OFFSET - this.redButton.width;
|
|
273
|
+
this.redButton.y = this.card.y - this.redButton.height / 2;
|
|
274
|
+
this.blackButton.x = centerX + COLOR_BUTTONS_CENTER_OFFSET;
|
|
275
|
+
this.blackButton.y = this.card.y - this.redButton.height / 2;
|
|
276
|
+
this.currentWin.scale.set(ratio);
|
|
277
|
+
this.gambleWin.scale.set(ratio);
|
|
213
278
|
this.currentWin.x = width / 4;
|
|
214
|
-
this.
|
|
215
|
-
this.gambleWin.y = height - this.gambleWin.height;
|
|
279
|
+
this.currentWin.y = height - this.currentWin.height;
|
|
216
280
|
this.gambleWin.x = (width * 3) / 4;
|
|
217
|
-
this.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
this.
|
|
222
|
-
this.
|
|
223
|
-
this.
|
|
224
|
-
this.
|
|
225
|
-
this.
|
|
226
|
-
this.
|
|
227
|
-
this.
|
|
281
|
+
this.gambleWin.y = height - this.gambleWin.height;
|
|
282
|
+
}
|
|
283
|
+
layoutMobilePortrait(width, height, ratio) {
|
|
284
|
+
const centerX = width / 2;
|
|
285
|
+
this.card.scale.set(ratio * 0.65);
|
|
286
|
+
this.card.x = centerX;
|
|
287
|
+
this.card.y = height * 0.4;
|
|
288
|
+
this.collectText.x = centerX;
|
|
289
|
+
this.collectText.y = height - this.collectText.height;
|
|
290
|
+
this.collectButton.scale.set(ratio * 0.6);
|
|
291
|
+
this.collectButton.x = centerX;
|
|
292
|
+
this.collectButton.y = this.collectText.y - this.collectButton.height - 30;
|
|
293
|
+
this.redButton.scale.set(ratio * 0.7);
|
|
294
|
+
this.blackButton.scale.set(ratio * 0.7);
|
|
295
|
+
this.redButton.x = centerX - this.redButton.width - 20;
|
|
296
|
+
this.redButton.y = this.card.y + this.card.height / 2 + 30;
|
|
297
|
+
this.blackButton.x = centerX + 20;
|
|
298
|
+
this.blackButton.y = this.card.y + this.card.height / 2 + 30;
|
|
299
|
+
this.currentWin.scale.set(ratio);
|
|
300
|
+
this.gambleWin.scale.set(ratio);
|
|
301
|
+
this.currentWin.x = width * 0.25;
|
|
302
|
+
this.currentWin.y = this.collectButton.y - this.currentWin.height - 20;
|
|
303
|
+
this.gambleWin.x = width * 0.75;
|
|
304
|
+
this.gambleWin.y = this.collectButton.y - this.currentWin.height - 20;
|
|
305
|
+
}
|
|
306
|
+
layoutMobileLandscape(width, height, ratio) {
|
|
307
|
+
const centerX = width / 2;
|
|
308
|
+
const centerY = height / 2;
|
|
309
|
+
this.card.scale.set(ratio * 0.72);
|
|
310
|
+
this.card.x = centerX;
|
|
311
|
+
this.card.y = centerY - 18;
|
|
312
|
+
this.collectText.scale.set(0.55);
|
|
313
|
+
this.collectText.x = centerX;
|
|
314
|
+
this.collectText.y = height - 28;
|
|
315
|
+
this.collectButton.scale.set(ratio * 0.65);
|
|
316
|
+
this.collectButton.x = centerX;
|
|
317
|
+
this.collectButton.y = this.collectText.y - this.collectButton.height - 16;
|
|
318
|
+
this.redButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X * 1.18);
|
|
319
|
+
this.blackButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X * 1.18);
|
|
320
|
+
this.redButton.x = centerX - COLOR_BUTTONS_CENTER_OFFSET * 0.68 - this.redButton.width;
|
|
321
|
+
this.redButton.y = this.card.y - this.redButton.height / 2;
|
|
322
|
+
this.blackButton.x = centerX + COLOR_BUTTONS_CENTER_OFFSET * 0.68;
|
|
323
|
+
this.blackButton.y = this.card.y - this.redButton.height / 2;
|
|
324
|
+
this.currentWin.scale.set(ratio * 1.45);
|
|
325
|
+
this.gambleWin.scale.set(ratio * 1.45);
|
|
326
|
+
this.currentWin.x = width * 0.24;
|
|
327
|
+
this.currentWin.y = height - this.currentWin.height / 2 - 8;
|
|
328
|
+
this.gambleWin.x = width * 0.8;
|
|
329
|
+
this.gambleWin.y = height - this.gambleWin.height / 2 - 8;
|
|
228
330
|
}
|
|
229
331
|
}
|
|
@@ -98,6 +98,7 @@ export declare abstract class AbstractSymbolBase extends Container implements Sp
|
|
|
98
98
|
* @returns {Promise<void>} - A promise that resolves when the animation is complete
|
|
99
99
|
*/
|
|
100
100
|
play(suffix?: string): Promise<void>;
|
|
101
|
+
isCurrentAnimationPastHalf(): boolean;
|
|
101
102
|
/**
|
|
102
103
|
* Function for stopping the symbol animation.
|
|
103
104
|
* @public
|
|
@@ -214,6 +214,18 @@ export class AbstractSymbolBase extends Container {
|
|
|
214
214
|
});
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
|
+
isCurrentAnimationPastHalf() {
|
|
218
|
+
const entry = this.spine.state.tracks[0];
|
|
219
|
+
if (!entry) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
const trackTime = entry.trackTime ?? 0;
|
|
223
|
+
const animationEnd = entry.animationEnd ?? 0;
|
|
224
|
+
if (animationEnd <= 0) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return trackTime >= animationEnd / 3;
|
|
228
|
+
}
|
|
217
229
|
/**
|
|
218
230
|
* Function for stopping the symbol animation.
|
|
219
231
|
* @public
|
|
@@ -22,6 +22,7 @@ export declare abstract class UpdatableValueComponent extends Container implemen
|
|
|
22
22
|
protected tween: TWEEN.Tween<{
|
|
23
23
|
value: number;
|
|
24
24
|
}> | null;
|
|
25
|
+
private readonly animateTick;
|
|
25
26
|
limitValue: number | null;
|
|
26
27
|
protected countingDivider: number;
|
|
27
28
|
readonly speedLevelMapper: SpeedLevelDirectory<number>;
|
|
@@ -23,6 +23,7 @@ export class UpdatableValueComponent extends Container {
|
|
|
23
23
|
valueTextComponent;
|
|
24
24
|
shouldBeUpdated = false;
|
|
25
25
|
tween = null;
|
|
26
|
+
animateTick = () => this.animate();
|
|
26
27
|
limitValue = null;
|
|
27
28
|
countingDivider;
|
|
28
29
|
speedLevelMapper = {
|
|
@@ -68,7 +69,8 @@ export class UpdatableValueComponent extends Container {
|
|
|
68
69
|
}
|
|
69
70
|
async update(newValue, time = RainMan.config.durationOfActions.updatableTextCountingDuration) {
|
|
70
71
|
this.finalValue = newValue;
|
|
71
|
-
Ticker.shared.
|
|
72
|
+
Ticker.shared.remove(this.animateTick);
|
|
73
|
+
Ticker.shared.add(this.animateTick);
|
|
72
74
|
await this.initAnimation(newValue, time / this.countingDivider);
|
|
73
75
|
}
|
|
74
76
|
/**
|
|
@@ -78,7 +80,8 @@ export class UpdatableValueComponent extends Container {
|
|
|
78
80
|
* @returns {Promise<void>} A promise that resolves when the update is complete.
|
|
79
81
|
*/
|
|
80
82
|
async loseUpdate(time = RainMan.config.durationOfActions.updatableTextCountingDuration) {
|
|
81
|
-
Ticker.shared.
|
|
83
|
+
Ticker.shared.remove(this.animateTick);
|
|
84
|
+
Ticker.shared.add(this.animateTick);
|
|
82
85
|
await this.initAnimation(0, time / this.countingDivider, true);
|
|
83
86
|
}
|
|
84
87
|
/**
|
|
@@ -162,7 +165,7 @@ export class UpdatableValueComponent extends Container {
|
|
|
162
165
|
if (!this.shouldBeUpdated) {
|
|
163
166
|
this.tween?.stop();
|
|
164
167
|
this.tween = null;
|
|
165
|
-
Ticker.shared.remove(
|
|
168
|
+
Ticker.shared.remove(this.animateTick);
|
|
166
169
|
return;
|
|
167
170
|
}
|
|
168
171
|
this.changeCurrentWin(value);
|
|
@@ -188,11 +191,10 @@ export class UpdatableValueComponent extends Container {
|
|
|
188
191
|
* @returns {void}
|
|
189
192
|
*/
|
|
190
193
|
setResultAndClearTween(finalValue) {
|
|
191
|
-
|
|
192
|
-
return;
|
|
194
|
+
this.shouldBeUpdated = false;
|
|
193
195
|
this.tween?.stop();
|
|
194
196
|
this.tween = null;
|
|
195
|
-
Ticker.shared.remove(
|
|
197
|
+
Ticker.shared.remove(this.animateTick);
|
|
196
198
|
this.changeCurrentWin(finalValue);
|
|
197
199
|
}
|
|
198
200
|
/**
|
|
@@ -33,6 +33,9 @@ export type EggWin = BaseWin & {
|
|
|
33
33
|
export type GoldWin = BaseWin & {
|
|
34
34
|
type: typeof PossibleWins.gold;
|
|
35
35
|
};
|
|
36
|
+
export type PearlWin = BaseWin & {
|
|
37
|
+
type: typeof PossibleWins.pearl;
|
|
38
|
+
};
|
|
36
39
|
export type BigWin = BaseWin & {
|
|
37
40
|
type: typeof PossibleWins.bigWin;
|
|
38
41
|
};
|
|
@@ -60,7 +63,7 @@ export type JackpotWin = BaseWin & {
|
|
|
60
63
|
export type CoinWin = BaseWin & {
|
|
61
64
|
type: typeof PossibleWins.coin;
|
|
62
65
|
};
|
|
63
|
-
export type Win = StreakWin | FreeSpinWin | GambleWin | MysteryWin | EggWin | GoldWin | BigWin | BonusWin | SuperBonusWin | ScatterWin | RouletteWin | JackpotWin | CoinWin | MultiWin | JokerWin;
|
|
66
|
+
export type Win = StreakWin | FreeSpinWin | GambleWin | MysteryWin | EggWin | GoldWin | BigWin | PearlWin | BonusWin | SuperBonusWin | ScatterWin | RouletteWin | JackpotWin | CoinWin | MultiWin | JokerWin;
|
|
64
67
|
/**
|
|
65
68
|
* Type represents data that come from backend
|
|
66
69
|
* @typedef {WinDetails}
|
package/dist/constants/wins.d.ts
CHANGED
package/dist/constants/wins.js
CHANGED
|
@@ -59,6 +59,9 @@ export declare abstract class AbstractController<T> {
|
|
|
59
59
|
shouldStopMobileSpin: boolean;
|
|
60
60
|
disableMessageBoxChange: boolean;
|
|
61
61
|
shouldClearQuickReelsStopAfterSpin: boolean;
|
|
62
|
+
protected firstAnimationTarget: {
|
|
63
|
+
isCurrentAnimationPastHalf?: () => boolean;
|
|
64
|
+
} | null;
|
|
62
65
|
protected resolveBigWin?: () => void;
|
|
63
66
|
protected resolveMysteryWin?: () => void;
|
|
64
67
|
protected resolveBonusWin?: () => void;
|
|
@@ -59,6 +59,7 @@ export class AbstractController {
|
|
|
59
59
|
shouldStopMobileSpin = false;
|
|
60
60
|
disableMessageBoxChange = false;
|
|
61
61
|
shouldClearQuickReelsStopAfterSpin = false;
|
|
62
|
+
firstAnimationTarget = null;
|
|
62
63
|
resolveBigWin;
|
|
63
64
|
resolveMysteryWin;
|
|
64
65
|
resolveBonusWin;
|
|
@@ -387,6 +388,7 @@ export class AbstractController {
|
|
|
387
388
|
const availableFreeSpins = spinLogic.availableFreeSpins;
|
|
388
389
|
if (availableFreeSpins > 0) {
|
|
389
390
|
this._lastWinAmount = this.initData.round_win_amount;
|
|
391
|
+
this.uiController.totalFreeSpinWinAmount = ceilToDecimal(this.initData.round_win_amount);
|
|
390
392
|
}
|
|
391
393
|
if (spinLogic.winTotalAmount !== 0 && spinLogic.winTotalAmount !== undefined) {
|
|
392
394
|
this.uiController.recentWin = ceilToDecimal(spinLogic.winTotalAmount);
|
|
@@ -836,6 +838,11 @@ export class AbstractController {
|
|
|
836
838
|
if (!RainMan.settingsStore.isFreeSpinsBought) {
|
|
837
839
|
return;
|
|
838
840
|
}
|
|
841
|
+
const boughtRoundNumber = RainMan.settingsStore.buyFreeSpinsData?.getRawData().round_number;
|
|
842
|
+
if (boughtRoundNumber !== undefined) {
|
|
843
|
+
this.roundNumber = boughtRoundNumber;
|
|
844
|
+
RainMan.settingsStore.setRoundNumber(boughtRoundNumber);
|
|
845
|
+
}
|
|
839
846
|
this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
|
|
840
847
|
RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
|
|
841
848
|
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
@@ -846,7 +853,8 @@ export class AbstractController {
|
|
|
846
853
|
* @returns {number} - number of free spins bought
|
|
847
854
|
*/
|
|
848
855
|
getBoughtNumberOfFreeSpins() {
|
|
849
|
-
return RainMan.settingsStore.buyFreeSpinsData?.getRawData()
|
|
856
|
+
return (RainMan.settingsStore.buyFreeSpinsData?.getRawData()?.extra_data?.available_free_spins ??
|
|
857
|
+
RainMan.settingsStore.freeSpinNumberBought);
|
|
850
858
|
}
|
|
851
859
|
/**
|
|
852
860
|
* Function for autoplay spin
|
|
@@ -1021,10 +1029,14 @@ export class AbstractController {
|
|
|
1021
1029
|
*/
|
|
1022
1030
|
gambleGameEnabler(winAmount) {
|
|
1023
1031
|
if (RainMan.componentRegistry.has(BUTTONS.gamble) && RainMan.settingsStore.isGambleGameAvailable) {
|
|
1024
|
-
RainMan.componentRegistry
|
|
1032
|
+
RainMan.componentRegistry
|
|
1033
|
+
.get(BUTTONS.gamble)
|
|
1034
|
+
.flipDisabledFlag(winAmount === 0 || RainMan.settingsStore.isAutoplayEnabled);
|
|
1025
1035
|
}
|
|
1026
1036
|
if (RainMan.componentRegistry.has(BUTTONS.take) && RainMan.settingsStore.isTakeActionAvailable) {
|
|
1027
|
-
RainMan.componentRegistry
|
|
1037
|
+
RainMan.componentRegistry
|
|
1038
|
+
.get(BUTTONS.take)
|
|
1039
|
+
.flipDisabledFlag(winAmount === 0 || RainMan.settingsStore.isAutoplayEnabled);
|
|
1028
1040
|
}
|
|
1029
1041
|
}
|
|
1030
1042
|
/**
|
|
@@ -1144,6 +1156,8 @@ export class AbstractController {
|
|
|
1144
1156
|
this.uiController.limitWinAmount(spinLogic.winTotalAmount);
|
|
1145
1157
|
}
|
|
1146
1158
|
this.composeWinActionsQueue(spinLogic);
|
|
1159
|
+
this.firstAnimationTarget =
|
|
1160
|
+
this.winActionsQueue.find((action) => action.animationTarget)?.animationTarget ?? null;
|
|
1147
1161
|
if (spinLogic.winTotalAmount === 0 && this.invokeFreeSpinPlateAfterWin) {
|
|
1148
1162
|
this.uiController.messageBox.hideCurrentWinText();
|
|
1149
1163
|
}
|
|
@@ -1194,7 +1208,9 @@ export class AbstractController {
|
|
|
1194
1208
|
this.uiController.messageBox.hideCurrentWinText();
|
|
1195
1209
|
this.uiController.messageBox.hideAutoSpinText();
|
|
1196
1210
|
await this.handleFreeSpinPlateInvocation(freeSpinAward, isAdditionalFreeSpins || additionalFreeSpinsOnLastSpin);
|
|
1197
|
-
|
|
1211
|
+
if (!isAdditionalFreeSpins && !additionalFreeSpinsOnLastSpin) {
|
|
1212
|
+
this.uiController.currentBalance = RainMan.settingsStore.balanceAfterSpin;
|
|
1213
|
+
}
|
|
1198
1214
|
this.uiController.triggerUiElementsUpdate();
|
|
1199
1215
|
this.uiController.messageBox.showFreeSpinText();
|
|
1200
1216
|
}
|
|
@@ -136,7 +136,6 @@ export declare class SettingsStore {
|
|
|
136
136
|
/**
|
|
137
137
|
* Sets the free spins price table.
|
|
138
138
|
* @public
|
|
139
|
-
* @param freeSpinsBuyOptions
|
|
140
139
|
* @param {Record<number, number>} freeSpinsPriceTable table with free spins prices
|
|
141
140
|
* @returns {void}
|
|
142
141
|
*/
|
|
@@ -151,7 +150,6 @@ export declare class SettingsStore {
|
|
|
151
150
|
/**
|
|
152
151
|
* Sets the free spins price table.
|
|
153
152
|
* @public
|
|
154
|
-
* @param buyTypes
|
|
155
153
|
* @param {Record<number, number>} jokerBuyOption table with free spins prices
|
|
156
154
|
* @returns {void}
|
|
157
155
|
*/
|
|
@@ -218,7 +218,6 @@ export class SettingsStore {
|
|
|
218
218
|
/**
|
|
219
219
|
* Sets the free spins price table.
|
|
220
220
|
* @public
|
|
221
|
-
* @param freeSpinsBuyOptions
|
|
222
221
|
* @param {Record<number, number>} freeSpinsPriceTable table with free spins prices
|
|
223
222
|
* @returns {void}
|
|
224
223
|
*/
|
|
@@ -237,7 +236,6 @@ export class SettingsStore {
|
|
|
237
236
|
/**
|
|
238
237
|
* Sets the free spins price table.
|
|
239
238
|
* @public
|
|
240
|
-
* @param buyTypes
|
|
241
239
|
* @param {Record<number, number>} jokerBuyOption table with free spins prices
|
|
242
240
|
* @returns {void}
|
|
243
241
|
*/
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { sound } from "@pixi/sound";
|
|
1
2
|
import { SoundManager } from "../../application";
|
|
2
3
|
import { RainMan } from "../../Rainman";
|
|
3
4
|
let shouldResumeAudioOnInterruption = false;
|
|
5
|
+
let isResumingAudio = false;
|
|
4
6
|
const removeInterruptedAudioResumeListeners = () => {
|
|
5
7
|
window.removeEventListener("pointerdown", resumeAudioOnInterruption);
|
|
6
8
|
window.removeEventListener("touchend", resumeAudioOnInterruption);
|
|
@@ -18,6 +20,7 @@ const interruptedAudioResume = () => {
|
|
|
18
20
|
* @returns {void}
|
|
19
21
|
*/
|
|
20
22
|
const pauseAudio = () => {
|
|
23
|
+
isResumingAudio = false;
|
|
21
24
|
shouldResumeAudioOnInterruption = false;
|
|
22
25
|
removeInterruptedAudioResumeListeners();
|
|
23
26
|
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
@@ -32,16 +35,29 @@ const resumeAudio = async () => {
|
|
|
32
35
|
if (document.hidden || !RainMan.settingsStore.isSoundEnabled()) {
|
|
33
36
|
return;
|
|
34
37
|
}
|
|
35
|
-
if (
|
|
36
|
-
await SoundManager.resumeOnFocus();
|
|
37
|
-
SoundManager.resumeAll();
|
|
38
|
-
}
|
|
39
|
-
if (SoundManager.isAudioContextRunning()) {
|
|
40
|
-
shouldResumeAudioOnInterruption = false;
|
|
41
|
-
removeInterruptedAudioResumeListeners();
|
|
38
|
+
if (isResumingAudio) {
|
|
42
39
|
return;
|
|
43
40
|
}
|
|
44
|
-
|
|
41
|
+
isResumingAudio = true;
|
|
42
|
+
try {
|
|
43
|
+
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
44
|
+
const hasResumedAudioContext = await SoundManager.resumeOnFocus();
|
|
45
|
+
if (!hasResumedAudioContext) {
|
|
46
|
+
interruptedAudioResume();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
SoundManager.resumeAll();
|
|
50
|
+
}
|
|
51
|
+
if (SoundManager.isAudioContextRunning()) {
|
|
52
|
+
shouldResumeAudioOnInterruption = false;
|
|
53
|
+
removeInterruptedAudioResumeListeners();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
interruptedAudioResume();
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
isResumingAudio = false;
|
|
60
|
+
}
|
|
45
61
|
};
|
|
46
62
|
/**
|
|
47
63
|
* Restore audio on the next user action if browser blocked it earlier.
|
|
@@ -61,16 +77,16 @@ const handleVisibilityChange = () => {
|
|
|
61
77
|
pauseAudio();
|
|
62
78
|
return;
|
|
63
79
|
}
|
|
64
|
-
|
|
80
|
+
interruptedAudioResume();
|
|
65
81
|
};
|
|
66
82
|
/**
|
|
67
83
|
* Sets up audio states for tab switches and iOS app interruptions.
|
|
68
84
|
* @returns {void}
|
|
69
85
|
*/
|
|
70
86
|
export const loadSoundsOnTabChange = () => {
|
|
87
|
+
sound.disableAutoPause = true;
|
|
71
88
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
72
|
-
window.addEventListener("pagehide", pauseAudio);
|
|
73
|
-
window.addEventListener("
|
|
74
|
-
window.addEventListener("
|
|
75
|
-
window.addEventListener("focus", () => resumeAudio());
|
|
89
|
+
window.addEventListener("pagehide", () => pauseAudio());
|
|
90
|
+
window.addEventListener("pageshow", () => interruptedAudioResume());
|
|
91
|
+
window.addEventListener("focus", () => interruptedAudioResume());
|
|
76
92
|
};
|
package/package.json
CHANGED