pixi-rainman-game-engine 0.3.35 → 0.3.36

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.
@@ -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?.();
@@ -186,10 +186,7 @@ export class SoundManagerInstance {
186
186
  if (!ambientMusic || ambientMusic.isPlaying) {
187
187
  return;
188
188
  }
189
- if (ambientMusic.paused) {
190
- ambientMusic.resume();
191
- return;
192
- }
189
+ ambientMusic.stop();
193
190
  this.play(ambientTrack);
194
191
  }
195
192
  /**
@@ -266,6 +263,7 @@ export class SoundManagerInstance {
266
263
  if (!this.isAudioContextRunning()) {
267
264
  return false;
268
265
  }
266
+ sound.resumeAll();
269
267
  this.restoreAmbientPlayback();
270
268
  return true;
271
269
  }
@@ -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
@@ -68,8 +73,13 @@ export declare class GambleGame extends Container {
68
73
  resize(): void;
69
74
  /**
70
75
  * Function for initializing child positions
76
+ * @param width
77
+ * @param height
71
78
  * @private
72
79
  * @returns {void}
73
80
  */
74
81
  private initChildPositions;
82
+ private layoutPc;
83
+ private layoutMobilePortrait;
84
+ private layoutMobileLandscape;
75
85
  }
@@ -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
- this.resize();
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) => this.previousGamblesContainer.removeChild(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
- Promise.all([
149
- this.loseDoubleAndWinFields(),
150
- setTimeout(() => {
151
- this.closeGame();
152
- }, 2000)
153
- ]);
199
+ await this.loseDoubleAndWinFields();
200
+ window.setTimeout(() => {
201
+ this.closeGame();
202
+ }, 2000);
154
203
  }
155
204
  }
156
205
  /**
@@ -162,68 +211,123 @@ 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.width = width;
166
- this.height = height;
167
- this.initChildPositions();
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
221
+ * @param width
222
+ * @param height
171
223
  * @private
172
224
  * @returns {void}
173
225
  */
174
- initChildPositions() {
175
- this.removeChild(this.background);
176
- this.removeChild(this.frame);
177
- this.removeChild(this.previousGamblesText);
178
- this.removeChild(this.collectButton);
179
- this.removeChild(this.collectText);
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;
226
+ initChildPositions(width, height) {
227
+ const ratio = globalMinRatio();
228
+ const deviceOrientation = getDeviceOrientation();
229
+ const centerX = width / 2;
230
+ this.background.x = 0;
231
+ this.background.y = 0;
187
232
  this.background.width = width;
188
233
  this.background.height = height;
234
+ this.frame.x = 0;
235
+ this.frame.y = 0;
189
236
  this.frame.width = width;
190
237
  this.frame.height = height;
191
- const CENTER = RainMan.app.screen.width / 2;
192
238
  const previousGambles = window.connectionWrapper.getLastGambleResponse()?.previous_gambles || [];
193
- this.previousGamblesText.x = CENTER - this.previousGamblesText.width / 2;
239
+ this.previousGamblesText.x = centerX - this.previousGamblesText.width / 2;
194
240
  this.previousGamblesText.y = 20;
241
+ if (deviceOrientation === "mobile-landscape") {
242
+ this.previousGamblesText.scale.set(0.38);
243
+ this.previousGamblesText.y = 6;
244
+ }
245
+ else {
246
+ this.previousGamblesText.scale.set(1);
247
+ this.previousGamblesText.y = 20;
248
+ }
249
+ this.previousGamblesText.x = centerX - this.previousGamblesText.width / 2;
195
250
  this.showPreviousGambles(previousGambles);
196
- this.card.scale.set(globalMinRatio() * 0.8);
197
- this.card.x = CENTER;
198
- this.card.y = height / 2;
199
- this.collectText.x = CENTER;
251
+ if (deviceOrientation === "pc") {
252
+ this.layoutPc(width, height, ratio);
253
+ return;
254
+ }
255
+ if (deviceOrientation === "mobile-portrait") {
256
+ this.layoutMobilePortrait(width, height, ratio);
257
+ return;
258
+ }
259
+ this.layoutMobileLandscape(width, height, ratio);
260
+ }
261
+ layoutPc(width, height, ratio) {
262
+ const centerX = width / 2;
263
+ const centerY = height / 2;
264
+ this.card.scale.set(ratio * 0.8);
265
+ this.card.x = centerX;
266
+ this.card.y = centerY;
267
+ this.collectText.x = centerX;
200
268
  this.collectText.y = height - this.collectText.height;
201
- this.collectButton.scale.set(globalMinRatio() * 0.6);
202
- this.collectButton.x = CENTER;
269
+ this.collectButton.scale.set(ratio * 0.6);
270
+ this.collectButton.x = centerX;
203
271
  this.collectButton.y = this.collectText.y - this.collectButton.height - 30;
204
- this.redButton.scale.set(globalMinRatio() * COLOR_BUTTONS_SCALE_X);
205
- const COLOR_BUTTONS_Y = this.card.y - this.redButton.height / 2;
206
- this.redButton.x = CENTER - COLOR_BUTTONS_CENTER_OFFSET - this.redButton.width;
207
- this.redButton.y = COLOR_BUTTONS_Y;
208
- this.blackButton.scale.set(globalMinRatio() * COLOR_BUTTONS_SCALE_X);
209
- this.blackButton.x = CENTER + COLOR_BUTTONS_CENTER_OFFSET;
210
- this.blackButton.y = COLOR_BUTTONS_Y;
211
- this.currentWin.scale.set(globalMinRatio());
212
- this.currentWin.y = height - this.currentWin.height;
272
+ this.redButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X);
273
+ this.blackButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X);
274
+ this.redButton.x = centerX - COLOR_BUTTONS_CENTER_OFFSET - this.redButton.width;
275
+ this.redButton.y = this.card.y - this.redButton.height / 2;
276
+ this.blackButton.x = centerX + COLOR_BUTTONS_CENTER_OFFSET;
277
+ this.blackButton.y = this.card.y - this.redButton.height / 2;
278
+ this.currentWin.scale.set(ratio);
279
+ this.gambleWin.scale.set(ratio);
213
280
  this.currentWin.x = width / 4;
