pixi-rainman-game-engine 0.3.26 → 0.3.27
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/components/AbstractIntroScreen/AbstractIntroScreen.d.ts +62 -0
- package/dist/components/AbstractIntroScreen/AbstractIntroScreen.js +192 -0
- package/dist/components/AbstractIntroScreen/IntroContinueButton.d.ts +13 -0
- package/dist/components/AbstractIntroScreen/IntroContinueButton.js +21 -0
- package/dist/components/AbstractIntroScreen/IntroDotButton.d.ts +15 -0
- package/dist/components/AbstractIntroScreen/IntroDotButton.js +30 -0
- package/dist/components/AbstractIntroScreen/IntroPageData.d.ts +8 -0
- package/dist/components/AbstractIntroScreen/IntroPageData.js +1 -0
- package/dist/components/AbstractIntroScreen/index.d.ts +4 -0
- package/dist/components/AbstractIntroScreen/index.js +4 -0
- package/dist/components/frame/AbstractColumnsContainer.js +2 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/controllers/AbstractController.d.ts +3 -0
- package/dist/controllers/AbstractController.js +52 -26
- package/dist/localStorage/localStorage.d.ts +1 -0
- package/dist/localStorage/localStorage.js +2 -1
- package/dist/stores/SettingsStore.d.ts +1 -0
- package/dist/stores/SettingsStore.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Container, Sprite, Text, TextStyle, Texture } from "pixi.js";
|
|
2
|
+
import { Logo } from "../common";
|
|
3
|
+
import { IntroContinueButton } from "./IntroContinueButton";
|
|
4
|
+
import { IntroDotButton } from "./IntroDotButton";
|
|
5
|
+
import { IntroPageData } from "./IntroPageData";
|
|
6
|
+
/**
|
|
7
|
+
* Abstract intro screen shown between loading and gameplay.
|
|
8
|
+
* Each game subclasses this and provides assets + page definitions as properties.
|
|
9
|
+
* @abstract
|
|
10
|
+
* @class AbstractIntroScreen
|
|
11
|
+
* @typedef {AbstractIntroScreen}
|
|
12
|
+
* @augments {Container}
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class AbstractIntroScreen extends Container {
|
|
15
|
+
static shouldSkip(): boolean;
|
|
16
|
+
protected abstract background: Sprite;
|
|
17
|
+
protected abstract backgroundPortrait: Sprite;
|
|
18
|
+
protected abstract checkboxLabelText: string;
|
|
19
|
+
protected abstract checkboxTextStyle: TextStyle;
|
|
20
|
+
protected abstract checkboxTextures: {
|
|
21
|
+
frame: Texture;
|
|
22
|
+
tick: Texture;
|
|
23
|
+
};
|
|
24
|
+
protected abstract logo: Logo;
|
|
25
|
+
protected abstract pages: IntroPageData[];
|
|
26
|
+
protected abstract pageTextStyle: TextStyle;
|
|
27
|
+
protected checkboxLabel: Text;
|
|
28
|
+
protected checkboxSprite: Sprite;
|
|
29
|
+
protected checkboxTick: Sprite;
|
|
30
|
+
protected continueButton: IntroContinueButton;
|
|
31
|
+
protected dots: IntroDotButton[];
|
|
32
|
+
protected frameImage: Sprite;
|
|
33
|
+
protected pageImage: Sprite;
|
|
34
|
+
protected pageText: Text;
|
|
35
|
+
private currentPage;
|
|
36
|
+
private isChecked;
|
|
37
|
+
private isAnimating;
|
|
38
|
+
private fadeTween?;
|
|
39
|
+
private readonly FADE_DURATION;
|
|
40
|
+
private readonly onContinueCallback;
|
|
41
|
+
private readonly resizeHandler;
|
|
42
|
+
protected constructor(onContinue: () => void);
|
|
43
|
+
init(): void;
|
|
44
|
+
resize(): void;
|
|
45
|
+
protected abstract positionContinueButton(): void;
|
|
46
|
+
protected abstract positionDots(): void;
|
|
47
|
+
protected abstract positionText(): void;
|
|
48
|
+
protected abstract positionCheckbox(): void;
|
|
49
|
+
protected abstract positionLogo(): void;
|
|
50
|
+
protected abstract getPageImageScale(): {
|
|
51
|
+
vertical: number;
|
|
52
|
+
horizontal: number;
|
|
53
|
+
};
|
|
54
|
+
protected abstract positionPageImage(): void;
|
|
55
|
+
protected showPage(index: number): void;
|
|
56
|
+
private updateFade;
|
|
57
|
+
private cleanup;
|
|
58
|
+
private createDots;
|
|
59
|
+
private navigatePage;
|
|
60
|
+
private handleContinue;
|
|
61
|
+
private toggleCheckbox;
|
|
62
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as TWEEN from "@tweenjs/tween.js";
|
|
2
|
+
import { Container, Sprite, Text, Texture, Ticker } from "pixi.js";
|
|
3
|
+
import { UXLayer } from "../../layers";
|
|
4
|
+
import { getFromLocalStorage, LOCAL_STORAGE, setToLocalStorage } from "../../localStorage";
|
|
5
|
+
import { RainMan } from "../../Rainman";
|
|
6
|
+
import { getDeviceOrientation, getTexture, scaleToParent } from "../../utils";
|
|
7
|
+
import { IntroContinueButton } from "./IntroContinueButton";
|
|
8
|
+
import { IntroDotButton } from "./IntroDotButton";
|
|
9
|
+
/**
|
|
10
|
+
* Abstract intro screen shown between loading and gameplay.
|
|
11
|
+
* Each game subclasses this and provides assets + page definitions as properties.
|
|
12
|
+
* @abstract
|
|
13
|
+
* @class AbstractIntroScreen
|
|
14
|
+
* @typedef {AbstractIntroScreen}
|
|
15
|
+
* @augments {Container}
|
|
16
|
+
*/
|
|
17
|
+
export class AbstractIntroScreen extends Container {
|
|
18
|
+
static shouldSkip() {
|
|
19
|
+
return getFromLocalStorage(LOCAL_STORAGE.introScreenHidden, false);
|
|
20
|
+
}
|
|
21
|
+
checkboxLabel;
|
|
22
|
+
checkboxSprite;
|
|
23
|
+
checkboxTick;
|
|
24
|
+
continueButton;
|
|
25
|
+
dots = [];
|
|
26
|
+
frameImage;
|
|
27
|
+
pageImage;
|
|
28
|
+
pageText;
|
|
29
|
+
currentPage = 0;
|
|
30
|
+
isChecked = false;
|
|
31
|
+
isAnimating = false;
|
|
32
|
+
fadeTween;
|
|
33
|
+
FADE_DURATION = 200;
|
|
34
|
+
onContinueCallback;
|
|
35
|
+
resizeHandler = () => this.resize();
|
|
36
|
+
constructor(onContinue) {
|
|
37
|
+
super();
|
|
38
|
+
this.onContinueCallback = onContinue;
|
|
39
|
+
this.parentLayer = UXLayer;
|
|
40
|
+
this.eventMode = "static";
|
|
41
|
+
}
|
|
42
|
+
init() {
|
|
43
|
+
this.frameImage = new Sprite();
|
|
44
|
+
this.pageImage = new Sprite();
|
|
45
|
+
this.pageText = new Text("", this.pageTextStyle);
|
|
46
|
+
this.pageText.anchor.set(0.5);
|
|
47
|
+
this.continueButton = new IntroContinueButton();
|
|
48
|
+
this.continueButton.setOnClick(() => {
|
|
49
|
+
this.handleContinue();
|
|
50
|
+
});
|
|
51
|
+
this.createDots();
|
|
52
|
+
this.checkboxSprite = new Sprite(this.checkboxTextures.frame);
|
|
53
|
+
this.checkboxSprite.eventMode = "static";
|
|
54
|
+
this.checkboxSprite.cursor = "pointer";
|
|
55
|
+
this.checkboxSprite.anchor.set(0.5);
|
|
56
|
+
this.checkboxSprite.on("pointerdown", () => this.toggleCheckbox());
|
|
57
|
+
this.checkboxTick = new Sprite(this.checkboxTextures.tick);
|
|
58
|
+
this.checkboxTick.visible = false;
|
|
59
|
+
this.checkboxTick.eventMode = "static";
|
|
60
|
+
this.checkboxTick.cursor = "pointer";
|
|
61
|
+
this.checkboxTick.anchor.set(0.5);
|
|
62
|
+
this.checkboxTick.on("pointerdown", () => this.toggleCheckbox());
|
|
63
|
+
this.checkboxLabel = new Text(this.checkboxLabelText, this.checkboxTextStyle);
|
|
64
|
+
this.checkboxLabel.eventMode = "static";
|
|
65
|
+
this.checkboxLabel.cursor = "pointer";
|
|
66
|
+
this.checkboxLabel.anchor.set(0.5);
|
|
67
|
+
this.checkboxLabel.on("pointerdown", () => this.toggleCheckbox());
|
|
68
|
+
Ticker.shared.add(this.updateFade, this);
|
|
69
|
+
this.showPage(0);
|
|
70
|
+
RainMan.app.renderer.on("resize", this.resizeHandler);
|
|
71
|
+
this.resize();
|
|
72
|
+
}
|
|
73
|
+
resize() {
|
|
74
|
+
this.fadeTween?.stop();
|
|
75
|
+
this.fadeTween = undefined;
|
|
76
|
+
this.isAnimating = false;
|
|
77
|
+
const orientation = getDeviceOrientation();
|
|
78
|
+
const isPortrait = orientation === "mobile-portrait";
|
|
79
|
+
this.removeChildren();
|
|
80
|
+
const bg = isPortrait ? this.backgroundPortrait : this.background;
|
|
81
|
+
bg.width = RainMan.app.screen.width;
|
|
82
|
+
bg.height = RainMan.app.screen.height;
|
|
83
|
+
this.addChild(bg);
|
|
84
|
+
this.frameImage.texture = getTexture(isPortrait ? "intro-frame-mobile.png" : "intro-frame.png");
|
|
85
|
+
this.showPage(this.currentPage);
|
|
86
|
+
this.pageImage.alpha = 1;
|
|
87
|
+
this.pageText.alpha = 1;
|
|
88
|
+
const pageImageScale = this.getPageImageScale();
|
|
89
|
+
const dimensions = scaleToParent(this.pageImage.texture.width, this.pageImage.texture.height, RainMan.app.screen.width * pageImageScale.horizontal, RainMan.app.screen.height * pageImageScale.vertical);
|
|
90
|
+
this.pageImage.width = dimensions.width;
|
|
91
|
+
this.pageImage.height = dimensions.height;
|
|
92
|
+
const scale = this.pageImage.scale.x;
|
|
93
|
+
this.continueButton.scale.set(scale);
|
|
94
|
+
this.pageText.scale.set(scale);
|
|
95
|
+
this.checkboxSprite.scale.set(scale);
|
|
96
|
+
this.checkboxTick.scale.set(scale);
|
|
97
|
+
this.checkboxLabel.scale.set(scale);
|
|
98
|
+
this.dots.forEach((dot) => dot.scale.set(scale));
|
|
99
|
+
this.pageImage.x = RainMan.app.screen.width / 2 - this.pageImage.width / 2;
|
|
100
|
+
this.pageImage.y = RainMan.app.screen.height / 2 - this.pageImage.height / 2;
|
|
101
|
+
this.addChild(this.frameImage);
|
|
102
|
+
this.addChild(this.frameImage);
|
|
103
|
+
this.addChild(this.pageImage);
|
|
104
|
+
this.addChild(this.pageText);
|
|
105
|
+
this.addChild(this.continueButton);
|
|
106
|
+
this.addChild(this.checkboxSprite);
|
|
107
|
+
this.addChild(this.checkboxTick);
|
|
108
|
+
this.addChild(this.checkboxLabel);
|
|
109
|
+
this.dots.forEach((dot) => this.addChild(dot));
|
|
110
|
+
this.positionPageImage();
|
|
111
|
+
this.positionLogo();
|
|
112
|
+
this.positionDots();
|
|
113
|
+
this.positionCheckbox();
|
|
114
|
+
this.positionContinueButton();
|
|
115
|
+
this.positionText();
|
|
116
|
+
this.frameImage.x = this.pageImage.x;
|
|
117
|
+
this.frameImage.y = this.pageImage.y;
|
|
118
|
+
this.frameImage.width = this.pageImage.width;
|
|
119
|
+
this.frameImage.height = this.pageImage.height;
|
|
120
|
+
this.frameImage.x = this.pageImage.x;
|
|
121
|
+
this.frameImage.y = this.pageImage.y;
|
|
122
|
+
this.frameImage.width = this.pageImage.width;
|
|
123
|
+
this.frameImage.height = this.pageImage.height;
|
|
124
|
+
}
|
|
125
|
+
showPage(index) {
|
|
126
|
+
if (index < 0 || index >= this.pages.length)
|
|
127
|
+
return;
|
|
128
|
+
this.currentPage = index;
|
|
129
|
+
const page = this.pages[index];
|
|
130
|
+
const isPortrait = getDeviceOrientation() === "mobile-portrait";
|
|
131
|
+
this.pageImage.texture = Texture.from(isPortrait ? page.imageMobile : page.imageDesktop);
|
|
132
|
+
this.pageText.text = page.text;
|
|
133
|
+
for (let i = 0; i < this.dots.length; i++) {
|
|
134
|
+
this.dots[i].setActive(i === index);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
updateFade() {
|
|
138
|
+
this.fadeTween?.update();
|
|
139
|
+
}
|
|
140
|
+
cleanup() {
|
|
141
|
+
Ticker.shared.remove(this.updateFade, this);
|
|
142
|
+
Ticker.shared.remove(this.updateFade, this);
|
|
143
|
+
RainMan.app.renderer.off("resize", this.resizeHandler);
|
|
144
|
+
this.destroy({ children: true });
|
|
145
|
+
}
|
|
146
|
+
createDots() {
|
|
147
|
+
this.dots = [];
|
|
148
|
+
for (let i = 0; i < this.pages.length; i++) {
|
|
149
|
+
const dot = new IntroDotButton(i);
|
|
150
|
+
dot.setOnClick(() => this.navigatePage(i));
|
|
151
|
+
dot.setOnClick(() => this.navigatePage(i));
|
|
152
|
+
this.dots.push(dot);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
navigatePage(index) {
|
|
156
|
+
if (this.isAnimating || index === this.currentPage)
|
|
157
|
+
return;
|
|
158
|
+
this.isAnimating = true;
|
|
159
|
+
this.fadeTween?.stop();
|
|
160
|
+
this.fadeTween = new TWEEN.Tween({ alpha: this.pageImage.alpha })
|
|
161
|
+
.to({ alpha: 0 }, this.FADE_DURATION)
|
|
162
|
+
.onUpdate((obj) => {
|
|
163
|
+
this.pageImage.alpha = obj.alpha;
|
|
164
|
+
this.pageText.alpha = obj.alpha;
|
|
165
|
+
})
|
|
166
|
+
.onComplete(() => {
|
|
167
|
+
this.showPage(index);
|
|
168
|
+
this.fadeTween = new TWEEN.Tween({ alpha: 0 })
|
|
169
|
+
.to({ alpha: 1 }, this.FADE_DURATION)
|
|
170
|
+
.onUpdate((obj) => {
|
|
171
|
+
this.pageImage.alpha = obj.alpha;
|
|
172
|
+
this.pageText.alpha = obj.alpha;
|
|
173
|
+
})
|
|
174
|
+
.onComplete(() => {
|
|
175
|
+
this.isAnimating = false;
|
|
176
|
+
})
|
|
177
|
+
.start();
|
|
178
|
+
})
|
|
179
|
+
.start();
|
|
180
|
+
}
|
|
181
|
+
handleContinue() {
|
|
182
|
+
if (this.isChecked) {
|
|
183
|
+
setToLocalStorage(LOCAL_STORAGE.introScreenHidden, true);
|
|
184
|
+
}
|
|
185
|
+
this.cleanup();
|
|
186
|
+
this.onContinueCallback();
|
|
187
|
+
}
|
|
188
|
+
toggleCheckbox() {
|
|
189
|
+
this.isChecked = !this.isChecked;
|
|
190
|
+
this.checkboxTick.visible = this.isChecked;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseButton } from "../buttons/BaseButton";
|
|
2
|
+
/**
|
|
3
|
+
* Button for starting game after intro screen.
|
|
4
|
+
* It needs following textures:
|
|
5
|
+
* - normal - `intro-continue-n.png`
|
|
6
|
+
* - hover - `intro-continue-h.png`
|
|
7
|
+
* - clicked - `intro-continue-c.png`
|
|
8
|
+
* @augments {BaseButton}
|
|
9
|
+
*/
|
|
10
|
+
export declare class IntroContinueButton extends BaseButton {
|
|
11
|
+
static registryName: string;
|
|
12
|
+
constructor();
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getTexture } from "../../utils";
|
|
2
|
+
import { BaseButton, ButtonStates } from "../buttons/BaseButton";
|
|
3
|
+
/**
|
|
4
|
+
* Button for starting game after intro screen.
|
|
5
|
+
* It needs following textures:
|
|
6
|
+
* - normal - `intro-continue-n.png`
|
|
7
|
+
* - hover - `intro-continue-h.png`
|
|
8
|
+
* - clicked - `intro-continue-c.png`
|
|
9
|
+
* @augments {BaseButton}
|
|
10
|
+
*/
|
|
11
|
+
export class IntroContinueButton extends BaseButton {
|
|
12
|
+
static registryName = "introContinueButton";
|
|
13
|
+
constructor() {
|
|
14
|
+
const textureMap = {
|
|
15
|
+
[ButtonStates.NORMAL]: getTexture("intro-continue-n.png"),
|
|
16
|
+
[ButtonStates.OVER]: getTexture("intro-continue-h.png"),
|
|
17
|
+
[ButtonStates.CLICKED]: getTexture("intro-continue-c.png")
|
|
18
|
+
};
|
|
19
|
+
super(IntroContinueButton.registryName, textureMap);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseButton } from "../buttons/BaseButton";
|
|
2
|
+
/**
|
|
3
|
+
* Dot button for intro screen page navigation.
|
|
4
|
+
* Textures:
|
|
5
|
+
* - normal - `dot-off-n.png`
|
|
6
|
+
* - hover - `dot-off-h.png`
|
|
7
|
+
* - clicked - `dot-off-c.png`
|
|
8
|
+
* - active (current page) - `dot-on.png`
|
|
9
|
+
* @augments {BaseButton}
|
|
10
|
+
*/
|
|
11
|
+
export declare class IntroDotButton extends BaseButton {
|
|
12
|
+
static registryName: string;
|
|
13
|
+
constructor(index: number);
|
|
14
|
+
setActive(active: boolean): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getTexture } from "../../utils";
|
|
2
|
+
import { BaseButton, ButtonStates } from "../buttons/BaseButton";
|
|
3
|
+
/**
|
|
4
|
+
* Dot button for intro screen page navigation.
|
|
5
|
+
* Textures:
|
|
6
|
+
* - normal - `dot-off-n.png`
|
|
7
|
+
* - hover - `dot-off-h.png`
|
|
8
|
+
* - clicked - `dot-off-c.png`
|
|
9
|
+
* - active (current page) - `dot-on.png`
|
|
10
|
+
* @augments {BaseButton}
|
|
11
|
+
*/
|
|
12
|
+
export class IntroDotButton extends BaseButton {
|
|
13
|
+
static registryName = "introDotButton";
|
|
14
|
+
constructor(index) {
|
|
15
|
+
const textureMap = {
|
|
16
|
+
[ButtonStates.NORMAL]: getTexture("dot-off-n.png"),
|
|
17
|
+
[ButtonStates.OVER]: getTexture("dot-off-h.png"),
|
|
18
|
+
[ButtonStates.CLICKED]: getTexture("dot-off-c.png"),
|
|
19
|
+
[ButtonStates.ACTIVE]: getTexture("dot-on.png"),
|
|
20
|
+
[ButtonStates.ACTIVE_OVER]: getTexture("dot-on.png"),
|
|
21
|
+
[ButtonStates.ACTIVE_CLICKED]: getTexture("dot-on.png")
|
|
22
|
+
};
|
|
23
|
+
super(`${IntroDotButton.registryName}-${index}`, textureMap);
|
|
24
|
+
this.anchor.set(0.5);
|
|
25
|
+
this.cursor = "pointer";
|
|
26
|
+
}
|
|
27
|
+
setActive(active) {
|
|
28
|
+
this.activate(active);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -93,6 +93,7 @@ export class AbstractColumnsContainer extends Container {
|
|
|
93
93
|
*/
|
|
94
94
|
enableQuickReelsStop() {
|
|
95
95
|
this.quickReelsStop = true;
|
|
96
|
+
RainMan.settingsStore.isQuickSpinsActive = true;
|
|
96
97
|
RainMan.settingsStore.setIsTemporarySpeed(true);
|
|
97
98
|
RainMan.componentRegistry.setTemporarySpeedLevel(SPEED_LEVELS.fast);
|
|
98
99
|
this.skipScatterDelay?.();
|
|
@@ -109,6 +110,7 @@ export class AbstractColumnsContainer extends Container {
|
|
|
109
110
|
*/
|
|
110
111
|
clearQuickReelsStop() {
|
|
111
112
|
this.quickReelsStop = false;
|
|
113
|
+
RainMan.settingsStore.isQuickSpinsActive = false;
|
|
112
114
|
RainMan.componentRegistry.revertTemporarySpeedLevel();
|
|
113
115
|
}
|
|
114
116
|
/**
|
|
@@ -138,7 +140,6 @@ export class AbstractColumnsContainer extends Container {
|
|
|
138
140
|
await Promise.all(configuredBlindSpinsActions.map(async (action) => await action()));
|
|
139
141
|
configuredBlindSpinsActions.length = 0;
|
|
140
142
|
SoundManager.play(SoundTracks.allRollStops);
|
|
141
|
-
this.clearQuickReelsStop();
|
|
142
143
|
break;
|
|
143
144
|
}
|
|
144
145
|
const configureSpinAction = configuredBlindSpinsActions.shift();
|
package/dist/components/index.js
CHANGED
|
@@ -53,6 +53,9 @@ export declare abstract class AbstractController<T> {
|
|
|
53
53
|
protected shouldDisableBetButtons: boolean;
|
|
54
54
|
protected wasAutoplayEnabledBeforeFreeSpin: boolean;
|
|
55
55
|
protected setSlowerSpeedForFreeSpins: boolean;
|
|
56
|
+
protected quickReelsCounter: number;
|
|
57
|
+
protected buttonPressed: boolean;
|
|
58
|
+
protected buttonHeldSince: number;
|
|
56
59
|
shouldStopMobileSpin: boolean;
|
|
57
60
|
disableMessageBoxChange: boolean;
|
|
58
61
|
protected resolveBigWin?: () => void;
|
|
@@ -53,6 +53,9 @@ export class AbstractController {
|
|
|
53
53
|
shouldDisableBetButtons = false;
|
|
54
54
|
wasAutoplayEnabledBeforeFreeSpin = false;
|
|
55
55
|
setSlowerSpeedForFreeSpins = false;
|
|
56
|
+
quickReelsCounter = 0;
|
|
57
|
+
buttonPressed = false;
|
|
58
|
+
buttonHeldSince = 0;
|
|
56
59
|
shouldStopMobileSpin = false;
|
|
57
60
|
disableMessageBoxChange = false;
|
|
58
61
|
resolveBigWin;
|
|
@@ -164,6 +167,13 @@ export class AbstractController {
|
|
|
164
167
|
window.addEventListener("keydown", (keyboardEvent) => {
|
|
165
168
|
if (keyboardEvent.code === "Space" || keyboardEvent.code === "Enter") {
|
|
166
169
|
keyboardEvent.preventDefault();
|
|
170
|
+
if (this.buttonHeldSince === 0) {
|
|
171
|
+
this.buttonHeldSince = Date.now();
|
|
172
|
+
}
|
|
173
|
+
const buttonHold = Date.now() - this.buttonHeldSince;
|
|
174
|
+
if (buttonHold >= 500) {
|
|
175
|
+
this.columnsContainer.enableQuickReelsStop();
|
|
176
|
+
}
|
|
167
177
|
if (RainMan.settingsStore.isGambleGameActive || RainMan.settingsStore.isSpeedModalShown) {
|
|
168
178
|
return;
|
|
169
179
|
}
|
|
@@ -174,6 +184,17 @@ export class AbstractController {
|
|
|
174
184
|
this.handleSpinLogic();
|
|
175
185
|
}
|
|
176
186
|
});
|
|
187
|
+
window.addEventListener("keyup", (keyboardEvent) => {
|
|
188
|
+
if (keyboardEvent.code === "Space" || keyboardEvent.code === "Enter") {
|
|
189
|
+
keyboardEvent.preventDefault();
|
|
190
|
+
this.buttonHeldSince = 0;
|
|
191
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
window.addEventListener("blur", () => {
|
|
195
|
+
this.buttonHeldSince = 0;
|
|
196
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
197
|
+
});
|
|
177
198
|
}
|
|
178
199
|
/**
|
|
179
200
|
* This function sets up a listener for resize event
|
|
@@ -359,7 +380,7 @@ export class AbstractController {
|
|
|
359
380
|
if (availableFreeSpins > 0) {
|
|
360
381
|
this._lastWinAmount = this.initData.round_win_amount;
|
|
361
382
|
}
|
|
362
|
-
if (spinLogic.winTotalAmount !== 0 && spinLogic.winTotalAmount) {
|
|
383
|
+
if (spinLogic.winTotalAmount !== 0 && spinLogic.winTotalAmount !== undefined) {
|
|
363
384
|
this.uiController.recentWin = ceilToDecimal(spinLogic.winTotalAmount);
|
|
364
385
|
this.uiController.totalFreeSpinWinAmount = this._lastWinAmount;
|
|
365
386
|
}
|
|
@@ -407,6 +428,8 @@ export class AbstractController {
|
|
|
407
428
|
initSpinButton() {
|
|
408
429
|
const refreshButton = RainMan.componentRegistry.get(RefreshButton.registryName);
|
|
409
430
|
this.clearMobileSpinTimeout = () => {
|
|
431
|
+
this.buttonHeldSince = 0;
|
|
432
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
410
433
|
if (this.mobileSpinTimeout) {
|
|
411
434
|
clearInterval(this.mobileSpinTimeout);
|
|
412
435
|
this.quickStopController.setQuickStopCounterLock(false);
|
|
@@ -450,25 +473,30 @@ export class AbstractController {
|
|
|
450
473
|
this.clearMobileSpinTimeout();
|
|
451
474
|
});
|
|
452
475
|
refreshButton.on("touchstart", () => {
|
|
453
|
-
this.
|
|
454
|
-
this.
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
476
|
+
if (this.buttonHeldSince === 0) {
|
|
477
|
+
this.buttonHeldSince = Date.now();
|
|
478
|
+
}
|
|
479
|
+
this.mobileSpinTimeout = setInterval(() => {
|
|
480
|
+
const buttonHold = Date.now() - this.buttonHeldSince;
|
|
481
|
+
if (buttonHold >= 500) {
|
|
482
|
+
this.columnsContainer.enableQuickReelsStop();
|
|
483
|
+
}
|
|
484
|
+
this.handleDisablingButtons(true);
|
|
485
|
+
this.quickStopController.setQuickStopCounterLock(true);
|
|
486
|
+
this.summaryStop = this.skipFreeSpinSummary ? false : this.invokeFreeSpinSummaryPlateAfterWin;
|
|
487
|
+
if (this.invokeFreeSpinPlateAfterWin ||
|
|
488
|
+
this.summaryStop ||
|
|
489
|
+
this.shouldStopMobileSpin ||
|
|
490
|
+
this.resolveBigWin !== undefined ||
|
|
491
|
+
this.resolveSuperBonusWin !== undefined ||
|
|
492
|
+
this.resolveMysteryWin !== undefined) {
|
|
493
|
+
if (this.clearMobileSpinTimeout) {
|
|
494
|
+
this.clearMobileSpinTimeout();
|
|
468
495
|
}
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
this.handleSpinLogic();
|
|
499
|
+
}, RainMan.config.durationOfActions.mobileSpinTimeout);
|
|
472
500
|
});
|
|
473
501
|
}
|
|
474
502
|
/**
|
|
@@ -672,7 +700,10 @@ export class AbstractController {
|
|
|
672
700
|
this.handleDisablingButtons(true);
|
|
673
701
|
RainMan.globals.shouldShowModals = false;
|
|
674
702
|
RainMan.settingsStore.closeCurrentlyOpenModal?.();
|
|
675
|
-
|
|
703
|
+
const realTime = Date.now() - this.buttonHeldSince;
|
|
704
|
+
if (realTime <= 500) {
|
|
705
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
706
|
+
}
|
|
676
707
|
if (this.mainContainer.freeSpinPlate) {
|
|
677
708
|
if (this.mainContainer.freeSpinPlate.shownAt === null ||
|
|
678
709
|
performance.now() - this.mainContainer.freeSpinPlate.shownAt <
|
|
@@ -729,6 +760,7 @@ export class AbstractController {
|
|
|
729
760
|
* @returns {void}
|
|
730
761
|
*/
|
|
731
762
|
throttledSpin() {
|
|
763
|
+
this.quickReelsCounter += 1;
|
|
732
764
|
this.columnsContainer.setInteractivityForSymbols(false);
|
|
733
765
|
this.handleDisablingButtons(true);
|
|
734
766
|
RainMan.globals.shouldShowModals = false;
|
|
@@ -741,7 +773,6 @@ export class AbstractController {
|
|
|
741
773
|
if (this.gamePhase === gamePhases.DATA_FETCH ||
|
|
742
774
|
this.gamePhase === gamePhases.SPINNING ||
|
|
743
775
|
this.gamePhase === gamePhases.CONFIGURING_SPIN) {
|
|
744
|
-
this.columnsContainer.enableQuickReelsStop();
|
|
745
776
|
this.isSpinThrottled = true;
|
|
746
777
|
this.quickStopController.handleResetCounter(this.spinThrottlerTimeout !== null);
|
|
747
778
|
this.quickStopController.handleInvokingSpeedPopup();
|
|
@@ -762,10 +793,6 @@ export class AbstractController {
|
|
|
762
793
|
this.mainContainer.destroyBigWin();
|
|
763
794
|
this.changeGamePhase(gamePhases.IDLE);
|
|
764
795
|
}
|
|
765
|
-
if (this.spinThrottlerTimeout !== null && !RainMan.settingsStore.isFreeSpinsPlayEnabled) {
|
|
766
|
-
this.columnsContainer.clearQuickReelsStop();
|
|
767
|
-
return;
|
|
768
|
-
}
|
|
769
796
|
if (this.gamePhase === gamePhases.IDLE || this.gamePhase === gamePhases.HANDLING_ACTIONS) {
|
|
770
797
|
this.spin();
|
|
771
798
|
}
|
|
@@ -1025,7 +1052,6 @@ export class AbstractController {
|
|
|
1025
1052
|
await this.onSpinningStart();
|
|
1026
1053
|
hideVolumeModal();
|
|
1027
1054
|
RainMan.settingsStore.disableSpecialButtons();
|
|
1028
|
-
this.columnsContainer.clearQuickReelsStop();
|
|
1029
1055
|
this.columnsContainer.blindSpin();
|
|
1030
1056
|
this.clearAndDestroyActions();
|
|
1031
1057
|
const { spinLogic } = await this.fetchAndPrepareSpinData();
|
|
@@ -9,6 +9,7 @@ export declare const LOCAL_STORAGE: {
|
|
|
9
9
|
readonly isSoundEnabled: "isSoundEnabledLocalStorage";
|
|
10
10
|
readonly isSoundFxEnabled: "isSoundFxEnabledLocalStorage";
|
|
11
11
|
readonly isAmbientMusicEnabled: "isAmbientMusicEnabledLocalStorage";
|
|
12
|
+
readonly introScreenHidden: "introScreenHiddenLocalStorage";
|
|
12
13
|
};
|
|
13
14
|
/**
|
|
14
15
|
* Type for local storage keys
|
|
@@ -8,7 +8,8 @@ export const LOCAL_STORAGE = {
|
|
|
8
8
|
volumeLevel: "volumeLevelLocalStorage",
|
|
9
9
|
isSoundEnabled: "isSoundEnabledLocalStorage",
|
|
10
10
|
isSoundFxEnabled: "isSoundFxEnabledLocalStorage",
|
|
11
|
-
isAmbientMusicEnabled: "isAmbientMusicEnabledLocalStorage"
|
|
11
|
+
isAmbientMusicEnabled: "isAmbientMusicEnabledLocalStorage",
|
|
12
|
+
introScreenHidden: "introScreenHiddenLocalStorage"
|
|
12
13
|
};
|
|
13
14
|
/**
|
|
14
15
|
* Get a value from local storage
|
package/package.json
CHANGED