@rpgjs/client 5.0.0-beta.11 → 5.0.0-beta.13

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 (133) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/Game/AnimationManager.d.ts +1 -0
  3. package/dist/Game/AnimationManager.js +3 -0
  4. package/dist/Game/AnimationManager.js.map +1 -1
  5. package/dist/Game/ClientVisuals.d.ts +61 -0
  6. package/dist/Game/ClientVisuals.js +96 -0
  7. package/dist/Game/ClientVisuals.js.map +1 -0
  8. package/dist/Game/ClientVisuals.spec.d.ts +1 -0
  9. package/dist/Game/EventComponentResolver.d.ts +16 -0
  10. package/dist/Game/EventComponentResolver.js +52 -0
  11. package/dist/Game/EventComponentResolver.js.map +1 -0
  12. package/dist/Game/EventComponentResolver.spec.d.ts +1 -0
  13. package/dist/Game/Map.js +9 -0
  14. package/dist/Game/Map.js.map +1 -1
  15. package/dist/Game/Object.d.ts +2 -0
  16. package/dist/Game/Object.js +22 -8
  17. package/dist/Game/Object.js.map +1 -1
  18. package/dist/Game/Object.spec.d.ts +1 -0
  19. package/dist/Game/ProjectileManager.d.ts +11 -2
  20. package/dist/Game/ProjectileManager.js +19 -2
  21. package/dist/Game/ProjectileManager.js.map +1 -1
  22. package/dist/Gui/Gui.d.ts +3 -2
  23. package/dist/Gui/Gui.js +18 -6
  24. package/dist/Gui/Gui.js.map +1 -1
  25. package/dist/RpgClient.d.ts +85 -1
  26. package/dist/RpgClientEngine.d.ts +77 -2
  27. package/dist/RpgClientEngine.js +290 -31
  28. package/dist/RpgClientEngine.js.map +1 -1
  29. package/dist/components/animations/fx.ce.js +58 -0
  30. package/dist/components/animations/fx.ce.js.map +1 -0
  31. package/dist/components/animations/index.d.ts +1 -0
  32. package/dist/components/animations/index.js +3 -1
  33. package/dist/components/animations/index.js.map +1 -1
  34. package/dist/components/character.ce.js +192 -19
  35. package/dist/components/character.ce.js.map +1 -1
  36. package/dist/components/gui/dialogbox/index.ce.js +27 -12
  37. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  38. package/dist/components/gui/gameover.ce.js +4 -3
  39. package/dist/components/gui/gameover.ce.js.map +1 -1
  40. package/dist/components/gui/menu/equip-menu.ce.js +9 -8
  41. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
  42. package/dist/components/gui/menu/exit-menu.ce.js +7 -5
  43. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
  44. package/dist/components/gui/menu/items-menu.ce.js +8 -7
  45. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  46. package/dist/components/gui/menu/main-menu.ce.js +12 -11
  47. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  48. package/dist/components/gui/menu/options-menu.ce.js +7 -5
  49. package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
  50. package/dist/components/gui/menu/skills-menu.ce.js +4 -2
  51. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
  52. package/dist/components/gui/notification/notification.ce.js +4 -1
  53. package/dist/components/gui/notification/notification.ce.js.map +1 -1
  54. package/dist/components/gui/save-load.ce.js +10 -9
  55. package/dist/components/gui/save-load.ce.js.map +1 -1
  56. package/dist/components/gui/shop/shop.ce.js +17 -16
  57. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  58. package/dist/components/gui/title-screen.ce.js +4 -3
  59. package/dist/components/gui/title-screen.ce.js.map +1 -1
  60. package/dist/components/interaction-components.ce.js +20 -0
  61. package/dist/components/interaction-components.ce.js.map +1 -0
  62. package/dist/components/scenes/canvas.ce.js +12 -7
  63. package/dist/components/scenes/canvas.ce.js.map +1 -1
  64. package/dist/components/scenes/draw-map.ce.js +18 -13
  65. package/dist/components/scenes/draw-map.ce.js.map +1 -1
  66. package/dist/i18n.d.ts +55 -0
  67. package/dist/i18n.js +60 -0
  68. package/dist/i18n.js.map +1 -0
  69. package/dist/i18n.spec.d.ts +1 -0
  70. package/dist/index.d.ts +3 -0
  71. package/dist/index.js +5 -2
  72. package/dist/module.js +30 -3
  73. package/dist/module.js.map +1 -1
  74. package/dist/services/actionInput.d.ts +3 -1
  75. package/dist/services/actionInput.js +33 -1
  76. package/dist/services/actionInput.js.map +1 -1
  77. package/dist/services/interactions.d.ts +159 -0
  78. package/dist/services/interactions.js +460 -0
  79. package/dist/services/interactions.js.map +1 -0
  80. package/dist/services/interactions.spec.d.ts +1 -0
  81. package/dist/services/keyboardControls.d.ts +1 -0
  82. package/dist/services/keyboardControls.js +1 -0
  83. package/dist/services/keyboardControls.js.map +1 -1
  84. package/dist/services/standalone.d.ts +3 -1
  85. package/dist/services/standalone.js +31 -13
  86. package/dist/services/standalone.js.map +1 -1
  87. package/dist/utils/mapId.d.ts +1 -0
  88. package/dist/utils/mapId.js +6 -0
  89. package/dist/utils/mapId.js.map +1 -0
  90. package/package.json +4 -4
  91. package/src/Game/AnimationManager.ts +4 -0
  92. package/src/Game/ClientVisuals.spec.ts +56 -0
  93. package/src/Game/ClientVisuals.ts +184 -0
  94. package/src/Game/EventComponentResolver.spec.ts +84 -0
  95. package/src/Game/EventComponentResolver.ts +74 -0
  96. package/src/Game/Map.ts +10 -0
  97. package/src/Game/Object.spec.ts +59 -0
  98. package/src/Game/Object.ts +36 -12
  99. package/src/Game/ProjectileManager.spec.ts +111 -0
  100. package/src/Game/ProjectileManager.ts +24 -2
  101. package/src/Gui/Gui.spec.ts +67 -0
  102. package/src/Gui/Gui.ts +24 -7
  103. package/src/RpgClient.ts +96 -1
  104. package/src/RpgClientEngine.ts +378 -45
  105. package/src/components/animations/fx.ce +101 -0
  106. package/src/components/animations/index.ts +4 -2
  107. package/src/components/character.ce +243 -17
  108. package/src/components/gui/dialogbox/index.ce +35 -14
  109. package/src/components/gui/gameover.ce +4 -3
  110. package/src/components/gui/menu/equip-menu.ce +9 -8
  111. package/src/components/gui/menu/exit-menu.ce +4 -3
  112. package/src/components/gui/menu/items-menu.ce +8 -7
  113. package/src/components/gui/menu/main-menu.ce +12 -11
  114. package/src/components/gui/menu/options-menu.ce +4 -3
  115. package/src/components/gui/menu/skills-menu.ce +2 -1
  116. package/src/components/gui/notification/notification.ce +7 -1
  117. package/src/components/gui/save-load.ce +11 -10
  118. package/src/components/gui/shop/shop.ce +17 -16
  119. package/src/components/gui/title-screen.ce +4 -3
  120. package/src/components/interaction-components.ce +23 -0
  121. package/src/components/scenes/canvas.ce +12 -7
  122. package/src/components/scenes/draw-map.ce +16 -5
  123. package/src/i18n.spec.ts +39 -0
  124. package/src/i18n.ts +59 -0
  125. package/src/index.ts +3 -0
  126. package/src/module.ts +43 -10
  127. package/src/services/actionInput.spec.ts +54 -0
  128. package/src/services/actionInput.ts +68 -1
  129. package/src/services/interactions.spec.ts +175 -0
  130. package/src/services/interactions.ts +722 -0
  131. package/src/services/keyboardControls.ts +2 -1
  132. package/src/services/standalone.ts +39 -10
  133. package/src/utils/mapId.ts +2 -0
