pixi-rainman-game-engine 0.3.16 → 0.3.18

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.
@@ -28,8 +28,12 @@
28
28
  .autoplay-settings__title h2 {
29
29
  color: #ec5e27;
30
30
  margin: 0px;
31
- text-decoration: underline;
32
31
  text-transform: uppercase;
32
+ font-weight: bold;
33
+ font-size: 32px;
34
+ @media only screen and (max-width: 600px) {
35
+ font-size: 24px;
36
+ }
33
37
  }
34
38
 
35
39
  .autoplay-settings__sliders {
@@ -71,7 +75,7 @@
71
75
  justify-content: center;
72
76
  width: 40px;
73
77
  border: solid 2px white;
74
- font-size: 20px;
78
+ font-size: 24px;
75
79
  font-weight: bolder;
76
80
  margin: 0px 5px;
77
81
  color: white;
@@ -125,12 +129,16 @@
125
129
 
126
130
  .autoplay-settings__limit.left p {
127
131
  position: relative;
128
- top: -2px;
132
+ font-size: 24px;
133
+ top: -3px;
134
+ right: -1px;
129
135
  }
130
136
 
131
137
  .autoplay-settings__limit.right p {
132
138
  position: relative;
133
- top: -2px;
139
+ font-size: 24px;
140
+ top: -3px;
141
+ left: -1px;
134
142
  }
135
143
 
136
144
  .autoplay-settings__confirmation {
@@ -256,3 +264,9 @@
256
264
  top: 10px;
257
265
  }
258
266
  }
