@rpgjs/client 5.0.0-alpha.3 → 5.0.0-alpha.30
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/Game/AnimationManager.d.ts +8 -0
- package/dist/{index19.js → Game/AnimationManager.js} +4 -3
- package/dist/Game/AnimationManager.js.map +1 -0
- package/dist/{index30.js → Game/Event.js} +2 -2
- package/dist/Game/Event.js.map +1 -0
- package/dist/Game/Map.d.ts +8 -1
- package/dist/Game/Map.js +54 -0
- package/dist/Game/Map.js.map +1 -0
- package/dist/Game/Object.d.ts +129 -0
- package/dist/Game/Object.js +218 -0
- package/dist/Game/Object.js.map +1 -0
- package/dist/{index29.js → Game/Player.js} +2 -2
- package/dist/Game/Player.js.map +1 -0
- package/dist/Gui/Gui.d.ts +177 -5
- package/dist/Gui/Gui.js +478 -0
- package/dist/Gui/Gui.js.map +1 -0
- package/dist/Gui/NotificationManager.d.ts +23 -0
- package/dist/Gui/NotificationManager.js +51 -0
- package/dist/Gui/NotificationManager.js.map +1 -0
- package/dist/Resource.d.ts +97 -0
- package/dist/Resource.js +114 -0
- package/dist/Resource.js.map +1 -0
- package/dist/RpgClient.d.ts +259 -59
- package/dist/RpgClientEngine.d.ts +632 -9
- package/dist/RpgClientEngine.js +1262 -0
- package/dist/RpgClientEngine.js.map +1 -0
- package/dist/Sound.d.ts +199 -0
- package/dist/Sound.js +97 -0
- package/dist/Sound.js.map +1 -0
- package/dist/components/animations/animation.ce.js +21 -0
- package/dist/components/animations/animation.ce.js.map +1 -0
- package/dist/{index23.js → components/animations/hit.ce.js} +3 -3
- package/dist/components/animations/hit.ce.js.map +1 -0
- package/dist/components/animations/index.d.ts +4 -0
- package/dist/components/animations/index.js +10 -0
- package/dist/components/animations/index.js.map +1 -0
- package/dist/components/character.ce.js +316 -0
- package/dist/components/character.ce.js.map +1 -0
- package/dist/components/dynamics/parse-value.d.ts +1 -0
- package/dist/components/dynamics/parse-value.js +54 -0
- package/dist/components/dynamics/parse-value.js.map +1 -0
- package/dist/components/dynamics/text.ce.js +141 -0
- package/dist/components/dynamics/text.ce.js.map +1 -0
- package/dist/components/gui/box.ce.js +27 -0
- package/dist/components/gui/box.ce.js.map +1 -0
- package/dist/components/gui/dialogbox/index.ce.js +152 -0
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -0
- package/dist/components/gui/gameover.ce.js +141 -0
- package/dist/components/gui/gameover.ce.js.map +1 -0
- package/dist/components/gui/hud/hud.ce.js +35 -0
- package/dist/components/gui/hud/hud.ce.js.map +1 -0
- package/dist/components/gui/index.d.ts +15 -3
- package/dist/components/gui/menu/equip-menu.ce.js +349 -0
- package/dist/components/gui/menu/equip-menu.ce.js.map +1 -0
- package/dist/components/gui/menu/exit-menu.ce.js +35 -0
- package/dist/components/gui/menu/exit-menu.ce.js.map +1 -0
- package/dist/components/gui/menu/items-menu.ce.js +229 -0
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -0
- package/dist/components/gui/menu/main-menu.ce.js +205 -0
- package/dist/components/gui/menu/main-menu.ce.js.map +1 -0
- package/dist/components/gui/menu/options-menu.ce.js +28 -0
- package/dist/components/gui/menu/options-menu.ce.js.map +1 -0
- package/dist/components/gui/menu/skills-menu.ce.js +53 -0
- package/dist/components/gui/menu/skills-menu.ce.js.map +1 -0
- package/dist/components/gui/mobile/index.d.ts +8 -0
- package/dist/components/gui/mobile/index.js +24 -0
- package/dist/components/gui/mobile/index.js.map +1 -0
- package/dist/components/gui/mobile/mobile.ce.js +17 -0
- package/dist/components/gui/mobile/mobile.ce.js.map +1 -0
- package/dist/components/gui/notification/notification.ce.js +38 -0
- package/dist/components/gui/notification/notification.ce.js.map +1 -0
- package/dist/components/gui/save-load.ce.js +242 -0
- package/dist/components/gui/save-load.ce.js.map +1 -0
- package/dist/components/gui/shop/shop.ce.js +322 -0
- package/dist/components/gui/shop/shop.ce.js.map +1 -0
- package/dist/components/gui/title-screen.ce.js +148 -0
- package/dist/components/gui/title-screen.ce.js.map +1 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/components/prebuilt/hp-bar.ce.js +106 -0
- package/dist/components/prebuilt/hp-bar.ce.js.map +1 -0
- package/dist/components/prebuilt/index.d.ts +19 -0
- package/dist/components/prebuilt/light-halo.ce.js +76 -0
- package/dist/components/prebuilt/light-halo.ce.js.map +1 -0
- package/dist/components/scenes/canvas.ce.js +44 -0
- package/dist/components/scenes/canvas.ce.js.map +1 -0
- package/dist/components/scenes/draw-map.ce.js +34 -0
- package/dist/components/scenes/draw-map.ce.js.map +1 -0
- package/dist/{index13.js → components/scenes/event-layer.ce.js} +7 -6
- package/dist/components/scenes/event-layer.ce.js.map +1 -0
- package/dist/{index6.js → core/inject.js} +2 -2
- package/dist/core/inject.js.map +1 -0
- package/dist/core/setup.js +16 -0
- package/dist/core/setup.js.map +1 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +40 -12
- package/dist/index.js.map +1 -1
- package/dist/module.d.ts +43 -4
- package/dist/module.js +175 -0
- package/dist/module.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_di@2.8.2/node_modules/@signe/di/dist/index.js +366 -0
- package/dist/node_modules/.pnpm/@signe_di@2.8.2/node_modules/@signe/di/dist/index.js.map +1 -0
- package/dist/{index27.js → node_modules/.pnpm/@signe_reactive@2.8.2/node_modules/@signe/reactive/dist/index.js} +229 -11
- package/dist/node_modules/.pnpm/@signe_reactive@2.8.2/node_modules/@signe/reactive/dist/index.js.map +1 -0
- package/dist/{index20.js → node_modules/.pnpm/@signe_room@2.8.2/node_modules/@signe/room/dist/index.js} +308 -40
- package/dist/node_modules/.pnpm/@signe_room@2.8.2/node_modules/@signe/room/dist/index.js.map +1 -0
- package/dist/{index26.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js} +1 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/{index21.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/client/index.js} +5 -5
- package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/client/index.js.map +1 -0
- package/dist/{index17.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/index.js} +89 -12
- package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/index.js.map +1 -0
- package/dist/{index33.js → node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js} +1 -1
- package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -0
- package/dist/{index31.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js} +2 -2
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -0
- package/dist/{index32.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js} +1 -1
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -0
- package/dist/{index34.js → node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js} +1 -1
- package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -0
- package/dist/presets/animation.d.ts +31 -0
- package/dist/presets/animation.js +27 -0
- package/dist/presets/animation.js.map +1 -0
- package/dist/presets/faceset.d.ts +30 -0
- package/dist/presets/faceset.js +24 -0
- package/dist/presets/faceset.js.map +1 -0
- package/dist/presets/icon.d.ts +20 -0
- package/dist/presets/icon.js +15 -0
- package/dist/presets/icon.js.map +1 -0
- package/dist/presets/index.d.ts +123 -0
- package/dist/presets/index.js +16 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/lpc.d.ts +89 -0
- package/dist/presets/lpc.js +95 -0
- package/dist/presets/lpc.js.map +1 -0
- package/dist/{index25.js → presets/rmspritesheet.js} +1 -1
- package/dist/presets/rmspritesheet.js.map +1 -0
- package/dist/{index16.js → services/AbstractSocket.js} +1 -1
- package/dist/services/AbstractSocket.js.map +1 -0
- package/dist/services/keyboardControls.d.ts +15 -0
- package/dist/services/keyboardControls.js +21 -0
- package/dist/services/keyboardControls.js.map +1 -0
- package/dist/services/loadMap.d.ts +123 -2
- package/dist/{index7.js → services/loadMap.js} +12 -4
- package/dist/services/loadMap.js.map +1 -0
- package/dist/services/mmorpg.d.ts +16 -4
- package/dist/services/mmorpg.js +84 -0
- package/dist/services/mmorpg.js.map +1 -0
- package/dist/services/save.d.ts +19 -0
- package/dist/services/save.js +69 -0
- package/dist/services/save.js.map +1 -0
- package/dist/services/standalone.d.ts +65 -3
- package/dist/services/standalone.js +170 -0
- package/dist/services/standalone.js.map +1 -0
- package/dist/utils/getEntityProp.d.ts +39 -0
- package/dist/utils/getEntityProp.js +54 -0
- package/dist/utils/getEntityProp.js.map +1 -0
- package/package.json +24 -18
- package/src/Game/{EffectManager.ts → AnimationManager.ts} +3 -2
- package/src/Game/Map.ts +37 -2
- package/src/Game/Object.ts +296 -11
- package/src/Gui/Gui.ts +506 -18
- package/src/Gui/NotificationManager.ts +69 -0
- package/src/Resource.ts +150 -0
- package/src/RpgClient.ts +264 -58
- package/src/RpgClientEngine.ts +1421 -44
- package/src/Sound.ts +253 -0
- package/src/components/{effects → animations}/animation.ce +3 -6
- package/src/components/{effects → animations}/index.ts +1 -1
- package/src/components/character.ce +406 -40
- package/src/components/dynamics/parse-value.ts +80 -0
- package/src/components/dynamics/text.ce +183 -0
- package/src/components/gui/box.ce +17 -0
- package/src/components/gui/dialogbox/index.ce +204 -187
- package/src/components/gui/gameover.ce +158 -0
- package/src/components/gui/hud/hud.ce +56 -0
- package/src/components/gui/index.ts +30 -4
- package/src/components/gui/menu/equip-menu.ce +410 -0
- package/src/components/gui/menu/exit-menu.ce +41 -0
- package/src/components/gui/menu/items-menu.ce +317 -0
- package/src/components/gui/menu/main-menu.ce +291 -0
- package/src/components/gui/menu/options-menu.ce +35 -0
- package/src/components/gui/menu/skills-menu.ce +83 -0
- package/src/components/gui/mobile/index.ts +24 -0
- package/src/components/gui/mobile/mobile.ce +80 -0
- package/src/components/gui/notification/notification.ce +51 -0
- package/src/components/gui/save-load.ce +208 -0
- package/src/components/gui/shop/shop.ce +493 -0
- package/src/components/gui/title-screen.ce +163 -0
- package/src/components/index.ts +5 -1
- package/src/components/prebuilt/hp-bar.ce +255 -0
- package/src/components/prebuilt/index.ts +24 -0
- package/src/components/prebuilt/light-halo.ce +148 -0
- package/src/components/scenes/canvas.ce +19 -14
- package/src/components/scenes/draw-map.ce +21 -29
- package/src/components/scenes/event-layer.ce +10 -3
- package/src/components/scenes/transition.ce +60 -0
- package/src/core/setup.ts +2 -0
- package/src/index.ts +16 -2
- package/src/module.ts +145 -9
- package/src/presets/animation.ts +46 -0
- package/src/presets/faceset.ts +60 -0
- package/src/presets/icon.ts +17 -0
- package/src/presets/index.ts +9 -1
- package/src/presets/lpc.ts +108 -0
- package/src/services/keyboardControls.ts +20 -0
- package/src/services/loadMap.ts +132 -3
- package/src/services/mmorpg.ts +39 -5
- package/src/services/save.ts +103 -0
- package/src/services/standalone.ts +107 -15
- package/src/utils/getEntityProp.ts +87 -0
- package/tsconfig.json +1 -1
- package/vite.config.ts +5 -3
- package/CHANGELOG.md +0 -9
- package/dist/Game/EffectManager.d.ts +0 -5
- package/dist/components/effects/index.d.ts +0 -4
- package/dist/index10.js +0 -8
- package/dist/index10.js.map +0 -1
- package/dist/index11.js +0 -10
- package/dist/index11.js.map +0 -1
- package/dist/index12.js +0 -8
- package/dist/index12.js.map +0 -1
- package/dist/index13.js.map +0 -1
- package/dist/index14.js +0 -50
- package/dist/index14.js.map +0 -1
- package/dist/index15.js +0 -191
- package/dist/index15.js.map +0 -1
- package/dist/index16.js.map +0 -1
- package/dist/index17.js.map +0 -1
- package/dist/index18.js +0 -31
- package/dist/index18.js.map +0 -1
- package/dist/index19.js.map +0 -1
- package/dist/index2.js +0 -112
- package/dist/index2.js.map +0 -1
- package/dist/index20.js.map +0 -1
- package/dist/index21.js.map +0 -1
- package/dist/index22.js +0 -109
- package/dist/index22.js.map +0 -1
- package/dist/index23.js.map +0 -1
- package/dist/index24.js +0 -21
- package/dist/index24.js.map +0 -1
- package/dist/index25.js.map +0 -1
- package/dist/index26.js.map +0 -1
- package/dist/index27.js.map +0 -1
- package/dist/index28.js +0 -25
- package/dist/index28.js.map +0 -1
- package/dist/index29.js.map +0 -1
- package/dist/index3.js +0 -87
- package/dist/index3.js.map +0 -1
- package/dist/index30.js.map +0 -1
- package/dist/index31.js.map +0 -1
- package/dist/index32.js.map +0 -1
- package/dist/index33.js.map +0 -1
- package/dist/index34.js.map +0 -1
- package/dist/index35.js +0 -91
- package/dist/index35.js.map +0 -1
- package/dist/index36.js +0 -61
- package/dist/index36.js.map +0 -1
- package/dist/index37.js +0 -20
- package/dist/index37.js.map +0 -1
- package/dist/index38.js +0 -20
- package/dist/index38.js.map +0 -1
- package/dist/index4.js +0 -54
- package/dist/index4.js.map +0 -1
- package/dist/index5.js +0 -15
- package/dist/index5.js.map +0 -1
- package/dist/index6.js.map +0 -1
- package/dist/index7.js.map +0 -1
- package/dist/index8.js +0 -90
- package/dist/index8.js.map +0 -1
- package/dist/index9.js +0 -76
- package/dist/index9.js.map +0 -1
- package/src/components/gui/dialogbox/itemMenu.ce +0 -23
- package/src/components/gui/dialogbox/selection.ce +0 -67
- package/src/components/scenes/element-map.ce +0 -23
- /package/src/components/{effects → animations}/hit.ce +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<DOMContainer width="100%" height="100%">
|
|
2
|
+
<div class="rpg-ui-gameover-screen rpg-anim-fade-in">
|
|
3
|
+
<div class="rpg-ui-gameover-splatter rpg-ui-gameover-splatter-left"></div>
|
|
4
|
+
<div class="rpg-ui-gameover-splatter rpg-ui-gameover-splatter-right"></div>
|
|
5
|
+
<div class="rpg-ui-gameover-splatter rpg-ui-gameover-splatter-center"></div>
|
|
6
|
+
<div class="rpg-ui-gameover-header rpg-anim-shake">
|
|
7
|
+
<div class="rpg-ui-gameover-title">{titleText()}</div>
|
|
8
|
+
@if (subtitleText()) {
|
|
9
|
+
<div class="rpg-ui-gameover-subtitle">{subtitleText()}</div>
|
|
10
|
+
}
|
|
11
|
+
</div>
|
|
12
|
+
<Navigation tabindex={selectedEntry} controls={controls}>
|
|
13
|
+
<div class="rpg-ui-menu rpg-ui-gameover-menu rpg-anim-slide-up">
|
|
14
|
+
@for ((entry,index) of entryList()) {
|
|
15
|
+
<div
|
|
16
|
+
class="rpg-ui-menu-item"
|
|
17
|
+
class={{disabled: isEntryDisabled(entry)}}
|
|
18
|
+
data-selected={selectedEntry() === index ? "true" : "false"}
|
|
19
|
+
tabindex={index}
|
|
20
|
+
click={selectEntry(index)}
|
|
21
|
+
>{entry.label}</div>
|
|
22
|
+
}
|
|
23
|
+
</div>
|
|
24
|
+
</Navigation>
|
|
25
|
+
</div>
|
|
26
|
+
</DOMContainer>
|
|
27
|
+
|
|
28
|
+
<script>
|
|
29
|
+
import { signal, computed, effect } from "canvasengine";
|
|
30
|
+
import { PrebuiltGui } from "@rpgjs/common";
|
|
31
|
+
import { inject } from "../../core/inject";
|
|
32
|
+
import { RpgClientEngine } from "../../RpgClientEngine";
|
|
33
|
+
import { RpgGui } from "../../Gui/Gui";
|
|
34
|
+
|
|
35
|
+
const engine = inject(RpgClientEngine);
|
|
36
|
+
const guiService = inject(RpgGui);
|
|
37
|
+
const keyboardControls = engine.globalConfig.keyboardControls;
|
|
38
|
+
|
|
39
|
+
const { entries, title, subtitle, saveLoad, localActions, onInteraction } = defineProps({
|
|
40
|
+
entries: {
|
|
41
|
+
default: () => []
|
|
42
|
+
},
|
|
43
|
+
saveLoad: {
|
|
44
|
+
default: () => ({})
|
|
45
|
+
},
|
|
46
|
+
localActions: {
|
|
47
|
+
default: false
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const defaultEntries = [
|
|
52
|
+
{ id: "title", label: "Title Screen" },
|
|
53
|
+
{ id: "load", label: "Load Game" }
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const resolveProp = (value) => typeof value === "function" ? value() : value;
|
|
57
|
+
const titleText = computed(() => resolveProp(title) || "Game Over");
|
|
58
|
+
const subtitleText = computed(() => resolveProp(subtitle) || "");
|
|
59
|
+
const localActionsEnabled = computed(() => resolveProp(localActions) === true);
|
|
60
|
+
|
|
61
|
+
const entryList = computed(() => {
|
|
62
|
+
const list = resolveProp(entries);
|
|
63
|
+
if (Array.isArray(list) && list.length) return list;
|
|
64
|
+
return defaultEntries;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const isEntryDisabled = (entry) => {
|
|
68
|
+
if (!entry) return true;
|
|
69
|
+
if (entry.disabled) return true;
|
|
70
|
+
if (entry.enabled === false) return true;
|
|
71
|
+
return false;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const selectedEntry = signal(0);
|
|
75
|
+
const selectableIndexes = computed(() => {
|
|
76
|
+
const list = entryList();
|
|
77
|
+
return list
|
|
78
|
+
.map((entry, index) => (isEntryDisabled(entry) ? null : index))
|
|
79
|
+
.filter((value) => value !== null);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
effect(() => {
|
|
83
|
+
const available = selectableIndexes();
|
|
84
|
+
if (!available.length) return;
|
|
85
|
+
const current = selectedEntry();
|
|
86
|
+
if (!available.includes(current)) {
|
|
87
|
+
selectedEntry.set(available[0]);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const moveSelection = (delta) => {
|
|
92
|
+
const available = selectableIndexes();
|
|
93
|
+
if (!available.length) return;
|
|
94
|
+
const current = selectedEntry();
|
|
95
|
+
const currentIndex = Math.max(0, available.indexOf(current));
|
|
96
|
+
const nextIndex = (currentIndex + delta + available.length) % available.length;
|
|
97
|
+
selectedEntry.set(available[nextIndex]);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const triggerSelect = (index) => {
|
|
101
|
+
const list = entryList();
|
|
102
|
+
const entry = list[index];
|
|
103
|
+
if (!entry || isEntryDisabled(entry)) return;
|
|
104
|
+
if (localActionsEnabled()) {
|
|
105
|
+
if (entry.id === "title") {
|
|
106
|
+
guiService.hide(PrebuiltGui.Gameover);
|
|
107
|
+
guiService.display(PrebuiltGui.TitleScreen);
|
|
108
|
+
}
|
|
109
|
+
if (entry.id === "load") {
|
|
110
|
+
const config = resolveProp(saveLoad) || {};
|
|
111
|
+
const slots = Array.isArray(config.slots) ? config.slots : [null, null, null];
|
|
112
|
+
guiService.display(PrebuiltGui.Save, {
|
|
113
|
+
...config,
|
|
114
|
+
mode: config.mode || "load",
|
|
115
|
+
slots
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (onInteraction) {
|
|
120
|
+
onInteraction("select", { id: entry.id, index, entry });
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
function selectEntry(index) {
|
|
125
|
+
return function() {
|
|
126
|
+
selectedEntry.set(index);
|
|
127
|
+
triggerSelect(index);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const controls = signal({
|
|
132
|
+
up: {
|
|
133
|
+
repeat: true,
|
|
134
|
+
bind: keyboardControls.up,
|
|
135
|
+
throttle: 150,
|
|
136
|
+
keyDown() {
|
|
137
|
+
moveSelection(-1);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
down: {
|
|
141
|
+
repeat: true,
|
|
142
|
+
bind: keyboardControls.down,
|
|
143
|
+
throttle: 150,
|
|
144
|
+
keyDown() {
|
|
145
|
+
moveSelection(1);
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
action: {
|
|
149
|
+
bind: keyboardControls.action,
|
|
150
|
+
keyDown() {
|
|
151
|
+
triggerSelect(selectedEntry());
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
gamepad: {
|
|
155
|
+
enabled: true
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<DOMContainer>
|
|
2
|
+
<div class="rpg-hud">
|
|
3
|
+
<div class="rpg-avatar">
|
|
4
|
+
@if (hasFace()) {
|
|
5
|
+
<div class="rpg-avatar-face">
|
|
6
|
+
<DOMSprite sheet={faceSheet(face())} />
|
|
7
|
+
</div>
|
|
8
|
+
}
|
|
9
|
+
<div class="rpg-avatar-level">{{ level() }}</div>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="rpg-status-bars">
|
|
12
|
+
<div class="rpg-bar-container">
|
|
13
|
+
<span class="rpg-bar-text">HP {{ hp() }}/{{ hpMax() }}</span>
|
|
14
|
+
<div class="rpg-bar-fill health" style={{width: percentHp}}></div>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="rpg-bar-container">
|
|
17
|
+
<span class="rpg-bar-text">SP {{ sp() }}/{{ spMax() }}</span>
|
|
18
|
+
<div class="rpg-bar-fill mana" style={{width: percentSp}}></div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</DOMContainer>
|
|
23
|
+
|
|
24
|
+
<script>
|
|
25
|
+
import { inject } from "../../../core/inject";
|
|
26
|
+
import { RpgClientEngine } from "../../../RpgClientEngine";
|
|
27
|
+
import { computed } from "canvasengine";
|
|
28
|
+
import { getEntityProp } from "../../../utils/getEntityProp";
|
|
29
|
+
|
|
30
|
+
const engine = inject(RpgClientEngine)
|
|
31
|
+
const currentPlayer = engine.scene.currentPlayer
|
|
32
|
+
const { data } = defineProps();
|
|
33
|
+
const { faceset } = data();
|
|
34
|
+
|
|
35
|
+
const resolveProp = (value) => typeof value === "function" ? value() : value;
|
|
36
|
+
const face = computed(() => resolveProp(data().faceset));
|
|
37
|
+
|
|
38
|
+
const hasFace = computed(() => {
|
|
39
|
+
const value = face();
|
|
40
|
+
return !!(value && value.id);
|
|
41
|
+
});
|
|
42
|
+
const faceSheet = (faceValue) => ({
|
|
43
|
+
definition: engine.getSpriteSheet(faceValue.id),
|
|
44
|
+
playing: faceValue.expression || "default",
|
|
45
|
+
});
|
|
46
|
+
const hp = getEntityProp(currentPlayer, "hp")
|
|
47
|
+
const hpMax = getEntityProp(currentPlayer, "params.maxHp")
|
|
48
|
+
const percentHp = computed(() => (hp() / hpMax() * 100) + '%')
|
|
49
|
+
|
|
50
|
+
const sp = getEntityProp(currentPlayer, "sp")
|
|
51
|
+
const spMax = getEntityProp(currentPlayer, "params.maxSp")
|
|
52
|
+
const percentSp = computed(() => (sp() / spMax() * 100) + '%')
|
|
53
|
+
|
|
54
|
+
const level = getEntityProp(currentPlayer, "level")
|
|
55
|
+
</script>
|
|
56
|
+
|
|
@@ -1,5 +1,31 @@
|
|
|
1
|
-
import
|
|
1
|
+
import DialogboxComponent from "./dialogbox/index.ce";
|
|
2
|
+
import BoxComponent from "./box.ce";
|
|
3
|
+
import ShopComponent from "./shop/shop.ce";
|
|
4
|
+
import HudComponent from "./hud/hud.ce";
|
|
5
|
+
import SaveLoadComponent from "./save-load.ce";
|
|
6
|
+
import MainMenuComponent from "./menu/main-menu.ce";
|
|
7
|
+
import ItemsMenuComponent from "./menu/items-menu.ce";
|
|
8
|
+
import SkillsMenuComponent from "./menu/skills-menu.ce";
|
|
9
|
+
import EquipMenuComponent from "./menu/equip-menu.ce";
|
|
10
|
+
import OptionsMenuComponent from "./menu/options-menu.ce";
|
|
11
|
+
import ExitMenuComponent from "./menu/exit-menu.ce";
|
|
12
|
+
import NotificationComponent from "./notification/notification.ce";
|
|
13
|
+
import TitleScreenComponent from "./title-screen.ce";
|
|
14
|
+
import GameoverComponent from "./gameover.ce";
|
|
2
15
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
16
|
+
export {
|
|
17
|
+
DialogboxComponent,
|
|
18
|
+
BoxComponent,
|
|
19
|
+
ShopComponent,
|
|
20
|
+
HudComponent,
|
|
21
|
+
SaveLoadComponent,
|
|
22
|
+
MainMenuComponent,
|
|
23
|
+
ItemsMenuComponent,
|
|
24
|
+
SkillsMenuComponent,
|
|
25
|
+
EquipMenuComponent,
|
|
26
|
+
OptionsMenuComponent,
|
|
27
|
+
ExitMenuComponent,
|
|
28
|
+
NotificationComponent,
|
|
29
|
+
TitleScreenComponent,
|
|
30
|
+
GameoverComponent
|
|
31
|
+
}
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
<DOMContainer width="100%" height="100%">
|
|
2
|
+
<div class="rpg-ui-menu-panel rpg-ui-panel">
|
|
3
|
+
<div class="rpg-ui-menu-panel-header">Equip</div>
|
|
4
|
+
<div class="rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked">
|
|
5
|
+
<div>
|
|
6
|
+
<div class="rpg-ui-menu-panel-details rpg-ui-panel">
|
|
7
|
+
<div class="rpg-ui-menu-panel-hero">
|
|
8
|
+
<div class="rpg-ui-menu-panel-hero-icon">
|
|
9
|
+
<DOMSprite
|
|
10
|
+
sheet={iconSheet(detailsItem()?.icon)}
|
|
11
|
+
playing="default"
|
|
12
|
+
width="48px"
|
|
13
|
+
height="48px"
|
|
14
|
+
objectFit="contain"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
<div>
|
|
18
|
+
<div class="rpg-ui-menu-panel-details-title">
|
|
19
|
+
{detailsItem()?.name || currentSlot()?.label || "Equip"}
|
|
20
|
+
</div>
|
|
21
|
+
<div class="rpg-ui-menu-panel-details-desc">
|
|
22
|
+
{detailsItem()?.description || ""}
|
|
23
|
+
</div>
|
|
24
|
+
@if (displayStats().length > 0) {
|
|
25
|
+
<div class="rpg-ui-equip-stats">
|
|
26
|
+
@for ((stat,index) of displayStats) {
|
|
27
|
+
<div class="rpg-ui-equip-stat" class={{positive: stat.delta > 0, negative: stat.delta < 0}}>
|
|
28
|
+
<div class="rpg-ui-equip-stat-key">{stat.label}</div>
|
|
29
|
+
<div class="rpg-ui-equip-stat-value">
|
|
30
|
+
{stat.delta > 0 ? "+" : ""}{stat.delta}
|
|
31
|
+
</div>
|
|
32
|
+
@if (stat.current) {
|
|
33
|
+
<div class="rpg-ui-equip-stat-current">{stat.current} -> {stat.next}</div>
|
|
34
|
+
}
|
|
35
|
+
</div>
|
|
36
|
+
}
|
|
37
|
+
</div>
|
|
38
|
+
}
|
|
39
|
+
<div class="rpg-ui-menu-panel-details-meta">
|
|
40
|
+
<span>{equippedText()}</span>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="rpg-ui-menu-panel-list rpg-ui-menu rpg-ui-menu-panel-list-full">
|
|
48
|
+
<div class="rpg-ui-menu-tabs">
|
|
49
|
+
@for ((tab,tabIndex) of slotList) {
|
|
50
|
+
<div
|
|
51
|
+
class="rpg-ui-menu-tab"
|
|
52
|
+
class={{active: selectedTab() === tabIndex}}
|
|
53
|
+
tabindex={tabIndex}
|
|
54
|
+
click={selectTab(tabIndex)}
|
|
55
|
+
>{tab.label}</div>
|
|
56
|
+
}
|
|
57
|
+
</div>
|
|
58
|
+
<Navigation tabindex={selectedItem} controls={controls}>
|
|
59
|
+
@for ((entry,index) of listEntries) {
|
|
60
|
+
<div
|
|
61
|
+
class="rpg-ui-menu-item rpg-ui-menu-row"
|
|
62
|
+
data-selected={selectedItem() === index ? "true" : "false"}
|
|
63
|
+
tabindex={index}
|
|
64
|
+
click={selectItem(index)}
|
|
65
|
+
>
|
|
66
|
+
<div class="rpg-ui-menu-row-main">
|
|
67
|
+
<div class="rpg-ui-menu-row-icon">
|
|
68
|
+
@if (entry?.icon) {
|
|
69
|
+
<DOMSprite
|
|
70
|
+
sheet={iconSheet(entry.icon)}
|
|
71
|
+
playing="default"
|
|
72
|
+
width="28px"
|
|
73
|
+
height="28px"
|
|
74
|
+
objectFit="contain"
|
|
75
|
+
/>
|
|
76
|
+
}
|
|
77
|
+
</div>
|
|
78
|
+
<span>{entry.name}</span>
|
|
79
|
+
</div>
|
|
80
|
+
<span class="rpg-ui-menu-row-end">{entry.tag || ""}</span>
|
|
81
|
+
</div>
|
|
82
|
+
}
|
|
83
|
+
</Navigation>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</DOMContainer>
|
|
88
|
+
|
|
89
|
+
<script>
|
|
90
|
+
import { signal, computed, createTabindexNavigator, effect } from "canvasengine";
|
|
91
|
+
import { inject } from "../../../core/inject";
|
|
92
|
+
import { RpgClientEngine } from "../../../RpgClientEngine";
|
|
93
|
+
|
|
94
|
+
const engine = inject(RpgClientEngine);
|
|
95
|
+
const keyboardControls = engine.globalConfig.keyboardControls;
|
|
96
|
+
const currentPlayer = engine.scene.currentPlayer;
|
|
97
|
+
|
|
98
|
+
const selectedTab = signal(0);
|
|
99
|
+
const selectedItem = signal(0);
|
|
100
|
+
const { data, onInteraction, onBack } = defineProps();
|
|
101
|
+
|
|
102
|
+
const equips = computed(() => data().equips ?? data().items);
|
|
103
|
+
const slots = computed(() => data().slots);
|
|
104
|
+
|
|
105
|
+
const defaultSlots = [
|
|
106
|
+
{ id: "weapon", label: "Weapon", types: ["weapon"] },
|
|
107
|
+
{ id: "armor", label: "Armor", types: ["armor"] }
|
|
108
|
+
];
|
|
109
|
+
const resolveProp = (value) => typeof value === "function" ? value() : value;
|
|
110
|
+
const safeEquips = computed(() => {
|
|
111
|
+
const list = resolveProp(equips);
|
|
112
|
+
return Array.isArray(list) ? list : [];
|
|
113
|
+
});
|
|
114
|
+
const slotList = computed(() => {
|
|
115
|
+
const list = resolveProp(slots);
|
|
116
|
+
if (Array.isArray(list) && list.length) return list;
|
|
117
|
+
return defaultSlots;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const currentSlot = computed(() => slotList()[selectedTab()]);
|
|
121
|
+
|
|
122
|
+
const equippedIds = computed(() => {
|
|
123
|
+
const equipped = currentPlayer().equipments?.() || [];
|
|
124
|
+
return new Set(equipped.map((it) => it?.id?.() ?? it?.id ?? it?.name));
|
|
125
|
+
});
|
|
126
|
+
const equippedOverrides = signal({});
|
|
127
|
+
|
|
128
|
+
effect(() => {
|
|
129
|
+
const next = {};
|
|
130
|
+
safeEquips().forEach((item) => {
|
|
131
|
+
if (item?.id && typeof item.equipped === "boolean") {
|
|
132
|
+
next[item.id] = item.equipped;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
equippedOverrides.set(next);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const itemEquipped = (item) => {
|
|
139
|
+
if (!item) return false;
|
|
140
|
+
const overrides = equippedOverrides();
|
|
141
|
+
if (Object.prototype.hasOwnProperty.call(overrides, item.id)) {
|
|
142
|
+
return overrides[item.id];
|
|
143
|
+
}
|
|
144
|
+
if (typeof item.equipped === "boolean") return item.equipped;
|
|
145
|
+
return equippedIds().has(item.id);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const slotTypes = (slot) => {
|
|
149
|
+
if (!slot) return [];
|
|
150
|
+
if (Array.isArray(slot.types)) return slot.types;
|
|
151
|
+
if (slot.type) return [slot.type];
|
|
152
|
+
if (slot.id) return [slot.id];
|
|
153
|
+
return [];
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const slotItems = computed(() => {
|
|
157
|
+
const slot = currentSlot();
|
|
158
|
+
if (!slot) return [];
|
|
159
|
+
const types = new Set(slotTypes(slot));
|
|
160
|
+
return safeEquips().filter((item) => item && types.has(item.type));
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const currentEquippedItem = computed(() => {
|
|
164
|
+
const list = slotItems();
|
|
165
|
+
return list.find((item) => itemEquipped(item)) || null;
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const listEntries = computed(() => {
|
|
169
|
+
const items = slotItems().map((item) => ({
|
|
170
|
+
...item,
|
|
171
|
+
kind: "item",
|
|
172
|
+
tag: itemEquipped(item) ? "Equipped" : ""
|
|
173
|
+
}));
|
|
174
|
+
const equipped = currentEquippedItem();
|
|
175
|
+
if (!equipped) return items;
|
|
176
|
+
return [
|
|
177
|
+
{
|
|
178
|
+
id: "__unequip__",
|
|
179
|
+
name: "Unequip",
|
|
180
|
+
description: "Remove the current equipment",
|
|
181
|
+
kind: "unequip",
|
|
182
|
+
tag: ""
|
|
183
|
+
},
|
|
184
|
+
...items
|
|
185
|
+
];
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const currentEntry = computed(() => listEntries()[selectedItem()]);
|
|
189
|
+
const detailsItem = computed(() => {
|
|
190
|
+
const entry = currentEntry();
|
|
191
|
+
if (entry?.kind === "item") return entry;
|
|
192
|
+
return currentEquippedItem();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const equippedText = computed(() => {
|
|
196
|
+
const slot = currentSlot();
|
|
197
|
+
if (!slot) return "";
|
|
198
|
+
const equipped = currentEquippedItem();
|
|
199
|
+
return equipped ? `${slot.label}: ${equipped.name}` : `${slot.label}: Empty`;
|
|
200
|
+
});
|
|
201
|
+
const listEmpty = computed(() => listEntries().length === 0);
|
|
202
|
+
|
|
203
|
+
const nav = createTabindexNavigator(selectedItem, { count: () => listEntries().length }, "wrap");
|
|
204
|
+
|
|
205
|
+
const playerParams = computed(() => {
|
|
206
|
+
const menuData = data();
|
|
207
|
+
if (menuData?.playerStats) return menuData.playerStats;
|
|
208
|
+
if (menuData?.playerParams) return menuData.playerParams;
|
|
209
|
+
return currentPlayer()?._param?.() || {};
|
|
210
|
+
});
|
|
211
|
+
const statOrder = ["atk", "def", "pdef", "sdef", "str", "dex", "int", "agi", "maxHp", "maxSp"];
|
|
212
|
+
const statLabels = {
|
|
213
|
+
atk: "ATK",
|
|
214
|
+
def: "DEF",
|
|
215
|
+
pdef: "PDEF",
|
|
216
|
+
sdef: "SDEF",
|
|
217
|
+
str: "STR",
|
|
218
|
+
dex: "DEX",
|
|
219
|
+
int: "INT",
|
|
220
|
+
agi: "AGI",
|
|
221
|
+
maxHp: "MAX HP",
|
|
222
|
+
maxSp: "MAX SP"
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const getItemStats = (item) => {
|
|
226
|
+
if (!item) return {};
|
|
227
|
+
const stats = item.stats || item.params || {};
|
|
228
|
+
if (Object.keys(stats).length) return stats;
|
|
229
|
+
const keys = ["atk", "def", "pdef", "sdef", "str", "dex", "int", "agi", "maxHp", "maxSp"];
|
|
230
|
+
const direct = {};
|
|
231
|
+
keys.forEach((key) => {
|
|
232
|
+
if (item[key] !== undefined) direct[key] = item[key];
|
|
233
|
+
});
|
|
234
|
+
return direct;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const buildStatsList = (deltaStats) => {
|
|
238
|
+
const params = playerParams() || {};
|
|
239
|
+
const orderedKeys = statOrder.filter((key) => deltaStats[key] !== undefined);
|
|
240
|
+
const extraKeys = Object.keys(deltaStats).filter((key) => !statOrder.includes(key));
|
|
241
|
+
const keys = orderedKeys.concat(extraKeys);
|
|
242
|
+
const list = [];
|
|
243
|
+
for (const key of keys) {
|
|
244
|
+
const delta = deltaStats[key];
|
|
245
|
+
if (delta === undefined || delta === 0) continue;
|
|
246
|
+
let current = params[key];
|
|
247
|
+
if (current === undefined && key === "def") current = params.pdef;
|
|
248
|
+
const next = current !== undefined ? current + delta : undefined;
|
|
249
|
+
list.push({
|
|
250
|
+
key,
|
|
251
|
+
label: statLabels[key] || key.toUpperCase(),
|
|
252
|
+
delta,
|
|
253
|
+
current,
|
|
254
|
+
next
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return list;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const displayStats = computed(() => {
|
|
261
|
+
const entry = currentEntry();
|
|
262
|
+
const equipped = currentEquippedItem();
|
|
263
|
+
if (!entry) return [];
|
|
264
|
+
if (entry.kind === "unequip") {
|
|
265
|
+
|
|
266
|
+
if (!equipped) return [];
|
|
267
|
+
const stats = getItemStats(equipped);
|
|
268
|
+
const delta = {};
|
|
269
|
+
Object.keys(stats).forEach((key) => {
|
|
270
|
+
delta[key] = -stats[key];
|
|
271
|
+
});
|
|
272
|
+
return buildStatsList(delta);
|
|
273
|
+
}
|
|
274
|
+
if (entry.kind === "item") {
|
|
275
|
+
const equippedStats = getItemStats(equipped);
|
|
276
|
+
const nextStats = getItemStats(entry);
|
|
277
|
+
const delta = {};
|
|
278
|
+
const keys = new Set([...Object.keys(nextStats), ...Object.keys(equippedStats)]);
|
|
279
|
+
keys.forEach((key) => {
|
|
280
|
+
delta[key] = (nextStats[key] || 0) - (equippedStats[key] || 0);
|
|
281
|
+
});
|
|
282
|
+
return buildStatsList(delta);
|
|
283
|
+
}
|
|
284
|
+
return [];
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const applyEquipState = (slot, itemId, equip) => {
|
|
288
|
+
const types = slotTypes(slot);
|
|
289
|
+
const next = { ...equippedOverrides() };
|
|
290
|
+
if (types.length) {
|
|
291
|
+
safeEquips().forEach((item) => {
|
|
292
|
+
if (!item) return;
|
|
293
|
+
if (types.includes(item.type)) {
|
|
294
|
+
next[item.id] = false;
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
if (itemId) {
|
|
299
|
+
next[itemId] = equip;
|
|
300
|
+
}
|
|
301
|
+
equippedOverrides.set(next);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const commitSelection = (index) => {
|
|
305
|
+
const entry = listEntries()[index];
|
|
306
|
+
if (!entry) return;
|
|
307
|
+
if (entry.kind === "unequip") {
|
|
308
|
+
const equipped = currentEquippedItem();
|
|
309
|
+
if (equipped && onInteraction) {
|
|
310
|
+
onInteraction("equipItem", { id: equipped.id, equip: false });
|
|
311
|
+
}
|
|
312
|
+
applyEquipState(currentSlot(), equipped?.id, false);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (entry.kind === "item" && onInteraction) {
|
|
316
|
+
if (!itemEquipped(entry)) {
|
|
317
|
+
onInteraction("equipItem", { id: entry.id, equip: true });
|
|
318
|
+
}
|
|
319
|
+
applyEquipState(currentSlot(), entry.id, true);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
function selectTab(index) {
|
|
324
|
+
return function() {
|
|
325
|
+
selectedTab.set(index);
|
|
326
|
+
selectedItem.set(0);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function selectItem(index) {
|
|
331
|
+
return function() {
|
|
332
|
+
selectedItem.set(index);
|
|
333
|
+
commitSelection(index);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const iconSheet = (iconId) => ({
|
|
338
|
+
definition: engine.getSpriteSheet(iconId)
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const controls = signal({
|
|
342
|
+
up: {
|
|
343
|
+
repeat: true,
|
|
344
|
+
bind: keyboardControls.up,
|
|
345
|
+
throttle: 150,
|
|
346
|
+
keyDown() {
|
|
347
|
+
if (!listEntries().length) return;
|
|
348
|
+
nav.next(-1);
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
left: {
|
|
352
|
+
repeat: true,
|
|
353
|
+
bind: keyboardControls.left,
|
|
354
|
+
throttle: 150,
|
|
355
|
+
keyDown() {
|
|
356
|
+
const tabs = slotList();
|
|
357
|
+
if (!tabs.length) return;
|
|
358
|
+
selectedTab.update((value) => (value - 1 + tabs.length) % tabs.length);
|
|
359
|
+
selectedItem.set(0);
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
right: {
|
|
363
|
+
repeat: true,
|
|
364
|
+
bind: keyboardControls.right,
|
|
365
|
+
throttle: 150,
|
|
366
|
+
keyDown() {
|
|
367
|
+
const tabs = slotList();
|
|
368
|
+
if (!tabs.length) return;
|
|
369
|
+
selectedTab.update((value) => (value + 1) % tabs.length);
|
|
370
|
+
selectedItem.set(0);
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
down: {
|
|
374
|
+
repeat: true,
|
|
375
|
+
bind: keyboardControls.down,
|
|
376
|
+
throttle: 150,
|
|
377
|
+
keyDown() {
|
|
378
|
+
if (!listEntries().length) return;
|
|
379
|
+
nav.next(1);
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
action: {
|
|
383
|
+
bind: keyboardControls.action,
|
|
384
|
+
keyDown() {
|
|
385
|
+
if (!listEntries().length) return;
|
|
386
|
+
commitSelection(selectedItem());
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
escape: {
|
|
390
|
+
bind: keyboardControls.escape,
|
|
391
|
+
keyDown() {
|
|
392
|
+
if (onBack) onBack();
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
gamepad: {
|
|
396
|
+
enabled: true
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
effect(() => {
|
|
401
|
+
const count = listEntries().length;
|
|
402
|
+
if (!count) {
|
|
403
|
+
selectedItem.set(0);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (selectedItem() >= count) {
|
|
407
|
+
selectedItem.set(count - 1);
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
</script>
|