@@ -12,17 +12,28 @@ function component($$props) {
12
12
  const keyboardControls = engine.globalConfig.keyboardControls;
13
13
  engine.stopProcessingInput = true;
14
14
  const selectedItem = signal(0);
15
- const { data, onFinish, onInteraction } = defineProps();
16
- const { message, choices, face, speaker, position, typewriterEffect, autoClose } = data();
17
- const fullWidth = computed(() => data().fullWidth || false);
15
+ const ACTION_OPEN_GUARD_MS = 150;
16
+ const openedAt = Date.now();
17
+ const { data, onFinish, onInteraction, guiOpenId } = defineProps();
18
+ const dialogData = computed(() => data() || {});
19
+ const dialogChoices = computed(() => Array.isArray(dialogData().choices) ? dialogData().choices : []);
20
+ const message = computed(() => dialogData().message);
21
+ const speaker = computed(() => dialogData().speaker);
22
+ const position = computed(() => dialogData().position);
23
+ const typewriterEffect = computed(() => dialogData().typewriterEffect);
24
+ const fullWidth = computed(() => dialogData().fullWidth || false);
18
25
  const resolveProp = (value) => typeof value === "function" ? value() : value;
26
+ const normalizeOpenId = (value) => {
27
+ const resolved = resolveProp(value);
28
+ return typeof resolved === "string" && resolved.length > 0 ? resolved : void 0;
29
+ };
19
30
  const speakerName = computed(() => {
20
- const value = resolveProp(speaker);
31
+ const value = resolveProp(speaker());
21
32
  return value ? String(value) : "";
22
33
  });
23
- const dialogPosition = computed(() => resolveProp(position) || "bottom");
34
+ const dialogPosition = computed(() => resolveProp(position()) || "bottom");
24
35
  const isFullWidth = computed(() => resolveProp(fullWidth) !== false);
25
- const dialogFace = computed(() => resolveProp(face));
36
+ const dialogFace = computed(() => resolveProp(dialogData().face));
26
37
  const hasFace = computed(() => {
27
38
  const value = dialogFace();
28
39
  return !!(value && value.id);
@@ -55,17 +66,17 @@ function component($$props) {
55
66
  isTyping.set(false);
56
67
  };
57
68
  effect(() => {
58
- const text = resolveProp(message) || "";
69
+ const text = resolveProp(message()) || "";
59
70
  fullMessage.set(text);
60
- if (!(resolveProp(typewriterEffect) !== false)) {
71
+ if (!(resolveProp(typewriterEffect()) !== false)) {
61
72
  finishTyping();
62
73
  return;
63
74
  }
64
75
  startTypewriter(text);
65
76
  });
66
- const hasChoices = computed(() => choices.length > 0);
77
+ const hasChoices = computed(() => dialogChoices().length > 0);
67
78
  const showIndicator = computed(() => !hasChoices() && !isTyping());
68
- const nav = createTabindexNavigator(selectedItem, { count: () => choices.length }, "wrap");
79
+ const nav = createTabindexNavigator(selectedItem, { count: () => dialogChoices().length }, "wrap");
69
80
  function selectChoice(index) {
70
81
  return function() {
71
82
  selectedItem.set(index);
@@ -73,11 +84,12 @@ function component($$props) {
73
84
  };
74
85
  }
75
86
  function _onFinish(value) {
76
- if (onFinish) onFinish(value);
87
+ if (onFinish) onFinish(value, normalizeOpenId(guiOpenId));
77
88
  }
78
89
  const onSelect = (index) => {
79
90
  _onFinish(index);
80
91
  };
92
+ const canAcceptAction = () => Date.now() - openedAt >= ACTION_OPEN_GUARD_MS;
81
93
  const controls = signal({
82
94
  up: {
83
95
  repeat: true,
@@ -100,6 +112,7 @@ function component($$props) {
100
112
  action: {
101
113
  bind: getKeyboardControlBind(keyboardControls.action),
102
114
  keyDown() {
115
+ if (!canAcceptAction()) return;
103
116
  if (isTyping()) {
104
117
  finishTyping();
105
118
  return;
@@ -113,6 +126,7 @@ function component($$props) {
113
126
  const dialogControls = signal({ action: {
114
127
  bind: getKeyboardControlBind(keyboardControls.action),
115
128
  keyDown() {
129
+ if (!canAcceptAction()) return;
116
130
  if (isTyping()) {
117
131
  finishTyping();
118
132
  return;
@@ -122,6 +136,7 @@ function component($$props) {
122
136
  }
123
137
  } });
124
138
  const faceSheet = (faceValue) => {
139
+ if (!faceValue || !faceValue.id) return;
125
140
  return {
126
141
  definition: engine.getSpriteSheet(faceValue.id),
127
142
  playing: faceValue.expression || "default"
@@ -169,7 +184,7 @@ function component($$props) {
169
184
  }, h(DOMElement, {
170
185
  element: "div",
171
186
  attrs: { class: "rpg-ui-dialog-choices" }
172
- }, loop(choices, (choice, index) => h(DOMElement, {
187
+ }, loop(computed(() => dialogChoices()), (choice, index) => h(DOMElement, {
173
188
  element: "div",
174
189
  attrs: {
175
190
  class: ["rpg-ui-dialog-choice", computed(() => ({ active: selectedItem() === index }))],
@@ -1 +1 @@
1
- {"version":3,"file":"index.ce.js","names":[],"sources":["../../../../src/components/gui/dialogbox/index.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={dialogControls}>\n <div\n class=\"rpg-ui-dialog-container\"\n data-position={dialogPosition()}\n data-full-width={isFullWidth() ? \"true\" : \"false\"}\n data-has-face={hasFace() ? \"true\" : \"false\"}\n >\n <div class=\"rpg-ui-dialog rpg-anim-fade-in\">\n <div class=\"rpg-ui-dialog-body\">\n <div>\n @if (speakerName()) {\n <div class=\"rpg-ui-dialog-speaker\">{speakerName()}</div>\n }\n <div class=\"rpg-ui-dialog-content\">\n {displayMessage()}\n </div>\n @if (hasChoices()) {\n <Navigation tabindex={selectedItem} controls={controls}>\n <div class=\"rpg-ui-dialog-choices\">\n @for ((choice,index) of choices) {\n <div\n class=\"rpg-ui-dialog-choice\"\n class={{active: selectedItem() === index}}\n tabindex={index}\n data-choice-index={index}\n click={selectChoice(index)}\n >{{ choice.text }}</div>\n }\n </div>\n </Navigation>\n }\n </div>\n @if (hasFace()) {\n <div class=\"rpg-ui-dialog-face\">\n <DOMSprite\n sheet={faceSheet(dialogFace())}\n width=\"100%\"\n height=\"100%\"\n objectFit=\"contain\"\n />\n </div>\n }\n </div>\n @if (showIndicator) {\n <div class=\"rpg-ui-dialog-indicator\"></div>\n }\n </div>\n </div>\n</DOMContainer>\n \n<script>\n import { effect, signal, computed, createTabindexNavigator, mount } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const currentPlayer = engine.scene.currentPlayer\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n engine.stopProcessingInput = true;\n\n const selectedItem = signal(0)\n let isDestroyed = false;\n\n const {\n data,\n onFinish,\n onInteraction\n } = defineProps();\n\n const { message, choices, face, speaker, position, typewriterEffect, autoClose } = data();\n const fullWidth = computed(() => data().fullWidth || false);\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n\n const speakerName = computed(() => {\n const value = resolveProp(speaker);\n return value ? String(value) : \"\";\n });\n\n const dialogPosition = computed(() => resolveProp(position) || \"bottom\");\n const isFullWidth = computed(() => resolveProp(fullWidth) !== false);\n const dialogFace = computed(() => resolveProp(face));\n const hasFace = computed(() => {\n const value = dialogFace();\n return !!(value && value.id);\n });\n\n const displayMessage = signal(\"\");\n const fullMessage = signal(\"\");\n const isTyping = signal(false);\n let typewriterTimer = null;\n let rootElement = null;\n\n mount((element) => {\n rootElement = element;\n });\n\n const startTypewriter = (text) => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n displayMessage.set(\"\");\n if (!text) return;\n let index = 0;\n isTyping.set(true);\n typewriterTimer = setInterval(() => {\n index += 1;\n displayMessage.set(text.slice(0, index));\n if (index >= text.length) {\n clearInterval(typewriterTimer);\n typewriterTimer = null;\n isTyping.set(false);\n }\n }, 20);\n };\n\n const finishTyping = () => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n typewriterTimer = null;\n displayMessage.set(fullMessage());\n isTyping.set(false);\n };\n\n effect(() => {\n const text = resolveProp(message) || \"\";\n fullMessage.set(text);\n const useTypewriter = resolveProp(typewriterEffect) !== false;\n if (!useTypewriter) {\n finishTyping();\n return;\n }\n startTypewriter(text);\n });\n\n\n const hasChoices = computed(() => choices.length > 0);\n const showIndicator = computed(() => !hasChoices() && !isTyping());\n const nav = createTabindexNavigator(selectedItem, { count: () => choices.length }, 'wrap');\n\n function selectChoice(index) {\n return function() {\n selectedItem.set(index);\n onSelect(index);\n }\n }\n\n function _onFinish(value) {\n if (onFinish) onFinish(value);\n }\n\n const onSelect = (index) => {\n _onFinish(index);\n };\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (!hasChoices()) return;\n onSelect(selectedItem());\n }\n },\n gamepad: {\n enabled: true\n }\n });\n \n const dialogControls = signal({\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (hasChoices()) return;\n _onFinish();\n }\n },\n })\n\n const faceSheet = (faceValue) => {\n return {\n definition: engine.getSpriteSheet(faceValue.id),\n playing: faceValue.expression || \"default\",\n };\n }\n\n mount((element) => {\n return () => {\n isDestroyed = true;\n // Wait destroy is finished before start processing input\n delay(() => {\n engine.stopProcessingInput = false;\n })\n }\n })\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.ce.js","names":[],"sources":["../../../../src/components/gui/dialogbox/index.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={dialogControls}>\n <div\n class=\"rpg-ui-dialog-container\"\n data-position={dialogPosition()}\n data-full-width={isFullWidth() ? \"true\" : \"false\"}\n data-has-face={hasFace() ? \"true\" : \"false\"}\n >\n <div class=\"rpg-ui-dialog rpg-anim-fade-in\">\n <div class=\"rpg-ui-dialog-body\">\n <div>\n @if (speakerName()) {\n <div class=\"rpg-ui-dialog-speaker\">{speakerName()}</div>\n }\n <div class=\"rpg-ui-dialog-content\">\n {displayMessage()}\n </div>\n @if (hasChoices()) {\n <Navigation tabindex={selectedItem} controls={controls}>\n <div class=\"rpg-ui-dialog-choices\">\n @for ((choice,index) of dialogChoices()) {\n <div\n class=\"rpg-ui-dialog-choice\"\n class={{active: selectedItem() === index}}\n tabindex={index}\n data-choice-index={index}\n click={selectChoice(index)}\n >{{ choice.text }}</div>\n }\n </div>\n </Navigation>\n }\n </div>\n @if (hasFace()) {\n <div class=\"rpg-ui-dialog-face\">\n <DOMSprite\n sheet={faceSheet(dialogFace())}\n width=\"100%\"\n height=\"100%\"\n objectFit=\"contain\"\n />\n </div>\n }\n </div>\n @if (showIndicator) {\n <div class=\"rpg-ui-dialog-indicator\"></div>\n }\n </div>\n </div>\n</DOMContainer>\n \n<script>\n import { effect, signal, computed, createTabindexNavigator, mount } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const currentPlayer = engine.scene.currentPlayer\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n engine.stopProcessingInput = true;\n\n const selectedItem = signal(0)\n const ACTION_OPEN_GUARD_MS = 150;\n const openedAt = Date.now();\n\n const {\n data,\n onFinish,\n onInteraction,\n guiOpenId\n } = defineProps();\n\n const dialogData = computed(() => data() || {});\n const dialogChoices = computed(() => Array.isArray(dialogData().choices) ? dialogData().choices : []);\n const message = computed(() => dialogData().message);\n const speaker = computed(() => dialogData().speaker);\n const position = computed(() => dialogData().position);\n const typewriterEffect = computed(() => dialogData().typewriterEffect);\n const fullWidth = computed(() => dialogData().fullWidth || false);\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const normalizeOpenId = (value) => {\n const resolved = resolveProp(value);\n return typeof resolved === \"string\" && resolved.length > 0 ? resolved : undefined;\n };\n\n const speakerName = computed(() => {\n const value = resolveProp(speaker());\n return value ? String(value) : \"\";\n });\n\n const dialogPosition = computed(() => resolveProp(position()) || \"bottom\");\n const isFullWidth = computed(() => resolveProp(fullWidth) !== false);\n const dialogFace = computed(() => resolveProp(dialogData().face));\n const hasFace = computed(() => {\n const value = dialogFace();\n return !!(value && value.id);\n });\n\n const displayMessage = signal(\"\");\n const fullMessage = signal(\"\");\n const isTyping = signal(false);\n let typewriterTimer = null;\n let rootElement = null;\n\n mount((element) => {\n rootElement = element;\n });\n\n const startTypewriter = (text) => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n displayMessage.set(\"\");\n if (!text) return;\n let index = 0;\n isTyping.set(true);\n typewriterTimer = setInterval(() => {\n index += 1;\n displayMessage.set(text.slice(0, index));\n if (index >= text.length) {\n clearInterval(typewriterTimer);\n typewriterTimer = null;\n isTyping.set(false);\n }\n }, 20);\n };\n\n const finishTyping = () => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n typewriterTimer = null;\n displayMessage.set(fullMessage());\n isTyping.set(false);\n };\n\n effect(() => {\n const text = resolveProp(message()) || \"\";\n fullMessage.set(text);\n const useTypewriter = resolveProp(typewriterEffect()) !== false;\n if (!useTypewriter) {\n finishTyping();\n return;\n }\n startTypewriter(text);\n });\n\n\n const hasChoices = computed(() => dialogChoices().length > 0);\n const showIndicator = computed(() => !hasChoices() && !isTyping());\n const nav = createTabindexNavigator(selectedItem, { count: () => dialogChoices().length }, 'wrap');\n\n function selectChoice(index) {\n return function() {\n selectedItem.set(index);\n onSelect(index);\n }\n }\n\n function _onFinish(value) {\n if (onFinish) onFinish(value, normalizeOpenId(guiOpenId));\n }\n\n const onSelect = (index) => {\n _onFinish(index);\n };\n\n const canAcceptAction = () => Date.now() - openedAt >= ACTION_OPEN_GUARD_MS;\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!canAcceptAction()) {\n return;\n }\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (!hasChoices()) return;\n onSelect(selectedItem());\n }\n },\n gamepad: {\n enabled: true\n }\n });\n \n const dialogControls = signal({\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!canAcceptAction()) {\n return;\n }\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (hasChoices()) return;\n _onFinish();\n }\n },\n })\n\n const faceSheet = (faceValue) => {\n if (!faceValue || !faceValue.id) {\n return undefined;\n }\n return {\n definition: engine.getSpriteSheet(faceValue.id),\n playing: faceValue.expression || \"default\",\n };\n }\n\n mount((element) => {\n return () => {\n // Wait destroy is finished before start processing input\n delay(() => {\n engine.stopProcessingInput = false;\n })\n }\n })\n</script>\n"],"mappings":"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"}
@@ -9,6 +9,7 @@ function component($$props) {
9
9
  useProps($$props);
10
10
  const defineProps = useDefineProps($$props);
11
11
  const engine = inject(RpgClientEngine);
12
+ const { t } = engine.i18n();
12
13
  const guiService = inject(RpgGui);
13
14
  const keyboardControls = engine.globalConfig.keyboardControls;
14
15
  const { entries, title, subtitle, saveLoad, localActions, onInteraction } = defineProps({
@@ -18,13 +19,13 @@ function component($$props) {
18
19
  });
19
20
  const defaultEntries = [{
20
21
  id: "title",
21
- label: "Title Screen"
22
+ label: t("rpg.gameover.title-screen")
22
23
  }, {
23
24
  id: "load",
24
- label: "Load Game"
25
+ label: t("rpg.gameover.load-game")
25
26
  }];
26
27
  const resolveProp = (value) => typeof value === "function" ? value() : value;
27
- const titleText = computed(() => resolveProp(title) || "Game Over");
28
+ const titleText = computed(() => resolveProp(title) || t("rpg.gameover.title"));
28
29
  const subtitleText = computed(() => resolveProp(subtitle) || "");
29
30
  const localActionsEnabled = computed(() => resolveProp(localActions) === true);
30
31
  const entryList = computed(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"gameover.ce.js","names":[],"sources":["../../../src/components/gui/gameover.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-gameover-screen rpg-anim-fade-in\">\n <div class=\"rpg-ui-gameover-splatter rpg-ui-gameover-splatter-left\"></div>\n <div class=\"rpg-ui-gameover-splatter rpg-ui-gameover-splatter-right\"></div>\n <div class=\"rpg-ui-gameover-splatter rpg-ui-gameover-splatter-center\"></div>\n <div class=\"rpg-ui-gameover-header rpg-anim-shake\">\n <div class=\"rpg-ui-gameover-title\">{titleText()}</div>\n @if (subtitleText()) {\n <div class=\"rpg-ui-gameover-subtitle\">{subtitleText()}</div>\n }\n </div>\n <Navigation tabindex={selectedEntry} controls={controls}>\n <div class=\"rpg-ui-menu rpg-ui-gameover-menu rpg-anim-slide-up\">\n @for ((entry,index) of entryList()) {\n <div\n class=\"rpg-ui-menu-item\"\n class={{disabled: isEntryDisabled(entry)}}\n data-selected={selectedEntry() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectEntry(index)}\n >{entry.label}</div>\n }\n </div>\n </Navigation>\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, effect } from \"canvasengine\";\n import { PrebuiltGui } from \"@rpgjs/common\";\n import { inject } from \"../../core/inject\";\n import { RpgClientEngine } from \"../../RpgClientEngine\";\n import { RpgGui } from \"../../Gui/Gui\";\n import { getKeyboardControlBind } from \"../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const guiService = inject(RpgGui);\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const { entries, title, subtitle, saveLoad, localActions, onInteraction } = defineProps({\n entries: {\n default: () => []\n },\n saveLoad: {\n default: () => ({})\n },\n localActions: {\n default: false\n }\n });\n\n const defaultEntries = [\n { id: \"title\", label: \"Title Screen\" },\n { id: \"load\", label: \"Load Game\" }\n ];\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const titleText = computed(() => resolveProp(title) || \"Game Over\");\n const subtitleText = computed(() => resolveProp(subtitle) || \"\");\n const localActionsEnabled = computed(() => resolveProp(localActions) === true);\n\n const entryList = computed(() => {\n const list = resolveProp(entries);\n if (Array.isArray(list) && list.length) return list;\n return defaultEntries;\n });\n\n const isEntryDisabled = (entry) => {\n if (!entry) return true;\n if (entry.disabled) return true;\n if (entry.enabled === false) return true;\n return false;\n };\n\n const selectedEntry = signal(0);\n const selectableIndexes = computed(() => {\n const list = entryList();\n return list\n .map((entry, index) => (isEntryDisabled(entry) ? null : index))\n .filter((value) => value !== null);\n });\n\n effect(() => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedEntry();\n if (!available.includes(current)) {\n selectedEntry.set(available[0]);\n }\n });\n\n const moveSelection = (delta) => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedEntry();\n const currentIndex = Math.max(0, available.indexOf(current));\n const nextIndex = (currentIndex + delta + available.length) % available.length;\n selectedEntry.set(available[nextIndex]);\n };\n\n const triggerSelect = (index) => {\n const list = entryList();\n const entry = list[index];\n if (!entry || isEntryDisabled(entry)) return;\n if (localActionsEnabled()) {\n if (entry.id === \"title\") {\n guiService.hide(PrebuiltGui.Gameover);\n guiService.display(PrebuiltGui.TitleScreen);\n }\n if (entry.id === \"load\") {\n const config = resolveProp(saveLoad) || {};\n const slots = Array.isArray(config.slots) ? config.slots : [null, null, null];\n guiService.display(PrebuiltGui.Save, {\n ...config,\n mode: config.mode || \"load\",\n slots\n });\n }\n }\n if (onInteraction) {\n onInteraction(\"select\", { id: entry.id, index, entry });\n }\n };\n\n function selectEntry(index) {\n return function() {\n selectedEntry.set(index);\n triggerSelect(index);\n };\n }\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n moveSelection(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n moveSelection(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n triggerSelect(selectedEntry());\n }\n },\n gamepad: {\n enabled: true\n }\n });\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"gameover.ce.js","names":[],"sources":["../../../src/components/gui/gameover.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-gameover-screen rpg-anim-fade-in\">\n <div class=\"rpg-ui-gameover-splatter rpg-ui-gameover-splatter-left\"></div>\n <div class=\"rpg-ui-gameover-splatter rpg-ui-gameover-splatter-right\"></div>\n <div class=\"rpg-ui-gameover-splatter rpg-ui-gameover-splatter-center\"></div>\n <div class=\"rpg-ui-gameover-header rpg-anim-shake\">\n <div class=\"rpg-ui-gameover-title\">{titleText()}</div>\n @if (subtitleText()) {\n <div class=\"rpg-ui-gameover-subtitle\">{subtitleText()}</div>\n }\n </div>\n <Navigation tabindex={selectedEntry} controls={controls}>\n <div class=\"rpg-ui-menu rpg-ui-gameover-menu rpg-anim-slide-up\">\n @for ((entry,index) of entryList()) {\n <div\n class=\"rpg-ui-menu-item\"\n class={{disabled: isEntryDisabled(entry)}}\n data-selected={selectedEntry() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectEntry(index)}\n >{entry.label}</div>\n }\n </div>\n </Navigation>\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, effect } from \"canvasengine\";\n import { PrebuiltGui } from \"@rpgjs/common\";\n import { inject } from \"../../core/inject\";\n import { RpgClientEngine } from \"../../RpgClientEngine\";\n import { RpgGui } from \"../../Gui/Gui\";\n import { getKeyboardControlBind } from \"../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const guiService = inject(RpgGui);\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const { entries, title, subtitle, saveLoad, localActions, onInteraction } = defineProps({\n entries: {\n default: () => []\n },\n saveLoad: {\n default: () => ({})\n },\n localActions: {\n default: false\n }\n });\n\n const defaultEntries = [\n { id: \"title\", label: t(\"rpg.gameover.title-screen\") },\n { id: \"load\", label: t(\"rpg.gameover.load-game\") }\n ];\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const titleText = computed(() => resolveProp(title) || t(\"rpg.gameover.title\"));\n const subtitleText = computed(() => resolveProp(subtitle) || \"\");\n const localActionsEnabled = computed(() => resolveProp(localActions) === true);\n\n const entryList = computed(() => {\n const list = resolveProp(entries);\n if (Array.isArray(list) && list.length) return list;\n return defaultEntries;\n });\n\n const isEntryDisabled = (entry) => {\n if (!entry) return true;\n if (entry.disabled) return true;\n if (entry.enabled === false) return true;\n return false;\n };\n\n const selectedEntry = signal(0);\n const selectableIndexes = computed(() => {\n const list = entryList();\n return list\n .map((entry, index) => (isEntryDisabled(entry) ? null : index))\n .filter((value) => value !== null);\n });\n\n effect(() => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedEntry();\n if (!available.includes(current)) {\n selectedEntry.set(available[0]);\n }\n });\n\n const moveSelection = (delta) => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedEntry();\n const currentIndex = Math.max(0, available.indexOf(current));\n const nextIndex = (currentIndex + delta + available.length) % available.length;\n selectedEntry.set(available[nextIndex]);\n };\n\n const triggerSelect = (index) => {\n const list = entryList();\n const entry = list[index];\n if (!entry || isEntryDisabled(entry)) return;\n if (localActionsEnabled()) {\n if (entry.id === \"title\") {\n guiService.hide(PrebuiltGui.Gameover);\n guiService.display(PrebuiltGui.TitleScreen);\n }\n if (entry.id === \"load\") {\n const config = resolveProp(saveLoad) || {};\n const slots = Array.isArray(config.slots) ? config.slots : [null, null, null];\n guiService.display(PrebuiltGui.Save, {\n ...config,\n mode: config.mode || \"load\",\n slots\n });\n }\n }\n if (onInteraction) {\n onInteraction(\"select\", { id: entry.id, index, entry });\n }\n };\n\n function selectEntry(index) {\n return function() {\n selectedEntry.set(index);\n triggerSelect(index);\n };\n }\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n moveSelection(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n moveSelection(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n triggerSelect(selectedEntry());\n }\n },\n gamepad: {\n enabled: true\n }\n });\n</script>\n"],"mappings":"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"}
@@ -7,6 +7,7 @@ function component($$props) {
7
7
  useProps($$props);
8
8
  const defineProps = useDefineProps($$props);
9
9
  const engine = inject(RpgClientEngine);
10
+ const { t } = engine.i18n();
10
11
  const keyboardControls = engine.globalConfig.keyboardControls;
11
12
  const currentPlayer = engine.scene.currentPlayer;
12
13
  const selectedTab = signal(0);
@@ -16,11 +17,11 @@ function component($$props) {
16
17
  const slots = computed(() => data().slots);
17
18
  const defaultSlots = [{
18
19
  id: "weapon",
19
- label: "Weapon",
20
+ label: t("rpg.menu.weapons"),
20
21
  types: ["weapon"]
21
22
  }, {
22
23
  id: "armor",
23
- label: "Armor",
24
+ label: t("rpg.menu.armor"),
24
25
  types: ["armor"]
25
26
  }];
26
27
  const resolveProp = (value) => typeof value === "function" ? value() : value;
@@ -73,13 +74,13 @@ function component($$props) {
73
74
  const items = slotItems().map((item) => ({
74
75
  ...item,
75
76
  kind: "item",
76
- tag: itemEquipped(item) ? "Equipped" : ""
77
+ tag: itemEquipped(item) ? t("rpg.shop.equipped") : ""
77
78
  }));
78
79
  if (!currentEquippedItem()) return items;
79
80
  return [{
80
81
  id: "__unequip__",
81
- name: "Unequip",
82
- description: "Remove the current equipment",
82
+ name: t("rpg.menu.unequip"),
83
+ description: t("rpg.menu.remove-equipment"),
83
84
  kind: "unequip",
84
85
  tag: ""
85
86
  }, ...items];
@@ -94,7 +95,7 @@ function component($$props) {
94
95
  const slot = currentSlot();
95
96
  if (!slot) return "";
96
97
  const equipped = currentEquippedItem();
97
- return equipped ? `${slot.label}: ${equipped.name}` : `${slot.label}: Empty`;
98
+ return equipped ? `${slot.label}: ${equipped.name}` : `${slot.label}: ${t("rpg.menu.empty")}`;
98
99
  });
99
100
  computed(() => listEntries().length === 0);
100
101
  const nav = createTabindexNavigator(selectedItem, { count: () => listEntries().length }, "wrap");
@@ -312,7 +313,7 @@ function component($$props) {
312
313
  }, [h(DOMElement, {
313
314
  element: "div",
314
315
  attrs: { class: "rpg-ui-menu-panel-header" },
315
- textContent: "Equip"
316
+ textContent: computed(() => t("rpg.menu.equip"))
316
317
  }), h(DOMElement, {
317
318
  element: "div",
318
319
  attrs: { class: "rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked" }
@@ -335,7 +336,7 @@ function component($$props) {
335
336
  h(DOMElement, {
336
337
  element: "div",
337
338
  attrs: { class: "rpg-ui-menu-panel-details-title" },
338
- textContent: computed(() => detailsItem()?.name || currentSlot()?.label || "Equip")
339
+ textContent: computed(() => detailsItem()?.name || currentSlot()?.label || t("rpg.menu.equip"))
339
340
  }),
340
341
  h(DOMElement, {
341
342
  element: "div",
@@ -1 +1 @@
1
- {"version":3,"file":"equip-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/equip-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-menu-panel rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-header\">Equip</div>\n <div class=\"rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked\">\n <div>\n <div class=\"rpg-ui-menu-panel-details rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-hero\">\n <div class=\"rpg-ui-menu-panel-hero-icon\">\n <DOMSprite \n sheet={iconSheet(detailsItem()?.icon)} \n playing=\"default\" \n width=\"48px\"\n height=\"48px\"\n objectFit=\"contain\"\n />\n </div>\n <div>\n <div class=\"rpg-ui-menu-panel-details-title\">\n {detailsItem()?.name || currentSlot()?.label || \"Equip\"}\n </div>\n <div class=\"rpg-ui-menu-panel-details-desc\">\n {detailsItem()?.description || \"\"}\n </div>\n @if (displayStats().length > 0) {\n <div class=\"rpg-ui-equip-stats\">\n @for ((stat,index) of displayStats) {\n <div class=\"rpg-ui-equip-stat\" class={{positive: stat.delta > 0, negative: stat.delta < 0}}>\n <div class=\"rpg-ui-equip-stat-key\">{stat.label}</div>\n <div class=\"rpg-ui-equip-stat-value\">\n {stat.delta > 0 ? \"+\" : \"\"}{stat.delta}\n </div>\n @if (stat.current) {\n <div class=\"rpg-ui-equip-stat-current\">{stat.current} -> {stat.next}</div>\n }\n </div>\n }\n </div>\n }\n <div class=\"rpg-ui-menu-panel-details-meta\">\n <span>{equippedText()}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"rpg-ui-menu-panel-list rpg-ui-menu rpg-ui-menu-panel-list-full\">\n <div class=\"rpg-ui-menu-tabs\">\n @for ((tab,tabIndex) of slotList) {\n <div\n class=\"rpg-ui-menu-tab\"\n class={{active: selectedTab() === tabIndex}}\n tabindex={tabIndex}\n click={selectTab(tabIndex)}\n >{tab.label}</div>\n }\n </div>\n <Navigation tabindex={selectedItem} controls={controls}>\n @for ((entry,index) of listEntries) {\n <div\n class=\"rpg-ui-menu-item rpg-ui-menu-row\"\n data-selected={selectedItem() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectItem(index)}\n >\n <div class=\"rpg-ui-menu-row-main\">\n <div class=\"rpg-ui-menu-row-icon\">\n @if (entry?.icon) {\n <DOMSprite \n sheet={iconSheet(entry.icon)} \n playing=\"default\" \n width=\"28px\"\n height=\"28px\"\n objectFit=\"contain\"\n />\n }\n </div>\n <span>{entry.name}</span>\n </div>\n <span class=\"rpg-ui-menu-row-end\">{entry.tag || \"\"}</span>\n </div>\n }\n </Navigation>\n </div>\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, createTabindexNavigator, effect } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const keyboardControls = engine.globalConfig.keyboardControls;\n const currentPlayer = engine.scene.currentPlayer;\n\n const selectedTab = signal(0);\n const selectedItem = signal(0);\n const { data, onInteraction, onBack } = defineProps();\n\n const equips = computed(() => data().equips ?? data().items);\n const slots = computed(() => data().slots);\n\n const defaultSlots = [\n { id: \"weapon\", label: \"Weapon\", types: [\"weapon\"] },\n { id: \"armor\", label: \"Armor\", types: [\"armor\"] }\n ];\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const safeEquips = computed(() => {\n const list = resolveProp(equips);\n return Array.isArray(list) ? list : [];\n });\n const slotList = computed(() => {\n const list = resolveProp(slots);\n if (Array.isArray(list) && list.length) return list;\n return defaultSlots;\n });\n\n const currentSlot = computed(() => slotList()[selectedTab()]);\n\n const equippedIds = computed(() => {\n const equipped = currentPlayer().equipments?.() || [];\n return new Set(equipped.map((it) => it?.id?.() ?? it?.id ?? it?.name));\n });\n const equippedOverrides = signal({});\n\n effect(() => {\n const next = {};\n safeEquips().forEach((item) => {\n if (item?.id && typeof item.equipped === \"boolean\") {\n next[item.id] = item.equipped;\n }\n });\n equippedOverrides.set(next);\n });\n\n const itemEquipped = (item) => {\n if (!item) return false;\n const overrides = equippedOverrides();\n if (Object.prototype.hasOwnProperty.call(overrides, item.id)) {\n return overrides[item.id];\n }\n if (typeof item.equipped === \"boolean\") return item.equipped;\n return equippedIds().has(item.id);\n };\n\n const slotTypes = (slot) => {\n if (!slot) return [];\n if (Array.isArray(slot.types)) return slot.types;\n if (slot.type) return [slot.type];\n if (slot.id) return [slot.id];\n return [];\n };\n\n const slotItems = computed(() => {\n const slot = currentSlot();\n if (!slot) return [];\n const types = new Set(slotTypes(slot));\n return safeEquips().filter((item) => item && types.has(item.type));\n });\n\n const currentEquippedItem = computed(() => {\n const list = slotItems();\n return list.find((item) => itemEquipped(item)) || null;\n });\n\n const listEntries = computed(() => {\n const items = slotItems().map((item) => ({\n ...item,\n kind: \"item\",\n tag: itemEquipped(item) ? \"Equipped\" : \"\"\n }));\n const equipped = currentEquippedItem();\n if (!equipped) return items;\n return [\n {\n id: \"__unequip__\",\n name: \"Unequip\",\n description: \"Remove the current equipment\",\n kind: \"unequip\",\n tag: \"\"\n },\n ...items\n ];\n });\n\n const currentEntry = computed(() => listEntries()[selectedItem()]);\n const detailsItem = computed(() => {\n const entry = currentEntry();\n if (entry?.kind === \"item\") return entry;\n return currentEquippedItem();\n });\n\n const equippedText = computed(() => {\n const slot = currentSlot();\n if (!slot) return \"\";\n const equipped = currentEquippedItem();\n return equipped ? `${slot.label}: ${equipped.name}` : `${slot.label}: Empty`;\n });\n const listEmpty = computed(() => listEntries().length === 0);\n\n const nav = createTabindexNavigator(selectedItem, { count: () => listEntries().length }, \"wrap\");\n\n const playerParams = computed(() => {\n const menuData = data();\n if (menuData?.playerStats) return menuData.playerStats;\n if (menuData?.playerParams) return menuData.playerParams;\n return currentPlayer()?._param?.() || {};\n });\n const statOrder = [\"atk\", \"def\", \"pdef\", \"sdef\", \"str\", \"dex\", \"int\", \"agi\", \"maxHp\", \"maxSp\"];\n const statLabels = {\n atk: \"ATK\",\n def: \"DEF\",\n pdef: \"PDEF\",\n sdef: \"SDEF\",\n str: \"STR\",\n dex: \"DEX\",\n int: \"INT\",\n agi: \"AGI\",\n maxHp: \"MAX HP\",\n maxSp: \"MAX SP\"\n };\n\n const getItemStats = (item) => {\n if (!item) return {};\n const stats = item.stats || item.params || {};\n if (Object.keys(stats).length) return stats;\n const keys = [\"atk\", \"def\", \"pdef\", \"sdef\", \"str\", \"dex\", \"int\", \"agi\", \"maxHp\", \"maxSp\"];\n const direct = {};\n keys.forEach((key) => {\n if (item[key] !== undefined) direct[key] = item[key];\n });\n return direct;\n };\n\n const buildStatsList = (deltaStats) => {\n const params = playerParams() || {};\n const orderedKeys = statOrder.filter((key) => deltaStats[key] !== undefined);\n const extraKeys = Object.keys(deltaStats).filter((key) => !statOrder.includes(key));\n const keys = orderedKeys.concat(extraKeys);\n const list = [];\n for (const key of keys) {\n const delta = deltaStats[key];\n if (delta === undefined || delta === 0) continue;\n let current = params[key];\n if (current === undefined && key === \"def\") current = params.pdef;\n const next = current !== undefined ? current + delta : undefined;\n list.push({\n key,\n label: statLabels[key] || key.toUpperCase(),\n delta,\n current,\n next\n });\n }\n return list;\n };\n\n const displayStats = computed(() => {\n const entry = currentEntry();\n const equipped = currentEquippedItem();\n if (!entry) return [];\n if (entry.kind === \"unequip\") {\n \n if (!equipped) return [];\n const stats = getItemStats(equipped);\n const delta = {};\n Object.keys(stats).forEach((key) => {\n delta[key] = -stats[key];\n });\n return buildStatsList(delta);\n }\n if (entry.kind === \"item\") {\n const equippedStats = getItemStats(equipped);\n const nextStats = getItemStats(entry);\n const delta = {};\n const keys = new Set([...Object.keys(nextStats), ...Object.keys(equippedStats)]);\n keys.forEach((key) => {\n delta[key] = (nextStats[key] || 0) - (equippedStats[key] || 0);\n });\n return buildStatsList(delta);\n }\n return [];\n });\n\n const applyEquipState = (slot, itemId, equip) => {\n const types = slotTypes(slot);\n const next = { ...equippedOverrides() };\n if (types.length) {\n safeEquips().forEach((item) => {\n if (!item) return;\n if (types.includes(item.type)) {\n next[item.id] = false;\n }\n });\n }\n if (itemId) {\n next[itemId] = equip;\n }\n equippedOverrides.set(next);\n };\n\n const commitSelection = (index) => {\n const entry = listEntries()[index];\n if (!entry) return;\n if (entry.kind === \"unequip\") {\n const equipped = currentEquippedItem();\n if (equipped && onInteraction) {\n onInteraction(\"equipItem\", { id: equipped.id, equip: false });\n }\n applyEquipState(currentSlot(), equipped?.id, false);\n return;\n }\n if (entry.kind === \"item\" && onInteraction) {\n if (!itemEquipped(entry)) {\n onInteraction(\"equipItem\", { id: entry.id, equip: true });\n }\n applyEquipState(currentSlot(), entry.id, true);\n }\n };\n\n function selectTab(index) {\n return function() {\n selectedTab.set(index);\n selectedItem.set(0);\n }\n }\n\n function selectItem(index) {\n return function() {\n selectedItem.set(index);\n commitSelection(index);\n }\n }\n\n const iconSheet = (iconId) => ({\n definition: engine.getSpriteSheet(iconId)\n });\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (!listEntries().length) return;\n nav.next(-1);\n }\n },\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n const tabs = slotList();\n if (!tabs.length) return;\n selectedTab.update((value) => (value - 1 + tabs.length) % tabs.length);\n selectedItem.set(0);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n const tabs = slotList();\n if (!tabs.length) return;\n selectedTab.update((value) => (value + 1) % tabs.length);\n selectedItem.set(0);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (!listEntries().length) return;\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!listEntries().length) return;\n commitSelection(selectedItem());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n effect(() => {\n const count = listEntries().length;\n if (!count) {\n selectedItem.set(0);\n return;\n }\n if (selectedItem() >= count) {\n selectedItem.set(count - 1);\n }\n });\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"equip-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/equip-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-menu-panel rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-header\">{t(\"rpg.menu.equip\")}</div>\n <div class=\"rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked\">\n <div>\n <div class=\"rpg-ui-menu-panel-details rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-hero\">\n <div class=\"rpg-ui-menu-panel-hero-icon\">\n <DOMSprite \n sheet={iconSheet(detailsItem()?.icon)} \n playing=\"default\" \n width=\"48px\"\n height=\"48px\"\n objectFit=\"contain\"\n />\n </div>\n <div>\n <div class=\"rpg-ui-menu-panel-details-title\">\n {detailsItem()?.name || currentSlot()?.label || t(\"rpg.menu.equip\")}\n </div>\n <div class=\"rpg-ui-menu-panel-details-desc\">\n {detailsItem()?.description || \"\"}\n </div>\n @if (displayStats().length > 0) {\n <div class=\"rpg-ui-equip-stats\">\n @for ((stat,index) of displayStats) {\n <div class=\"rpg-ui-equip-stat\" class={{positive: stat.delta > 0, negative: stat.delta < 0}}>\n <div class=\"rpg-ui-equip-stat-key\">{stat.label}</div>\n <div class=\"rpg-ui-equip-stat-value\">\n {stat.delta > 0 ? \"+\" : \"\"}{stat.delta}\n </div>\n @if (stat.current) {\n <div class=\"rpg-ui-equip-stat-current\">{stat.current} -> {stat.next}</div>\n }\n </div>\n }\n </div>\n }\n <div class=\"rpg-ui-menu-panel-details-meta\">\n <span>{equippedText()}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"rpg-ui-menu-panel-list rpg-ui-menu rpg-ui-menu-panel-list-full\">\n <div class=\"rpg-ui-menu-tabs\">\n @for ((tab,tabIndex) of slotList) {\n <div\n class=\"rpg-ui-menu-tab\"\n class={{active: selectedTab() === tabIndex}}\n tabindex={tabIndex}\n click={selectTab(tabIndex)}\n >{tab.label}</div>\n }\n </div>\n <Navigation tabindex={selectedItem} controls={controls}>\n @for ((entry,index) of listEntries) {\n <div\n class=\"rpg-ui-menu-item rpg-ui-menu-row\"\n data-selected={selectedItem() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectItem(index)}\n >\n <div class=\"rpg-ui-menu-row-main\">\n <div class=\"rpg-ui-menu-row-icon\">\n @if (entry?.icon) {\n <DOMSprite \n sheet={iconSheet(entry.icon)} \n playing=\"default\" \n width=\"28px\"\n height=\"28px\"\n objectFit=\"contain\"\n />\n }\n </div>\n <span>{entry.name}</span>\n </div>\n <span class=\"rpg-ui-menu-row-end\">{entry.tag || \"\"}</span>\n </div>\n }\n </Navigation>\n </div>\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, createTabindexNavigator, effect } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const keyboardControls = engine.globalConfig.keyboardControls;\n const currentPlayer = engine.scene.currentPlayer;\n\n const selectedTab = signal(0);\n const selectedItem = signal(0);\n const { data, onInteraction, onBack } = defineProps();\n\n const equips = computed(() => data().equips ?? data().items);\n const slots = computed(() => data().slots);\n\n const defaultSlots = [\n { id: \"weapon\", label: t(\"rpg.menu.weapons\"), types: [\"weapon\"] },\n { id: \"armor\", label: t(\"rpg.menu.armor\"), types: [\"armor\"] }\n ];\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const safeEquips = computed(() => {\n const list = resolveProp(equips);\n return Array.isArray(list) ? list : [];\n });\n const slotList = computed(() => {\n const list = resolveProp(slots);\n if (Array.isArray(list) && list.length) return list;\n return defaultSlots;\n });\n\n const currentSlot = computed(() => slotList()[selectedTab()]);\n\n const equippedIds = computed(() => {\n const equipped = currentPlayer().equipments?.() || [];\n return new Set(equipped.map((it) => it?.id?.() ?? it?.id ?? it?.name));\n });\n const equippedOverrides = signal({});\n\n effect(() => {\n const next = {};\n safeEquips().forEach((item) => {\n if (item?.id && typeof item.equipped === \"boolean\") {\n next[item.id] = item.equipped;\n }\n });\n equippedOverrides.set(next);\n });\n\n const itemEquipped = (item) => {\n if (!item) return false;\n const overrides = equippedOverrides();\n if (Object.prototype.hasOwnProperty.call(overrides, item.id)) {\n return overrides[item.id];\n }\n if (typeof item.equipped === \"boolean\") return item.equipped;\n return equippedIds().has(item.id);\n };\n\n const slotTypes = (slot) => {\n if (!slot) return [];\n if (Array.isArray(slot.types)) return slot.types;\n if (slot.type) return [slot.type];\n if (slot.id) return [slot.id];\n return [];\n };\n\n const slotItems = computed(() => {\n const slot = currentSlot();\n if (!slot) return [];\n const types = new Set(slotTypes(slot));\n return safeEquips().filter((item) => item && types.has(item.type));\n });\n\n const currentEquippedItem = computed(() => {\n const list = slotItems();\n return list.find((item) => itemEquipped(item)) || null;\n });\n\n const listEntries = computed(() => {\n const items = slotItems().map((item) => ({\n ...item,\n kind: \"item\",\n tag: itemEquipped(item) ? t(\"rpg.shop.equipped\") : \"\"\n }));\n const equipped = currentEquippedItem();\n if (!equipped) return items;\n return [\n {\n id: \"__unequip__\",\n name: t(\"rpg.menu.unequip\"),\n description: t(\"rpg.menu.remove-equipment\"),\n kind: \"unequip\",\n tag: \"\"\n },\n ...items\n ];\n });\n\n const currentEntry = computed(() => listEntries()[selectedItem()]);\n const detailsItem = computed(() => {\n const entry = currentEntry();\n if (entry?.kind === \"item\") return entry;\n return currentEquippedItem();\n });\n\n const equippedText = computed(() => {\n const slot = currentSlot();\n if (!slot) return \"\";\n const equipped = currentEquippedItem();\n return equipped ? `${slot.label}: ${equipped.name}` : `${slot.label}: ${t(\"rpg.menu.empty\")}`;\n });\n const listEmpty = computed(() => listEntries().length === 0);\n\n const nav = createTabindexNavigator(selectedItem, { count: () => listEntries().length }, \"wrap\");\n\n const playerParams = computed(() => {\n const menuData = data();\n if (menuData?.playerStats) return menuData.playerStats;\n if (menuData?.playerParams) return menuData.playerParams;\n return currentPlayer()?._param?.() || {};\n });\n const statOrder = [\"atk\", \"def\", \"pdef\", \"sdef\", \"str\", \"dex\", \"int\", \"agi\", \"maxHp\", \"maxSp\"];\n const statLabels = {\n atk: \"ATK\",\n def: \"DEF\",\n pdef: \"PDEF\",\n sdef: \"SDEF\",\n str: \"STR\",\n dex: \"DEX\",\n int: \"INT\",\n agi: \"AGI\",\n maxHp: \"MAX HP\",\n maxSp: \"MAX SP\"\n };\n\n const getItemStats = (item) => {\n if (!item) return {};\n const stats = item.stats || item.params || {};\n if (Object.keys(stats).length) return stats;\n const keys = [\"atk\", \"def\", \"pdef\", \"sdef\", \"str\", \"dex\", \"int\", \"agi\", \"maxHp\", \"maxSp\"];\n const direct = {};\n keys.forEach((key) => {\n if (item[key] !== undefined) direct[key] = item[key];\n });\n return direct;\n };\n\n const buildStatsList = (deltaStats) => {\n const params = playerParams() || {};\n const orderedKeys = statOrder.filter((key) => deltaStats[key] !== undefined);\n const extraKeys = Object.keys(deltaStats).filter((key) => !statOrder.includes(key));\n const keys = orderedKeys.concat(extraKeys);\n const list = [];\n for (const key of keys) {\n const delta = deltaStats[key];\n if (delta === undefined || delta === 0) continue;\n let current = params[key];\n if (current === undefined && key === \"def\") current = params.pdef;\n const next = current !== undefined ? current + delta : undefined;\n list.push({\n key,\n label: statLabels[key] || key.toUpperCase(),\n delta,\n current,\n next\n });\n }\n return list;\n };\n\n const displayStats = computed(() => {\n const entry = currentEntry();\n const equipped = currentEquippedItem();\n if (!entry) return [];\n if (entry.kind === \"unequip\") {\n \n if (!equipped) return [];\n const stats = getItemStats(equipped);\n const delta = {};\n Object.keys(stats).forEach((key) => {\n delta[key] = -stats[key];\n });\n return buildStatsList(delta);\n }\n if (entry.kind === \"item\") {\n const equippedStats = getItemStats(equipped);\n const nextStats = getItemStats(entry);\n const delta = {};\n const keys = new Set([...Object.keys(nextStats), ...Object.keys(equippedStats)]);\n keys.forEach((key) => {\n delta[key] = (nextStats[key] || 0) - (equippedStats[key] || 0);\n });\n return buildStatsList(delta);\n }\n return [];\n });\n\n const applyEquipState = (slot, itemId, equip) => {\n const types = slotTypes(slot);\n const next = { ...equippedOverrides() };\n if (types.length) {\n safeEquips().forEach((item) => {\n if (!item) return;\n if (types.includes(item.type)) {\n next[item.id] = false;\n }\n });\n }\n if (itemId) {\n next[itemId] = equip;\n }\n equippedOverrides.set(next);\n };\n\n const commitSelection = (index) => {\n const entry = listEntries()[index];\n if (!entry) return;\n if (entry.kind === \"unequip\") {\n const equipped = currentEquippedItem();\n if (equipped && onInteraction) {\n onInteraction(\"equipItem\", { id: equipped.id, equip: false });\n }\n applyEquipState(currentSlot(), equipped?.id, false);\n return;\n }\n if (entry.kind === \"item\" && onInteraction) {\n if (!itemEquipped(entry)) {\n onInteraction(\"equipItem\", { id: entry.id, equip: true });\n }\n applyEquipState(currentSlot(), entry.id, true);\n }\n };\n\n function selectTab(index) {\n return function() {\n selectedTab.set(index);\n selectedItem.set(0);\n }\n }\n\n function selectItem(index) {\n return function() {\n selectedItem.set(index);\n commitSelection(index);\n }\n }\n\n const iconSheet = (iconId) => ({\n definition: engine.getSpriteSheet(iconId)\n });\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (!listEntries().length) return;\n nav.next(-1);\n }\n },\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n const tabs = slotList();\n if (!tabs.length) return;\n selectedTab.update((value) => (value - 1 + tabs.length) % tabs.length);\n selectedItem.set(0);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n const tabs = slotList();\n if (!tabs.length) return;\n selectedTab.update((value) => (value + 1) % tabs.length);\n selectedItem.set(0);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (!listEntries().length) return;\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!listEntries().length) return;\n commitSelection(selectedItem());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n effect(() => {\n const count = listEntries().length;\n if (!count) {\n selectedItem.set(0);\n return;\n }\n if (selectedItem() >= count) {\n selectedItem.set(count - 1);\n }\n });\n</script>\n"],"mappings":"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"}
@@ -1,12 +1,14 @@
1
1
  import { inject } from "../../../core/inject.js";
2
2
  import { getKeyboardControlBind } from "../../../services/actionInput.js";
3
3
  import { RpgClientEngine } from "../../../RpgClientEngine.js";
4
- import { DOMContainer, DOMElement, h, signal, useDefineProps, useProps } from "canvasengine";
4
+ import { DOMContainer, DOMElement, computed, h, signal, useDefineProps, useProps } from "canvasengine";
5
5
  //#region src/components/gui/menu/exit-menu.ce
6
6
  function component($$props) {
7
7
  useProps($$props);
8
8
  const defineProps = useDefineProps($$props);
9
- const keyboardControls = inject(RpgClientEngine).globalConfig.keyboardControls;
9
+ const engine = inject(RpgClientEngine);
10
+ const { t } = engine.i18n();
11
+ const keyboardControls = engine.globalConfig.keyboardControls;
10
12
  const { onConfirm, onBack } = defineProps();
11
13
  return h(DOMContainer, {
12
14
  width: "100%",
@@ -32,7 +34,7 @@ function component($$props) {
32
34
  }, [h(DOMElement, {
33
35
  element: "div",
34
36
  attrs: { class: "rpg-ui-menu-panel-header" },
35
- textContent: "Exit"
37
+ textContent: computed(() => t("rpg.menu.exit"))
36
38
  }), h(DOMElement, {
37
39
  element: "div",
38
40
  attrs: { class: "rpg-ui-menu-panel-body" }
@@ -42,11 +44,11 @@ function component($$props) {
42
44
  }, [h(DOMElement, {
43
45
  element: "div",
44
46
  attrs: { class: "rpg-ui-menu-panel-details-title" },
45
- textContent: "Leave the game?"
47
+ textContent: computed(() => t("rpg.menu.leave-game"))
46
48
  }), h(DOMElement, {
47
49
  element: "div",
48
50
  attrs: { class: "rpg-ui-menu-panel-details-desc" },
49
- textContent: "Press Action to confirm or Escape to go back.\n "
51
+ textContent: computed(() => t("rpg.menu.exit-help"))
50
52
  })]))]));
51
53
  }
52
54
  var __ce_component = component;
@@ -1 +1 @@
1
- {"version":3,"file":"exit-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/exit-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={controls}>\n <div class=\"rpg-ui-menu-panel rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-header\">Exit</div>\n <div class=\"rpg-ui-menu-panel-body\">\n <div class=\"rpg-ui-menu-panel-details\">\n <div class=\"rpg-ui-menu-panel-details-title\">Leave the game?</div>\n <div class=\"rpg-ui-menu-panel-details-desc\">\n Press Action to confirm or Escape to go back.\n </div>\n </div>\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { signal } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const keyboardControls = engine.globalConfig.keyboardControls;\n const { onConfirm, onBack } = defineProps();\n\n const controls = signal({\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (onConfirm) onConfirm();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n</script>\n"],"mappings":";;;;;AAUM,SAAO,UAAA,SAAA;CACJ,SAAA,OAAA;CACP,MAAY,cAAA,eAAA,OAAA;CAEd,MAAC,mBAAA,OAAA,eAAM,EAAA,aAAA;CACP,MAAI,EAAA,WAAe,WAAS,YAAa;CAqBjC,OADI,EAAA,cAAA;EAAA,OAAA;EAAA,QAAA;EAAA,UAnBC,OAAS;GAClB,QAAQ;IACR,MAAS,uBAAwB,iBAAgB,MAAA;;KAE3C,IAAM,WACN,UAAgB;IACtB;;GAEA,QAAM;IACF,MAAM,iBAAE;IACR,UAAU;KACN,IAAA,QACI,OAAI;IACZ;GACJ;GACA,SAAI,EACA,SAAS,KACb;EACJ,CACY;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,iCAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,2BAAA;EAAA,aAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,yBAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,4BAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,kCAAA;EAAA,aAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,iCAAA;EAAA,aAAA;CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACH;AACH;AAEA,IAAE,iBAAA"}
1
+ {"version":3,"file":"exit-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/exit-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={controls}>\n <div class=\"rpg-ui-menu-panel rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-header\">{t(\"rpg.menu.exit\")}</div>\n <div class=\"rpg-ui-menu-panel-body\">\n <div class=\"rpg-ui-menu-panel-details\">\n <div class=\"rpg-ui-menu-panel-details-title\">{t(\"rpg.menu.leave-game\")}</div>\n <div class=\"rpg-ui-menu-panel-details-desc\">\n {t(\"rpg.menu.exit-help\")}\n </div>\n </div>\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { signal } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const keyboardControls = engine.globalConfig.keyboardControls;\n const { onConfirm, onBack } = defineProps();\n\n const controls = signal({\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (onConfirm) onConfirm();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n</script>\n"],"mappings":";;;;;AAUM,SAAO,UAAA,SAAA;CACJ,SAAA,OAAA;CACP,MAAY,cAAA,eAAA,OAAA;;CAEd,MAAC,EAAM,MAAA,OAAA,KAAA;CACP,MAAI,mBAAkB,OAAM,aAAa;CACzC,MAAI,EAAA,WAAe,WAAW,YAAY;CAqBlC,OADI,EAAA,cAAA;EAAA,OAAA;EAAA,QAAA;EAAA,UAnBC,OAAA;GACT,QAAQ;;IAER,UAAc;KACN,IAAI,WACN,UAAgB;IACtB;;GAEA,QAAM;IACF,MAAM,iBAAE;IACR,UAAU;KACN,IAAA,QACI,OAAI;IACZ;GACJ;GACA,SAAI,EACA,SAAS,KACb;EACJ,CACY;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,iCAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,2BAAA;EAAA,aAAA,eAAA,EAAA,eAAA,CAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,yBAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,4BAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,kCAAA;EAAA,aAAA,eAAA,EAAA,qBAAA,CAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,iCAAA;EAAA,aAAA,eAAA,EAAA,oBAAA,CAAA;CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACH;AACH;AAEA,IAAE,iBAAA"}
@@ -8,6 +8,7 @@ function component($$props) {
8
8
  useProps($$props);
9
9
  const defineProps = useDefineProps($$props);
10
10
  const engine = inject(RpgClientEngine);
11
+ const { t } = engine.i18n();
11
12
  const keyboardControls = engine.globalConfig.keyboardControls;
12
13
  const selectedItem = signal(0);
13
14
  const selectedTab = signal(0);
@@ -19,15 +20,15 @@ function component($$props) {
19
20
  const tabs = [
20
21
  {
21
22
  id: "item",
22
- label: "Items"
23
+ label: t("rpg.menu.items")
23
24
  },
24
25
  {
25
26
  id: "weapon",
26
- label: "Weapons"
27
+ label: t("rpg.menu.weapons")
27
28
  },
28
29
  {
29
30
  id: "armor",
30
- label: "Armor"
31
+ label: t("rpg.menu.armor")
31
32
  }
32
33
  ];
33
34
  const resolveProp = (value) => typeof value === "function" ? value() : value;
@@ -43,10 +44,10 @@ function component($$props) {
43
44
  });
44
45
  const confirmOptions = [{
45
46
  id: "use",
46
- label: "Use"
47
+ label: t("rpg.menu.use")
47
48
  }, {
48
49
  id: "cancel",
49
- label: "Cancel"
50
+ label: t("rpg.menu.cancel")
50
51
  }];
51
52
  const nav = createTabindexNavigator(selectedItem, { count: () => filteredItems().length }, "wrap");
52
53
  const navConfirm = createTabindexNavigator(selectedConfirm, { count: () => confirmOptions.length }, "wrap");
@@ -219,7 +220,7 @@ function component($$props) {
219
220
  h(DOMElement, {
220
221
  element: "div",
221
222
  attrs: { class: "rpg-ui-menu-panel-header" },
222
- textContent: "Items"
223
+ textContent: computed(() => t("rpg.menu.items"))
223
224
  }),
224
225
  h(DOMElement, {
225
226
  element: "div",
@@ -301,7 +302,7 @@ function component($$props) {
301
302
  }, [h(DOMElement, {
302
303
  element: "div",
303
304
  attrs: { class: "rpg-ui-menu-confirm-title" },
304
- textContent: computed(() => "Use " + confirmItem()?.name + "?")
305
+ textContent: computed(() => t("rpg.menu.use") + confirmItem()?.name + "?")
305
306
  }), h(Navigation, {
306
307
  tabindex: selectedConfirm,
307
308
  controls: confirmControls