214
- this.gambleWin.scale.set(globalMinRatio());
215
- this.gambleWin.y = height - this.gambleWin.height;
281
+ this.currentWin.y = height - this.currentWin.height;
216
282
  this.gambleWin.x = (width * 3) / 4;
217
- this.addChild(this.background);
218
- this.addChild(this.frame);
219
- this.addChild(this.previousGamblesText);
220
- this.addChild(this.collectButton);
221
- this.addChild(this.collectText);
222
- this.addChild(this.redButton);
223
- this.addChild(this.blackButton);
224
- this.addChild(this.card);
225
- this.addChild(this.currentWin);
226
- this.addChild(this.gambleWin);
227
- this.addChild(this.previousGamblesContainer);
283
+ this.gambleWin.y = height - this.gambleWin.height;
284
+ }
285
+ layoutMobilePortrait(width, height, ratio) {
286
+ const centerX = width / 2;
287
+ this.card.scale.set(ratio * 0.65);
288
+ this.card.x = centerX;
289
+ this.card.y = height * 0.4;
290
+ this.collectText.x = centerX;
291
+ this.collectText.y = height - this.collectText.height;
292
+ this.collectButton.scale.set(ratio * 0.6);
293
+ this.collectButton.x = centerX;
294
+ this.collectButton.y = this.collectText.y - this.collectButton.height - 30;
295
+ this.redButton.scale.set(ratio * 0.7);
296
+ this.blackButton.scale.set(ratio * 0.7);
297
+ this.redButton.x = centerX - this.redButton.width - 20;
298
+ this.redButton.y = this.card.y + this.card.height / 2 + 30;
299
+ this.blackButton.x = centerX + 20;
300
+ this.blackButton.y = this.card.y + this.card.height / 2 + 30;
301
+ this.currentWin.scale.set(ratio);
302
+ this.gambleWin.scale.set(ratio);
303
+ this.currentWin.x = width * 0.25;
304
+ this.currentWin.y = this.collectButton.y - this.currentWin.height - 20;
305
+ this.gambleWin.x = width * 0.75;
306
+ this.gambleWin.y = this.collectButton.y - this.currentWin.height - 20;
307
+ }
308
+ layoutMobileLandscape(width, height, ratio) {
309
+ const centerX = width / 2;
310
+ const centerY = height / 2;
311
+ this.card.scale.set(ratio * 0.72);
312
+ this.card.x = centerX;
313
+ this.card.y = centerY - 18;
314
+ this.collectText.scale.set(0.55);
315
+ this.collectText.x = centerX;
316
+ this.collectText.y = height - 28;
317
+ this.collectButton.scale.set(ratio * 0.65);
318
+ this.collectButton.x = centerX;
319
+ this.collectButton.y = this.collectText.y - this.collectButton.height - 16;
320
+ this.redButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X * 1.18);
321
+ this.blackButton.scale.set(ratio * COLOR_BUTTONS_SCALE_X * 1.18);
322
+ this.redButton.x = centerX - COLOR_BUTTONS_CENTER_OFFSET * 0.68 - this.redButton.width;
323
+ this.redButton.y = this.card.y - this.redButton.height / 2;
324
+ this.blackButton.x = centerX + COLOR_BUTTONS_CENTER_OFFSET * 0.68;
325
+ this.blackButton.y = this.card.y - this.redButton.height / 2;
326
+ this.currentWin.scale.set(ratio * 1.45);
327
+ this.gambleWin.scale.set(ratio * 1.45);
328
+ this.currentWin.x = width * 0.24;
329
+ this.currentWin.y = height - this.currentWin.height / 2 - 8;
330
+ this.gambleWin.x = width * 0.8;
331
+ this.gambleWin.y = height - this.gambleWin.height / 2 - 8;
228
332
  }