267
+
268
+ .separator {
269
+ width: 100%;
270
+ height: 1px;
271
+ background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.7), transparent);
272
+ }
@@ -84,6 +84,7 @@ export const AutoplaySettings = observer(() => {
84
84
  <p>∞</p>
85
85
  </button>
86
86
  </div>
87
+ <div className="separator"/>
87
88
  <div className="autoplay-settings__title">
88
89
  <h2>{i18next.t("stopAutoPlay")}</h2>
89
90
  </div>
@@ -92,7 +93,7 @@ export const AutoplaySettings = observer(() => {
92
93
  <RichLimitingSlider value={balancedIncreased} setValue={setBalancedIncreased} maxValue={Number(i18next.t("ifBalanceIncreasesBy"))} description={i18next.t("ifBalanceIncreasesByDescription")}/>
93
94
  <RichLimitingSlider value={balancedDecreased} setValue={setBalancedDecreased} maxValue={Number(i18next.t("ifSingleWinExceedsMax"))} description={i18next.t("ifBalanceDecreaseByDescription")}/>
94
95
  </div>
95
-
96
+ <div className="separator"/>
96
97
  <div className="autoplay-settings__switches">
97
98
  <div className="autoplay-settings__switch">
98
99
  <SwitchWithHeader header={i18next.t("onAnyWin")} flag={settingStore.onAnyWin} setFlag={settingStore.setOnAnyWin}/>
@@ -11,6 +11,7 @@ export const CloseModalButton = observer(({ layerId, afterClose }) => {
11
11
  settingStore.handleModalInvocation?.(layerId);
12
12
  if (layerId === UI_ITEMS.speedSettings) {
13
13
  settingStore.setSpeedPopupVisibility?.("none");
14
+ settingStore.isSpeedModalShown = false;
14
15
  }
15
16
  if (isBetDisabled) {
16
17
  settingStore.enableButtons?.();
@@ -1,26 +1,88 @@
1
1
  import "rc-slider/assets/index.css";
2
2
  import "./richLimitingSlider.css";
3
3
  import { observer } from "mobx-react-lite";
4
- import Slider from "rc-slider";
5
- import React from "react";
4
+ import React, { useEffect, useRef, useState } from "react";
5
+ const clamp = (v, maxValue) => {
6
+ const clamped = Math.min(Math.max(v, 0), maxValue);
7
+ const rounded = Math.round(clamped * 10) / 10;
8
+ return Math.min(rounded, maxValue);
9
+ };
6
10
  export const RichLimitingSlider = observer(({ value, setValue, maxValue, description }) => {
11
+ const valueRef = useRef(value);
12
+ const [rawValue, setRawValue] = useState(String(value));
13
+ useEffect(() => {
14
+ valueRef.current = value;
15
+ setRawValue(String(value));
16
+ console.log("🚀 $$ ~ value:", value);
17
+ }, [value]);
18
+ const holdInterval = useRef(null);
19
+ const isHeldRef = useRef(false);
20
+ const increment = () => {
21
+ setValue(clamp(valueRef.current + 0.2, maxValue));
22
+ };
23
+ const decrement = () => {
24
+ setValue(clamp(valueRef.current - 0.2, maxValue));
25
+ };
26
+ const stopHold = () => {
27
+ isHeldRef.current = false;
28
+ if (holdInterval.current) {
29
+ clearInterval(holdInterval.current);
30
+ holdInterval.current = null;
31
+ }
32
+ window.removeEventListener("mouseup", stopHold);
33
+ window.removeEventListener("touchend", stopHold);
34
+ window.removeEventListener("pointerup", stopHold);
35
+ window.removeEventListener("touchcancel", stopHold);
36
+ };
37
+ const startHold = (action) => {
38
+ isHeldRef.current = true;
39
+ if (holdInterval.current) {
40
+ clearInterval(holdInterval.current);
41
+ holdInterval.current = null;
42
+ }
43
+ holdInterval.current = setTimeout(() => {
44
+ if (isHeldRef.current) {
45
+ holdInterval.current = setInterval(action, 100);
46
+ }
47
+ }, 500);
48
+ window.addEventListener("mouseup", stopHold);
49
+ window.addEventListener("touchend", stopHold, { passive: true });
50
+ window.addEventListener("pointerup", stopHold);
51
+ window.addEventListener("touchcancel", stopHold);
52
+ };
53
+ const onChange = (e) => {
54
+ const v = e.target.value;
55
+ const parsed = Number(v);
56
+ setRawValue(String(clamp(parsed, maxValue)));
57
+ if (v === "")
58
+ return;
59
+ if (!isNaN(parsed)) {
60
+ setValue(clamp(parsed, maxValue));
61
+ }
62
+ };
63
+ useEffect(() => {
64
+ return () => {
65
+ stopHold();
66
+ };
67
+ }, []);
7
68
  return (<div className="rich-slider">
8
- {/* @ts-expect-error type error in library */}
9
- <Slider className="rich-slider__slider" step={1} min={0} max={maxValue} defaultValue={value} value={value} handleStyle={{
10
- backgroundColor: "#fdf425",
11
- borderColor: "#fdf425",
12
- width: "20px",
13
- height: "20px",
14
- bottom: "-4px",
15
- }} railStyle={{
16
- backgroundColor: "#fff",
17
- }} trackStyle={{
18
- backgroundColor: "#fdf425",
19
- }} dotStyle={{
20
- borderColor: "#fdf425",
21
- }} onChange={(value) => setValue(value)}>
22
- <p className="rich-slider__description">{description}</p>
23
- </Slider>
24
- <div className="rich-slider__number">{value}</div>
69
+ <p className="rich-slider__description">{description}</p>
70
+ <div className="rich-slider_button">
71
+ <button onClick={decrement} className="rich-slider_button-left" onMouseDown={() => startHold(decrement)} onMouseUp={stopHold} onMouseLeave={stopHold} onTouchStart={(e) => {
72
+ e.preventDefault();
73
+ startHold(decrement);
74
+ }} onTouchEnd={stopHold} onPointerDown={() => startHold(decrement)} onPointerUp={stopHold}>
75
+ -
76
+ </button>
77
+
78
+ <input className="rich-slider_input" type="number" style={{}} value={rawValue} onClick={() => setRawValue("0")} onChange={onChange}/>
79
+
80
+ <button onClick={increment} className="rich-slider_button-right" onMouseDown={() => startHold(increment)} onMouseUp={stopHold} onMouseLeave={stopHold} onTouchStart={(e) => {
81
+ e.preventDefault();
82
+ startHold(increment);
83
+ }} onTouchEnd={stopHold} onPointerDown={() => startHold(increment)} onPointerUp={stopHold}>
84
+ +
85
+ </button>
86
+ </div>
25
87
  </div>);
26
88
  });
@@ -3,6 +3,7 @@
3
3
  flex-direction: row;
4
4
  align-items: center;
5
5
  padding-inline: 16px;
6
+ justify-content: space-between;
6
7
  }
7
8
 
8
9
  .rich-slider__slider {
@@ -12,9 +13,23 @@
12
13
  align-items: center;
13
14
  }
14
15
 
15
- .rich-slider__number {
16
+ .rich-slider__description {
17
+ text-transform: uppercase;
18
+ @media only screen and (max-width: 650px) {
19
+ width: 50%;
20
+ }
21
+ }
22
+
23
+ @media only screen and (max-width: 650px) {
24
+ .rich-slider__description {
25
+ padding-top: 4px;
26
+ font-size: 9px;
27
+ }
28
+ }
29
+
30
+ .rich-slider_button {
16
31
  margin: 10px 0px 10px 10px;
17
- width: 100px;
32
+ width: 250px;
18
33
  height: 40px;
19
34
  border: solid white 2px;
20
35
  background-color: black;
@@ -25,15 +40,67 @@
25
40
  display: flex;
26
41
  justify-content: center;
27
42
  align-items: center;
43
+ position: relative;
44
+ overflow: hidden;
45
+ @media only screen and (max-width: 650px) {
46
+ width: 50%;
47
+ height: 30px;
48
+ }
28
49
  }
29
50
 
30
- .rich-slider__description {
31
- text-transform: uppercase;
51
+ .rich-slider_button-left,
52
+ .rich-slider_button-right {
53
+ width: 40px;
54
+ border: none;
55
+ color: white;
56
+ display: flex;
57
+ transition: all 0.3s ease;
58
+ justify-content: center;
59
+ padding-bottom: 6px;
60
+ background-color: transparent;
61
+ height: 100%;
62
+ display: flex;
63
+ align-items: center;
64
+ cursor: pointer;
65
+ font-size: 24px;
66
+ }
67
+ .rich-slider_button-left {
68
+ border-right: solid white 2px;
69
+ }
70
+ .rich-slider_button-right {
71
+ border-left: solid white 2px;
32
72
  }
33
73
 
34
- @media only screen and (max-width: 650px) {
35
- .rich-slider__description {
36
- padding-top: 4px;
37
- font-size: 9px;
74
+ .rich-slider_button-left:hover,
75
+ .rich-slider_button-right:hover {
76
+ background-color: #fdf42525;
77
+ color: #fdf425;
78
+ }
79
+
80
+ .rich-slider_input {
81
+ background-color: transparent;
82
+ border: none;
83
+ color: white;
84
+ width: 100%;
85
+ height: 100%;
86
+ text-align: center;
87
+ font-size: 20px;
88
+ @media only screen and (max-width: 650px) {
89
+ font-size: 14px;
38
90
  }
39
91
  }
92
+
93
+ .rich-slider_input:focus-visible {
94
+ outline: none;
95
+ }
96
+
97
+ input[type="number"]::-webkit-inner-spin-button,
98
+ input[type="number"]::-webkit-outer-spin-button {
99
+ -webkit-appearance: none;
100
+ margin: 0;
101
+ }
102
+
103
+ input[type="number"] {
104
+ -moz-appearance: textfield;
105
+ appearance: textfield;
106
+ }
@@ -55,7 +55,7 @@
55
55
  flex-direction: row;
56
56
  width: 36px;
57
57
  justify-content: space-between;
58
- bottom: 10px;
58
+ bottom: 12px;
59
59
  left: 36px;
60
60
  }
61
61
 
@@ -89,7 +89,7 @@
89
89
  .switch__text {
90
90
  margin: 0;
91
91
  position: absolute;
92
- top: 7px;
92
+ top: 5px;
93
93
  right: 9px;
94
94
  }
95
95
 
@@ -5,14 +5,25 @@
5
5
  left: 25vw;
6
6
  align-items: center;
7
7
  justify-content: center;
8
+ z-index: 0;
9
+ }
10
+
11
+ .modal-overlay {
12
+ position: fixed;
13
+ inset: 0;
14
+ background: rgba(0, 0, 0, 0.6);
15
+ backdrop-filter: blur(2px);
16
+ display: flex;
17
+ align-items: center;
18
+ justify-content: center;
19
+ z-index: 0;
8
20
  }
9
21
 
10
22
  .speed-settings-popup {
11
23
  display: flex;
12
24
  flex-direction: column;
25
+ gap: 20px;
13
26
  align-items: center;
14
- width: 90%;
15
- height: 90%;
16
27
  justify-content: space-between;
17
28
  }
18
29
 
@@ -27,6 +38,7 @@
27
38
  display: flex;
28
39
  flex-direction: row;
29
40
  justify-content: space-between;
41
+ gap: 25px;
30
42
  width: 100%;
31
43
  height: 120px;
32
44
  }
@@ -8,6 +8,12 @@
8
8
  text-transform: uppercase;
9
9
  }
10
10
 
11
+ @media only screen and (max-width: 650px) {
12
+ .header-description__title {
13
+ font-size: 14px !important;
14
+ }
15
+ }
16
+
11
17
  .header-description__text {
12
18
  max-width: 170px;
13
19
  margin: 0px;
@@ -18,10 +24,6 @@
18
24
  max-width: 150px;
19
25
  }
20
26
 
21
- .header-description h2 {
22
- font-size: 20px;
23
- }
24
-
25
27
  .header-description h6 {
26
28
  font-size: 10px;
27
29
  }
@@ -1,7 +1,7 @@
1
1
  import "./index.css";
2
2
  import React from "react";
3
3
  import { UI_ITEMS } from "../utils";
4
- import { AutoplaySettings, BetSettings, BuyFreeSpinModal, GameRules, SpeedSettingsPopup, SymbolMultiplierPopup, VolumeSettings, } from "./components";
4
+ import { AutoplaySettings, BetSettings, BuyFreeSpinModal, GameRules, SpeedSettingsPopup, SymbolMultiplierPopup, VolumeSettings } from "./components";
5
5
  import { SystemSettingsComponent } from "./SystemSettings/SystemSettingsComponent";
6
6
  export const SettingsUI = () => {
7
7
  return (<>
@@ -17,8 +17,10 @@ export const SettingsUI = () => {
17
17
  <div id={UI_ITEMS.autoplay} className="modal modal-style">
18
18
  <AutoplaySettings />
19
19
  </div>
20
- <div id={UI_ITEMS.speedSettings} className="speed-settings-modal modal-style">
21
- <SpeedSettingsPopup />
20
+ <div id={UI_ITEMS.speedSettings} className=" modal-overlay">
21
+ <div className="speed-settings-modal modal-style">
22
+ <SpeedSettingsPopup />
23
+ </div>
22
24
  </div>
23
25
  <div id={UI_ITEMS.symbolPayTable}>
24
26
  <SymbolMultiplierPopup />
@@ -1,7 +1,7 @@
1
1
  import i18n from "i18next";
2
2
  import { sample } from "lodash";
3
3
  import { SoundManager, SoundTracks } from "../../application";
4
- import { AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, MessageBox, SpeedControlButton, VolumeButton } from "../../components";
4
+ import { AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, MessageBox, VolumeButton } from "../../components";
5
5
  import { RainMan } from "../../Rainman";
6
6
  import { allUiItems, hideLayerIfPresent, UI_ITEMS, wait } from "../../utils";
7
7
  import { SPEED_LEVELS } from "../SpeedState";
@@ -47,12 +47,7 @@ export class ButtonsEventManager {
47
47
  * @returns {() => void} function for enabling/disabling buttons
48
48
  */
49
49
  setButtonAvailability = (makeDisabled) => () => {
50
- const isDisabled = RainMan.settingsStore.isFreeSpinsPlayEnabled ||
51
- RainMan.settingsStore.isFreeSpinsBought ||
52
- RainMan.settingsStore.betChangeDisabled;
53
- const buttonsToDisable = isDisabled
54
- ? [SpeedControlButton.registryName]
55
- : [SpeedControlButton.registryName, BUTTONS.neg, BUTTONS.plus];
50
+ const buttonsToDisable = [BUTTONS.neg, BUTTONS.plus];
56
51
  buttonsToDisable.forEach((buttonRegistryName) => RainMan.componentRegistry.get(buttonRegistryName).flipDisabledFlag(makeDisabled));
57
52
  RainMan.componentRegistry.get(VolumeButton.registryName).changeTextureDependOnVolume();
58
53
  };
@@ -110,6 +105,8 @@ export class ButtonsEventManager {
110
105
  this.settingsSpeedTurtle.addEventListener("click", () => {
111
106
  RainMan.componentRegistry.setSpeedLevel(SPEED_LEVELS.slow);
112
107
  this.setSpeedPopupVisibility("none");
108
+ this.enableButtons();
109
+ RainMan.settingsStore.isSpeedModalShown = false;
113
110
  messageBox.updateIncentiveText(i18n.t("turtleSelected"));
114
111
  });
115
112
  }
@@ -120,6 +117,8 @@ export class ButtonsEventManager {
120
117
  this.settingsSpeedRabbit.addEventListener("click", () => {
121
118
  RainMan.componentRegistry.setSpeedLevel(SPEED_LEVELS.normal);
122
119
  this.setSpeedPopupVisibility("none");
120
+ RainMan.settingsStore.isSpeedModalShown = false;
121
+ this.enableButtons();
123
122
  messageBox.updateIncentiveText(i18n.t("rabbitSelected"));
124
123
  RainMan.globals.disableSpeedPopup?.(true);
125
124
  });
@@ -131,6 +130,8 @@ export class ButtonsEventManager {
131
130
  this.settingsSpeedCheetah.addEventListener("click", () => {
132
131
  RainMan.componentRegistry.setSpeedLevel(SPEED_LEVELS.fast);
133
132
  this.setSpeedPopupVisibility("none");
133
+ this.enableButtons();
134
+ RainMan.settingsStore.isSpeedModalShown = false;
134
135
  messageBox.updateIncentiveText(i18n.t("cheetahSelected"));
135
136
  RainMan.globals.disableSpeedPopup?.(true);
136
137
  });
@@ -270,6 +271,7 @@ export class ButtonsEventManager {
270
271
  RainMan.settingsStore.resetAutoplaySettings();
271
272
  RainMan.componentRegistry.get(MessageBox.registryName).hideAutoSpinText();
272
273
  RainMan.componentRegistry.get(AutoplayButton.registryName).activate(false);
274
+ RainMan.settingsStore.changeBetChangeDisabled(false);
273
275
  if (!RainMan.settingsStore.isPlayingAnyAction) {
274
276
  RainMan.componentRegistry.get(BUTTONS.neg).flipDisabledFlag(false);
275
277
  RainMan.componentRegistry.get(BUTTONS.plus).flipDisabledFlag(false);
@@ -478,6 +478,7 @@ export class AbstractMainContainer extends Container {
478
478
  if (this.bonusWinContainer === null) {
479
479
  return;
480
480
  }
481
+ RainMan.settingsStore.disableKeyboardShortcuts = false;
481
482
  this.removeChild(this.bonusWinContainer);
482
483
  this.bonusWinContainer.destroyAnimations();
483
484
  this.bonusWinContainer.destroy({ children: true });
@@ -19,7 +19,7 @@ export declare class AnimatedNumber extends Container {
19
19
  * @private
20
20
  * @returns {void}
21
21
  */
22
- private setDigits;
22
+ setDigits(): void;
23
23
  /**
24
24
  * Function for setting move animation for digits.
25
25
  * @public
@@ -36,11 +36,11 @@
36
36
  },
37
37
  "credit": "CREDIT: ",
38
38
  "bet": "BET: ",
39
- "ifBalanceIncreasesBy": "1000",
39
+ "ifBalanceIncreasesBy": "50000",
40
40
  "ifBalanceIncreasesByDescription": "If balance increases by",
41
- "ifSingleWinExceedsMax": "10000",
42
- "ifSingleWinExceedsMaxDescription": "If balance increases by",
43
- "ifBalanceDecreasedBy": "1000",
41
+ "ifSingleWinExceedsMax": "50000",
42
+ "ifSingleWinExceedsMaxDescription": "If single win exceeds",
43
+ "ifBalanceDecreasedBy": "50000",
44
44
  "ifBalanceDecreaseByDescription": "If balance decreases by",
45
45
  "speedButtonHeader": "Quick spin",
46
46
  "speedButtonDescription": "Play faster by reducing total spin time",
@@ -22,7 +22,7 @@ export declare abstract class AbstractSymbolsColumn extends Container implements
22
22
  private velocity;
23
23
  protected velocityMultiplier: number;
24
24
  private previousVelocityMultiplier;
25
- private spritesCount;
25
+ protected spritesCount: number;
26
26
  protected phase: Phase;
27
27
  private ending;
28
28
  private lastEnding;
@@ -258,7 +258,7 @@ export declare abstract class AbstractSymbolsColumn extends Container implements
258
258
  * @private
259
259
  * @returns {void}
260
260
  */
261
- private initSymbolSprites;
261
+ protected initSymbolSprites(): void;
262
262
  /**
263
263
  * This method ensures that top tile is in right place (it might not be due to some FPS issue)
264
264
  * @private
@@ -26,11 +26,6 @@ export class ConnectionWrapper {
26
26
  */
27
27
  handleMessage = (messageData) => {
28
28
  this.lastFetchResponse.set(messageData.action, messageData);
29
- if (messageData.status) {
30
- if (messageData.status.code >= 300) {
31
- throw new Error(`${messageData.status.code}: ${messageData.status.message}`);
32
- }
33
- }
34
29
  switch (messageData.action) {
35
30
  case "init":
36
31
  this.config = new ApiConfig(messageData);
@@ -105,6 +100,9 @@ export class ConnectionWrapper {
105
100
  RainMan.globals.currency = Currencies[this._initData.currency];
106
101
  RainMan.settingsStore.setFreeSpinsPriceTable(this._initData.free_spins_buy_table);
107
102
  RainMan.settingsStore.setRoundNumber(this._initData.round_number);
103
+ if (this._initData.status?.code && this._initData.status.code >= 400) {
104
+ throw new Error(`Init failed with status code: ${this._initData.status?.code}: ${this._initData.status?.message}`);
105
+ }
108
106
  }
109
107
  /**
110
108
  * Method for getting initial data from the server
@@ -12,7 +12,7 @@ export class SpinData {
12
12
  this.config = config;
13
13
  this.balance = data.balance;
14
14
  this.balanceAfterSpin = data.future_balance_prediction;
15
- if (data.action !== "spin" && data.action !== "buy") {
15
+ if (data.action !== "spin" && data.action !== "buy" && data.action !== "mini-game") {
16
16
  throw new Error(`Invalid type "${data.action}" provided, "spin" or "buy" expected`);
17
17
  }
18
18
  }
@@ -104,6 +104,7 @@ export class AbstractController {
104
104
  this.uiController.currentBalance = initData.balance;
105
105
  if (RainMan.config.reinitMode) {
106
106
  this.initControllerReinit();
107
+ RainMan.settingsStore.disableSpecialButtons();
107
108
  }
108
109
  this.reinitializeAllButtons();
109
110
  this.buttonsEventManager.initSettingsEvents();
@@ -117,6 +118,7 @@ export class AbstractController {
117
118
  RainMan.componentRegistry.get(AutoplayButton.registryName).activate(true);
118
119
  RainMan.componentRegistry.get(BUTTONS.plus).flipDisabledFlag(true);
119
120
  RainMan.componentRegistry.get(BUTTONS.neg).flipDisabledFlag(true);
121
+ RainMan.settingsStore.changeBetChangeDisabled(true);
120
122
  this.throttledSpin();
121
123
  });
122
124
  SoundManager.setPlayStatus(SoundTracks.music, RainMan.settingsStore.shouldPlayAmbientMusic);
@@ -160,7 +162,10 @@ export class AbstractController {
160
162
  window.addEventListener("keydown", (keyboardEvent) => {
161
163
  if (keyboardEvent.code === "Space" || keyboardEvent.code === "Enter") {
162
164
  keyboardEvent.preventDefault();
163
- if (RainMan.settingsStore.isGambleGameActive) {
165
+ if (RainMan.settingsStore.isGambleGameActive || RainMan.settingsStore.isSpeedModalShown) {
166
+ return;
167
+ }
168
+ if (RainMan.settingsStore.disableKeyboardShortcuts) {
164
169
  return;
165
170
  }
166
171
  this.handleDisablingButtons(true);
@@ -253,7 +258,9 @@ export class AbstractController {
253
258
  */
254
259
  handleDisablingButtons(disabled) {
255
260
  this.disableBetButtons(disabled ?? this.shouldBetButtonsBeDisabled);
256
- if (RainMan.settingsStore.isFreeSpinsPlayEnabled || RainMan.globals.isSuperBonusGameEnabled) {
261
+ if (RainMan.settingsStore.isFreeSpinsPlayEnabled ||
262
+ RainMan.globals.isSuperBonusGameEnabled ||
263
+ RainMan.settingsStore.isAutoplayEnabled) {
257
264
  this.disableSpeedButton(false);
258
265
  }
259
266
  else {
@@ -376,6 +383,12 @@ export class AbstractController {
376
383
  }
377
384
  RainMan.settingsStore.setTotalNumberOfFreeSpins(availableFreeSpins);
378
385
  RainMan.settingsStore.setNumberOfFreeSpin(availableFreeSpins);
386
+ if (RainMan.settingsStore.isFreeSpinsPlayEnabled) {
387
+ const freeSpinsUsed = this.initData?.free_spins_used ?? 0;
388
+ const freeSpinsAvailable = RainMan.settingsStore.reinitData?.[0]?.available_free_spins ?? 0;
389
+ this.uiController.totalNumberOfFreeSpins = freeSpinsUsed + freeSpinsAvailable;
390
+ RainMan.componentRegistry.get(MessageBox.currentWinTextRegistryName).update(this.initData.round_win_amount);
391
+ }
379
392
  this.initControllerReinitModifier(spinLogic, spinData);
380
393
  }
381
394
  initControllerReinitModifier(_spinLogic, _spinData) { }
@@ -825,8 +838,10 @@ export class AbstractController {
825
838
  * @returns {void}
826
839
  */
827
840
  disableAutoplay() {
841
+ this.autoSpinBalance = 0;
828
842
  RainMan.componentRegistry.get(MessageBox.registryName).hideAutoSpinText();
829
843
  RainMan.componentRegistry.get(AutoplayButton.registryName).activate(false);
844
+ RainMan.settingsStore.changeBetChangeDisabled(false);
830
845
  RainMan.componentRegistry.get(BUTTONS.plus).flipDisabledFlag(false);
831
846
  RainMan.componentRegistry.get(BUTTONS.neg).flipDisabledFlag(false);
832
847
  RainMan.settingsStore.resetAutoplaySettings();
@@ -1059,6 +1074,8 @@ export class AbstractController {
1059
1074
  if (RainMan.settingsStore.howManyFreeSpinsLeft !== 0 &&
1060
1075
  (this.invokeFreeSpinPlateAfterWin || this.setSlowerSpeedForFreeSpins) &&
1061
1076
  RainMan.settingsStore.isFreeSpinsPlayEnabled) {
1077
+ this.columnsContainer.clearQuickReelsStop();
1078
+ RainMan.settingsStore.setIsTemporarySpeed(false);
1062
1079
  RainMan.componentRegistry.setSpeedLevel(SPEED_LEVELS.slow);
1063
1080
  this.uiController.updateShownSpeedLevel(SPEED_LEVELS.slow);
1064
1081
  this.disableSpeedButton(false);
@@ -1194,26 +1211,29 @@ export class AbstractController {
1194
1211
  */
1195
1212
  handleAutoplayLogic() {
1196
1213
  RainMan.globals.shouldShowModals = false;
1197
- this.autoSpinBalance += this.uiController.recentWin;
1214
+ RainMan.settingsStore.changeBetChangeDisabled(true);
1215
+ if (this.uiController.recentWin === 0) {
1216
+ this.autoSpinBalance -= RainMan.settingsStore.bet;
1217
+ }
1218
+ else {
1219
+ this.autoSpinBalance += this.uiController.recentWin;
1220
+ }
1198
1221
  const { balancedIncreased, balancedDecreased, singleWinExceeds } = RainMan.settingsStore;
1199
1222
  if (balancedIncreased > 0) {
1200
1223
  if (this.autoSpinBalance >= balancedIncreased) {
1201
1224
  this.disableAutoplay();
1202
- this.autoSpinBalance = 0;
1203
1225
  return;
1204
1226
  }
1205
1227
  }
1206
1228
  if (balancedDecreased > 0) {
1207
1229
  if (this.autoSpinBalance <= -balancedDecreased) {
1208
1230
  this.disableAutoplay();
1209
- this.autoSpinBalance = 0;
1210
1231
  return;
1211
1232
  }
1212
1233
  }
1213
1234
  if (singleWinExceeds > 0) {
1214
1235
  if (this.uiController.recentWin >= singleWinExceeds) {
1215
1236
  this.disableAutoplay();
1216
- this.autoSpinBalance = 0;
1217
1237
  return;
1218
1238
  }
1219
1239
  }
@@ -44,8 +44,10 @@ export class QuickStopController {
44
44
  * @returns {void}
45
45
  */
46
46
  handleSpeedPopupInvocation() {
47
- if (this.shouldInvokeSpeedPopup && !this.speedPopupDisabled) {
47
+ if (this.shouldInvokeSpeedPopup && !this.speedPopupDisabled && !RainMan.settingsStore.isFreeSpinsPlayEnabled) {
48
48
  this.buttonsEventManager?.setSpeedPopupVisibility("flex");
49
+ RainMan.settingsStore.isSpeedModalShown = true;
50
+ this.buttonsEventManager.disableButtons();
49
51
  this.shouldInvokeSpeedPopup = false;
50
52
  this.speedPopupDisabled = true;
51
53
  }
@@ -11,6 +11,7 @@ import { PaytableData } from "./types";
11
11
  export declare class SettingsStore {
12
12
  static instance: SettingsStore | null;
13
13
  betChangeDisabled: boolean;
14
+ disableKeyboardShortcuts: boolean;
14
15
  bet: number;
15
16
  betText: string;
16
17
  shouldPlayAmbientMusic: boolean;
@@ -50,6 +51,7 @@ export declare class SettingsStore {
50
51
  isTemporarySpeed: boolean;
51
52
  disableBigWin: boolean;
52
53
  isAfterFreeSpinsSummary: boolean;
54
+ isSpeedModalShown: boolean;
53
55
  reinitData?: SpinDataInterface[];
54
56
  setSpeedPopupVisibility?: (visibility: "flex" | "none") => void;
55
57
  popupPaytableRepositionCallback?: () => void;
@@ -15,6 +15,7 @@ const INITIAL_AUTO_SPIN_COUNT = 50;
15
15
  export class SettingsStore {
16
16
  static instance = null;
17
17
  betChangeDisabled = false;
18
+ disableKeyboardShortcuts = false;
18
19
  bet = 0;
19
20
  betText = "";
20
21
  shouldPlayAmbientMusic = true;
@@ -54,6 +55,7 @@ export class SettingsStore {
54
55
  isTemporarySpeed = false;
55
56
  disableBigWin = false;
56
57
  isAfterFreeSpinsSummary = true;
58
+ isSpeedModalShown = false;
57
59
  reinitData;
58
60
  setSpeedPopupVisibility;
59
61
  popupPaytableRepositionCallback;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixi-rainman-game-engine",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
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",