@rpgjs/client 5.0.0-alpha.9 → 5.0.0-beta.1

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.
Files changed (304) hide show
  1. package/dist/Game/AnimationManager.d.ts +8 -0
  2. package/dist/Game/AnimationManager.js +26 -0
  3. package/dist/Game/AnimationManager.js.map +1 -0
  4. package/dist/Game/Event.d.ts +1 -1
  5. package/dist/Game/Event.js +12 -0
  6. package/dist/Game/Event.js.map +1 -0
  7. package/dist/Game/Map.d.ts +23 -2
  8. package/dist/Game/Map.js +80 -0
  9. package/dist/Game/Map.js.map +1 -0
  10. package/dist/Game/Object.d.ts +157 -0
  11. package/dist/Game/Object.js +211 -0
  12. package/dist/Game/Object.js.map +1 -0
  13. package/dist/Game/Player.d.ts +1 -1
  14. package/dist/Game/Player.js +12 -0
  15. package/dist/Game/Player.js.map +1 -0
  16. package/dist/Gui/Gui.d.ts +177 -5
  17. package/dist/Gui/Gui.js +445 -0
  18. package/dist/Gui/Gui.js.map +1 -0
  19. package/dist/Gui/NotificationManager.d.ts +23 -0
  20. package/dist/Gui/NotificationManager.js +49 -0
  21. package/dist/Gui/NotificationManager.js.map +1 -0
  22. package/dist/Resource.d.ts +97 -0
  23. package/dist/Resource.js +133 -0
  24. package/dist/Resource.js.map +1 -0
  25. package/dist/RpgClient.d.ts +238 -11
  26. package/dist/RpgClientEngine.d.ts +615 -14
  27. package/dist/RpgClientEngine.js +1334 -0
  28. package/dist/RpgClientEngine.js.map +1 -0
  29. package/dist/Sound.d.ts +199 -0
  30. package/dist/Sound.js +167 -0
  31. package/dist/Sound.js.map +1 -0
  32. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +9 -0
  33. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +6 -0
  34. package/dist/components/animations/animation.ce.js +24 -0
  35. package/dist/components/animations/animation.ce.js.map +1 -0
  36. package/dist/components/animations/hit.ce.js +70 -0
  37. package/dist/components/animations/hit.ce.js.map +1 -0
  38. package/dist/components/animations/index.d.ts +4 -0
  39. package/dist/components/animations/index.js +11 -0
  40. package/dist/components/animations/index.js.map +1 -0
  41. package/dist/components/character.ce.js +392 -0
  42. package/dist/components/character.ce.js.map +1 -0
  43. package/dist/components/dynamics/parse-value.d.ts +1 -0
  44. package/dist/components/dynamics/parse-value.js +44 -0
  45. package/dist/components/dynamics/parse-value.js.map +1 -0
  46. package/dist/components/dynamics/text.ce.js +73 -0
  47. package/dist/components/dynamics/text.ce.js.map +1 -0
  48. package/dist/components/gui/box.ce.js +28 -0
  49. package/dist/components/gui/box.ce.js.map +1 -0
  50. package/dist/components/gui/dialogbox/index.ce.js +205 -0
  51. package/dist/components/gui/dialogbox/index.ce.js.map +1 -0
  52. package/dist/components/gui/gameover.ce.js +193 -0
  53. package/dist/components/gui/gameover.ce.js.map +1 -0
  54. package/dist/components/gui/hud/hud.ce.js +92 -0
  55. package/dist/components/gui/hud/hud.ce.js.map +1 -0
  56. package/dist/components/gui/index.d.ts +15 -3
  57. package/dist/components/gui/index.js +14 -0
  58. package/dist/components/gui/menu/equip-menu.ce.js +481 -0
  59. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -0
  60. package/dist/components/gui/menu/exit-menu.ce.js +54 -0
  61. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -0
  62. package/dist/components/gui/menu/items-menu.ce.js +344 -0
  63. package/dist/components/gui/menu/items-menu.ce.js.map +1 -0
  64. package/dist/components/gui/menu/main-menu.ce.js +417 -0
  65. package/dist/components/gui/menu/main-menu.ce.js.map +1 -0
  66. package/dist/components/gui/menu/options-menu.ce.js +48 -0
  67. package/dist/components/gui/menu/options-menu.ce.js.map +1 -0
  68. package/dist/components/gui/menu/skills-menu.ce.js +107 -0
  69. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -0
  70. package/dist/components/gui/mobile/index.d.ts +8 -0
  71. package/dist/components/gui/mobile/index.js +21 -0
  72. package/dist/components/gui/mobile/index.js.map +1 -0
  73. package/dist/components/gui/mobile/mobile.ce.js +78 -0
  74. package/dist/components/gui/mobile/mobile.ce.js.map +1 -0
  75. package/dist/components/gui/notification/notification.ce.js +64 -0
  76. package/dist/components/gui/notification/notification.ce.js.map +1 -0
  77. package/dist/components/gui/save-load.ce.js +389 -0
  78. package/dist/components/gui/save-load.ce.js.map +1 -0
  79. package/dist/components/gui/shop/shop.ce.js +652 -0
  80. package/dist/components/gui/shop/shop.ce.js.map +1 -0
  81. package/dist/components/gui/title-screen.ce.js +190 -0
  82. package/dist/components/gui/title-screen.ce.js.map +1 -0
  83. package/dist/components/index.d.ts +1 -0
  84. package/dist/components/index.js +4 -0
  85. package/dist/components/prebuilt/hp-bar.ce.js +116 -0
  86. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -0
  87. package/dist/components/prebuilt/index.d.ts +19 -0
  88. package/dist/components/prebuilt/index.js +2 -0
  89. package/dist/components/prebuilt/light-halo.ce.js +94 -0
  90. package/dist/components/prebuilt/light-halo.ce.js.map +1 -0
  91. package/dist/components/scenes/canvas.ce.js +60 -0
  92. package/dist/components/scenes/canvas.ce.js.map +1 -0
  93. package/dist/components/scenes/draw-map.ce.js +89 -0
  94. package/dist/components/scenes/draw-map.ce.js.map +1 -0
  95. package/dist/components/scenes/event-layer.ce.js +28 -0
  96. package/dist/components/scenes/event-layer.ce.js.map +1 -0
  97. package/dist/core/inject.js +18 -0
  98. package/dist/core/inject.js.map +1 -0
  99. package/dist/core/setup.js +16 -0
  100. package/dist/core/setup.js.map +1 -0
  101. package/dist/index.d.ts +15 -1
  102. package/dist/index.js +44 -14
  103. package/dist/module.d.ts +43 -4
  104. package/dist/module.js +176 -0
  105. package/dist/module.js.map +1 -0
  106. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js +277 -0
  107. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +1 -0
  108. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +457 -0
  109. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +1 -0
  110. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +463 -0
  111. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
  112. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +2191 -0
  113. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +1 -0
  114. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +10 -0
  115. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -0
  116. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +91 -0
  117. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  118. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js +325 -0
  119. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +1 -0
  120. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +14 -0
  121. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -0
  122. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js +115 -0
  123. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -0
  124. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js +401 -0
  125. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -0
  126. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/index.js +2 -0
  127. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js +3756 -0
  128. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -0
  129. package/dist/presets/animation.d.ts +31 -0
  130. package/dist/presets/animation.js +39 -0
  131. package/dist/presets/animation.js.map +1 -0
  132. package/dist/presets/faceset.d.ts +30 -0
  133. package/dist/presets/faceset.js +51 -0
  134. package/dist/presets/faceset.js.map +1 -0
  135. package/dist/presets/icon.d.ts +20 -0
  136. package/dist/presets/icon.js +15 -0
  137. package/dist/presets/icon.js.map +1 -0
  138. package/dist/presets/index.d.ts +123 -0
  139. package/dist/presets/index.js +17 -0
  140. package/dist/presets/index.js.map +1 -0
  141. package/dist/presets/lpc.d.ts +89 -0
  142. package/dist/presets/lpc.js +98 -0
  143. package/dist/presets/lpc.js.map +1 -0
  144. package/dist/presets/rmspritesheet.js +42 -0
  145. package/dist/presets/rmspritesheet.js.map +1 -0
  146. package/dist/services/AbstractSocket.d.ts +9 -5
  147. package/dist/services/AbstractSocket.js +11 -0
  148. package/dist/services/AbstractSocket.js.map +1 -0
  149. package/dist/services/keyboardControls.d.ts +15 -0
  150. package/dist/services/keyboardControls.js +23 -0
  151. package/dist/services/keyboardControls.js.map +1 -0
  152. package/dist/services/loadMap.js +123 -0
  153. package/dist/services/loadMap.js.map +1 -0
  154. package/dist/services/mmorpg.d.ts +21 -9
  155. package/dist/services/mmorpg.js +131 -0
  156. package/dist/services/mmorpg.js.map +1 -0
  157. package/dist/services/save.d.ts +19 -0
  158. package/dist/services/save.js +77 -0
  159. package/dist/services/save.js.map +1 -0
  160. package/dist/services/standalone.d.ts +67 -7
  161. package/dist/services/standalone.js +168 -0
  162. package/dist/services/standalone.js.map +1 -0
  163. package/dist/utils/getEntityProp.d.ts +39 -0
  164. package/dist/utils/getEntityProp.js +52 -0
  165. package/dist/utils/getEntityProp.js.map +1 -0
  166. package/package.json +13 -9
  167. package/src/Game/{EffectManager.ts → AnimationManager.ts} +3 -2
  168. package/src/Game/Event.ts +1 -1
  169. package/src/Game/Map.ts +95 -3
  170. package/src/Game/Object.ts +330 -14
  171. package/src/Game/Player.ts +1 -1
  172. package/src/Gui/Gui.ts +506 -18
  173. package/src/Gui/NotificationManager.ts +69 -0
  174. package/src/Resource.ts +150 -0
  175. package/src/RpgClient.ts +246 -12
  176. package/src/RpgClientEngine.ts +1641 -62
  177. package/src/Sound.ts +253 -0
  178. package/src/components/{effects → animations}/animation.ce +3 -6
  179. package/src/components/{effects → animations}/index.ts +1 -1
  180. package/src/components/character.ce +387 -52
  181. package/src/components/dynamics/parse-value.ts +80 -0
  182. package/src/components/dynamics/text.ce +183 -0
  183. package/src/components/gui/box.ce +17 -0
  184. package/src/components/gui/dialogbox/index.ce +204 -187
  185. package/src/components/gui/gameover.ce +158 -0
  186. package/src/components/gui/hud/hud.ce +61 -0
  187. package/src/components/gui/index.ts +30 -4
  188. package/src/components/gui/menu/equip-menu.ce +410 -0
  189. package/src/components/gui/menu/exit-menu.ce +41 -0
  190. package/src/components/gui/menu/items-menu.ce +317 -0
  191. package/src/components/gui/menu/main-menu.ce +294 -0
  192. package/src/components/gui/menu/options-menu.ce +35 -0
  193. package/src/components/gui/menu/skills-menu.ce +83 -0
  194. package/src/components/gui/mobile/index.ts +24 -0
  195. package/src/components/gui/mobile/mobile.ce +80 -0
  196. package/src/components/gui/notification/notification.ce +51 -0
  197. package/src/components/gui/save-load.ce +208 -0
  198. package/src/components/gui/shop/shop.ce +493 -0
  199. package/src/components/gui/title-screen.ce +163 -0
  200. package/src/components/index.ts +3 -0
  201. package/src/components/prebuilt/hp-bar.ce +255 -0
  202. package/src/components/prebuilt/index.ts +24 -0
  203. package/src/components/prebuilt/light-halo.ce +148 -0
  204. package/src/components/scenes/canvas.ce +20 -15
  205. package/src/components/scenes/draw-map.ce +60 -13
  206. package/src/components/scenes/event-layer.ce +7 -0
  207. package/src/components/scenes/transition.ce +60 -0
  208. package/src/index.ts +16 -2
  209. package/src/module.ts +127 -9
  210. package/src/presets/animation.ts +46 -0
  211. package/src/presets/faceset.ts +60 -0
  212. package/src/presets/icon.ts +17 -0
  213. package/src/presets/index.ts +9 -1
  214. package/src/presets/lpc.ts +108 -0
  215. package/src/services/AbstractSocket.ts +10 -2
  216. package/src/services/keyboardControls.ts +20 -0
  217. package/src/services/loadMap.ts +1 -1
  218. package/src/services/mmorpg.ts +100 -12
  219. package/src/services/save.ts +103 -0
  220. package/src/services/standalone.ts +110 -18
  221. package/src/utils/getEntityProp.ts +87 -0
  222. package/vite.config.ts +4 -2
  223. package/dist/Game/EffectManager.d.ts +0 -5
  224. package/dist/components/effects/index.d.ts +0 -4
  225. package/dist/index.js.map +0 -1
  226. package/dist/index10.js +0 -8
  227. package/dist/index10.js.map +0 -1
  228. package/dist/index11.js +0 -10
  229. package/dist/index11.js.map +0 -1
  230. package/dist/index12.js +0 -8
  231. package/dist/index12.js.map +0 -1
  232. package/dist/index13.js +0 -17
  233. package/dist/index13.js.map +0 -1
  234. package/dist/index14.js +0 -107
  235. package/dist/index14.js.map +0 -1
  236. package/dist/index15.js +0 -50
  237. package/dist/index15.js.map +0 -1
  238. package/dist/index16.js +0 -191
  239. package/dist/index16.js.map +0 -1
  240. package/dist/index17.js +0 -9
  241. package/dist/index17.js.map +0 -1
  242. package/dist/index18.js +0 -387
  243. package/dist/index18.js.map +0 -1
  244. package/dist/index19.js +0 -31
  245. package/dist/index19.js.map +0 -1
  246. package/dist/index2.js +0 -181
  247. package/dist/index2.js.map +0 -1
  248. package/dist/index20.js +0 -24
  249. package/dist/index20.js.map +0 -1
  250. package/dist/index21.js +0 -2421
  251. package/dist/index21.js.map +0 -1
  252. package/dist/index22.js +0 -114
  253. package/dist/index22.js.map +0 -1
  254. package/dist/index23.js +0 -109
  255. package/dist/index23.js.map +0 -1
  256. package/dist/index24.js +0 -71
  257. package/dist/index24.js.map +0 -1
  258. package/dist/index25.js +0 -21
  259. package/dist/index25.js.map +0 -1
  260. package/dist/index26.js +0 -41
  261. package/dist/index26.js.map +0 -1
  262. package/dist/index27.js +0 -5
  263. package/dist/index27.js.map +0 -1
  264. package/dist/index28.js +0 -322
  265. package/dist/index28.js.map +0 -1
  266. package/dist/index29.js +0 -27
  267. package/dist/index29.js.map +0 -1
  268. package/dist/index3.js +0 -87
  269. package/dist/index3.js.map +0 -1
  270. package/dist/index30.js +0 -11
  271. package/dist/index30.js.map +0 -1
  272. package/dist/index31.js +0 -11
  273. package/dist/index31.js.map +0 -1
  274. package/dist/index32.js +0 -174
  275. package/dist/index32.js.map +0 -1
  276. package/dist/index33.js +0 -501
  277. package/dist/index33.js.map +0 -1
  278. package/dist/index34.js +0 -12
  279. package/dist/index34.js.map +0 -1
  280. package/dist/index35.js +0 -4403
  281. package/dist/index35.js.map +0 -1
  282. package/dist/index36.js +0 -316
  283. package/dist/index36.js.map +0 -1
  284. package/dist/index37.js +0 -61
  285. package/dist/index37.js.map +0 -1
  286. package/dist/index38.js +0 -20
  287. package/dist/index38.js.map +0 -1
  288. package/dist/index39.js +0 -20
  289. package/dist/index39.js.map +0 -1
  290. package/dist/index4.js +0 -67
  291. package/dist/index4.js.map +0 -1
  292. package/dist/index5.js +0 -16
  293. package/dist/index5.js.map +0 -1
  294. package/dist/index6.js +0 -17
  295. package/dist/index6.js.map +0 -1
  296. package/dist/index7.js +0 -39
  297. package/dist/index7.js.map +0 -1
  298. package/dist/index8.js +0 -108
  299. package/dist/index8.js.map +0 -1
  300. package/dist/index9.js +0 -76
  301. package/dist/index9.js.map +0 -1
  302. package/src/components/gui/dialogbox/itemMenu.ce +0 -23
  303. package/src/components/gui/dialogbox/selection.ce +0 -67
  304. /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,61 @@
