@rpgjs/client 5.0.0-beta.23 → 5.0.0-beta.24
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/CHANGELOG.md +13 -0
- package/dist/Game/Object.d.ts +5 -0
- package/dist/Game/Object.js +48 -2
- package/dist/Game/Object.js.map +1 -1
- package/dist/components/character.ce.js +9 -2
- package/dist/components/character.ce.js.map +1 -1
- package/dist/components/gui/dialogbox/index.ce.js +31 -2
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/hud/hud.ce.js +2 -2
- package/dist/components/gui/hud/hud.ce.js.map +1 -1
- package/dist/components/gui/menu/items-menu.ce.js +27 -4
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/main-menu.ce.js +210 -155
- package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
- package/dist/components/gui/save-load.ce.js +33 -4
- package/dist/components/gui/save-load.ce.js.map +1 -1
- package/dist/components/gui/shop/shop.ce.js +47 -4
- package/dist/components/gui/shop/shop.ce.js.map +1 -1
- package/package.json +4 -4
- package/src/Game/Object.spec.ts +26 -2
- package/src/Game/Object.ts +71 -2
- package/src/components/character.ce +12 -6
- package/src/components/gui/dialogbox/index.ce +56 -40
- package/src/components/gui/hud/hud.ce +2 -2
- package/src/components/gui/menu/items-menu.ce +12 -2
- package/src/components/gui/menu/main-menu.ce +37 -6
- package/src/components/gui/save-load.ce +48 -32
- package/src/components/gui/shop/shop.ce +28 -3
package/src/Game/Object.ts
CHANGED
|
@@ -29,12 +29,49 @@ type ConfigurableTrigger<T> = Omit<Trigger<T>, "start"> & {
|
|
|
29
29
|
start(config?: T): Promise<void>;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
const toFiniteScale = (value: unknown, fallback: number): number => {
|
|
33
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
34
|
+
if (typeof value === "string" && value.trim()) {
|
|
35
|
+
const parsed = Number(value);
|
|
36
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
37
|
+
}
|
|
38
|
+
return fallback;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const normalizeGraphicScale = (value: unknown, fallback: [number, number] = [1, 1]): [number, number] => {
|
|
42
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
43
|
+
const scale = toFiniteScale(value, fallback[0]);
|
|
44
|
+
return [scale, scale];
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
const x = toFiniteScale(value[0], fallback[0]);
|
|
48
|
+
const y = toFiniteScale(value[1] ?? value[0], x);
|
|
49
|
+
return [x, y];
|
|
50
|
+
}
|
|
51
|
+
if (value && typeof value === "object") {
|
|
52
|
+
const scale = value as { x?: unknown; y?: unknown };
|
|
53
|
+
const x = toFiniteScale(scale.x, fallback[0]);
|
|
54
|
+
const y = toFiniteScale(scale.y ?? scale.x, x);
|
|
55
|
+
return [x, y];
|
|
56
|
+
}
|
|
57
|
+
return fallback;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const multiplyGraphicDisplayScale = (
|
|
61
|
+
baseScale: unknown,
|
|
62
|
+
instanceScale: unknown,
|
|
63
|
+
): [number, number] => {
|
|
64
|
+
const base = normalizeGraphicScale(baseScale);
|
|
65
|
+
const instance = normalizeGraphicScale(instanceScale);
|
|
66
|
+
return [base[0] * instance[0], base[1] * instance[1]];
|
|
67
|
+
};
|
|
68
|
+
|
|
32
69
|
export const withGraphicDisplayScale = (spritesheet: any, scale: unknown): any => {
|
|
33
70
|
if (!spritesheet || typeof spritesheet !== "object") return spritesheet;
|
|
34
71
|
if (scale === undefined || scale === null) return spritesheet;
|
|
35
72
|
return {
|
|
36
73
|
...spritesheet,
|
|
37
|
-
displayScale: scale,
|
|
74
|
+
displayScale: multiplyGraphicDisplayScale(spritesheet.displayScale, scale),
|
|
38
75
|
};
|
|
39
76
|
};
|
|
40
77
|
|
|
@@ -47,6 +84,24 @@ export const appendFramePayload = (current: unknown, items: unknown): Frame[] =>
|
|
|
47
84
|
return currentFrames.concat(nextFrames);
|
|
48
85
|
};
|
|
49
86
|
|
|
87
|
+
export const getFrameTimestamp = (frame: Frame): number => {
|
|
88
|
+
const timestamp = Number(frame.ts);
|
|
89
|
+
return Number.isFinite(timestamp) ? timestamp : 0;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const mergeFreshFramePayload = (
|
|
93
|
+
current: unknown,
|
|
94
|
+
items: unknown,
|
|
95
|
+
lastAppliedFrameTs = 0,
|
|
96
|
+
): Frame[] => {
|
|
97
|
+
return appendFramePayload(current, items)
|
|
98
|
+
.filter((frame) => {
|
|
99
|
+
const timestamp = getFrameTimestamp(frame);
|
|
100
|
+
return timestamp === 0 || timestamp > lastAppliedFrameTs;
|
|
101
|
+
})
|
|
102
|
+
.sort((a, b) => getFrameTimestamp(a) - getFrameTimestamp(b));
|
|
103
|
+
};
|
|
104
|
+
|
|
50
105
|
export abstract class RpgClientObject extends RpgCommonPlayer {
|
|
51
106
|
abstract _type: string;
|
|
52
107
|
emitParticleTrigger = trigger();
|
|
@@ -57,6 +112,7 @@ export abstract class RpgClientObject extends RpgCommonPlayer {
|
|
|
57
112
|
frames: Frame[] = [];
|
|
58
113
|
graphicsSignals = signal<any[]>([]);
|
|
59
114
|
flashTrigger: ConfigurableTrigger<FlashTriggerOptions> = trigger<FlashTriggerOptions>();
|
|
115
|
+
private lastAppliedFrameTs = 0;
|
|
60
116
|
private animationRestoreState?: {
|
|
61
117
|
animationName: string;
|
|
62
118
|
graphics: any[];
|
|
@@ -70,7 +126,11 @@ export abstract class RpgClientObject extends RpgCommonPlayer {
|
|
|
70
126
|
this._frames.observable.subscribe(({ items }) => {
|
|
71
127
|
if (!this.id) return;
|
|
72
128
|
//if (this.id == this.engine.playerIdSignal()!) return;
|
|
73
|
-
this.frames =
|
|
129
|
+
this.frames = mergeFreshFramePayload(
|
|
130
|
+
this.frames,
|
|
131
|
+
items,
|
|
132
|
+
this.lastAppliedFrameTs,
|
|
133
|
+
);
|
|
74
134
|
});
|
|
75
135
|
|
|
76
136
|
const graphics$ = this.graphics.observable.pipe(map(({ items }) => items));
|
|
@@ -102,16 +162,25 @@ export abstract class RpgClientObject extends RpgCommonPlayer {
|
|
|
102
162
|
const frame = this.frames.shift();
|
|
103
163
|
if (frame) {
|
|
104
164
|
if (typeof frame.x !== "number" || typeof frame.y !== "number") return;
|
|
165
|
+
const frameTs = this.getFrameTimestamp(frame);
|
|
166
|
+
if (frameTs > 0 && frameTs <= this.lastAppliedFrameTs) return;
|
|
105
167
|
engine.scene.setBodyPosition(
|
|
106
168
|
this.id,
|
|
107
169
|
frame.x,
|
|
108
170
|
frame.y,
|
|
109
171
|
"top-left"
|
|
110
172
|
);
|
|
173
|
+
if (frameTs > this.lastAppliedFrameTs) {
|
|
174
|
+
this.lastAppliedFrameTs = frameTs;
|
|
175
|
+
}
|
|
111
176
|
}
|
|
112
177
|
});
|
|
113
178
|
}
|
|
114
179
|
|
|
180
|
+
private getFrameTimestamp(frame: Frame): number {
|
|
181
|
+
return getFrameTimestamp(frame);
|
|
182
|
+
}
|
|
183
|
+
|
|
115
184
|
/**
|
|
116
185
|
* Access the shared client hook registry.
|
|
117
186
|
*
|
|
@@ -521,6 +521,16 @@
|
|
|
521
521
|
});
|
|
522
522
|
};
|
|
523
523
|
|
|
524
|
+
let lastEscapeActionAt = 0;
|
|
525
|
+
const processEscapeInput = () => {
|
|
526
|
+
const now = Date.now();
|
|
527
|
+
if (now - lastEscapeActionAt < 50) return;
|
|
528
|
+
lastEscapeActionAt = now;
|
|
529
|
+
if (canControls()) {
|
|
530
|
+
client.processAction({ action: 'escape' })
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
|
|
524
534
|
const actionBind = () => getKeyboardControlBind(keyboardControls.action);
|
|
525
535
|
const keyboardEventId = (event) => `${event.keyCode}:${event.code}:${event.key}`;
|
|
526
536
|
|
|
@@ -616,17 +626,13 @@
|
|
|
616
626
|
back: {
|
|
617
627
|
bind: keyboardControls.escape,
|
|
618
628
|
keyDown() {
|
|
619
|
-
|
|
620
|
-
client.processAction({ action: 'escape' })
|
|
621
|
-
}
|
|
629
|
+
processEscapeInput()
|
|
622
630
|
},
|
|
623
631
|
},
|
|
624
632
|
escape: {
|
|
625
633
|
bind: keyboardControls.escape,
|
|
626
634
|
keyDown() {
|
|
627
|
-
|
|
628
|
-
client.processAction({ action: 'escape' })
|
|
629
|
-
}
|
|
635
|
+
processEscapeInput()
|
|
630
636
|
},
|
|
631
637
|
},
|
|
632
638
|
joystick: {
|
|
@@ -1,49 +1,52 @@
|
|
|
1
1
|
<DOMContainer width="100%" height="100%" controls={dialogControls}>
|
|
2
|
-
<div
|
|
3
|
-
class="rpg-ui-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
<div class="rpg-ui-dialog-layer" click={closeDialogFromPointer}>
|
|
3
|
+
<button class="rpg-ui-close-button" type="button" title="Close" aria-label="Close dialog" click={closeDialogFromPointer}>x</button>
|
|
4
|
+
<div
|
|
5
|
+
class="rpg-ui-dialog-container"
|
|
6
|
+
data-position={dialogPosition()}
|
|
7
|
+
data-full-width={isFullWidth() ? "true" : "false"}
|
|
8
|
+
data-has-face={hasFace() ? "true" : "false"}
|
|
9
|
+
>
|
|
10
|
+
<div class="rpg-ui-dialog rpg-anim-fade-in" click={stopEvent}>
|
|
11
|
+
<div class="rpg-ui-dialog-body">
|
|
12
|
+
<div>
|
|
13
|
+
@if (speakerName()) {
|
|
14
|
+
<div class="rpg-ui-dialog-speaker">{speakerName()}</div>
|
|
15
|
+
}
|
|
16
|
+
<div class="rpg-ui-dialog-content">
|
|
17
|
+
{displayMessage()}
|
|
18
|
+
</div>
|
|
19
|
+
@if (hasChoices()) {
|
|
20
|
+
<Navigation tabindex={selectedItem} controls={controls}>
|
|
21
|
+
<div class="rpg-ui-dialog-choices">
|
|
22
|
+
@for ((choice,index) of dialogChoices()) {
|
|
23
|
+
<div
|
|
24
|
+
class="rpg-ui-dialog-choice"
|
|
25
|
+
class={{active: selectedItem() === index}}
|
|
26
|
+
tabindex={index}
|
|
27
|
+
data-choice-index={index}
|
|
28
|
+
click={selectChoice(index)}
|
|
29
|
+
>{{ choice.text }}</div>
|
|
30
|
+
}
|
|
31
|
+
</div>
|
|
32
|
+
</Navigation>
|
|
33
|
+
}
|
|
16
34
|
</div>
|
|
17
|
-
@if (
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
click={selectChoice(index)}
|
|
27
|
-
>{{ choice.text }}</div>
|
|
28
|
-
}
|
|
29
|
-
</div>
|
|
30
|
-
</Navigation>
|
|
35
|
+
@if (hasFace()) {
|
|
36
|
+
<div class="rpg-ui-dialog-face">
|
|
37
|
+
<DOMSprite
|
|
38
|
+
sheet={faceSheet(dialogFace())}
|
|
39
|
+
width="100%"
|
|
40
|
+
height="100%"
|
|
41
|
+
objectFit="contain"
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
31
44
|
}
|
|
32
45
|
</div>
|
|
33
|
-
@if (
|
|
34
|
-
<div class="rpg-ui-dialog-
|
|
35
|
-
<DOMSprite
|
|
36
|
-
sheet={faceSheet(dialogFace())}
|
|
37
|
-
width="100%"
|
|
38
|
-
height="100%"
|
|
39
|
-
objectFit="contain"
|
|
40
|
-
/>
|
|
41
|
-
</div>
|
|
46
|
+
@if (showIndicator) {
|
|
47
|
+
<div class="rpg-ui-dialog-indicator"></div>
|
|
42
48
|
}
|
|
43
49
|
</div>
|
|
44
|
-
@if (showIndicator) {
|
|
45
|
-
<div class="rpg-ui-dialog-indicator"></div>
|
|
46
|
-
}
|
|
47
50
|
</div>
|
|
48
51
|
</div>
|
|
49
52
|
</DOMContainer>
|
|
@@ -160,6 +163,19 @@
|
|
|
160
163
|
if (onFinish) onFinish(value, normalizeOpenId(guiOpenId));
|
|
161
164
|
}
|
|
162
165
|
|
|
166
|
+
const stopEvent = (event) => {
|
|
167
|
+
event?.stopPropagation?.();
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const closeDialog = () => {
|
|
171
|
+
_onFinish();
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const closeDialogFromPointer = (event) => {
|
|
175
|
+
stopEvent(event);
|
|
176
|
+
closeDialog();
|
|
177
|
+
};
|
|
178
|
+
|
|
163
179
|
const onSelect = (index) => {
|
|
164
180
|
_onFinish(index);
|
|
165
181
|
};
|
|
@@ -63,8 +63,9 @@
|
|
|
63
63
|
</div>
|
|
64
64
|
</div>
|
|
65
65
|
@if (confirmOpen) {
|
|
66
|
-
<div class="rpg-ui-menu-confirm">
|
|
67
|
-
<
|
|
66
|
+
<div class="rpg-ui-menu-confirm" click={cancelConfirmFromPointer}>
|
|
67
|
+
<button class="rpg-ui-close-button" type="button" title="Close" aria-label="Close confirmation" click={cancelConfirmFromPointer}>x</button>
|
|
68
|
+
<div class="rpg-ui-menu-confirm-card" click={stopEvent}>
|
|
68
69
|
<div class="rpg-ui-menu-confirm-title">{t("rpg.menu.use")} {confirmItem()?.name}?</div>
|
|
69
70
|
<Navigation tabindex={selectedConfirm} controls={confirmControls}>
|
|
70
71
|
<div class="rpg-ui-menu-confirm-actions">
|
|
@@ -197,6 +198,15 @@
|
|
|
197
198
|
});
|
|
198
199
|
};
|
|
199
200
|
|
|
201
|
+
const stopEvent = (event) => {
|
|
202
|
+
event?.stopPropagation?.();
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const cancelConfirmFromPointer = (event) => {
|
|
206
|
+
stopEvent(event);
|
|
207
|
+
cancelConfirm();
|
|
208
|
+
};
|
|
209
|
+
|
|
200
210
|
function confirmSelect(index) {
|
|
201
211
|
return function() {
|
|
202
212
|
selectedConfirm.set(index);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<DOMContainer width="100%" height="100%" controls={menuControls}>
|
|
2
|
-
<div class="rpg-ui-main-menu rpg-anim-fade-in">
|
|
3
|
-
<div class="rpg-ui-main-menu-
|
|
2
|
+
<div class="rpg-ui-main-menu rpg-anim-fade-in" click={closeMenuFromPointer}>
|
|
3
|
+
<div class="rpg-ui-main-menu-backdrop"></div>
|
|
4
|
+
<button class="rpg-ui-close-button" type="button" title="Close" aria-label="Close menu" click={closeMenuFromPointer}>x</button>
|
|
5
|
+
<div class="rpg-ui-main-menu-layout" click={stopEvent}>
|
|
4
6
|
<div class="rpg-ui-main-menu-left rpg-ui-menu rpg-ui-panel">
|
|
5
7
|
<div class="rpg-ui-menu-header">{t("rpg.menu.title")}</div>
|
|
6
8
|
<div class="rpg-ui-main-menu-list">
|
|
@@ -77,8 +79,8 @@
|
|
|
77
79
|
</div>
|
|
78
80
|
@if (saveOverlay) {
|
|
79
81
|
<div class="rpg-ui-main-menu-overlay">
|
|
80
|
-
<div class="rpg-ui-main-menu-overlay-backdrop"></div>
|
|
81
|
-
<div class="rpg-ui-main-menu-overlay-content">
|
|
82
|
+
<div class="rpg-ui-main-menu-overlay-backdrop" click={closeSaveOverlayFromPointer}></div>
|
|
83
|
+
<div class="rpg-ui-main-menu-overlay-content" click={stopEvent}>
|
|
82
84
|
<SaveLoadComponent
|
|
83
85
|
data={saveLoadData}
|
|
84
86
|
onFinish={closeSaveOverlay}
|
|
@@ -202,6 +204,28 @@
|
|
|
202
204
|
});
|
|
203
205
|
};
|
|
204
206
|
|
|
207
|
+
const stopEvent = (event) => {
|
|
208
|
+
event?.stopPropagation?.();
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const closeSaveOverlayFromPointer = (event) => {
|
|
212
|
+
stopEvent(event);
|
|
213
|
+
closeSaveOverlay();
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const closeMenu = () => {
|
|
217
|
+
if (saveOverlay()) {
|
|
218
|
+
closeSaveOverlay();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
onFinish();
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const closeMenuFromPointer = (event) => {
|
|
225
|
+
stopEvent(event);
|
|
226
|
+
closeMenu();
|
|
227
|
+
};
|
|
228
|
+
|
|
205
229
|
const confirmExit = () => {
|
|
206
230
|
if (onInteraction) onInteraction("exit");
|
|
207
231
|
};
|
|
@@ -285,11 +309,18 @@
|
|
|
285
309
|
});
|
|
286
310
|
|
|
287
311
|
mount((element) => {
|
|
312
|
+
const inputLockToken = {};
|
|
313
|
+
const previousStopProcessingInput = engine.stopProcessingInput;
|
|
314
|
+
const previousGamePause = engine.gamePause();
|
|
315
|
+
engine.__rpgMainMenuInputLock = inputLockToken;
|
|
316
|
+
engine.stopProcessingInput = true;
|
|
288
317
|
engine.gamePause.set(true);
|
|
289
318
|
return () => {
|
|
290
319
|
delay(() => {
|
|
291
|
-
engine.
|
|
292
|
-
engine.
|
|
320
|
+
if (engine.__rpgMainMenuInputLock !== inputLockToken) return;
|
|
321
|
+
engine.__rpgMainMenuInputLock = undefined;
|
|
322
|
+
engine.stopProcessingInput = previousStopProcessingInput;
|
|
323
|
+
engine.gamePause.set(previousGamePause);
|
|
293
324
|
});
|
|
294
325
|
}
|
|
295
326
|
});
|
|
@@ -1,35 +1,38 @@
|
|
|
1
1
|
<DOMContainer width="100%" height="100%">
|
|
2
|
-
<div class="rpg-ui-save-load
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
<div class="rpg-ui-save-load-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<div class="rpg-ui-save-load-list">
|
|
9
|
-
@for ((item,displayIndex) of displaySlots) {
|
|
10
|
-
<div
|
|
11
|
-
class="rpg-ui-save-load-slot"
|
|
12
|
-
class={{active: selectedSlot() === displayIndex}}
|
|
13
|
-
tabindex={displayIndex}
|
|
14
|
-
data-slot-index={displayIndex}
|
|
15
|
-
click={selectSlot(displayIndex)}
|
|
16
|
-
>
|
|
17
|
-
<div class="rpg-ui-save-load-slot-index">{item.label}</div>
|
|
18
|
-
@if (item.slot) {
|
|
19
|
-
<div class="rpg-ui-save-load-slot-meta">
|
|
20
|
-
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.level")}: {item.slot.level ?? "-"}</div>
|
|
21
|
-
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.exp")}: {item.slot.exp ?? "-"}</div>
|
|
22
|
-
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.map")}: {item.slot.map ?? "-"}</div>
|
|
23
|
-
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.date")}: {item.slot.date ?? "-"}</div>
|
|
24
|
-
</div>
|
|
25
|
-
}
|
|
26
|
-
@else {
|
|
27
|
-
<div class="rpg-ui-save-load-slot-empty">{t("rpg.save.empty-slot")}</div>
|
|
28
|
-
}
|
|
29
|
-
</div>
|
|
30
|
-
}
|
|
2
|
+
<div class="rpg-ui-save-load-layer" click={closeSaveLoadFromPointer}>
|
|
3
|
+
<button class="rpg-ui-close-button" type="button" title="Close" aria-label="Close save menu" click={closeSaveLoadFromPointer}>x</button>
|
|
4
|
+
<div class="rpg-ui-save-load rpg-anim-fade-in" click={stopEvent}>
|
|
5
|
+
<div class="rpg-ui-save-load-header">
|
|
6
|
+
<div class="rpg-ui-save-load-title">{title()}</div>
|
|
7
|
+
<div class="rpg-ui-save-load-subtitle">{subtitle()}</div>
|
|
31
8
|
</div>
|
|
32
|
-
|
|
9
|
+
<Navigation tabindex={selectedSlot} controls={controls}>
|
|
10
|
+
<div class="rpg-ui-save-load-list">
|
|
11
|
+
@for ((item,displayIndex) of displaySlots) {
|
|
12
|
+
<div
|
|
13
|
+
class="rpg-ui-save-load-slot"
|
|
14
|
+
class={{active: selectedSlot() === displayIndex}}
|
|
15
|
+
tabindex={displayIndex}
|
|
16
|
+
data-slot-index={displayIndex}
|
|
17
|
+
click={selectSlot(displayIndex)}
|
|
18
|
+
>
|
|
19
|
+
<div class="rpg-ui-save-load-slot-index">{item.label}</div>
|
|
20
|
+
@if (item.slot) {
|
|
21
|
+
<div class="rpg-ui-save-load-slot-meta">
|
|
22
|
+
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.level")}: {item.slot.level ?? "-"}</div>
|
|
23
|
+
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.exp")}: {item.slot.exp ?? "-"}</div>
|
|
24
|
+
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.map")}: {item.slot.map ?? "-"}</div>
|
|
25
|
+
<div class="rpg-ui-save-load-slot-line">{t("rpg.save.date")}: {item.slot.date ?? "-"}</div>
|
|
26
|
+
</div>
|
|
27
|
+
}
|
|
28
|
+
@else {
|
|
29
|
+
<div class="rpg-ui-save-load-slot-empty">{t("rpg.save.empty-slot")}</div>
|
|
30
|
+
}
|
|
31
|
+
</div>
|
|
32
|
+
}
|
|
33
|
+
</div>
|
|
34
|
+
</Navigation>
|
|
35
|
+
</div>
|
|
33
36
|
</div>
|
|
34
37
|
</DOMContainer>
|
|
35
38
|
|
|
@@ -169,6 +172,20 @@
|
|
|
169
172
|
}
|
|
170
173
|
}
|
|
171
174
|
|
|
175
|
+
const stopEvent = (event) => {
|
|
176
|
+
event?.stopPropagation?.();
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const closeSaveLoad = () => {
|
|
180
|
+
if (onFinish) onFinish();
|
|
181
|
+
gui.hide(PrebuiltGui.Save);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const closeSaveLoadFromPointer = (event) => {
|
|
185
|
+
stopEvent(event);
|
|
186
|
+
closeSaveLoad();
|
|
187
|
+
};
|
|
188
|
+
|
|
172
189
|
const controls = signal({
|
|
173
190
|
up: {
|
|
174
191
|
repeat: true,
|
|
@@ -195,8 +212,7 @@
|
|
|
195
212
|
escape: {
|
|
196
213
|
bind: keyboardControls.escape,
|
|
197
214
|
keyDown() {
|
|
198
|
-
|
|
199
|
-
gui.hide(PrebuiltGui.Save);
|
|
215
|
+
closeSaveLoad();
|
|
200
216
|
}
|
|
201
217
|
},
|
|
202
218
|
gamepad: {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<DOMContainer width="100%" height="100%">
|
|
2
|
-
<div class="rpg-shop-
|
|
2
|
+
<div class="rpg-shop-layer" click={closeShopFromPointer}>
|
|
3
|
+
<button class="rpg-ui-close-button" type="button" title="Close" aria-label="Close shop" click={closeShopFromPointer}>x</button>
|
|
4
|
+
<div class="rpg-shop-container rpg-anim-fade-in" click={stopEvent}>
|
|
3
5
|
<div class="rpg-shop-header">
|
|
4
6
|
<div class="rpg-shop-merchant">
|
|
5
7
|
<div>
|
|
@@ -143,8 +145,8 @@
|
|
|
143
145
|
</div>
|
|
144
146
|
}
|
|
145
147
|
@if (quantityDialogOpen) {
|
|
146
|
-
<div class="rpg-shop-modal">
|
|
147
|
-
<div class="rpg-shop-modal-card">
|
|
148
|
+
<div class="rpg-shop-modal" click={closeQuantityDialogFromPointer}>
|
|
149
|
+
<div class="rpg-shop-modal-card" click={stopEvent}>
|
|
148
150
|
<div class="rpg-shop-modal-title">{{ actionLabel }}</div>
|
|
149
151
|
<div class="rpg-shop-modal-item">{{ currentItem()?.name || "" }}</div>
|
|
150
152
|
@if (currentItem()?.quantity !== undefined) {
|
|
@@ -174,6 +176,7 @@
|
|
|
174
176
|
</div>
|
|
175
177
|
</div>
|
|
176
178
|
</div>
|
|
179
|
+
</div>
|
|
177
180
|
</DOMContainer>
|
|
178
181
|
|
|
179
182
|
<script>
|
|
@@ -351,6 +354,28 @@
|
|
|
351
354
|
}
|
|
352
355
|
}
|
|
353
356
|
|
|
357
|
+
const stopEvent = (event) => {
|
|
358
|
+
event?.stopPropagation?.()
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const closeQuantityDialogFromPointer = (event) => {
|
|
362
|
+
stopEvent(event)
|
|
363
|
+
quantityDialogOpen.set(false)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const closeShop = () => {
|
|
367
|
+
if (quantityDialogOpen()) {
|
|
368
|
+
quantityDialogOpen.set(false)
|
|
369
|
+
return
|
|
370
|
+
}
|
|
371
|
+
onFinish()
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const closeShopFromPointer = (event) => {
|
|
375
|
+
stopEvent(event)
|
|
376
|
+
closeShop()
|
|
377
|
+
}
|
|
378
|
+
|
|
354
379
|
function confirmTrade() {
|
|
355
380
|
return function() {
|
|
356
381
|
const item = currentItem()
|