pixi-rainman-game-engine 0.3.27 → 0.3.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/ButtonsEventManager/ButtonsEventManager.js +1 -1
- package/dist/components/AbstractBuyFreeSpins/AbstractBuyFreeSpinsPlate.d.ts +44 -0
- package/dist/components/AbstractBuyFreeSpins/AbstractBuyFreeSpinsPlate.js +181 -0
- package/dist/components/AbstractBuyFreeSpins/AcceptDeclineButton.d.ts +14 -0
- package/dist/components/AbstractBuyFreeSpins/AcceptDeclineButton.js +28 -0
- package/dist/components/AbstractBuyFreeSpins/BuyFreeSpinButton.d.ts +14 -0
- package/dist/components/AbstractBuyFreeSpins/BuyFreeSpinButton.js +22 -0
- package/dist/components/AbstractBuyFreeSpins/index.d.ts +3 -0
- package/dist/components/AbstractBuyFreeSpins/index.js +3 -0
- package/dist/components/AbstractIntroScreen/AbstractIntroScreen.d.ts +15 -2
- package/dist/components/AbstractIntroScreen/AbstractIntroScreen.js +37 -2
- package/dist/components/AbstractIntroScreen/IntroContinueButton.js +1 -0
- package/dist/components/AbstractMainContainer/AbstractMainContainer.d.ts +5 -0
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +31 -0
- package/dist/components/common/IntroLogo.d.ts +16 -0
- package/dist/components/common/IntroLogo.js +35 -0
- package/dist/components/common/index.d.ts +1 -0
- package/dist/components/common/index.js +1 -0
- package/dist/components/dictionary/locales/en.json +3 -0
- package/dist/components/frame/AbstractColumnsContainer.js +9 -6
- package/dist/components/frame/AbstractFrame.js +6 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/symbols/AbstractSymbolsColumn.js +6 -2
- package/dist/controllers/AbstractController.js +10 -2
- package/dist/stores/SettingsStore.d.ts +8 -0
- package/dist/stores/SettingsStore.js +10 -0
- package/package.json +1 -1
|
@@ -209,7 +209,7 @@ export class ButtonsEventManager {
|
|
|
209
209
|
initFreeSpinModal() {
|
|
210
210
|
RainMan.componentRegistry
|
|
211
211
|
.getIfExists(FreeSpinButton.registryName)
|
|
212
|
-
?.setOnClick(() =>
|
|
212
|
+
?.setOnClick(() => RainMan.settingsStore.handleBuyFreeSpinPopupActivation?.());
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
215
|
* Method for initializing volume button
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Container, Sprite } from "pixi.js";
|
|
2
|
+
import { BuyFreeSpinOption } from "SettingsUI/hooks";
|
|
3
|
+
import { AcceptDeclineButton } from "./AcceptDeclineButton";
|
|
4
|
+
export type BuyFreeSpinConfig = {
|
|
5
|
+
options: BuyFreeSpinOption[];
|
|
6
|
+
};
|
|
7
|
+
export type BuyFreeSpinState = "selection" | "confirmation";
|
|
8
|
+
export declare abstract class AbstractBuyFreeSpinsPlate extends Container {
|
|
9
|
+
private state;
|
|
10
|
+
protected selectedOption?: BuyFreeSpinOption;
|
|
11
|
+
protected readonly config: BuyFreeSpinConfig;
|
|
12
|
+
protected selectionPlate?: Sprite;
|
|
13
|
+
protected closeButton?: AcceptDeclineButton;
|
|
14
|
+
protected confirmationPlate?: Sprite;
|
|
15
|
+
protected acceptButton?: AcceptDeclineButton;
|
|
16
|
+
protected declineButton?: AcceptDeclineButton;
|
|
17
|
+
protected selectionPlateTexture: string;
|
|
18
|
+
protected confirmationPlateTexture: string;
|
|
19
|
+
private readonly onContinueCallback;
|
|
20
|
+
private readonly resizeHandler;
|
|
21
|
+
private handleClose;
|
|
22
|
+
protected constructor(onContinue: () => void, config: BuyFreeSpinConfig);
|
|
23
|
+
init(): void;
|
|
24
|
+
private createElements;
|
|
25
|
+
resize(): void;
|
|
26
|
+
private showSelectionScreen;
|
|
27
|
+
private showConfirmationScreen;
|
|
28
|
+
protected abstract getPlateScale(): {
|
|
29
|
+
vertical: number;
|
|
30
|
+
horizontal: number;
|
|
31
|
+
};
|
|
32
|
+
protected abstract createSelectionContent(): void;
|
|
33
|
+
protected abstract createConfirmationContent(): void;
|
|
34
|
+
protected abstract showSelectionContent(): void;
|
|
35
|
+
protected abstract showConfirmationContent(option: BuyFreeSpinOption): void;
|
|
36
|
+
protected abstract positionSelectionScreen(): void;
|
|
37
|
+
protected abstract positionConfirmationScreen(): void;
|
|
38
|
+
protected onCleanup(): void;
|
|
39
|
+
protected onBuyButtonClick(option: BuyFreeSpinOption): void;
|
|
40
|
+
private onAcceptClick;
|
|
41
|
+
private renderState;
|
|
42
|
+
private onDeclineClick;
|
|
43
|
+
private cleanup;
|
|
44
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { Container, Sprite, Texture } from "pixi.js";
|
|
2
|
+
import { UXLayer } from "../../layers";
|
|
3
|
+
import { RainMan } from "../../Rainman";
|
|
4
|
+
import { scaleToParent } from "../../utils";
|
|
5
|
+
import { AcceptDeclineButton } from "./AcceptDeclineButton";
|
|
6
|
+
export class AbstractBuyFreeSpinsPlate extends Container {
|
|
7
|
+
state = "selection";
|
|
8
|
+
selectedOption;
|
|
9
|
+
config;
|
|
10
|
+
selectionPlate;
|
|
11
|
+
closeButton;
|
|
12
|
+
confirmationPlate;
|
|
13
|
+
acceptButton;
|
|
14
|
+
declineButton;
|
|
15
|
+
selectionPlateTexture = "selection-freespin-frame";
|
|
16
|
+
confirmationPlateTexture = "confirmation-freespin-frame";
|
|
17
|
+
onContinueCallback;
|
|
18
|
+
resizeHandler = () => this.resize();
|
|
19
|
+
handleClose = () => {
|
|
20
|
+
this.cleanup();
|
|
21
|
+
this.onContinueCallback();
|
|
22
|
+
RainMan.settingsStore.disableKeyboardShortcuts = false;
|
|
23
|
+
};
|
|
24
|
+
constructor(onContinue, config) {
|
|
25
|
+
super();
|
|
26
|
+
RainMan.settingsStore.disableKeyboardShortcuts = true;
|
|
27
|
+
this.onContinueCallback = onContinue;
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.parentLayer = UXLayer;
|
|
30
|
+
this.eventMode = "static";
|
|
31
|
+
if (config.options.length === 1) {
|
|
32
|
+
this.state = "confirmation";
|
|
33
|
+
this.selectedOption = config.options[0];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
init() {
|
|
37
|
+
this.createElements();
|
|
38
|
+
this.renderState();
|
|
39
|
+
RainMan.app.renderer.on("resize", this.resizeHandler);
|
|
40
|
+
this.resize();
|
|
41
|
+
}
|
|
42
|
+
createElements() {
|
|
43
|
+
const numOptions = this.config.options.length;
|
|
44
|
+
this.selectionPlate = new Sprite(Texture.from(this.selectionPlateTexture));
|
|
45
|
+
this.selectionPlate.anchor.set(0.5);
|
|
46
|
+
if (numOptions > 1) {
|
|
47
|
+
this.closeButton = new AcceptDeclineButton(false);
|
|
48
|
+
this.closeButton.setOnClick(() => this.handleClose());
|
|
49
|
+
this.closeButton.anchor.set(0.5);
|
|
50
|
+
}
|
|
51
|
+
this.confirmationPlate = new Sprite(Texture.from(this.confirmationPlateTexture));
|
|
52
|
+
this.confirmationPlate.anchor.set(0.5);
|
|
53
|
+
this.acceptButton = new AcceptDeclineButton(true);
|
|
54
|
+
this.acceptButton.setOnClick(() => this.onAcceptClick(this.selectedOption));
|
|
55
|
+
this.acceptButton.anchor.set(0.5);
|
|
56
|
+
this.declineButton = new AcceptDeclineButton(false);
|
|
57
|
+
this.declineButton.setOnClick(() => this.onDeclineClick());
|
|
58
|
+
this.declineButton.anchor.set(0.5);
|
|
59
|
+
this.createSelectionContent();
|
|
60
|
+
this.createConfirmationContent();
|
|
61
|
+
}
|
|
62
|
+
resize() {
|
|
63
|
+
const { width, height } = RainMan.app.screen;
|
|
64
|
+
if (this.state === "selection") {
|
|
65
|
+
if (!this.selectionPlate)
|
|
66
|
+
return;
|
|
67
|
+
const plateScale = this.getPlateScale();
|
|
68
|
+
const texW = this.selectionPlate.texture.width;
|
|
69
|
+
const texH = this.selectionPlate.texture.height;
|
|
70
|
+
const targetW = width * plateScale.horizontal;
|
|
71
|
+
const targetH = height * plateScale.vertical;
|
|
72
|
+
const dims = scaleToParent(texW, texH, targetW, targetH);
|
|
73
|
+
const scaleX = dims.width / texW;
|
|
74
|
+
const scaleY = dims.height / texH;
|
|
75
|
+
const scale = Math.min(scaleX, scaleY);
|
|
76
|
+
this.scale.set(scale);
|
|
77
|
+
this.position.set(width / 2, height / 2);
|
|
78
|
+
this.positionSelectionScreen();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (this.state === "confirmation") {
|
|
82
|
+
if (!this.confirmationPlate)
|
|
83
|
+
return;
|
|
84
|
+
const plateScale = this.getPlateScale();
|
|
85
|
+
const texW = this.confirmationPlate.texture.width;
|
|
86
|
+
const texH = this.confirmationPlate.texture.height;
|
|
87
|
+
const targetW = RainMan.app.screen.width * plateScale.horizontal;
|
|
88
|
+
const targetH = RainMan.app.screen.height * plateScale.vertical;
|
|
89
|
+
const dims = scaleToParent(texW, texH, targetW, targetH);
|
|
90
|
+
const scaleX = dims.width / texW;
|
|
91
|
+
const scaleY = dims.height / texH;
|
|
92
|
+
const scale = Math.min(scaleX, scaleY);
|
|
93
|
+
this.scale.set(scale);
|
|
94
|
+
this.position.set(width / 2, height / 2);
|
|
95
|
+
this.positionConfirmationScreen();
|
|
96
|
+
}
|
|
97
|
+
this.parentLayer = UXLayer;
|
|
98
|
+
}
|
|
99
|
+
showSelectionScreen() {
|
|
100
|
+
if (!this.selectionPlate)
|
|
101
|
+
return;
|
|
102
|
+
this.selectionPlate.visible = true;
|
|
103
|
+
this.selectionPlate.alpha = 1;
|
|
104
|
+
this.addChild(this.selectionPlate);
|
|
105
|
+
this.showSelectionContent();
|
|
106
|
+
if (this.closeButton) {
|
|
107
|
+
this.addChild(this.closeButton);
|
|
108
|
+
}
|
|
109
|
+
this.positionSelectionScreen();
|
|
110
|
+
}
|
|
111
|
+
showConfirmationScreen() {
|
|
112
|
+
if (!this.confirmationPlate)
|
|
113
|
+
return;
|
|
114
|
+
if (!this.selectedOption) {
|
|
115
|
+
this.selectedOption = this.config.options[0];
|
|
116
|
+
}
|
|
117
|
+
this.addChild(this.confirmationPlate);
|
|
118
|
+
this.showConfirmationContent(this.selectedOption);
|
|
119
|
+
if (this.acceptButton) {
|
|
120
|
+
this.addChild(this.acceptButton);
|
|
121
|
+
}
|
|
122
|
+
if (this.declineButton) {
|
|
123
|
+
this.addChild(this.declineButton);
|
|
124
|
+
}
|
|
125
|
+
this.positionConfirmationScreen();
|
|
126
|
+
}
|
|
127
|
+
onCleanup() { }
|
|
128
|
+
onBuyButtonClick(option) {
|
|
129
|
+
this.selectedOption = option;
|
|
130
|
+
this.state = "confirmation";
|
|
131
|
+
this.renderState();
|
|
132
|
+
this.resize();
|
|
133
|
+
}
|
|
134
|
+
async onAcceptClick(option) {
|
|
135
|
+
const roundNumber = RainMan.settingsStore.roundNumber + 1;
|
|
136
|
+
try {
|
|
137
|
+
const data = await window.connectionWrapper.fetchFreeSpinData(roundNumber, option.amount, option.price);
|
|
138
|
+
const code = data.getRawData()?.status?.code;
|
|
139
|
+
if (code === 400 || code === 406) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
RainMan.settingsStore.setIsFreeSpinBought(true, data);
|
|
143
|
+
RainMan.settingsStore.setFreeSpinNumberBought(option.amount);
|
|
144
|
+
RainMan.globals.updateFreeSpinShown?.(option.amount);
|
|
145
|
+
RainMan.settingsStore.setRoundNumber(roundNumber);
|
|
146
|
+
this.cleanup();
|
|
147
|
+
this.onContinueCallback();
|
|
148
|
+
RainMan.settingsStore.handleModalInvocation?.("freeSpin");
|
|
149
|
+
RainMan.settingsStore.handleInvokeFreeSpinPlate?.(option.amount, false);
|
|
150
|
+
RainMan.settingsStore.disableKeyboardShortcuts = false;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
console.error(err);
|
|
154
|
+
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
155
|
+
RainMan.settingsStore.disableKeyboardShortcuts = false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
renderState() {
|
|
159
|
+
this.removeChildren();
|
|
160
|
+
if (this.state === "selection") {
|
|
161
|
+
this.showSelectionScreen();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.showConfirmationScreen();
|
|
165
|
+
}
|
|
166
|
+
onDeclineClick() {
|
|
167
|
+
if (this.config.options.length === 1) {
|
|
168
|
+
this.handleClose();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this.state = "selection";
|
|
172
|
+
this.selectedOption = undefined;
|
|
173
|
+
this.renderState();
|
|
174
|
+
this.resize();
|
|
175
|
+
}
|
|
176
|
+
cleanup() {
|
|
177
|
+
RainMan.app.renderer.off("resize", this.resizeHandler);
|
|
178
|
+
this.onCleanup();
|
|
179
|
+
this.destroy({ children: true });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseButton } from "../buttons/BaseButton";
|
|
2
|
+
/**
|
|
3
|
+
* Button for accepting or declining number of free spins to buy.
|
|
4
|
+
* It needs following textures:
|
|
5
|
+
* - normal - `v-n.png` for accept, `x-n.png` for decline
|
|
6
|
+
* - hover - `v-h.png` for accept, `x-h.png` for decline
|
|
7
|
+
* - clicked - `v-c.png` for accept, `x-c.png` for decline
|
|
8
|
+
* @param {boolean} isAcceptButton desides which texture to use
|
|
9
|
+
* @augments {BaseButton}
|
|
10
|
+
*/
|
|
11
|
+
export declare class AcceptDeclineButton extends BaseButton {
|
|
12
|
+
static registryName: string;
|
|
13
|
+
constructor(isAcceptButton?: boolean);
|
|
14
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getTexture } from "../../utils";
|
|
2
|
+
import { BaseButton, ButtonStates } from "../buttons/BaseButton";
|
|
3
|
+
/**
|
|
4
|
+
* Button for accepting or declining number of free spins to buy.
|
|
5
|
+
* It needs following textures:
|
|
6
|
+
* - normal - `v-n.png` for accept, `x-n.png` for decline
|
|
7
|
+
* - hover - `v-h.png` for accept, `x-h.png` for decline
|
|
8
|
+
* - clicked - `v-c.png` for accept, `x-c.png` for decline
|
|
9
|
+
* @param {boolean} isAcceptButton desides which texture to use
|
|
10
|
+
* @augments {BaseButton}
|
|
11
|
+
*/
|
|
12
|
+
export class AcceptDeclineButton extends BaseButton {
|
|
13
|
+
static registryName = "acceptDeclineButton";
|
|
14
|
+
constructor(isAcceptButton) {
|
|
15
|
+
const textureMap = isAcceptButton
|
|
16
|
+
? {
|
|
17
|
+
[ButtonStates.NORMAL]: getTexture("v-n.png"),
|
|
18
|
+
[ButtonStates.OVER]: getTexture("v-h.png"),
|
|
19
|
+
[ButtonStates.CLICKED]: getTexture("v-c.png")
|
|
20
|
+
}
|
|
21
|
+
: {
|
|
22
|
+
[ButtonStates.NORMAL]: getTexture("x-n.png"),
|
|
23
|
+
[ButtonStates.OVER]: getTexture("x-h.png"),
|
|
24
|
+
[ButtonStates.CLICKED]: getTexture("x-c.png")
|
|
25
|
+
};
|
|
26
|
+
super(AcceptDeclineButton.registryName, textureMap);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseButton } from "../buttons/BaseButton";
|
|
2
|
+
/**
|
|
3
|
+
* Button for selecting number of freespins to buy
|
|
4
|
+
* It needs following textures:
|
|
5
|
+
* - normal - `buttonTextureName-n.png`
|
|
6
|
+
* - hover - `buttonTextureName-h.png`
|
|
7
|
+
* - clicked - `buttonTextureName-c.png`
|
|
8
|
+
* @param {string} buttonTextureName name of a texture to use
|
|
9
|
+
* @augments {BaseButton}
|
|
10
|
+
*/
|
|
11
|
+
export declare class BuyFreeSpinButton extends BaseButton {
|
|
12
|
+
static registryName: string;
|
|
13
|
+
constructor(buttonTextureName: string);
|
|
14
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getTexture } from "../../utils";
|
|
2
|
+
import { BaseButton, ButtonStates } from "../buttons/BaseButton";
|
|
3
|
+
/**
|
|
4
|
+
* Button for selecting number of freespins to buy
|
|
5
|
+
* It needs following textures:
|
|
6
|
+
* - normal - `buttonTextureName-n.png`
|
|
7
|
+
* - hover - `buttonTextureName-h.png`
|
|
8
|
+
* - clicked - `buttonTextureName-c.png`
|
|
9
|
+
* @param {string} buttonTextureName name of a texture to use
|
|
10
|
+
* @augments {BaseButton}
|
|
11
|
+
*/
|
|
12
|
+
export class BuyFreeSpinButton extends BaseButton {
|
|
13
|
+
static registryName = "buyFreeSpinButton";
|
|
14
|
+
constructor(buttonTextureName) {
|
|
15
|
+
const textureMap = {
|
|
16
|
+
[ButtonStates.NORMAL]: getTexture(`${buttonTextureName}-n.png`),
|
|
17
|
+
[ButtonStates.OVER]: getTexture(`${buttonTextureName}-h.png`),
|
|
18
|
+
[ButtonStates.CLICKED]: getTexture(`${buttonTextureName}-c.png`)
|
|
19
|
+
};
|
|
20
|
+
super(BuyFreeSpinButton.registryName, textureMap);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { Container, Sprite, Text, TextStyle, Texture } from "pixi.js";
|
|
2
|
-
import {
|
|
2
|
+
import { IntroLogo } from "../common";
|
|
3
3
|
import { IntroContinueButton } from "./IntroContinueButton";
|
|
4
4
|
import { IntroDotButton } from "./IntroDotButton";
|
|
5
5
|
import { IntroPageData } from "./IntroPageData";
|
|
6
6
|
/**
|
|
7
7
|
* Abstract intro screen shown between loading and gameplay.
|
|
8
8
|
* Each game subclasses this and provides assets + page definitions as properties.
|
|
9
|
+
* Properly named assets:
|
|
10
|
+
* - bg - `bg.png` and `bg-mobile.png`
|
|
11
|
+
* - introFrame - `intro-frame.png` and `intro-frame-mobile.png`
|
|
12
|
+
* - interactable - 'intro-continue-n.png`, `intro-continue-h.png`, `intro-continue-c.png' for continue button, "dot-off" states, "dot-on", "check-box", "checkbox-tick" and `dot-shadow.png` for dot shadow (optional)
|
|
13
|
+
* - logo - `intro-logo.png` and `intro-logo-mobile.png`
|
|
14
|
+
* - screens-mobile and screens-desktop - defined in pages property of the class extending AbstractIntroScreen
|
|
9
15
|
* @abstract
|
|
10
16
|
* @class AbstractIntroScreen
|
|
11
17
|
* @typedef {AbstractIntroScreen}
|
|
@@ -21,7 +27,7 @@ export declare abstract class AbstractIntroScreen extends Container {
|
|
|
21
27
|
frame: Texture;
|
|
22
28
|
tick: Texture;
|
|
23
29
|
};
|
|
24
|
-
protected abstract logo:
|
|
30
|
+
protected abstract logo: IntroLogo;
|
|
25
31
|
protected abstract pages: IntroPageData[];
|
|
26
32
|
protected abstract pageTextStyle: TextStyle;
|
|
27
33
|
protected checkboxLabel: Text;
|
|
@@ -29,6 +35,7 @@ export declare abstract class AbstractIntroScreen extends Container {
|
|
|
29
35
|
protected checkboxTick: Sprite;
|
|
30
36
|
protected continueButton: IntroContinueButton;
|
|
31
37
|
protected dots: IntroDotButton[];
|
|
38
|
+
protected dotShadow?: Sprite;
|
|
32
39
|
protected frameImage: Sprite;
|
|
33
40
|
protected pageImage: Sprite;
|
|
34
41
|
protected pageText: Text;
|
|
@@ -55,6 +62,12 @@ export declare abstract class AbstractIntroScreen extends Container {
|
|
|
55
62
|
protected showPage(index: number): void;
|
|
56
63
|
private updateFade;
|
|
57
64
|
private cleanup;
|
|
65
|
+
/**
|
|
66
|
+
* Resizes dot shadow width to match all dots and centers it on them.
|
|
67
|
+
* Call this in positionDots() after positioning the dots.
|
|
68
|
+
*/
|
|
69
|
+
protected positionDotShadow(): void;
|
|
70
|
+
private createDotShadow;
|
|
58
71
|
private createDots;
|
|
59
72
|
private navigatePage;
|
|
60
73
|
private handleContinue;
|
|
@@ -3,12 +3,18 @@ import { Container, Sprite, Text, Texture, Ticker } from "pixi.js";
|
|
|
3
3
|
import { UXLayer } from "../../layers";
|
|
4
4
|
import { getFromLocalStorage, LOCAL_STORAGE, setToLocalStorage } from "../../localStorage";
|
|
5
5
|
import { RainMan } from "../../Rainman";
|
|
6
|
-
import { getDeviceOrientation, getTexture, scaleToParent } from "../../utils";
|
|
6
|
+
import { getDeviceOrientation, getTexture, getTextureSafely, scaleToParent } from "../../utils";
|
|
7
7
|
import { IntroContinueButton } from "./IntroContinueButton";
|
|
8
8
|
import { IntroDotButton } from "./IntroDotButton";
|
|
9
9
|
/**
|
|
10
10
|
* Abstract intro screen shown between loading and gameplay.
|
|
11
11
|
* Each game subclasses this and provides assets + page definitions as properties.
|
|
12
|
+
* Properly named assets:
|
|
13
|
+
* - bg - `bg.png` and `bg-mobile.png`
|
|
14
|
+
* - introFrame - `intro-frame.png` and `intro-frame-mobile.png`
|
|
15
|
+
* - interactable - 'intro-continue-n.png`, `intro-continue-h.png`, `intro-continue-c.png' for continue button, "dot-off" states, "dot-on", "check-box", "checkbox-tick" and `dot-shadow.png` for dot shadow (optional)
|
|
16
|
+
* - logo - `intro-logo.png` and `intro-logo-mobile.png`
|
|
17
|
+
* - screens-mobile and screens-desktop - defined in pages property of the class extending AbstractIntroScreen
|
|
12
18
|
* @abstract
|
|
13
19
|
* @class AbstractIntroScreen
|
|
14
20
|
* @typedef {AbstractIntroScreen}
|
|
@@ -23,6 +29,7 @@ export class AbstractIntroScreen extends Container {
|
|
|
23
29
|
checkboxTick;
|
|
24
30
|
continueButton;
|
|
25
31
|
dots = [];
|
|
32
|
+
dotShadow;
|
|
26
33
|
frameImage;
|
|
27
34
|
pageImage;
|
|
28
35
|
pageText;
|
|
@@ -49,6 +56,7 @@ export class AbstractIntroScreen extends Container {
|
|
|
49
56
|
this.handleContinue();
|
|
50
57
|
});
|
|
51
58
|
this.createDots();
|
|
59
|
+
this.createDotShadow();
|
|
52
60
|
this.checkboxSprite = new Sprite(this.checkboxTextures.frame);
|
|
53
61
|
this.checkboxSprite.eventMode = "static";
|
|
54
62
|
this.checkboxSprite.cursor = "pointer";
|
|
@@ -106,6 +114,8 @@ export class AbstractIntroScreen extends Container {
|
|
|
106
114
|
this.addChild(this.checkboxSprite);
|
|
107
115
|
this.addChild(this.checkboxTick);
|
|
108
116
|
this.addChild(this.checkboxLabel);
|
|
117
|
+
if (this.dotShadow)
|
|
118
|
+
this.addChild(this.dotShadow);
|
|
109
119
|
this.dots.forEach((dot) => this.addChild(dot));
|
|
110
120
|
this.positionPageImage();
|
|
111
121
|
this.positionLogo();
|
|
@@ -113,6 +123,7 @@ export class AbstractIntroScreen extends Container {
|
|
|
113
123
|
this.positionCheckbox();
|
|
114
124
|
this.positionContinueButton();
|
|
115
125
|
this.positionText();
|
|
126
|
+
this.positionDotShadow();
|
|
116
127
|
this.frameImage.x = this.pageImage.x;
|
|
117
128
|
this.frameImage.y = this.pageImage.y;
|
|
118
129
|
this.frameImage.width = this.pageImage.width;
|
|
@@ -138,11 +149,35 @@ export class AbstractIntroScreen extends Container {
|
|
|
138
149
|
this.fadeTween?.update();
|
|
139
150
|
}
|
|
140
151
|
cleanup() {
|
|
141
|
-
Ticker.shared.remove(this.updateFade, this);
|
|
142
152
|
Ticker.shared.remove(this.updateFade, this);
|
|
143
153
|
RainMan.app.renderer.off("resize", this.resizeHandler);
|
|
144
154
|
this.destroy({ children: true });
|
|
145
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Resizes dot shadow width to match all dots and centers it on them.
|
|
158
|
+
* Call this in positionDots() after positioning the dots.
|
|
159
|
+
*/
|
|
160
|
+
positionDotShadow() {
|
|
161
|
+
if (!this.dotShadow || this.dots.length === 0)
|
|
162
|
+
return;
|
|
163
|
+
const firstDot = this.dots[0];
|
|
164
|
+
const lastDot = this.dots[this.dots.length - 1];
|
|
165
|
+
const dotsSpan = lastDot.x - firstDot.x;
|
|
166
|
+
this.dotShadow.scale.set(firstDot.scale.x);
|
|
167
|
+
this.dotShadow.width = dotsSpan + firstDot.width;
|
|
168
|
+
if (getDeviceOrientation().includes("mobile")) {
|
|
169
|
+
this.dotShadow.width = dotsSpan;
|
|
170
|
+
}
|
|
171
|
+
this.dotShadow.x = (firstDot.x + lastDot.x) / 2;
|
|
172
|
+
this.dotShadow.y = firstDot.y;
|
|
173
|
+
}
|
|
174
|
+
createDotShadow() {
|
|
175
|
+
const texture = getTextureSafely("dot-shadow.png");
|
|
176
|
+
if (!texture)
|
|
177
|
+
return;
|
|
178
|
+
this.dotShadow = new Sprite(texture);
|
|
179
|
+
this.dotShadow.anchor.set(0.5);
|
|
180
|
+
}
|
|
146
181
|
createDots() {
|
|
147
182
|
this.dots = [];
|
|
148
183
|
for (let i = 0; i < this.pages.length; i++) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AbstractBuyFreeSpinsPlate } from "components/AbstractBuyFreeSpins/AbstractBuyFreeSpinsPlate";
|
|
1
2
|
import { Container, Graphics, Sprite } from "pixi.js";
|
|
2
3
|
import { ButtonsEventManager, WinTypeId } from "../../application";
|
|
3
4
|
import { AbstractController } from "../../controllers";
|
|
@@ -54,6 +55,7 @@ export declare abstract class AbstractMainContainer extends Container {
|
|
|
54
55
|
protected mysteryBonusContainer: Nullable<UpdatableSpineContainer>;
|
|
55
56
|
protected resolveMysteryBonusContainer?: PromiseResolverType;
|
|
56
57
|
protected _freeSpinPlate: Nullable<AbstractFreeSpinContainer>;
|
|
58
|
+
protected _buyFreeSpinsPlate: Nullable<AbstractBuyFreeSpinsPlate>;
|
|
57
59
|
protected _freeSpinSummary: Nullable<AbstractFreeSpinContainer>;
|
|
58
60
|
private _bigWinInvokedAt;
|
|
59
61
|
private _mysteryWinInvokedAt;
|
|
@@ -173,6 +175,9 @@ export declare abstract class AbstractMainContainer extends Container {
|
|
|
173
175
|
* @returns {Promise<void>}
|
|
174
176
|
*/
|
|
175
177
|
invokeFreeSpinPlate(freeSpinCount: number, isAdditionalFreeSpin?: boolean, isMoneyReward?: boolean): Promise<void>;
|
|
178
|
+
invokeBuyFreeSpinPlate(): void;
|
|
179
|
+
protected closeBuyFreeSpinPlate(): void;
|
|
180
|
+
protected createBuyFreeSpinPlate(): AbstractBuyFreeSpinsPlate | null;
|
|
176
181
|
/**
|
|
177
182
|
* Function for creating free spin summary
|
|
178
183
|
* @protected
|
|
@@ -47,6 +47,7 @@ export class AbstractMainContainer extends Container {
|
|
|
47
47
|
mysteryBonusContainer = null;
|
|
48
48
|
resolveMysteryBonusContainer = undefined;
|
|
49
49
|
_freeSpinPlate = null;
|
|
50
|
+
_buyFreeSpinsPlate = null;
|
|
50
51
|
_freeSpinSummary = null;
|
|
51
52
|
_bigWinInvokedAt = null;
|
|
52
53
|
_mysteryWinInvokedAt = null;
|
|
@@ -60,6 +61,7 @@ export class AbstractMainContainer extends Container {
|
|
|
60
61
|
this.messageBox = new MessageBox();
|
|
61
62
|
SoundManager.setPlayStatus(SoundTracks.music, RainMan.settingsStore.shouldPlayAmbientMusic);
|
|
62
63
|
RainMan.settingsStore.setHandleInvokeFreeSpinPlate(this.invokeFreeSpinPlate.bind(this));
|
|
64
|
+
RainMan.settingsStore.setHandleBuyFreeSpinPopupActivatio(this.invokeBuyFreeSpinPlate.bind(this));
|
|
63
65
|
RainMan.app.renderer.on("resize", () => this.resize());
|
|
64
66
|
}
|
|
65
67
|
/**
|
|
@@ -236,6 +238,30 @@ export class AbstractMainContainer extends Container {
|
|
|
236
238
|
this.hideOverlay();
|
|
237
239
|
refreshButton.flipDisabledFlag(false);
|
|
238
240
|
}
|
|
241
|
+
invokeBuyFreeSpinPlate() {
|
|
242
|
+
const refreshButton = RainMan.componentRegistry.get(RefreshButton.registryName);
|
|
243
|
+
refreshButton.flipDisabledFlag(true);
|
|
244
|
+
this._buyFreeSpinsPlate = this.createBuyFreeSpinPlate();
|
|
245
|
+
if (!this._buyFreeSpinsPlate) {
|
|
246
|
+
refreshButton.flipDisabledFlag(false);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
this._buyFreeSpinsPlate.init();
|
|
250
|
+
this._buyFreeSpinsPlate.resize();
|
|
251
|
+
this.showOverlay();
|
|
252
|
+
this.addChild(this._buyFreeSpinsPlate);
|
|
253
|
+
}
|
|
254
|
+
closeBuyFreeSpinPlate() {
|
|
255
|
+
this.removeChild(this._buyFreeSpinsPlate);
|
|
256
|
+
this._buyFreeSpinsPlate.destroy({ children: true });
|
|
257
|
+
this._buyFreeSpinsPlate = null;
|
|
258
|
+
this.hideOverlay();
|
|
259
|
+
const refreshButton = RainMan.componentRegistry.get(RefreshButton.registryName);
|
|
260
|
+
refreshButton.flipDisabledFlag(false);
|
|
261
|
+
}
|
|
262
|
+
createBuyFreeSpinPlate() {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
239
265
|
/**
|
|
240
266
|
* Function for creating free spin summary
|
|
241
267
|
* @protected
|
|
@@ -884,6 +910,11 @@ export class AbstractMainContainer extends Container {
|
|
|
884
910
|
this.addChild(this.freeSpinSummary);
|
|
885
911
|
this.freeSpinSummary.resize();
|
|
886
912
|
}
|
|
913
|
+
if (this._buyFreeSpinsPlate) {
|
|
914
|
+
this.removeChild(this._buyFreeSpinsPlate);
|
|
915
|
+
this.addChild(this._buyFreeSpinsPlate);
|
|
916
|
+
this._buyFreeSpinsPlate.resize();
|
|
917
|
+
}
|
|
887
918
|
RainMan.settingsStore.popupPaytableRepositionCallback?.();
|
|
888
919
|
}
|
|
889
920
|
/**
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Container } from "pixi.js";
|
|
2
|
+
/**
|
|
3
|
+
* Static intro logo that switches between desktop and mobile sprites based on orientation.
|
|
4
|
+
* Uses "intro-logo" for PC/landscape and "intro-logo-mobile" for portrait.
|
|
5
|
+
* @class IntroLogo
|
|
6
|
+
* @augments {Container}
|
|
7
|
+
*/
|
|
8
|
+
export declare class IntroLogo extends Container {
|
|
9
|
+
private desktopTextureName;
|
|
10
|
+
private mobileTextureName;
|
|
11
|
+
private maxScale;
|
|
12
|
+
private desktopSprite;
|
|
13
|
+
private mobileSprite;
|
|
14
|
+
constructor(desktopTextureName: string, mobileTextureName: string, maxScale?: number);
|
|
15
|
+
resize(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Container, Sprite } from "pixi.js";
|
|
2
|
+
import { RainMan } from "../../Rainman";
|
|
3
|
+
import { getDeviceOrientation, getTexture, globalMinRatio } from "../../utils";
|
|
4
|
+
/**
|
|
5
|
+
* Static intro logo that switches between desktop and mobile sprites based on orientation.
|
|
6
|
+
* Uses "intro-logo" for PC/landscape and "intro-logo-mobile" for portrait.
|
|
7
|
+
* @class IntroLogo
|
|
8
|
+
* @augments {Container}
|
|
9
|
+
*/
|
|
10
|
+
export class IntroLogo extends Container {
|
|
11
|
+
desktopTextureName;
|
|
12
|
+
mobileTextureName;
|
|
13
|
+
maxScale;
|
|
14
|
+
desktopSprite;
|
|
15
|
+
mobileSprite;
|
|
16
|
+
constructor(desktopTextureName, mobileTextureName, maxScale = 1.5) {
|
|
17
|
+
super();
|
|
18
|
+
this.desktopTextureName = desktopTextureName;
|
|
19
|
+
this.mobileTextureName = mobileTextureName;
|
|
20
|
+
this.maxScale = maxScale;
|
|
21
|
+
this.desktopSprite = new Sprite(getTexture(this.desktopTextureName));
|
|
22
|
+
this.desktopSprite.anchor.set(0.5);
|
|
23
|
+
this.mobileSprite = new Sprite(getTexture(this.mobileTextureName));
|
|
24
|
+
this.mobileSprite.anchor.set(0.5);
|
|
25
|
+
this.addChild(this.desktopSprite, this.mobileSprite);
|
|
26
|
+
this.resize();
|
|
27
|
+
}
|
|
28
|
+
resize() {
|
|
29
|
+
const isPortrait = getDeviceOrientation() === "mobile-portrait";
|
|
30
|
+
this.desktopSprite.visible = !isPortrait;
|
|
31
|
+
this.mobileSprite.visible = isPortrait;
|
|
32
|
+
this.scale.set(Math.min(this.maxScale, globalMinRatio()));
|
|
33
|
+
this.x = RainMan.app.screen.width / 2;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -2,6 +2,7 @@ export * from "./AnimatedBackground";
|
|
|
2
2
|
export * from "./AnimatedNumber";
|
|
3
3
|
export * from "./Background";
|
|
4
4
|
export * from "./FreeSpinButton";
|
|
5
|
+
export * from "./IntroLogo";
|
|
5
6
|
export * from "./Logo";
|
|
6
7
|
export * from "./LogoStatic";
|
|
7
8
|
export * from "./ResponsiveComponent";
|
|
@@ -2,6 +2,7 @@ export * from "./AnimatedBackground";
|
|
|
2
2
|
export * from "./AnimatedNumber";
|
|
3
3
|
export * from "./Background";
|
|
4
4
|
export * from "./FreeSpinButton";
|
|
5
|
+
export * from "./IntroLogo";
|
|
5
6
|
export * from "./Logo";
|
|
6
7
|
export * from "./LogoStatic";
|
|
7
8
|
export * from "./ResponsiveComponent";
|
|
@@ -60,6 +60,9 @@
|
|
|
60
60
|
"doubleTo": "DOUBLE TO",
|
|
61
61
|
"collect": "COLLECT",
|
|
62
62
|
"totalBet": "Bet",
|
|
63
|
+
"buyFreeSpinTitle": "BUY",
|
|
64
|
+
"freeSpinsAmount": "{{amount}}",
|
|
65
|
+
"freeSpinText": "FREE SPINS",
|
|
63
66
|
"buyFreeSpins": "Buy Free Spins",
|
|
64
67
|
"possibleWin": "POSSIBLE WIN: ",
|
|
65
68
|
"gamePaysText": "GAME PAYS: "
|
|
@@ -150,14 +150,17 @@ export class AbstractColumnsContainer extends Container {
|
|
|
150
150
|
frame.invokeMysteryFx(this.currentColumn.x, this.currentColumn.y);
|
|
151
151
|
this.skipScatterDelay = configureSpinAction;
|
|
152
152
|
await this.currentColumn.speedUpForMysterySpin(100, 1500);
|
|
153
|
-
if (!
|
|
154
|
-
(RainMan.settingsStore.isAutoplayEnabled
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
if (!this.quickReelsStop) {
|
|
154
|
+
if (!RainMan.settingsStore.isAutoplayEnabled ||
|
|
155
|
+
(RainMan.settingsStore.isAutoplayEnabled && !this.quickReelsStop)) {
|
|
156
|
+
setTimeout(() => {
|
|
157
|
+
this.skipScatterDelay?.();
|
|
158
|
+
this.skipScatterDelay = null;
|
|
159
|
+
}, RainMan.config.durationOfActions.scatterDelayerTime);
|
|
160
|
+
}
|
|
159
161
|
}
|
|
160
162
|
await this.currentColumn.changeVelocity(Speed.STOP, RainMan.config.durationOfActions.scatterSpinningTime, frame);
|
|
163
|
+
frame.destroyMysteryFx();
|
|
161
164
|
}
|
|
162
165
|
if (!indexesOfReelsToExtendSpinningTime.includes(index)) {
|
|
163
166
|
await configureSpinAction();
|
|
@@ -59,6 +59,8 @@ export class AbstractFrame extends ResumableContainer {
|
|
|
59
59
|
if (this.mysteryFxHighlight) {
|
|
60
60
|
SoundManager.pause(SoundTracks.mysteryFxLoop);
|
|
61
61
|
this.removeChild(this.mysteryFxHighlight);
|
|
62
|
+
this.mysteryFxHighlight.destroy();
|
|
63
|
+
this.mysteryFxHighlight = null;
|
|
62
64
|
}
|
|
63
65
|
this.mysteryFxCoordinates = { x, y };
|
|
64
66
|
const spineName = this.mysteryFxConfig.mobileSpineName && getDeviceOrientation() === "mobile-portrait"
|
|
@@ -71,8 +73,10 @@ export class AbstractFrame extends ResumableContainer {
|
|
|
71
73
|
this.repositionMysteryFx(x, y);
|
|
72
74
|
SoundManager.play(SoundTracks.mysteryFxLoop);
|
|
73
75
|
this.mysteryFxHighlight.state.setAnimation(0, this.mysteryFxConfig.startAnimationName || this.mysteryFxConfig.loopAnimationName, false);
|
|
74
|
-
this.mysteryFxHighlight
|
|
75
|
-
|
|
76
|
+
const spineInstance = this.mysteryFxHighlight;
|
|
77
|
+
const loopAnimationName = this.mysteryFxConfig.loopAnimationName;
|
|
78
|
+
spineInstance.state.addListener({
|
|
79
|
+
complete: () => spineInstance.state.setAnimation(0, loopAnimationName, true)
|
|
76
80
|
});
|
|
77
81
|
this.addChild(this.mysteryFxHighlight);
|
|
78
82
|
}
|
package/dist/components/index.js
CHANGED
|
@@ -142,6 +142,10 @@ export class AbstractSymbolsColumn extends Container {
|
|
|
142
142
|
* @returns {Promise<void>} promise that resolves when the speed change is complete
|
|
143
143
|
*/
|
|
144
144
|
async changeVelocity(velocity, duration, frame) {
|
|
145
|
+
if (this.tween !== null) {
|
|
146
|
+
this.tween.stop();
|
|
147
|
+
this.tween = null;
|
|
148
|
+
}
|
|
145
149
|
await new Promise((resolve) => {
|
|
146
150
|
this.tween = new TWEEN.Tween({ velocity: velocity })
|
|
147
151
|
.onUpdate((value) => {
|
|
@@ -152,7 +156,7 @@ export class AbstractSymbolsColumn extends Container {
|
|
|
152
156
|
.start()
|
|
153
157
|
.onComplete(async () => {
|
|
154
158
|
this.tween = null;
|
|
155
|
-
if (frame) {
|
|
159
|
+
if (frame && !this.skipHidingMysteryFx) {
|
|
156
160
|
frame.hideMysteryFx();
|
|
157
161
|
frame.destroyMysteryFx();
|
|
158
162
|
}
|
|
@@ -161,7 +165,7 @@ export class AbstractSymbolsColumn extends Container {
|
|
|
161
165
|
})
|
|
162
166
|
.onStop(async () => {
|
|
163
167
|
this.tween = null;
|
|
164
|
-
if (frame) {
|
|
168
|
+
if (frame && !this.skipHidingMysteryFx) {
|
|
165
169
|
frame.hideMysteryFx();
|
|
166
170
|
frame.destroyMysteryFx();
|
|
167
171
|
}
|
|
@@ -429,12 +429,19 @@ export class AbstractController {
|
|
|
429
429
|
const refreshButton = RainMan.componentRegistry.get(RefreshButton.registryName);
|
|
430
430
|
this.clearMobileSpinTimeout = () => {
|
|
431
431
|
this.buttonHeldSince = 0;
|
|
432
|
-
this.
|
|
432
|
+
const isSpinning = this.gamePhase === gamePhases.SPINNING ||
|
|
433
|
+
this.gamePhase === gamePhases.CONFIGURING_SPIN ||
|
|
434
|
+
this.gamePhase === gamePhases.DATA_FETCH;
|
|
435
|
+
if (!isSpinning) {
|
|
436
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
437
|
+
}
|
|
433
438
|
if (this.mobileSpinTimeout) {
|
|
434
439
|
clearInterval(this.mobileSpinTimeout);
|
|
435
440
|
this.quickStopController.setQuickStopCounterLock(false);
|
|
436
441
|
this.mobileSpinTimeout = null;
|
|
437
|
-
|
|
442
|
+
if (!isSpinning) {
|
|
443
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
444
|
+
}
|
|
438
445
|
}
|
|
439
446
|
if (this.mobileSpinDelay) {
|
|
440
447
|
clearTimeout(this.mobileSpinDelay);
|
|
@@ -773,6 +780,7 @@ export class AbstractController {
|
|
|
773
780
|
if (this.gamePhase === gamePhases.DATA_FETCH ||
|
|
774
781
|
this.gamePhase === gamePhases.SPINNING ||
|
|
775
782
|
this.gamePhase === gamePhases.CONFIGURING_SPIN) {
|
|
783
|
+
this.columnsContainer.enableQuickReelsStop();
|
|
776
784
|
this.isSpinThrottled = true;
|
|
777
785
|
this.quickStopController.handleResetCounter(this.spinThrottlerTimeout !== null);
|
|
778
786
|
this.quickStopController.handleInvokingSpeedPopup();
|
|
@@ -62,6 +62,7 @@ export declare class SettingsStore {
|
|
|
62
62
|
closeOtherModals?: (layerId: string) => void;
|
|
63
63
|
closeCurrentlyOpenModal?: () => void;
|
|
64
64
|
handleInvokeFreeSpinPlate?: (freeSpinAmount: number, isAdditionalFreeSpin: boolean) => Promise<void>;
|
|
65
|
+
handleBuyFreeSpinPopupActivation?: () => void;
|
|
65
66
|
increaseBet?: () => void;
|
|
66
67
|
decreaseBet?: () => void;
|
|
67
68
|
enableButtons?: () => void;
|
|
@@ -387,6 +388,13 @@ export declare class SettingsStore {
|
|
|
387
388
|
* @returns {void}
|
|
388
389
|
*/
|
|
389
390
|
setHandleInvokeFreeSpinPlate(handleInvokeFreeSpinPlate: (freeSpinAmount: number, isAdditionalFreeSpin: boolean) => Promise<void>): void;
|
|
391
|
+
/**
|
|
392
|
+
* Set the callback for invoking the free spin plate
|
|
393
|
+
* @param handleBuyFreeSpinPopupActivation
|
|
394
|
+
* @public
|
|
395
|
+
* @returns {void}
|
|
396
|
+
*/
|
|
397
|
+
setHandleBuyFreeSpinPopupActivatio(handleBuyFreeSpinPopupActivation: () => void): void;
|
|
390
398
|
/**
|
|
391
399
|
* Reset the number of free spins bought
|
|
392
400
|
* @public
|
|
@@ -66,6 +66,7 @@ export class SettingsStore {
|
|
|
66
66
|
closeOtherModals;
|
|
67
67
|
closeCurrentlyOpenModal;
|
|
68
68
|
handleInvokeFreeSpinPlate;
|
|
69
|
+
handleBuyFreeSpinPopupActivation;
|
|
69
70
|
increaseBet;
|
|
70
71
|
decreaseBet;
|
|
71
72
|
enableButtons;
|
|
@@ -641,6 +642,15 @@ export class SettingsStore {
|
|
|
641
642
|
setHandleInvokeFreeSpinPlate(handleInvokeFreeSpinPlate) {
|
|
642
643
|
this.handleInvokeFreeSpinPlate = handleInvokeFreeSpinPlate;
|
|
643
644
|
}
|
|
645
|
+
/**
|
|
646
|
+
* Set the callback for invoking the free spin plate
|
|
647
|
+
* @param handleBuyFreeSpinPopupActivation
|
|
648
|
+
* @public
|
|
649
|
+
* @returns {void}
|
|
650
|
+
*/
|
|
651
|
+
setHandleBuyFreeSpinPopupActivatio(handleBuyFreeSpinPopupActivation) {
|
|
652
|
+
this.handleBuyFreeSpinPopupActivation = handleBuyFreeSpinPopupActivation;
|
|
653
|
+
}
|
|
644
654
|
/**
|
|
645
655
|
* Reset the number of free spins bought
|
|
646
656
|
* @public
|
package/package.json
CHANGED