pixi-rainman-game-engine 0.3.1 → 0.3.3-b

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.
Files changed (34) hide show
  1. package/dist/ComponentRegistry/ComponentRegistry.d.ts +7 -0
  2. package/dist/ComponentRegistry/ComponentRegistry.js +16 -3
  3. package/dist/ComponentRegistry/types.d.ts +3 -2
  4. package/dist/Rainman/appConfig.js +1 -0
  5. package/dist/Rainman/types.d.ts +1 -0
  6. package/dist/application/ButtonsEventManager/ButtonsEventManager.d.ts +7 -0
  7. package/dist/application/ButtonsEventManager/ButtonsEventManager.js +17 -7
  8. package/dist/application/SoundManager/SoundManager.d.ts +6 -0
  9. package/dist/application/SoundManager/SoundManager.js +39 -13
  10. package/dist/components/AbstractMainContainer/AbstractMainContainer.js +1 -6
  11. package/dist/components/GambleGame/GambleGame.js +1 -0
  12. package/dist/components/buttons/BaseButton/BaseButton.d.ts +1 -1
  13. package/dist/components/buttons/buttonGroups/MiddleButtons.d.ts +9 -1
  14. package/dist/components/buttons/buttonGroups/MiddleButtons.js +28 -2
  15. package/dist/components/buttons/buttonGroups/RightButtons.d.ts +9 -3
  16. package/dist/components/buttons/buttonGroups/RightButtons.js +19 -1
  17. package/dist/components/buttons/default/GambleButton.d.ts +13 -0
  18. package/dist/components/buttons/default/GambleButton.js +43 -0
  19. package/dist/components/buttons/default/SpeedControlButton.js +4 -0
  20. package/dist/components/buttons/default/TakeButton.d.ts +13 -0
  21. package/dist/components/buttons/default/TakeButton.js +37 -0
  22. package/dist/components/buttons/default/index.d.ts +2 -0
  23. package/dist/components/buttons/default/index.js +2 -0
  24. package/dist/components/buttons/registrynames.d.ts +2 -0
  25. package/dist/components/buttons/registrynames.js +3 -1
  26. package/dist/components/frame/AbstractColumnsContainer.js +1 -0
  27. package/dist/components/messageBox/MessageBox.js +7 -7
  28. package/dist/components/symbols/AbstractSymbolBase.js +2 -2
  29. package/dist/components/winLineIndicator/WinLineIndicator.js +2 -2
  30. package/dist/controllers/AbstractController.d.ts +8 -0
  31. package/dist/controllers/AbstractController.js +88 -20
  32. package/dist/stores/SettingsStore.d.ts +16 -1
  33. package/dist/stores/SettingsStore.js +35 -4
  34. package/package.json +1 -1