229
333
  }
@@ -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.add(() => this.animate());
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.add(() => this.animate());
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(() => this.animate());
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
- if (this.shouldBeUpdated)
192
- return;
194
+ this.shouldBeUpdated = false;
193
195
  this.tween?.stop();
194
196
  this.tween = null;
195
- Ticker.shared.remove(() => this.animate());
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}
@@ -20,4 +20,5 @@ export declare const PossibleWins: {
20
20
  readonly superBonus: "super-bonus";
21
21
  readonly joker: "joker";
22
22
  readonly multi: "multi";
23
+ readonly pearl: "pearl";
23
24
  };
@@ -19,5 +19,6 @@ export const PossibleWins = {
19
19
  bonus: "bonus",
20
20
  superBonus: "super-bonus",
21
21
  joker: "joker",
22
- multi: "multi"
22
+ multi: "multi",
23
+ pearl: "pearl"
23
24
  };
@@ -387,6 +387,7 @@ export class AbstractController {
387
387
  const availableFreeSpins = spinLogic.availableFreeSpins;
388
388
  if (availableFreeSpins > 0) {
389
389
  this._lastWinAmount = this.initData.round_win_amount;
390
+ this.uiController.totalFreeSpinWinAmount = ceilToDecimal(this.initData.round_win_amount);
390
391
  }
391
392
  if (spinLogic.winTotalAmount !== 0 && spinLogic.winTotalAmount !== undefined) {
392
393
  this.uiController.recentWin = ceilToDecimal(spinLogic.winTotalAmount);
@@ -836,6 +837,11 @@ export class AbstractController {
836
837
  if (!RainMan.settingsStore.isFreeSpinsBought) {
837
838
  return;
838
839
  }
840
+ const boughtRoundNumber = RainMan.settingsStore.buyFreeSpinsData?.getRawData().round_number;
841
+ if (boughtRoundNumber !== undefined) {
842
+ this.roundNumber = boughtRoundNumber;
843
+ RainMan.settingsStore.setRoundNumber(boughtRoundNumber);
844
+ }
839
845
  this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
840
846
  RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
841
847
  RainMan.settingsStore.setIsFreeSpinBought(false);
@@ -846,7 +852,8 @@ export class AbstractController {
846
852
  * @returns {number} - number of free spins bought
847
853
  */
848
854
  getBoughtNumberOfFreeSpins() {
849
- return RainMan.settingsStore.buyFreeSpinsData?.getRawData().extra_data.available_free_spins || 0;
855
+ return (RainMan.settingsStore.buyFreeSpinsData?.getRawData()?.extra_data?.available_free_spins ??
856
+ RainMan.settingsStore.freeSpinNumberBought);
850
857
  }
851
858
  /**
852
859
  * Function for autoplay spin
@@ -1021,10 +1028,14 @@ export class AbstractController {
1021
1028
  */
1022
1029
  gambleGameEnabler(winAmount) {
1023
1030
  if (RainMan.componentRegistry.has(BUTTONS.gamble) && RainMan.settingsStore.isGambleGameAvailable) {
1024
- RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(winAmount === 0);
1031
+ RainMan.componentRegistry
1032
+ .get(BUTTONS.gamble)
1033
+ .flipDisabledFlag(winAmount === 0 || RainMan.settingsStore.isAutoplayEnabled);
1025
1034
  }
1026
1035
  if (RainMan.componentRegistry.has(BUTTONS.take) && RainMan.settingsStore.isTakeActionAvailable) {
1027
- RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(winAmount === 0);
1036
+ RainMan.componentRegistry
1037
+ .get(BUTTONS.take)
1038
+ .flipDisabledFlag(winAmount === 0 || RainMan.settingsStore.isAutoplayEnabled);
1028
1039
  }
1029
1040
  }
1030
1041
  /**
@@ -2,6 +2,7 @@ import { sound } from "@pixi/sound";
2
2
  import { SoundManager } from "../../application";
3
3
  import { RainMan } from "../../Rainman";
4
4
  let shouldResumeAudioOnInterruption = false;
5
+ let isResumingAudio = false;
5
6
  const removeInterruptedAudioResumeListeners = () => {
6
7
  window.removeEventListener("pointerdown", resumeAudioOnInterruption);
7
8
  window.removeEventListener("touchend", resumeAudioOnInterruption);
@@ -19,6 +20,7 @@ const interruptedAudioResume = () => {
19
20
  * @returns {void}
20
21
  */
21
22
  const pauseAudio = () => {
23
+ isResumingAudio = false;
22
24
  shouldResumeAudioOnInterruption = false;
23
25
  removeInterruptedAudioResumeListeners();
24
26
  if (RainMan.settingsStore.isSoundEnabled()) {
@@ -33,20 +35,29 @@ const resumeAudio = async () => {
33
35
  if (document.hidden || !RainMan.settingsStore.isSoundEnabled()) {
34
36
  return;
35
37
  }
36
- if (RainMan.settingsStore.isSoundEnabled()) {
37
- const hasResumedAudioContext = await SoundManager.resumeOnFocus();
38
- if (!hasResumedAudioContext) {
39
- interruptedAudioResume();
38
+ if (isResumingAudio) {
39
+ return;
40
+ }
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();
40
54
  return;
41
55
  }
42
- SoundManager.resumeAll();
56
+ interruptedAudioResume();
43
57
  }
44
- if (SoundManager.isAudioContextRunning()) {
45
- shouldResumeAudioOnInterruption = false;
46
- removeInterruptedAudioResumeListeners();
47
- return;
58
+ finally {
59
+ isResumingAudio = false;
48
60
  }
49
- interruptedAudioResume();
50
61
  };
51
62
  /**
52
63
  * Restore audio on the next user action if browser blocked it earlier.
@@ -66,7 +77,7 @@ const handleVisibilityChange = () => {
66
77
  pauseAudio();
67
78
  return;
68
79
  }
69
- resumeAudio();
80
+ interruptedAudioResume();
70
81
  };
71
82
  /**
72
83
  * Sets up audio states for tab switches and iOS app interruptions.
@@ -76,5 +87,6 @@ export const loadSoundsOnTabChange = () => {
76
87
  sound.disableAutoPause = true;
77
88
  document.addEventListener("visibilitychange", handleVisibilityChange);
78
89
  window.addEventListener("pagehide", () => pauseAudio());
79
- window.addEventListener("pageshow", () => resumeAudio());
90
+ window.addEventListener("pageshow", () => interruptedAudioResume());
91
+ window.addEventListener("focus", () => interruptedAudioResume());
80
92
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixi-rainman-game-engine",
3
- "version": "0.3.35",
3
+ "version": "0.3.36",
4
4
  "description": "This repository contains all of the mechanics that used in rainman games.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",