1
+ <DOMContainer>
2
+ <div class="rpg-hud">
3
+ <div class="rpg-avatar">
4
+ @if (hasFace()) {
5
+ <div class="rpg-avatar-face">
6
+ <DOMSprite
7
+ sheet={faceSheet(face())}
8
+ width={64}
9
+ height={64}
10
+ objectFit="contain"
11
+ />
12
+ </div>
13
+ }
14
+ <div class="rpg-avatar-level">{{ level() }}</div>
15
+ </div>
16
+ <div class="rpg-status-bars">
17
+ <div class="rpg-bar-container">
18
+ <span class="rpg-bar-text">HP {{ hp() }}/{{ hpMax() }}</span>
19
+ <div class="rpg-bar-fill health" style={{width: percentHp}}></div>
20
+ </div>
21
+ <div class="rpg-bar-container">
22
+ <span class="rpg-bar-text">SP {{ sp() }}/{{ spMax() }}</span>
23
+ <div class="rpg-bar-fill mana" style={{width: percentSp}}></div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </DOMContainer>
28
+
29
+ <script>
30
+ import { inject } from "../../../core/inject";
31
+ import { RpgClientEngine } from "../../../RpgClientEngine";
32
+ import { computed } from "canvasengine";
33
+ import { getEntityProp } from "../../../utils/getEntityProp";
34
+
35
+ const engine = inject(RpgClientEngine)
36
+ const currentPlayer = engine.scene.currentPlayer
37
+ const { data } = defineProps();
38
+ const { faceset } = data();
39
+
40
+ const resolveProp = (value) => typeof value === "function" ? value() : value;
41
+ const face = computed(() => resolveProp(data().faceset));
42
+
43
+ const hasFace = computed(() => {
44
+ const value = face();
45
+ return !!(value && value.id);
46
+ });
47
+ const faceSheet = (faceValue) => ({
48
+ definition: engine.getSpriteSheet(faceValue.id),
49
+ playing: faceValue.expression || "default",
50
+ });
51
+ const hp = getEntityProp(currentPlayer, "hp")
52
+ const hpMax = getEntityProp(currentPlayer, "params.maxHp")
53
+ const percentHp = computed(() => (hp() / hpMax() * 100) + '%')
54
+
55
+ const sp = getEntityProp(currentPlayer, "sp")
56
+ const spMax = getEntityProp(currentPlayer, "params.maxSp")
57
+ const percentSp = computed(() => (sp() / spMax() * 100) + '%')
58
+
59
+ const level = getEntityProp(currentPlayer, "level")
60
+ </script>
61
+
@@ -1,5 +1,31 @@
1
- import Dialogbox from "./dialogbox/index.ce";
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 const PrebuiltGui = {
4
- Dialogbox
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>