@@ -81,6 +81,13 @@ export declare class ComponentRegistry {
81
81
  * @returns {void}
82
82
  */
83
83
  updateAllSpeedAdaptable(speedLevel: SpeedLevel): void;
84
+ /**
85
+ * Function that adapt temporary speed to be applied only for reels and not for symbols.
86
+ * @public
87
+ * @param speedLevel
88
+ * @returns {void}
89
+ */
90
+ updateTemporaryReelSpeed(speedLevel: SpeedLevel): void;
84
91
  /**
85
92
  * Getter for components that are in ComponentRegistry
86
93
  * Throws error if component is not present
@@ -1,5 +1,5 @@
1
1
  import { isIncentiveComponentInterface, isSpeedAdapterInterface, SpeedLevelHandler, TimedIncentiveController } from "../application";
2
- import { SpeedControlButton } from "../components";
2
+ import { AbstractSymbolsColumn, SpeedControlButton } from "../components";
3
3
  import { RainMan } from "../Rainman";
4
4
  import { openFullscreen } from "../utils";
5
5
  /**
@@ -28,7 +28,7 @@ export class ComponentRegistry {
28
28
  */
29
29
  setTemporarySpeedLevel(newSpeedLevel) {
30
30
  this.speedLevelHandler.setSpeed(newSpeedLevel);
31
- this.updateAllSpeedAdaptable(newSpeedLevel);
31
+ this.updateTemporaryReelSpeed(newSpeedLevel);
32
32
  }
33
33
  /**
34
34
  * Method for reverting speed level for turbo spin
@@ -37,7 +37,7 @@ export class ComponentRegistry {
37
37
  */
38
38
  revertTemporarySpeedLevel() {
39
39
  this.speedLevelHandler.setSpeed(RainMan.settingsStore.currentSpeed);
40
- this.updateAllSpeedAdaptable(RainMan.settingsStore.currentSpeed);
40
+ this.updateTemporaryReelSpeed(RainMan.settingsStore.currentSpeed);
41
41
  }
42
42
  /**
43
43
  * Setter fo speed level
@@ -142,6 +142,19 @@ export class ComponentRegistry {
142
142
  speedAdaptableComponent.adaptToSpeed(speedLevel);
143
143
  });
144
144
  }
145
+ /**
146
+ * Function that adapt temporary speed to be applied only for reels and not for symbols.
147
+ * @public
148
+ * @param speedLevel
149
+ * @returns {void}
150
+ */
151
+ updateTemporaryReelSpeed(speedLevel) {
152
+ this.speedAdaptableComponents.forEach((speedAdaptableComponent) => {
153
+ if (!(speedAdaptableComponent instanceof AbstractSymbolsColumn)) {
154
+ speedAdaptableComponent.adaptToSpeed(speedLevel);
155
+ }
156
+ });
157
+ }
145
158
  /**
146
159
  * Getter for components that are in ComponentRegistry
147
160
  * Throws error if component is not present
@@ -1,4 +1,4 @@
1
- import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BaseButton, BUTTONS, COMPONENTS, FreeSpinButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, StylefulUpdatableText, UpdatableTextComponent, UpdatableValueComponent, VolumeButton } from "../components";
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";
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.
@@ -22,7 +22,8 @@ export interface RegistryMap {
22
22
  [NegButton.registryName]: NegButton;
23
23
  [InfoButton.registryName]: InfoButton;
24
24
  [MoreButton.registryName]: MoreButton;
25
- [BUTTONS.gamble]: BaseButton;
25
+ [BUTTONS.gamble]: GambleButton;
26
+ [BUTTONS.take]: TakeButton;
26
27
  [COMPONENTS.betText]: UpdatableTextComponent;
27
28
  [COMPONENTS.creditText]: UpdatableTextComponent;
28
29
  [COMPONENTS.bigWin]: StylefulUpdatableText;
@@ -18,6 +18,7 @@ export const defaultAppConfig = {
18
18
  disableFreeSpinText: false,
19
19
  winLineIndicatorSymbolScale: 0.75,
20
20
  disableBigWinOnBonus: false,
21
+ gambleGameEnabled: false,
21
22
  durationOfActions: {
22
23
  eachColumnsSpinDelay: [0, 200, 700, 1200, 1800],
23
24
  spinBaseTime: 800,
@@ -25,6 +25,7 @@ export type OptionalAppConfig = {
25
25
  winLineIndicatorSymbolScale: number;
26
26
  disableFreeSpinText: boolean;
27
27
  disableBigWinOnBonus?: boolean;
28
+ gambleGameEnabled?: boolean;
28
29
  durationOfActions: {
29
30
  eachColumnsSpinDelay: number[];
30
31
  spinBaseTime: number;
@@ -126,6 +126,13 @@ export declare class ButtonsEventManager {
126
126
  * @returns {void}
127
127
  */
128
128
  initGambleButton(onClick: () => void, disabled: boolean): void;
129
+ /**
130
+ * Initializing take button
131
+ * @public
132
+ * @param {() => void} onClick - callback for take action
133
+ * @param {boolean} disabled - flag for enabling/disabling button
134
+ */
135
+ initTakeButton(onClick: () => void, disabled: boolean): void;
129
136
  /**
130
137
  * Function for displaying speed modal
131
138
  * This modal is used while doing turbo spin
@@ -74,6 +74,7 @@ export class ButtonsEventManager {
74
74
  RainMan.settingsStore.handleModalInvocation = this.handleModalInvocation.bind(this);
75
75
  RainMan.settingsStore.setSpeedPopupVisibility = this.setSpeedPopupVisibility.bind(this);
76
76
  RainMan.settingsStore.enableButtons = this.enableButtons.bind(this);
77
+ RainMan.settingsStore.closeOtherModals = this.closeOtherModals.bind(this);
77
78
  }
78
79
  /**
79
80
  * Method for initializing events in Settings UI
@@ -169,11 +170,11 @@ export class ButtonsEventManager {
169
170
  * @returns {void}
170
171
  */
171
172
  initBetPlusButtonEvent(setBetCallback) {
172
- const { isFreeSpinsBought, isFreeSpinsPlayEnabled, betChangeDisabled } = RainMan.settingsStore;
173
+ const { isFreeSpinsBought, isFreeSpinsPlayEnabled } = RainMan.settingsStore;
173
174
  if (this.settingsPlusButton === null) {
174
175
  this.settingsPlusButton = window.document.getElementsByName("bet-plus")[0];
175
176
  this.settingsPlusButton.addEventListener("click", () => {
176
- if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled)
177
+ if (isFreeSpinsBought || isFreeSpinsPlayEnabled)
177
178
  return;
178
179
  setBetCallback("increase");
179
180
  });
@@ -188,10 +189,10 @@ export class ButtonsEventManager {
188
189
  */
189
190
  initBetMinusButtonEvent(setBetCallback) {
190
191
  if (this.settingsMinusButton === null) {
191
- const { isFreeSpinsBought, isFreeSpinsPlayEnabled, betChangeDisabled } = RainMan.settingsStore;
192
+ const { isFreeSpinsBought, isFreeSpinsPlayEnabled } = RainMan.settingsStore;
192
193
  this.settingsMinusButton = window.document.getElementsByName("bet-minus")[0];
193
194
  this.settingsMinusButton.addEventListener("click", () => {
194
- if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled) {
195
+ if (isFreeSpinsBought || isFreeSpinsPlayEnabled) {
195
196
  return;
196
197
  }
197
198
  setBetCallback("decrease");
@@ -284,11 +285,22 @@ export class ButtonsEventManager {
284
285
  * @returns {void}
285
286
  */
286
287
  initGambleButton(onClick, disabled) {
287
- if (!RainMan.componentRegistry.has(BUTTONS.gamble) && RainMan.settingsStore.gambleGameUsed) {
288
+ if (!RainMan.componentRegistry.has(BUTTONS.gamble) && !RainMan.settingsStore.isGambleGameAvailable) {
288
289
  return;
289
290
  }
291
+ RainMan.componentRegistry.get(BUTTONS.gamble).setOnClick(onClick);
290
292
  RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(disabled);
291
293
  }
294
+ /**
295
+ * Initializing take button
296
+ * @public
297
+ * @param {() => void} onClick - callback for take action
298
+ * @param {boolean} disabled - flag for enabling/disabling button
299
+ */
300
+ initTakeButton(onClick, disabled) {
301
+ RainMan.componentRegistry.get(BUTTONS.take).setOnClick(onClick);
302
+ RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(disabled);
303
+ }
292
304
  /**
293
305
  * Function for displaying speed modal
294
306
  * This modal is used while doing turbo spin
@@ -365,11 +377,9 @@ export class ButtonsEventManager {
365
377
  if (layer !== null) {
366
378
  if (layer.style.display !== "flex") {
367
379
  layer.style.display = "flex";
368
- this.disableButtons();
369
380
  }
370
381
  else {
371
382
  layer.style.display = "none";
372
- this.enableButtons();
373
383
  }
374
384
  }
375
385
  }
@@ -51,6 +51,12 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
51
51
  * @returns {void}
52
52
  */
53
53
  play(soundName: SoundTrack): void;
54
+ /**
55
+ * Returns the volume level for a given sound track.
56
+ * @param {SoundTracks} soundName - The name of the sound track.
57
+ * @returns {number} The volume level for the sound track.
58
+ */
59
+ getVolumeLevel(soundName: SoundTrack): number;
54
60
  /**
55
61
  * Function for resuming all sounds in game
56
62
  * If sound is not playing, it will be skipped
@@ -37,13 +37,15 @@ export class SoundManagerInstance {
37
37
  async loadSounds(assets) {
38
38
  const loadingSoundsPromises = [];
39
39
  for (const [soundName, url] of Object.entries(assets)) {
40
- if (!url)
40
+ if (!url) {
41
41
  continue;
42
+ }
42
43
  loadingSoundsPromises.push(new Promise((resolve) => {
43
44
  const sound = Sound.from({
44
45
  url,
45
46
  autoPlay: false,
46
47
  preload: true,
48
+ volume: this.getVolumeLevel(soundName),
47
49
  loaded: () => resolve()
48
50
  });
49
51
  sound.name = soundName;
@@ -59,12 +61,17 @@ export class SoundManagerInstance {
59
61
  * @returns {void}
60
62
  */
61
63
  setVolume(volumeLevel) {
62
- this.musicCatalogue.forEach((sound) => {
63
- if (sound?.name === "music") {
64
- sound.volume = volumeLevel * 0.5;
65
- }
66
- else {
67
- sound.volume = volumeLevel;
64
+ this.musicCatalogue.forEach((sound, soundName) => {
65
+ switch (soundName) {
66
+ case SoundTracks.music:
67
+ sound.volume = volumeLevel * 0.5;
68
+ break;
69
+ case SoundTracks.freeSpinsMusic:
70
+ sound.volume = volumeLevel * 0.95;
71
+ break;
72
+ default:
73
+ sound.volume = volumeLevel;
74
+ break;
68
75
  }
69
76
  });
70
77
  }
@@ -75,8 +82,9 @@ export class SoundManagerInstance {
75
82
  */
76
83
  stopPlayingFxSounds() {
77
84
  for (const [soundName, sound] of this.musicCatalogue.entries()) {
78
- if (soundName === SoundTracks.music)
85
+ if (soundName === SoundTracks.music) {
79
86
  continue;
87
+ }
80
88
  sound.stop();
81
89
  }
82
90
  }
@@ -113,15 +121,33 @@ export class SoundManagerInstance {
113
121
  !RainMan.settingsStore.shouldPlayAmbientMusic) {
114
122
  return;
115
123
  }
116
- const soundLevel = RainMan.settingsStore.volumeLevel / 100;
124
+ if (soundName === "freeSpinsMusic" &&
125
+ sound.isPlaying &&
126
+ RainMan.settingsStore.isFreeSpinsPlayEnabled &&
127
+ !RainMan.settingsStore.shouldPlayAmbientMusic) {
128
+ return;
129
+ }
117
130
  sound.play({
118
- loop: soundsToLoop.includes(soundName),
119
131
  singleInstance: true,
120
- volume: soundName === SoundTracks.music || soundName === SoundTracks.freeSpinsMusic
121
- ? soundLevel * 0.5
122
- : soundLevel
132
+ loop: soundsToLoop.includes(soundName),
133
+ volume: this.getVolumeLevel(soundName)
123
134
  });
124
135
  }
136
+ /**
137
+ * Returns the volume level for a given sound track.
138
+ * @param {SoundTracks} soundName - The name of the sound track.
139
+ * @returns {number} The volume level for the sound track.
140
+ */
141
+ getVolumeLevel(soundName) {
142
+ switch (soundName) {
143
+ case SoundTracks.music:
144
+ return Number((RainMan.settingsStore.volumeLevel / 100) * 0.5);
145
+ case SoundTracks.freeSpinsMusic:
146
+ return Number((RainMan.settingsStore.volumeLevel / 100) * 0.95);
147
+ default:
148
+ return Number(RainMan.settingsStore.volumeLevel / 100);
149
+ }
150
+ }
125
151
  /**
126
152
  * Function for resuming all sounds in game
127
153
  * If sound is not playing, it will be skipped
@@ -58,12 +58,7 @@ export class AbstractMainContainer extends Container {
58
58
  this.name = AbstractMainContainer.registryName;
59
59
  this.buttonsEventManager = new ButtonsEventManager();
60
60
  this.messageBox = new MessageBox();
61
- if (RainMan.settingsStore.isSoundEnabled()) {
62
- SoundManager.resumeAll();
63
- if (RainMan.settingsStore.shouldPlayAmbientMusic) {
64
- SoundManager.setPlayStatus(SoundTracks.music, RainMan.settingsStore.shouldPlayAmbientMusic);
65
- }
66
- }
61
+ SoundManager.setPlayStatus(SoundTracks.music, RainMan.settingsStore.shouldPlayAmbientMusic);
67
62
  RainMan.settingsStore.setHandleInvokeFreeSpinPlate(this.invokeFreeSpinPlate.bind(this));
68
63
  RainMan.app.renderer.on("resize", () => this.resize());
69
64
  }
@@ -108,6 +108,7 @@ export class GambleGame extends Container {
108
108
  * @returns {Promise<void>}
109
109
  */
110
110
  async loseDoubleAndWinFields() {
111
+ RainMan.settingsStore.disableSpecialButtons();
111
112
  return Promise.all([this.gambleWin.loseUpdate(), this.currentWin.loseUpdate()]);
112
113
  }
113
114
  /**
@@ -16,7 +16,7 @@ export declare class BaseButton extends Sprite {
16
16
  private isActive;
17
17
  private isOver;
18
18
  private isDisabled;
19
- private _onClick;
19
+ protected _onClick: () => void;
20
20
  private _customClickHandler;
21
21
  constructor(name: string, textureMap: TextureMap, stateful?: boolean, clickSound?: Nullable<SoundTrack>);
22
22
  /**
@@ -1,6 +1,6 @@
1
1
  import { Graphics } from "pixi.js";
2
2
  import { ResponsiveContainer } from "../../common";
3
- import { AutoplayButton, PlusButton, RefreshButton } from "../default";
3
+ import { AutoplayButton, GambleButton, PlusButton, RefreshButton, 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}.
@@ -12,6 +12,8 @@ export declare class MiddleButtons extends ResponsiveContainer {
12
12
  protected readonly betButton: PlusButton;
13
13
  protected readonly refreshButton: RefreshButton;
14
14
  protected readonly positioningFrame: Graphics;
15
+ protected readonly gambleButton: GambleButton;
16
+ protected readonly takeButton: TakeButton;
15
17
  constructor(landscape?: boolean);
16
18
  /**
17
19
  * Function for removing children from the registry
@@ -19,6 +21,12 @@ export declare class MiddleButtons extends ResponsiveContainer {
19
21
  * @returns {void}
20
22
  */
21
23
  removeChildrenFromRegistry(): void;
24
+ /**
25
+ * Function for adding Gamble and Take buttons if they are defined
26
+ * @protected
27
+ * @returns {void}
28
+ */
29
+ protected addGambleAndTakeButtons(): void;
22
30
  /**
23
31
  * Function for initializing child positions
24
32
  * @private
@@ -2,7 +2,7 @@ import { Graphics } from "pixi.js";
2
2
  import { UXLayer } from "../../../layers";
3
3
  import { RainMan } from "../../../Rainman";
4
4
  import { ResponsiveContainer } from "../../common";
5
- import { AutoplayButton, PlusButton, RefreshButton } from "../default";
5
+ import { AutoplayButton, GambleButton, PlusButton, RefreshButton, TakeButton } from "../default";
6
6
  import { REGISTRY } from "../registrynames";
7
7
  /**
8
8
  * Class for managing middle buttons in game (MOBILE ONLY).
@@ -15,6 +15,8 @@ export class MiddleButtons extends ResponsiveContainer {
15
15
  betButton = new PlusButton(true);
16
16
  refreshButton = new RefreshButton(true);
17
17
  positioningFrame = new Graphics();
18
+ gambleButton = new GambleButton(true);
19
+ takeButton = new TakeButton(true);
18
20
  constructor(landscape = false) {
19
21
  super();
20
22
  this.landscape = landscape;
@@ -23,21 +25,28 @@ export class MiddleButtons extends ResponsiveContainer {
23
25
  const buttons = [this.autoplayButton, this.betButton, this.refreshButton];
24
26
  this.addChild(...buttons);
25
27
  RainMan.componentRegistry.addMany(buttons);
28
+ this.addGambleAndTakeButtons();
26
29
  this.positioningFrame.beginFill(0x000000, 0);
27
30
  this.positioningFrame.drawRect(0, 0, 800, 250);
28
31
  this.addChild(this.positioningFrame);
29
32
  this.refreshButton.scale.set(0.75);
30
33
  this.autoplayButton.scale.set(0.75);
31
34
  this.betButton.scale.set(0.75);
35
+ this.takeButton.scale.set(0.75);
36
+ this.gambleButton.scale.set(0.75);
32
37
  if (this.landscape) {
33
38
  this.betButton.anchor.set(0.5, 2);
34
39
  this.refreshButton.anchor.set(0.5, 0.5);
35
40
  this.autoplayButton.anchor.set(0.5, -1);
41
+ this.takeButton.anchor.set(0.5, 2);
42
+ this.gambleButton.anchor.set(0.5, -1);
36
43
  }
37
44
  else {
38
45
  this.autoplayButton.anchor.set(2, 0.5);
39
46
  this.refreshButton.anchor.set(0.5, 0.5);
40
47
  this.betButton.anchor.set(-1, 0.5);
48
+ this.takeButton.anchor.set(-1, 0.5);
49
+ this.gambleButton.anchor.set(2, 0.5);
41
50
  }
42
51
  this.initChildPositions();
43
52
  if (this.landscape) {
@@ -54,9 +63,26 @@ export class MiddleButtons extends ResponsiveContainer {
54
63
  this.refreshButton,
55
64
  this.autoplayButton,
56
65
  this.betButton,
57
- this.positioningFrame
66
+ this.positioningFrame,
67
+ ...(this.gambleButton && RainMan.config.gambleGameEnabled ? [this.gambleButton] : []),
68
+ ...(this.takeButton ? [this.takeButton] : [])
58
69
  ]);
59
70
  }
71
+ /**
72
+ * Function for adding Gamble and Take buttons if they are defined
73
+ * @protected
74
+ * @returns {void}
75
+ */
76
+ addGambleAndTakeButtons() {
77
+ if (this.gambleButton && RainMan.config.gambleGameEnabled) {
78
+ this.addChild(this.gambleButton);
79
+ RainMan.componentRegistry.add(this.gambleButton);
80
+ }
81
+ if (this.takeButton) {
82
+ this.addChild(this.takeButton);
83
+ RainMan.componentRegistry.add(this.takeButton);
84
+ }
85
+ }
60
86
  /**
61
87
  * Function for initializing child positions
62
88
  * @private
@@ -1,7 +1,6 @@
1
1
  import { Nullable } from "../../../utils";
2
2
  import { ResponsiveContainer } from "../../common";
3
- import { BaseButton } from "../BaseButton";
4
- import { AutoplayButton, NegButton, PlusButton, RefreshButton, SpeedControlButton } from "../default";
3
+ import { AutoplayButton, GambleButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, TakeButton } from "../default";
5
4
  /**
6
5
  * Class for managing right buttons in game. The class uses {@link AutoplayButton}, {@link NegButton}, {@link PlusButton},
7
6
  * {@link RefreshButton}, {@link SpeedControlButton} and gamble button {@link BaseButton} if exists.
@@ -15,7 +14,8 @@ export declare class RightButtons extends ResponsiveContainer {
15
14
  protected readonly plusButton: PlusButton;
16
15
  protected readonly refreshButton: RefreshButton;
17
16
  protected readonly speedControlButton: SpeedControlButton;
18
- protected readonly gambleButton: Nullable<BaseButton>;
17
+ protected readonly gambleButton: Nullable<GambleButton>;
18
+ protected readonly takeButton: Nullable<TakeButton>;
19
19
  constructor();
20
20
  /**
21
21
  * Function for removing the components from the registry
@@ -29,4 +29,10 @@ export declare class RightButtons extends ResponsiveContainer {
29
29
  * @returns {void}
30
30
  */
31
31
  protected reposition(): void;
32
+ /**
33
+ * Function for adding Gamble and Take buttons if they are defined
34
+ * @protected
35
+ * @returns {void}
36
+ */
37
+ protected addGambleAndTakeButtons(): void;
32
38
  }
@@ -17,6 +17,7 @@ export class RightButtons extends ResponsiveContainer {
17
17
  refreshButton = new RefreshButton();
18
18
  speedControlButton = new SpeedControlButton();
19
19
  gambleButton = null;
20
+ takeButton = null;
20
21
  constructor() {
21
22
  super(-1);
22
23
  this.name = REGISTRY.rightButtons;
@@ -42,7 +43,9 @@ export class RightButtons extends ResponsiveContainer {
42
43
  this.negButton,
43
44
  this.plusButton,
44
45
  this.refreshButton,
45
- this.speedControlButton
46
+ this.speedControlButton,
47
+ ...(this.gambleButton ? [this.gambleButton] : []),
48
+ ...(this.takeButton ? [this.takeButton] : [])
46
49
  ]);
47
50
  }
48
51
  /**
@@ -54,4 +57,19 @@ export class RightButtons extends ResponsiveContainer {
54
57
  this.y = RainMan.app.screen.height;
55
58
  this.x = RainMan.app.screen.width;
56
59
  }
60
+ /**
61
+ * Function for adding Gamble and Take buttons if they are defined
62
+ * @protected
63
+ * @returns {void}
64
+ */
65
+ addGambleAndTakeButtons() {
66
+ if (this.gambleButton && RainMan.config.gambleGameEnabled) {
67
+ this.addChild(this.gambleButton);
68
+ RainMan.componentRegistry.add(this.gambleButton);
69
+ }
70
+ if (this.takeButton) {
71
+ this.addChild(this.takeButton);
72
+ RainMan.componentRegistry.add(this.takeButton);
73
+ }
74
+ }
57
75
  }
@@ -0,0 +1,13 @@
1
+ import { BaseButton } from "../BaseButton";
2
+ /**
3
+ * Class for a Gamble button in the game.
4
+ * Textures names should be "gamble.png", "gamble-over.png", and "gamble-clicked.png".
5
+ * @class TakeButton
6
+ * @augments {BaseButton}
7
+ */
8
+ export declare class GambleButton extends BaseButton {
9
+ static readonly registryName = "gambleButton";
10
+ private mobile;
11
+ constructor(mobile?: boolean);
12
+ flipDisabledFlag(disabled: boolean): void;
13
+ }
@@ -0,0 +1,43 @@
1
+ import { RainMan } from "../../../Rainman";
2
+ import { getTexture } from "../../../utils";
3
+ import { BaseButton, ButtonStates } from "../BaseButton";
4
+ import { BUTTONS } from "../registrynames";
5
+ /**
6
+ * Class for a Gamble button in the game.
7
+ * Textures names should be "gamble.png", "gamble-over.png", and "gamble-clicked.png".
8
+ * @class TakeButton
9
+ * @augments {BaseButton}
10
+ */
11
+ export class GambleButton extends BaseButton {
12
+ static registryName = "gambleButton";
13
+ mobile;
14
+ constructor(mobile = false) {
15
+ const textureMap = mobile
16
+ ? {
17
+ [ButtonStates.NORMAL]: getTexture("mobile-gamble.png")
18
+ }
19
+ : {
20
+ [ButtonStates.NORMAL]: getTexture("gamble.png"),
21
+ [ButtonStates.OVER]: getTexture("gamble-over.png"),
22
+ [ButtonStates.CLICKED]: getTexture("gamble-clicked.png")
23
+ };
24
+ super(GambleButton.registryName, textureMap);
25
+ this.mobile = mobile;
26
+ }
27
+ flipDisabledFlag(disabled) {
28
+ super.flipDisabledFlag(disabled);
29
+ this.alpha = disabled ? 0 : 1;
30
+ if (!disabled && this.mobile) {
31
+ RainMan.componentRegistry.get(BUTTONS.autoplay).alpha = 0;
32
+ }
33
+ else {
34
+ RainMan.componentRegistry.get(BUTTONS.autoplay).alpha = 1;
35
+ }
36
+ if (!disabled && !this.mobile) {
37
+ RainMan.componentRegistry.get(BUTTONS.neg).alpha = 0;
38
+ }
39
+ else {
40
+ RainMan.componentRegistry.get(BUTTONS.neg).alpha = 1;
41
+ }
42
+ }
43
+ }
@@ -1,3 +1,4 @@
1
+ import { RainMan } from "../../../Rainman";
1
2
  import { getTexture } from "../../../utils";
2
3
  import { BaseButton, ButtonStates } from "../BaseButton";
3
4
  const createTextureMap = (speedLevel) => {
@@ -33,6 +34,9 @@ export class SpeedControlButton extends BaseButton {
33
34
  * @returns {void}
34
35
  */
35
36
  adaptToSpeed(speedLevel) {
37
+ if (RainMan.settingsStore.isTemporarySpeed) {
38
+ return;
39
+ }
36
40
  this.setTextureMap(this.speedLevelMapper[speedLevel]);
37
41
  }
38
42
  }
@@ -0,0 +1,13 @@
1
+ import { BaseButton } from "../BaseButton";
2
+ /**
3
+ * Class for a Take button in the game.
4
+ * Textures names should be "take.png", "take-over.png", and "take-clicked.png".
5
+ * @class TakeButton
6
+ * @augments {BaseButton}
7
+ */
8
+ export declare class TakeButton extends BaseButton {
9
+ static readonly registryName = "takeButton";
10
+ private mobile;
11
+ constructor(mobile?: boolean);
12
+ flipDisabledFlag(disabled: boolean): void;
13
+ }
@@ -0,0 +1,37 @@
1
+ import { RainMan } from "../../../Rainman";
2
+ import { getTexture } from "../../../utils";
3
+ import { BaseButton, ButtonStates } from "../BaseButton";
4
+ import { BUTTONS } from "../registrynames";
5
+ /**
6
+ * Class for a Take button in the game.
7
+ * Textures names should be "take.png", "take-over.png", and "take-clicked.png".
8
+ * @class TakeButton
9
+ * @augments {BaseButton}
10
+ */
11
+ export class TakeButton extends BaseButton {
12
+ static registryName = "takeButton";
13
+ mobile;
14
+ constructor(mobile = false) {
15
+ const textureMap = mobile
16
+ ? {
17
+ [ButtonStates.NORMAL]: getTexture("mobile-take.png")
18
+ }
19
+ : {
20
+ [ButtonStates.NORMAL]: getTexture("take.png"),
21
+ [ButtonStates.OVER]: getTexture("take-over.png"),
22
+ [ButtonStates.CLICKED]: getTexture("take-clicked.png")
23
+ };
24
+ super(TakeButton.registryName, textureMap);
25
+ this.mobile = mobile;
26
+ }
27
+ flipDisabledFlag(disabled) {
28
+ super.flipDisabledFlag(disabled);
29
+ this.alpha = disabled ? 0 : 1;
30
+ if (!disabled) {
31
+ RainMan.componentRegistry.get(BUTTONS.plus).alpha = 0;
32
+ }
33
+ else {
34
+ RainMan.componentRegistry.get(BUTTONS.plus).alpha = 1;
35
+ }
36
+ }
37
+ }
@@ -1,6 +1,7 @@
1
1
  export * from "./AutoplayButton";
2
2
  export * from "./BlackButton";
3
3
  export * from "./CollectButton";
4
+ export * from "./GambleButton";
4
5
  export * from "./InfoButton";
5
6
  export * from "./MoreButton";
6
7
  export * from "./NegButton";
@@ -9,4 +10,5 @@ export * from "./RedButton";
9
10
  export * from "./RefreshButton";
10
11
  export * from "./SpeedControlButton";
11
12
  export * from "./SpinConfirmationButton";
13
+ export * from "./TakeButton";
12
14
  export * from "./VolumeButton";
@@ -1,6 +1,7 @@
1
1
  export * from "./AutoplayButton";
2
2
  export * from "./BlackButton";
3
3
  export * from "./CollectButton";
4
+ export * from "./GambleButton";
4
5
  export * from "./InfoButton";
5
6
  export * from "./MoreButton";
6
7
  export * from "./NegButton";
@@ -9,4 +10,5 @@ export * from "./RedButton";
9
10
  export * from "./RefreshButton";
10
11
  export * from "./SpeedControlButton";
11
12
  export * from "./SpinConfirmationButton";
13
+ export * from "./TakeButton";
12
14
  export * from "./VolumeButton";
@@ -9,7 +9,9 @@ export declare const BUTTONS: {
9
9
  readonly info: "infoButton";
10
10
  readonly more: "moreButton";
11
11
  readonly gamble: "gambleButton";
12
+ readonly take: "takeButton";
12
13
  readonly volume: "volumeButton";
14
+ readonly autoplay: "autoplayButton";
13
15
  };
14
16
  /**
15
17
  * Button groups in Rainman Registry
@@ -9,7 +9,9 @@ export const BUTTONS = {
9
9
  info: "infoButton",
10
10
  more: "moreButton",
11
11
  gamble: "gambleButton",
12
- volume: "volumeButton"
12
+ take: "takeButton",
13
+ volume: "volumeButton",
14
+ autoplay: "autoplayButton"
13
15
  };
14
16
  /**
15
17
  * Button groups in Rainman Registry
@@ -74,6 +74,7 @@ export class AbstractColumnsContainer extends Container {
74
74
  */
75
75
  enableQuickReelsStop() {
76
76
  this.quickReelsStop = true;
77
+ RainMan.settingsStore.setIsTemporarySpeed(true);
77
78
  RainMan.componentRegistry.setTemporarySpeedLevel(SPEED_LEVELS.fast);
78
79
  this.skipScatterDelay?.();
79
80
  this.resolveMysterySpeedUp();
@@ -47,10 +47,10 @@ export class MessageBox extends Container {
47
47
  this.positioningFrame.drawRect(0, 0, 800, 150);
48
48
  this.addChild(this.positioningFrame);
49
49
  this.parentLayer = UXLayer;
50
- this.freeSpinText = new UpdatableTextComponent(MessageBox.freeSpinTextRegistryName, i18n.t("currentFreeSpins"), UPDATABLE_MODES.int, fontSize, new Color(0xffffff).toHex(), () => this.centerTextOnX(this.freeSpinText));
51
- this.autoSpinText = new UpdatableTextComponent(MessageBox.autoSpinTextRegistryName, i18n.t("autoSpinsLeft"), UPDATABLE_MODES.int, fontSize, new Color(0xffffff).toHex(), () => this.centerTextOnX(this.autoSpinText));
52
- this.currentWinText = new UpdatableTextComponent(MessageBox.currentWinTextRegistryName, i18n.t("currentWin"), UPDATABLE_MODES.money, fontSize, undefined, () => this.centerTextOnX(this.currentWinText));
53
- this.possibleWinText = new UpdatableTextComponent(MessageBox.possibleWinTextRegistryName, i18n.t("possibleWin"), UPDATABLE_MODES.money, fontSize, undefined, () => this.centerTextOnX(this.possibleWinText));
50
+ this.freeSpinText = new UpdatableTextComponent(MessageBox.freeSpinTextRegistryName, i18n.t("currentFreeSpins"), UPDATABLE_MODES.int, fontSize - 5, new Color(0xffffff).toHex(), () => this.centerTextOnX(this.freeSpinText));
51
+ this.autoSpinText = new UpdatableTextComponent(MessageBox.autoSpinTextRegistryName, i18n.t("autoSpinsLeft"), UPDATABLE_MODES.int, fontSize - 5, new Color(0xffffff).toHex(), () => this.centerTextOnX(this.autoSpinText));
52
+ this.currentWinText = new UpdatableTextComponent(MessageBox.currentWinTextRegistryName, i18n.t("currentWin"), UPDATABLE_MODES.money, fontSize + 15, undefined, () => this.centerTextOnX(this.currentWinText));
53
+ this.possibleWinText = new UpdatableTextComponent(MessageBox.possibleWinTextRegistryName, i18n.t("possibleWin"), UPDATABLE_MODES.money, fontSize + 15, undefined, () => this.centerTextOnX(this.possibleWinText));
54
54
  this.incentiveText = new Text(sample(i18n.t("idleMessages", { returnObjects: true })[RainMan.componentRegistry.getSpeedLevel()]), {
55
55
  fontFamily: RainMan.config.fontFace,
56
56
  fontSize,
@@ -218,7 +218,7 @@ export class MessageBox extends Container {
218
218
  return;
219
219
  }
220
220
  this.autoSpinShown = true;
221
- this.autoSpinText.set(RainMan.settingsStore.howManyAutoSpinsLeft);
221
+ this.autoSpinText.setStringValue(RainMan.settingsStore.infinitySpinsEnabled ? "∞" : RainMan.settingsStore.howManyAutoSpinsLeft.toString());
222
222
  this.centerTextOnX(this.autoSpinText);
223
223
  this.addChild(this.autoSpinText);
224
224
  }
@@ -286,8 +286,8 @@ export class MessageBox extends Container {
286
286
  this.hideFreeSpinText();
287
287
  this.hideAutoSpinText();
288
288
  const fontSize = getDeviceOrientation().includes("mobile")
289
- ? RainMan.config.mobileFontSize
290
- : RainMan.config.fontSize;
289
+ ? RainMan.config.mobileFontSize - 5
290
+ : RainMan.config.fontSize - 5;
291
291
  const winLineTextStyle = {
292
292
  fontFamily: RainMan.config.fontFace,
293
293
  fontSize,
@@ -3,7 +3,7 @@ import { Spine } from "pixi-spine";
3
3
  import { animationsSpeedLevels, defaultSpeedConfig, SoundManager, SoundTracks } from "../../application";
4
4
  import { AnimationLayer } from "../../layers";
5
5
  import { RainMan } from "../../Rainman";
6
- import { getSpineData, getTexture, logError, togglePaytable } from "../../utils";
6
+ import { getSpineData, getTexture, logError, UI_ITEMS } from "../../utils";
7
7
  /**
8
8
  * Class represents symbol which is displayed in columns
9
9
  * @abstract
@@ -284,7 +284,7 @@ export class AbstractSymbolBase extends Container {
284
284
  const { x, y } = this.getGlobalPosition();
285
285
  RainMan.settingsStore.repositionSymbolPaytablePopup(x, y);
286
286
  });
287
- togglePaytable();
287
+ RainMan.settingsStore.handleModalInvocation?.(UI_ITEMS.symbolPayTable);
288
288
  }
289
289
  /**
290
290
  * Function for setting the symbol.
@@ -27,9 +27,9 @@ export class WinLineIndicator extends Container {
27
27
  current.anchor.set(0);
28
28
  if (previous)
29
29
  current.x += previous.x + previous.width;
30
- current.y -= current.height / 2;
30
+ current.y -= current.height / 2 - 5;
31
31
  }
32
- this.text.y -= this.text.height / 2;
32
+ this.text.y -= this.text.height / 2 - 5;
33
33
  const lastSymbol = last(this.symbols);
34
34
  if (lastSymbol) {
35
35
  this.text.x = lastSymbol.x + lastSymbol.width + WinLineIndicator.OFFSET;
@@ -31,6 +31,7 @@ export declare abstract class AbstractController<T> {
31
31
  protected currentlyPlayedAction: (Promise<void> | Promise<void[]>) | undefined;
32
32
  protected currentlyPlayedActionType: T | undefined;
33
33
  protected isPlayingUnskippableStreak: boolean;
34
+ protected shouldAutoplayFreeSpins: boolean;
34
35
  protected isLoopingWinActionsQueue: boolean;
35
36
  protected gamePhase: GamePhase;
36
37
  protected autoSpinBalance: number;
@@ -78,6 +79,13 @@ export declare abstract class AbstractController<T> {
78
79
  * @returns {void}
79
80
  */
80
81
  private setupSpaceOrEnterListener;
82
+ /**
83
+ * This function sets up a listener for resize event
84
+ * It prevents buttons from being interacted with after a resize
85
+ * @private
86
+ * @returns {void}
87
+ */
88
+ private setupResizeListener;
81
89
  /**
82
90
  * Function for disabling bet buttons
83
91
  * @public
@@ -30,6 +30,7 @@ export class AbstractController {
30
30
  currentlyPlayedAction;
31
31
  currentlyPlayedActionType;
32
32
  isPlayingUnskippableStreak = false;
33
+ shouldAutoplayFreeSpins = true;
33
34
  isLoopingWinActionsQueue = false;
34
35
  gamePhase = gamePhases.IDLE;
35
36
  autoSpinBalance = 0;
@@ -60,6 +61,7 @@ export class AbstractController {
60
61
  this.uiController = new UiController(this.config);
61
62
  this.componentRegistry = RainMan.componentRegistry;
62
63
  this.setupSpaceOrEnterListener();
64
+ this.setupResizeListener();
63
65
  this.roundNumber = initData.round_number;
64
66
  RainMan.settingsStore.setRoundNumber(this.roundNumber);
65
67
  RainMan.globals.handleDisablingButtons = this.handleDisablingButtons.bind(this);
@@ -94,14 +96,16 @@ export class AbstractController {
94
96
  this.buttonsEventManager.initFreeSpinModal();
95
97
  this.buttonsEventManager.setUpUIElementsInteractivity();
96
98
  this.buttonsEventManager.setConfirmAutoplayButton(() => {
97
- if (RainMan.settingsStore.isAutoplayEnabled)
99
+ if (RainMan.settingsStore.isAutoplayEnabled) {
98
100
  return;
101
+ }
99
102
  RainMan.settingsStore.setAutoPlayEnabledFlag(true);
100
103
  RainMan.componentRegistry.get(AutoplayButton.registryName).activate(true);
101
104
  RainMan.componentRegistry.get(BUTTONS.plus).flipDisabledFlag(true);
102
105
  RainMan.componentRegistry.get(BUTTONS.neg).flipDisabledFlag(true);
103
106
  this.throttledSpin();
104
107
  });
108
+ SoundManager.setPlayStatus(SoundTracks.music, RainMan.settingsStore.shouldPlayAmbientMusic);
105
109
  this.changeGamePhase(gamePhases.IDLE);
106
110
  }
107
111
  /**
@@ -150,6 +154,19 @@ export class AbstractController {
150
154
  }
151
155
  });
152
156
  }
157
+ /**
158
+ * This function sets up a listener for resize event
159
+ * It prevents buttons from being interacted with after a resize
160
+ * @private
161
+ * @returns {void}
162
+ */
163
+ setupResizeListener() {
164
+ window.addEventListener("resize", () => {
165
+ if (this.shouldBetButtonsBeDisabled) {
166
+ this.handleDisablingButtons(true);
167
+ }
168
+ });
169
+ }
153
170
  /**
154
171
  * Function for disabling bet buttons
155
172
  * @public
@@ -216,7 +233,12 @@ export class AbstractController {
216
233
  */
217
234
  handleDisablingButtons(disabled) {
218
235
  this.disableBetButtons(disabled ?? this.shouldBetButtonsBeDisabled);
219
- this.disableSpeedButton(disabled ?? this.shouldButtonsBeDisabled);
236
+ if (RainMan.settingsStore.isFreeSpinsPlayEnabled) {
237
+ this.disableSpeedButton(false);
238
+ }
239
+ else {
240
+ this.disableSpeedButton(disabled ?? this.shouldButtonsBeDisabled);
241
+ }
220
242
  this.disableInformationButtons(disabled ?? this.shouldButtonsBeDisabled);
221
243
  }
222
244
  /**
@@ -231,9 +253,22 @@ export class AbstractController {
231
253
  this.buttonsEventManager.initAutoplayButtonEvent();
232
254
  if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
233
255
  this.buttonsEventManager.initGambleButton(() => {
234
- RainMan.settingsStore.gambleGameUsed = true;
256
+ RainMan.settingsStore.isGambleGameAvailable = false;
235
257
  this.mainContainer.invokeGambleGame();
236
- }, this.lastWinAmount === 0);
258
+ }, this.lastWinAmount === 0 || !RainMan.settingsStore.isGambleGameAvailable);
259
+ }
260
+ if (RainMan.componentRegistry.has(BUTTONS.take)) {
261
+ this.buttonsEventManager.initTakeButton(() => {
262
+ RainMan.settingsStore.useTakeAction?.();
263
+ RainMan.settingsStore.isTakeActionAvailable = false;
264
+ RainMan.settingsStore.isGambleGameAvailable = false;
265
+ if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
266
+ RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(true);
267
+ }
268
+ RainMan.componentRegistry
269
+ .get(BUTTONS.take)
270
+ .flipDisabledFlag(!RainMan.settingsStore.isTakeActionAvailable);
271
+ }, !RainMan.settingsStore.isTakeActionAvailable);
237
272
  }
238
273
  RainMan.componentRegistry.get(SpeedControlButton.registryName).setOnClick(() => {
239
274
  this.quickStopController.speedPopupDisabled = true;
@@ -256,21 +291,26 @@ export class AbstractController {
256
291
  }
257
292
  if (getDeviceOrientation().includes("mobile")) {
258
293
  RainMan.componentRegistry.get(BUTTONS.plus).setOnClick(() => {
259
- if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled)
294
+ if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled) {
260
295
  return;
296
+ }
261
297
  RainMan.settingsStore.handleModalInvocation?.(UI_ITEMS.bet);
262
298
  });
263
299
  return;
264
300
  }
265
301
  RainMan.componentRegistry.get(BUTTONS.plus).setOnClick(() => {
266
- if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled)
302
+ if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled) {
267
303
  return;
304
+ }
268
305
  this.uiController.updateBet("increase");
306
+ RainMan.settingsStore.closeOtherModals?.("");
269
307
  });
270
308
  RainMan.componentRegistry.get(BUTTONS.neg).setOnClick(() => {
271
- if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled)
309
+ if (isFreeSpinsBought || isFreeSpinsPlayEnabled || betChangeDisabled) {
272
310
  return;
311
+ }
273
312
  this.uiController.updateBet("decrease");
313
+ RainMan.settingsStore.closeOtherModals?.("");
274
314
  });
275
315
  }
276
316
  /**
@@ -425,8 +465,9 @@ export class AbstractController {
425
465
  setMessageBoxBasedOnPhase(phase) {
426
466
  if (RainMan.settingsStore.isFreeSpinsPlayEnabled) {
427
467
  this.uiController.messageBox.showCurrentWinText();
428
- if (!this.hideFreeSpinsMessageBox)
468
+ if (!this.hideFreeSpinsMessageBox) {
429
469
  this.uiController.messageBox.showFreeSpinText();
470
+ }
430
471
  return;
431
472
  }
432
473
  switch (phase) {
@@ -443,13 +484,11 @@ export class AbstractController {
443
484
  }
444
485
  if (RainMan.settingsStore.isAutoplayEnabled) {
445
486
  const autoSpinText = RainMan.componentRegistry.get(MessageBox.autoSpinTextRegistryName);
446
- if (RainMan.settingsStore.infinitySpinsEnabled) {
447
- autoSpinText.setStringValue("∞");
487
+ autoSpinText.setStringValue(RainMan.settingsStore.infinitySpinsEnabled ? "∞" : RainMan.settingsStore.howManyAutoSpinsLeft.toString());
488
+ if (!RainMan.settingsStore.isFreeSpinsPlayEnabled) {
489
+ this.uiController.messageBox.showAutoSpinText();
448
490
  }
449
- else {
450
- autoSpinText.set(RainMan.settingsStore.howManyAutoSpinsLeft);
451
- }
452
- this.uiController.messageBox.showAutoSpinText();
491
+ return;
453
492
  }
454
493
  }
455
494
  /**
@@ -562,6 +601,7 @@ export class AbstractController {
562
601
  * @returns {void}
563
602
  */
564
603
  throttledSpin() {
604
+ this.columnsContainer.setInteractivityForSymbols(false);
565
605
  this.handleDisablingButtons(true);
566
606
  RainMan.globals.shouldShowModals = false;
567
607
  const elementsToSkipHide = [];
@@ -628,10 +668,12 @@ export class AbstractController {
628
668
  */
629
669
  autoplaySpin() {
630
670
  RainMan.globals.shouldShowModals = false;
671
+ const autoSpinText = RainMan.componentRegistry.get(MessageBox.autoSpinTextRegistryName);
672
+ autoSpinText.setStringValue(RainMan.settingsStore.infinitySpinsEnabled ? "∞" : RainMan.settingsStore.howManyAutoSpinsLeft.toString());
631
673
  if (!RainMan.settingsStore.howManyAutoSpinsLeft) {
632
674
  return;
633
675
  }
634
- if (!RainMan.settingsStore.infinitySpinsEnabled) {
676
+ if (!RainMan.settingsStore.infinitySpinsEnabled || !RainMan.settingsStore.isFreeSpinsPlayEnabled) {
635
677
  RainMan.settingsStore.decreaseAutoSpinsCount();
636
678
  }
637
679
  if (RainMan.settingsStore.howManyAutoSpinsLeft === 0) {
@@ -771,11 +813,16 @@ export class AbstractController {
771
813
  * @returns {void}
772
814
  */
773
815
  gambleGameEnabler(winAmount) {
774
- if (RainMan.componentRegistry.has(BUTTONS.gamble) && !RainMan.settingsStore.gambleGameUsed) {
816
+ if (RainMan.componentRegistry.has(BUTTONS.gamble) && RainMan.settingsStore.isGambleGameAvailable) {
775
817
  RainMan.componentRegistry
776
818
  .get(BUTTONS.gamble)
777
819
  .flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || winAmount === 0);
778
820
  }
821
+ if (RainMan.componentRegistry.has(BUTTONS.take) && RainMan.settingsStore.isTakeActionAvailable) {
822
+ RainMan.componentRegistry
823
+ .get(BUTTONS.take)
824
+ .flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || winAmount === 0);
825
+ }
779
826
  }
780
827
  /**
781
828
  * Function for spin logic of the game
@@ -792,6 +839,7 @@ export class AbstractController {
792
839
  * @returns {Promise<void>}
793
840
  */
794
841
  async spin() {
842
+ this.columnsContainer.setInteractivityForSymbols(false);
795
843
  RainMan.globals.shouldShowModals = false;
796
844
  if (this.uiController.currentBalance < RainMan.settingsStore.bet &&
797
845
  !RainMan.settingsStore.isFreeSpinsPlayEnabled) {
@@ -839,6 +887,7 @@ export class AbstractController {
839
887
  this.changeGamePhase(gamePhases.SPINNING);
840
888
  this.uiController.resetWinAmount();
841
889
  await this.onSpinningStart();
890
+ RainMan.settingsStore.disableSpecialButtons();
842
891
  this.columnsContainer.clearQuickReelsStop();
843
892
  this.columnsContainer.blindSpin();
844
893
  this.clearAndDestroyActions();
@@ -849,9 +898,17 @@ export class AbstractController {
849
898
  this.hideFreeSpinsMessageBox = availableFreeSpinsIncreased;
850
899
  if (this._lastWinAmount !== 0) {
851
900
  RainMan.settingsStore.isTakeActionAvailable = true;
901
+ RainMan.settingsStore.isGambleGameAvailable = true;
852
902
  }
853
903
  else {
854
904
  RainMan.settingsStore.isTakeActionAvailable = false;
905
+ RainMan.settingsStore.isGambleGameAvailable = false;
906
+ }
907
+ if (RainMan.settingsStore.howManyFreeSpinsLeft === 0 &&
908
+ availableFreeSpinsIncreased &&
909
+ !RainMan.settingsStore.isFreeSpinsPlayEnabled) {
910
+ RainMan.componentRegistry.setSpeedLevel(SPEED_LEVELS.slow);
911
+ this.disableSpeedButton(false);
855
912
  }
856
913
  if (!availableFreeSpinsIncreased) {
857
914
  this.uiController.updateShownFreeSpinAmount(availableFreeSpins);
@@ -898,6 +955,7 @@ export class AbstractController {
898
955
  logInfo("🔴 spinning end");
899
956
  logGroupEnd();
900
957
  await this.onSpinningEnd(spinLogic);
958
+ this.gambleGameEnabler(this.lastWinAmount);
901
959
  this.winActionsQueue = [];
902
960
  this.spinning = false;
903
961
  this.isSpinThrottled = false;
@@ -931,18 +989,27 @@ export class AbstractController {
931
989
  await this.handleFreeSpinSummaryPlateInvocation();
932
990
  }
933
991
  await this.performActionsAfterSpin();
934
- if (RainMan.settingsStore.isAutoplayEnabled) {
992
+ if (RainMan.settingsStore.isAutoplayEnabled ||
993
+ (RainMan.settingsStore.howManyFreeSpinsLeft !== 0 && this.shouldAutoplayFreeSpins)) {
935
994
  this.handleAutoplayLogic();
936
995
  }
937
996
  RainMan.settingsStore.setRoundNumber(this.roundNumber);
938
997
  this.handleDisablingButtons();
939
998
  if (RainMan.settingsStore.isFreeSpinsPlayEnabled) {
999
+ this.disableAutoplayButton(true);
1000
+ this.uiController.messageBox.hideAutoSpinText();
1001
+ }
1002
+ else {
940
1003
  this.disableAutoplayButton(false);
941
1004
  }
942
1005
  await this.performActionsAfterAllActions();
1006
+ if (RainMan.settingsStore.isTemporarySpeed) {
1007
+ RainMan.settingsStore.setIsTemporarySpeed(false);
1008
+ }
943
1009
  RainMan.settingsStore.setModalsAvailability(true);
944
1010
  RainMan.globals.shouldShowModals = true;
945
1011
  RainMan.settingsStore.setIsPlayingAnyAction(false);
1012
+ this.columnsContainer.setInteractivityForSymbols(true);
946
1013
  }
947
1014
  /**
948
1015
  * Function for invoking free spin plate, invoked in mainContainer
@@ -1032,10 +1099,9 @@ export class AbstractController {
1032
1099
  * @returns {void}
1033
1100
  */
1034
1101
  unlockLogicAfterSpinning() {
1035
- if (RainMan.settingsStore.isAutoplayEnabled) {
1102
+ if (RainMan.settingsStore.isAutoplayEnabled || RainMan.settingsStore.isFreeSpinsPlayEnabled) {
1036
1103
  return;
1037
1104
  }
1038
- this.columnsContainer.setInteractivityForSymbols(true);
1039
1105
  }
1040
1106
  /**
1041
1107
  * Function for stopping playing symbols streak
@@ -1300,7 +1366,9 @@ export class AbstractController {
1300
1366
  * @returns {Promise<void>}
1301
1367
  */
1302
1368
  async handleLoopingWinActionQueue() {
1303
- if (RainMan.settingsStore.isAutoplayEnabled || this.invokeFreeSpinPlateAfterWin) {
1369
+ if (RainMan.settingsStore.isAutoplayEnabled ||
1370
+ this.invokeFreeSpinPlateAfterWin ||
1371
+ RainMan.settingsStore.isFreeSpinsPlayEnabled) {
1304
1372
  return;
1305
1373
  }
1306
1374
  this.isLoopingWinActionsQueue = true;
@@ -28,7 +28,7 @@ export declare class SettingsStore {
28
28
  roundNumber: number;
29
29
  HiResolutionFlag: boolean;
30
30
  batterySaverFlag: boolean;
31
- gambleGameUsed: boolean;
31
+ isGambleGameAvailable: boolean;
32
32
  isGambleGameActive: boolean;
33
33
  gambleGameWin: number;
34
34
  containersWithSpines: (ResumableContainer | SpineWithResumableContainer | SpriteWithResumableContainer)[];
@@ -45,10 +45,12 @@ export declare class SettingsStore {
45
45
  popupPaytableData?: PaytableData[];
46
46
  currentSpeed: SpeedLevel;
47
47
  isPlayingAnyAction: boolean;
48
+ isTemporarySpeed: boolean;
48
49
  setSpeedPopupVisibility?: (visibility: "flex" | "none") => void;
49
50
  popupPaytableRepositionCallback?: () => void;
50
51
  updateVolumeButtonTexture?: () => void;
51
52
  handleModalInvocation?: (layerId: string) => void;
53
+ closeOtherModals?: (layerId: string) => void;
52
54
  handleInvokeFreeSpinPlate?: (freeSpinAmount: number, isAdditionalFreeSpin: boolean) => Promise<void>;
53
55
  increaseBet?: () => void;
54
56
  decreaseBet?: () => void;
@@ -84,6 +86,12 @@ export declare class SettingsStore {
84
86
  * @returns {void}
85
87
  */
86
88
  addCumulativeWinAmount(amount: number): void;
89
+ /**
90
+ * Disables special buttons like gamble and take.
91
+ * @public
92
+ * @returns {void}
93
+ */
94
+ disableSpecialButtons(): void;
87
95
  /**
88
96
  * Swaps the bet change disabled flag.
89
97
  * @public
@@ -174,6 +182,13 @@ export declare class SettingsStore {
174
182
  * @returns {void}
175
183
  */
176
184
  setHiResolutionFlag(flag: boolean): void;
185
+ /**
186
+ * Sets the temporary speed flag.
187
+ * @public
188
+ * @param {boolean} flag - New value temporary speed flag.
189
+ * @returns {void}
190
+ */
191
+ setIsTemporarySpeed(flag: boolean): void;
177
192
  /**
178
193
  * Sets the speed level.
179
194
  * @public
@@ -1,6 +1,7 @@
1
1
  import { first, last, range } from "lodash";
2
2
  import { action, computed, makeAutoObservable } from "mobx";
3
3
  import { SoundManager, SoundTracks } from "../application";
4
+ import { BUTTONS } from "../components";
4
5
  import { PaytableTypes } from "../constants";
5
6
  import { getFromLocalStorage, LOCAL_STORAGE, removeFromLocalStorage, setToLocalStorage } from "../localStorage";
6
7
  import { RainMan } from "../Rainman";
@@ -31,7 +32,7 @@ export class SettingsStore {
31
32
  roundNumber = 0;
32
33
  HiResolutionFlag = getFromLocalStorage(LOCAL_STORAGE.hiResolution, true);
33
34
  batterySaverFlag = getFromLocalStorage(LOCAL_STORAGE.batterySaver, false);
34
- gambleGameUsed = false;
35
+ isGambleGameAvailable = true;
35
36
  isGambleGameActive = false;
36
37
  gambleGameWin = 0;
37
38
  containersWithSpines = [];
@@ -43,15 +44,17 @@ export class SettingsStore {
43
44
  howManyFreeSpinsLeft = 0;
44
45
  howManyAutoSpinsLeft = INITIAL_AUTO_SPIN_COUNT;
45
46
  freeSpinBuyTable = {};
46
- volumeLevel = getFromLocalStorage(LOCAL_STORAGE.volumeLevel, 100);
47
+ volumeLevel = Number(getFromLocalStorage(LOCAL_STORAGE.volumeLevel, 100));
47
48
  popupPaytablePosition;
48
49
  popupPaytableData;
49
50
  currentSpeed = "slow";
50
51
  isPlayingAnyAction = false;
52
+ isTemporarySpeed = false;
51
53
  setSpeedPopupVisibility;
52
54
  popupPaytableRepositionCallback;
53
55
  updateVolumeButtonTexture;
54
56
  handleModalInvocation;
57
+ closeOtherModals;
55
58
  handleInvokeFreeSpinPlate;
56
59
  increaseBet;
57
60
  decreaseBet;
@@ -142,6 +145,21 @@ export class SettingsStore {
142
145
  addCumulativeWinAmount(amount) {
143
146
  this.cumulativeWinAmount = this.cumulativeWinAmount + amount;
144
147
  }
148
+ /**
149
+ * Disables special buttons like gamble and take.
150
+ * @public
151
+ * @returns {void}
152
+ */
153
+ disableSpecialButtons() {
154
+ if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
155
+ RainMan.settingsStore.isGambleGameAvailable = false;
156
+ RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(true);
157
+ }
158
+ if (RainMan.componentRegistry.has(BUTTONS.take)) {
159
+ RainMan.settingsStore.isTakeActionAvailable = false;
160
+ RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(true);
161
+ }
162
+ }
145
163
  /**
146
164
  * Swaps the bet change disabled flag.
147
165
  * @public
@@ -235,8 +253,9 @@ export class SettingsStore {
235
253
  */
236
254
  setShouldPlayFxSounds(flag, saveToLocalStorage = true) {
237
255
  this.shouldPlayFxSounds = flag;
238
- if (!flag)
256
+ if (!flag) {
239
257
  SoundManager.stopPlayingFxSounds();
258
+ }
240
259
  this.updateVolumeButtonTexture?.();
241
260
  if (saveToLocalStorage) {
242
261
  setToLocalStorage(LOCAL_STORAGE.isSoundFxEnabled, flag);
@@ -274,7 +293,7 @@ export class SettingsStore {
274
293
  * @returns {boolean} True if sound is enabled, false otherwise.
275
294
  */
276
295
  isSoundEnabled() {
277
- return this.shouldPlayFxSounds || this.shouldPlayAmbientMusic;
296
+ return this.shouldPlayAmbientMusic || this.shouldPlayFxSounds;
278
297
  }
279
298
  /**
280
299
  * Sets the full screen flag and enlarges the game container.
@@ -305,6 +324,15 @@ export class SettingsStore {
305
324
  changeResolution(flag);
306
325
  window.dispatchEvent(new Event("resize"));
307
326
  }
327
+ /**
328
+ * Sets the temporary speed flag.
329
+ * @public
330
+ * @param {boolean} flag - New value temporary speed flag.
331
+ * @returns {void}
332
+ */
333
+ setIsTemporarySpeed(flag) {
334
+ this.isTemporarySpeed = flag;
335
+ }
308
336
  /**
309
337
  * Sets the speed level.
310
338
  * @public
@@ -479,6 +507,9 @@ export class SettingsStore {
479
507
  * @returns {void}
480
508
  */
481
509
  decreaseAutoSpinsCount() {
510
+ if (this.infinitySpinsEnabled || this.isFreeSpinsPlayEnabled) {
511
+ return;
512
+ }
482
513
  this.howManyAutoSpinsLeft -= 1;
483
514
  }
484
515
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixi-rainman-game-engine",
3
- "version": "0.3.1",
3
+ "version": "0.3.3b",
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",