@rpgjs/client 5.0.0-beta.22 → 5.0.0-beta.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/Game/Object.d.ts +6 -0
  3. package/dist/Game/Object.js +58 -2
  4. package/dist/Game/Object.js.map +1 -1
  5. package/dist/RpgClientEngine.d.ts +2 -0
  6. package/dist/RpgClientEngine.js +15 -6
  7. package/dist/RpgClientEngine.js.map +1 -1
  8. package/dist/components/character-hitbox.d.ts +13 -0
  9. package/dist/components/character-hitbox.js +38 -0
  10. package/dist/components/character-hitbox.js.map +1 -0
  11. package/dist/components/character-hitbox.spec.d.ts +1 -0
  12. package/dist/components/character.ce.js +38 -29
  13. package/dist/components/character.ce.js.map +1 -1
  14. package/dist/components/gui/dialogbox/index.ce.js +31 -2
  15. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  16. package/dist/components/gui/hud/hud.ce.js +2 -2
  17. package/dist/components/gui/hud/hud.ce.js.map +1 -1
  18. package/dist/components/gui/menu/items-menu.ce.js +27 -4
  19. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  20. package/dist/components/gui/menu/main-menu.ce.js +210 -155
  21. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  22. package/dist/components/gui/save-load.ce.js +33 -4
  23. package/dist/components/gui/save-load.ce.js.map +1 -1
  24. package/dist/components/gui/shop/shop.ce.js +47 -4
  25. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  26. package/dist/services/standalone.d.ts +6 -1
  27. package/dist/services/standalone.js +35 -17
  28. package/dist/services/standalone.js.map +1 -1
  29. package/dist/utils/syncHitbox.d.ts +1 -0
  30. package/dist/utils/syncHitbox.js +69 -0
  31. package/dist/utils/syncHitbox.js.map +1 -0
  32. package/dist/utils/syncHitbox.spec.d.ts +1 -0
  33. package/package.json +4 -4
  34. package/src/Game/Object.spec.ts +70 -6
  35. package/src/Game/Object.ts +90 -2
  36. package/src/RpgClientEngine.ts +19 -6
  37. package/src/components/character-hitbox.spec.ts +33 -0
  38. package/src/components/character-hitbox.ts +72 -0
  39. package/src/components/character.ce +52 -45
  40. package/src/components/gui/dialogbox/index.ce +56 -40
  41. package/src/components/gui/hud/hud.ce +2 -2
  42. package/src/components/gui/menu/items-menu.ce +12 -2
  43. package/src/components/gui/menu/main-menu.ce +37 -6
  44. package/src/components/gui/save-load.ce +48 -32
  45. package/src/components/gui/shop/shop.ce +28 -3
  46. package/src/services/standalone.spec.ts +47 -0
  47. package/src/services/standalone.ts +53 -20
  48. package/src/utils/syncHitbox.spec.ts +79 -0
  49. package/src/utils/syncHitbox.ts +104 -0
@@ -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 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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"}
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 class=\"rpg-ui-dialog-layer\" click={closeDialogFromPointer}>\n <button class=\"rpg-ui-close-button\" type=\"button\" title=\"Close\" aria-label=\"Close dialog\" click={closeDialogFromPointer}>x</button>\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\" click={stopEvent}>\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 </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 stopEvent = (event) => {\n event?.stopPropagation?.();\n };\n\n const closeDialog = () => {\n _onFinish();\n };\n\n const closeDialogFromPointer = (event) => {\n stopEvent(event);\n closeDialog();\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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"}
@@ -39,8 +39,8 @@ function component($$props) {
39
39
  attrs: { class: "rpg-avatar-face" }
40
40
  }, h(DOMSprite, {
41
41
  sheet: computed(() => faceSheet(face())),
42
- width: 64,
43
- height: 64,
42
+ width: "100%",
43
+ height: "100%",
44
44
  objectFit: "contain"
45
45
  }))), h(DOMElement, {
46
46
  element: "div",
@@ -1 +1 @@
1
- {"version":3,"file":"hud.ce.js","names":[],"sources":["../../../../src/components/gui/hud/hud.ce"],"sourcesContent":["<DOMContainer>\n <div class=\"rpg-hud\">\n <div class=\"rpg-avatar\">\n @if (hasFace()) {\n <div class=\"rpg-avatar-face\">\n <DOMSprite \n sheet={faceSheet(face())} \n width={64} \n height={64} \n objectFit=\"contain\" \n />\n </div>\n }\n <div class=\"rpg-avatar-level\">{{ level() }}</div>\n </div>\n <div class=\"rpg-status-bars\">\n <div class=\"rpg-bar-container\">\n <span class=\"rpg-bar-text\">HP {{ hp() }}/{{ hpMax() }}</span>\n <div class=\"rpg-bar-fill health\" style={{width: percentHp}}></div>\n </div>\n <div class=\"rpg-bar-container\">\n <span class=\"rpg-bar-text\">SP {{ sp() }}/{{ spMax() }}</span>\n <div class=\"rpg-bar-fill mana\" style={{width: percentSp}}></div>\n </div>\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { computed } from \"canvasengine\";\n import { getEntityProp } from \"../../../utils/getEntityProp\";\n\n const engine = inject(RpgClientEngine)\n const currentPlayer = engine.scene.currentPlayer\n const { data } = defineProps();\n const { faceset } = data();\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const face = computed(() => resolveProp(data().faceset));\n\n const hasFace = computed(() => {\n const value = face();\n return !!(value && value.id);\n });\n const faceSheet = (faceValue) => ({\n definition: engine.getSpriteSheet(faceValue.id),\n playing: faceValue.expression || \"default\",\n });\n const hp = getEntityProp(currentPlayer, \"hp\")\n const hpMax = getEntityProp(currentPlayer, \"params.maxHp\")\n const percentHp = computed(() => (hp() / hpMax() * 100) + '%')\n\n const sp = getEntityProp(currentPlayer, \"sp\")\n const spMax = getEntityProp(currentPlayer, \"params.maxSp\")\n const percentSp = computed(() => (sp() / spMax() * 100) + '%')\n\n const level = getEntityProp(currentPlayer, \"level\")\n</script>\n \n"],"mappings":";;;;;AAWM,SAAS,UAAM,SAAA;CACT,SAAA,OAAA;CACJ,MAAK,cAAe,eAAe,OAAO;CACrC,eAAA,OAAA;CACL,MAAK,SAAU,OAAO,eAAM;CACpC,MAAM,gBAAgB,OAAM,MAAI;CAChC,MAAM,EAAE,SAAS,YAAY;CAC7B,MAAM,EAAE,YAAY,KAAC;CACrB,MAAM,eAAW,UAAA,OAAA,UAAA,aAAA,MAAA,IAAA;CACjB,MAAM,OAAO,eAAe,YAAI,KAAU,EAAA,OAAA,CAAA;CAC1C,MAAM,UAAU,eAAa;EACzB,MAAM,QAAO,KAAI;EACjB,OAAO,CAAC,EAAE,SAAG,MAAA;CACjB,CAAC;CACD,MAAM,aAAG,eAAA;EACP,YAAY,OAAA,eAAA,UAAA,EAAA;;CAEd;CACA,MAAI,KAAO,cAAW,eAAe,IAAK;CAC1C,MAAI,QAAS,cAAe,eAAe,cAAG;CAC9C,MAAI,YAAS,eAAiB,GAAA,IAAA,MAAa,IAAA,MAAA,GAAA;CAC3C,MAAI,KAAO,cAAE,eAA2B,IAAI;;CAE5C,MAAI,YAAc,eAAQ,GAAA,IAAe,MAAA,IAAA,MAAA,GAAA;CACzC,MAAI,QAAM,cAAgB,eAAa,OAAA;CAEnC,OADgB,EAAC,cAAa,MAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,UAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,aAAA;CAAA,GAAA,CAAA,KAAA,eAAA,QAAA,CAAA,SAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,kBAAA;CAAA,GAAA,EAAA,WAAA;EAAA,OAAA,eAAA,UAAA,KAAA,CAAA,CAAA;EAAA,OAAA;EAAA,QAAA;EAAA,WAAA;CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,mBAAA;EAAA,aAAA,eAAA,MAAA,CAAA;CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,kBAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,oBAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,eAAA;EAAA,aAAA,eAAA,QAAA,GAAA,IAAA,MAAA,MAAA,CAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,OAAA,EAAA,OAAA,UAAA;EAAA;CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,oBAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,eAAA;EAAA,aAAA,eAAA,QAAA,GAAA,IAAA,MAAA,MAAA,CAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,OAAA,EAAA,OAAA,UAAA;EAAA;CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACf;;AAGf,IAAM,iBAAmB"}
1
+ {"version":3,"file":"hud.ce.js","names":[],"sources":["../../../../src/components/gui/hud/hud.ce"],"sourcesContent":["<DOMContainer>\n <div class=\"rpg-hud\">\n <div class=\"rpg-avatar\">\n @if (hasFace()) {\n <div class=\"rpg-avatar-face\">\n <DOMSprite \n sheet={faceSheet(face())} \n width=\"100%\" \n height=\"100%\" \n objectFit=\"contain\" \n />\n </div>\n }\n <div class=\"rpg-avatar-level\">{{ level() }}</div>\n </div>\n <div class=\"rpg-status-bars\">\n <div class=\"rpg-bar-container\">\n <span class=\"rpg-bar-text\">HP {{ hp() }}/{{ hpMax() }}</span>\n <div class=\"rpg-bar-fill health\" style={{width: percentHp}}></div>\n </div>\n <div class=\"rpg-bar-container\">\n <span class=\"rpg-bar-text\">SP {{ sp() }}/{{ spMax() }}</span>\n <div class=\"rpg-bar-fill mana\" style={{width: percentSp}}></div>\n </div>\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { computed } from \"canvasengine\";\n import { getEntityProp } from \"../../../utils/getEntityProp\";\n\n const engine = inject(RpgClientEngine)\n const currentPlayer = engine.scene.currentPlayer\n const { data } = defineProps();\n const { faceset } = data();\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const face = computed(() => resolveProp(data().faceset));\n\n const hasFace = computed(() => {\n const value = face();\n return !!(value && value.id);\n });\n const faceSheet = (faceValue) => ({\n definition: engine.getSpriteSheet(faceValue.id),\n playing: faceValue.expression || \"default\",\n });\n const hp = getEntityProp(currentPlayer, \"hp\")\n const hpMax = getEntityProp(currentPlayer, \"params.maxHp\")\n const percentHp = computed(() => (hp() / hpMax() * 100) + '%')\n\n const sp = getEntityProp(currentPlayer, \"sp\")\n const spMax = getEntityProp(currentPlayer, \"params.maxSp\")\n const percentSp = computed(() => (sp() / spMax() * 100) + '%')\n\n const level = getEntityProp(currentPlayer, \"level\")\n</script>\n \n"],"mappings":";;;;;AAWM,SAAS,UAAM,SAAA;CACT,SAAA,OAAA;CACJ,MAAK,cAAe,eAAe,OAAO;CACrC,eAAA,OAAA;CACL,MAAK,SAAU,OAAO,eAAM;CACpC,MAAM,gBAAgB,OAAM,MAAI;CAChC,MAAM,EAAE,SAAS,YAAY;CAC7B,MAAM,EAAE,YAAY,KAAC;CACrB,MAAM,eAAW,UAAA,OAAA,UAAA,aAAA,MAAA,IAAA;CACjB,MAAM,OAAO,eAAe,YAAI,KAAU,EAAA,OAAA,CAAA;CAC1C,MAAM,UAAU,eAAa;EACzB,MAAM,QAAO,KAAI;EACjB,OAAO,CAAC,EAAE,SAAG,MAAA;CACjB,CAAC;CACD,MAAM,aAAG,eAAA;EACP,YAAY,OAAA,eAAA,UAAA,EAAA;;CAEd;CACA,MAAI,KAAO,cAAW,eAAe,IAAK;CAC1C,MAAI,QAAS,cAAe,eAAe,cAAG;CAC9C,MAAI,YAAS,eAAiB,GAAA,IAAA,MAAa,IAAA,MAAA,GAAA;CAC3C,MAAI,KAAO,cAAE,eAA2B,IAAI;;CAE5C,MAAI,YAAc,eAAQ,GAAA,IAAe,MAAA,IAAA,MAAA,GAAA;CACzC,MAAI,QAAM,cAAgB,eAAa,OAAA;CAEnC,OADgB,EAAC,cAAa,MAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,UAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,aAAA;CAAA,GAAA,CAAA,KAAA,eAAA,QAAA,CAAA,SAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,kBAAA;CAAA,GAAA,EAAA,WAAA;EAAA,OAAA,eAAA,UAAA,KAAA,CAAA,CAAA;EAAA,OAAA;EAAA,QAAA;EAAA,WAAA;CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,mBAAA;EAAA,aAAA,eAAA,MAAA,CAAA;CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,kBAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,oBAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,eAAA;EAAA,aAAA,eAAA,QAAA,GAAA,IAAA,MAAA,MAAA,CAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,OAAA,EAAA,OAAA,UAAA;EAAA;CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,oBAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,eAAA;EAAA,aAAA,eAAA,QAAA,GAAA,IAAA,MAAA,MAAA,CAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,OAAA,EAAA,OAAA,UAAA;EAAA;CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACf;;AAGf,IAAM,iBAAmB"}
@@ -105,6 +105,13 @@ function component($$props) {
105
105
  confirmItem.set(null);
106
106
  });
107
107
  };
108
+ const stopEvent = (event) => {
109
+ event?.stopPropagation?.();
110
+ };
111
+ const cancelConfirmFromPointer = (event) => {
112
+ stopEvent(event);
113
+ cancelConfirm();
114
+ };
108
115
  function confirmSelect(index) {
109
116
  return function() {
110
117
  selectedConfirm.set(index);
@@ -296,10 +303,26 @@ function component($$props) {
296
303
  })])))])]),
297
304
  cond(confirmOpen, () => h(DOMElement, {
298
305
  element: "div",
299
- attrs: { class: "rpg-ui-menu-confirm" }
300
- }, h(DOMElement, {
306
+ attrs: {
307
+ class: "rpg-ui-menu-confirm",
308
+ click: cancelConfirmFromPointer
309
+ }
310
+ }, [h(DOMElement, {
311
+ element: "button",
312
+ attrs: {
313
+ class: "rpg-ui-close-button",
314
+ type: "button",
315
+ title: "Close",
316
+ "aria-label": "Close confirmation",
317
+ click: cancelConfirmFromPointer
318
+ },
319
+ textContent: "x"
320
+ }), h(DOMElement, {
301
321
  element: "div",
302
- attrs: { class: "rpg-ui-menu-confirm-card" }
322
+ attrs: {
323
+ class: "rpg-ui-menu-confirm-card",
324
+ click: stopEvent
325
+ }
303
326
  }, [h(DOMElement, {
304
327
  element: "div",
305
328
  attrs: { class: "rpg-ui-menu-confirm-title" },
@@ -319,7 +342,7 @@ function component($$props) {
319
342
  click: confirmSelect(index)
320
343
  },
321
344
  textContent: option.label
322
- }))))])))
345
+ }))))])]))
323
346
  ]));
324
347
  }
325
348
  var __ce_component = component;
@@ -1 +1 @@
1
- {"version":3,"file":"items-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/items-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.items\")}</div>\n <div class=\"rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked\">\n <div>\n @if (currentItem) {\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(currentItem()?.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\">{currentItem()?.name}</div>\n <div class=\"rpg-ui-menu-panel-details-desc\">{currentItem()?.description || \"\"}</div>\n </div>\n </div>\n </div>\n }\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 tabs) {\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 ((item,index) of filteredItems) {\n <div\n class=\"rpg-ui-menu-item rpg-ui-menu-row\"\n class={{disabled: !item.usable}}\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 <DOMSprite \n sheet={iconSheet(item.icon)} \n playing=\"default\" \n width=\"28px\"\n height=\"28px\"\n objectFit=\"contain\"\n />\n </div>\n <span>{item.name}</span>\n </div>\n <span class=\"rpg-ui-menu-row-end\">x{item.quantity ?? 1}</span>\n </div>\n }\n </Navigation>\n </div>\n </div>\n @if (confirmOpen) {\n <div class=\"rpg-ui-menu-confirm\">\n <div class=\"rpg-ui-menu-confirm-card\">\n <div class=\"rpg-ui-menu-confirm-title\">{t(\"rpg.menu.use\")} {confirmItem()?.name}?</div>\n <Navigation tabindex={selectedConfirm} controls={confirmControls}>\n <div class=\"rpg-ui-menu-confirm-actions\">\n @for ((option,index) of confirmOptions) {\n <button\n class=\"rpg-ui-menu-confirm-btn\"\n class={{\"rpg-ui-menu-confirm-btn-secondary\": option.id === \"cancel\"}}\n data-selected={selectedConfirm() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={confirmSelect(index)}\n >{option.label}</button>\n }\n </div>\n </Navigation>\n </div>\n </div>\n }\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 { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const selectedItem = signal(0);\n const selectedTab = signal(0);\n const selectedConfirm = signal(0);\n const confirmOpen = signal(false);\n const confirmItem = signal(null);\n\n const { data, onInteraction, onBack } = defineProps();\n\n const items = computed(() => data().items);\n\n const tabs = [\n { id: \"item\", label: t(\"rpg.menu.items\") },\n { id: \"weapon\", label: t(\"rpg.menu.weapons\") },\n { id: \"armor\", label: t(\"rpg.menu.armor\") }\n ];\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const safeItems = computed(() => {\n const value = resolveProp(items);\n return Array.isArray(value) ? value : [];\n });\n\n const filteredItems = computed(() => {\n const items = safeItems();\n const tab = tabs[selectedTab()];\n if (!tab) return [];\n return items.filter((item) => item.type === tab.id && (item.quantity ?? 1) > 0);\n });\n\n const confirmOptions = [\n { id: \"use\", label: t(\"rpg.menu.use\") },\n { id: \"cancel\", label: t(\"rpg.menu.cancel\") }\n ];\n\n const nav = createTabindexNavigator(selectedItem, { count: () => filteredItems().length }, \"wrap\");\n const navConfirm = createTabindexNavigator(selectedConfirm, { count: () => confirmOptions.length }, \"wrap\");\n const currentItem = computed(() => filteredItems()[selectedItem()]);\n const iconSheet = (iconId) => ({\n definition: engine.getSpriteSheet(iconId)\n });\n\n const clampSelection = () => {\n const count = filteredItems().length;\n if (count === 0) {\n selectedItem.set(0);\n return;\n }\n if (selectedItem() >= count) {\n selectedItem.set(count - 1);\n }\n };\n\n function selectItem(index) {\n return function() {\n selectedItem.set(index);\n requestUseItem(index);\n }\n }\n\n function selectTab(index) {\n return function() {\n selectedItem.set(0);\n selectedTab.set(index);\n }\n }\n\n const useItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n };\n\n const requestUseItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (item.consumable) {\n confirmItem.set(item);\n confirmOpen.set(true);\n selectedConfirm.set(0);\n return;\n }\n useItem(index);\n };\n\n const confirmUse = () => {\n const item = confirmItem();\n if (!item) return;\n delay(() => {\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n const cancelConfirm = () => {\n delay(() => {\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n function confirmSelect(index) {\n return function() {\n selectedConfirm.set(index);\n if (index === 0) {\n confirmUse();\n return;\n }\n cancelConfirm();\n }\n }\n\n const confirmControls = signal({\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(-1);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!confirmOpen()) return;\n confirmSelect(selectedConfirm())();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (!confirmOpen()) return;\n cancelConfirm();\n }\n }\n });\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n nav.next(-1);\n }\n },\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\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 if (confirmOpen()) {\n return;\n }\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 (confirmOpen()) {\n return;\n }\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (confirmOpen()) {\n confirmSelect(selectedConfirm())();\n return;\n }\n requestUseItem(selectedItem());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (confirmOpen()) {\n cancelConfirm();\n return;\n }\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n clampSelection();\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"items-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/items-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.items\")}</div>\n <div class=\"rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked\">\n <div>\n @if (currentItem) {\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(currentItem()?.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\">{currentItem()?.name}</div>\n <div class=\"rpg-ui-menu-panel-details-desc\">{currentItem()?.description || \"\"}</div>\n </div>\n </div>\n </div>\n }\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 tabs) {\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 ((item,index) of filteredItems) {\n <div\n class=\"rpg-ui-menu-item rpg-ui-menu-row\"\n class={{disabled: !item.usable}}\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 <DOMSprite \n sheet={iconSheet(item.icon)} \n playing=\"default\" \n width=\"28px\"\n height=\"28px\"\n objectFit=\"contain\"\n />\n </div>\n <span>{item.name}</span>\n </div>\n <span class=\"rpg-ui-menu-row-end\">x{item.quantity ?? 1}</span>\n </div>\n }\n </Navigation>\n </div>\n </div>\n @if (confirmOpen) {\n <div class=\"rpg-ui-menu-confirm\" click={cancelConfirmFromPointer}>\n <button class=\"rpg-ui-close-button\" type=\"button\" title=\"Close\" aria-label=\"Close confirmation\" click={cancelConfirmFromPointer}>x</button>\n <div class=\"rpg-ui-menu-confirm-card\" click={stopEvent}>\n <div class=\"rpg-ui-menu-confirm-title\">{t(\"rpg.menu.use\")} {confirmItem()?.name}?</div>\n <Navigation tabindex={selectedConfirm} controls={confirmControls}>\n <div class=\"rpg-ui-menu-confirm-actions\">\n @for ((option,index) of confirmOptions) {\n <button\n class=\"rpg-ui-menu-confirm-btn\"\n class={{\"rpg-ui-menu-confirm-btn-secondary\": option.id === \"cancel\"}}\n data-selected={selectedConfirm() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={confirmSelect(index)}\n >{option.label}</button>\n }\n </div>\n </Navigation>\n </div>\n </div>\n }\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 { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const selectedItem = signal(0);\n const selectedTab = signal(0);\n const selectedConfirm = signal(0);\n const confirmOpen = signal(false);\n const confirmItem = signal(null);\n\n const { data, onInteraction, onBack } = defineProps();\n\n const items = computed(() => data().items);\n\n const tabs = [\n { id: \"item\", label: t(\"rpg.menu.items\") },\n { id: \"weapon\", label: t(\"rpg.menu.weapons\") },\n { id: \"armor\", label: t(\"rpg.menu.armor\") }\n ];\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const safeItems = computed(() => {\n const value = resolveProp(items);\n return Array.isArray(value) ? value : [];\n });\n\n const filteredItems = computed(() => {\n const items = safeItems();\n const tab = tabs[selectedTab()];\n if (!tab) return [];\n return items.filter((item) => item.type === tab.id && (item.quantity ?? 1) > 0);\n });\n\n const confirmOptions = [\n { id: \"use\", label: t(\"rpg.menu.use\") },\n { id: \"cancel\", label: t(\"rpg.menu.cancel\") }\n ];\n\n const nav = createTabindexNavigator(selectedItem, { count: () => filteredItems().length }, \"wrap\");\n const navConfirm = createTabindexNavigator(selectedConfirm, { count: () => confirmOptions.length }, \"wrap\");\n const currentItem = computed(() => filteredItems()[selectedItem()]);\n const iconSheet = (iconId) => ({\n definition: engine.getSpriteSheet(iconId)\n });\n\n const clampSelection = () => {\n const count = filteredItems().length;\n if (count === 0) {\n selectedItem.set(0);\n return;\n }\n if (selectedItem() >= count) {\n selectedItem.set(count - 1);\n }\n };\n\n function selectItem(index) {\n return function() {\n selectedItem.set(index);\n requestUseItem(index);\n }\n }\n\n function selectTab(index) {\n return function() {\n selectedItem.set(0);\n selectedTab.set(index);\n }\n }\n\n const useItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n };\n\n const requestUseItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (item.consumable) {\n confirmItem.set(item);\n confirmOpen.set(true);\n selectedConfirm.set(0);\n return;\n }\n useItem(index);\n };\n\n const confirmUse = () => {\n const item = confirmItem();\n if (!item) return;\n delay(() => {\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n const cancelConfirm = () => {\n delay(() => {\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n const stopEvent = (event) => {\n event?.stopPropagation?.();\n };\n\n const cancelConfirmFromPointer = (event) => {\n stopEvent(event);\n cancelConfirm();\n };\n\n function confirmSelect(index) {\n return function() {\n selectedConfirm.set(index);\n if (index === 0) {\n confirmUse();\n return;\n }\n cancelConfirm();\n }\n }\n\n const confirmControls = signal({\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(-1);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!confirmOpen()) return;\n confirmSelect(selectedConfirm())();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (!confirmOpen()) return;\n cancelConfirm();\n }\n }\n });\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n nav.next(-1);\n }\n },\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\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 if (confirmOpen()) {\n return;\n }\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 (confirmOpen()) {\n return;\n }\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (confirmOpen()) {\n confirmSelect(selectedConfirm())();\n return;\n }\n requestUseItem(selectedItem());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (confirmOpen()) {\n cancelConfirm();\n return;\n }\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n clampSelection();\n</script>\n"],"mappings":"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"}
@@ -112,6 +112,24 @@ function component($$props) {
112
112
  view.set("menu");
113
113
  });
114
114
  };
115
+ const stopEvent = (event) => {
116
+ event?.stopPropagation?.();
117
+ };
118
+ const closeSaveOverlayFromPointer = (event) => {
119
+ stopEvent(event);
120
+ closeSaveOverlay();
121
+ };
122
+ const closeMenu = () => {
123
+ if (saveOverlay()) {
124
+ closeSaveOverlay();
125
+ return;
126
+ }
127
+ onFinish();
128
+ };
129
+ const closeMenuFromPointer = (event) => {
130
+ stopEvent(event);
131
+ closeMenu();
132
+ };
115
133
  const confirmExit = () => {
116
134
  if (onInteraction) onInteraction("exit");
117
135
  };
@@ -210,11 +228,18 @@ function component($$props) {
210
228
  gamepad: { enabled: true }
211
229
  });
212
230
  mount((element) => {
231
+ const inputLockToken = {};
232
+ const previousStopProcessingInput = engine.stopProcessingInput;
233
+ const previousGamePause = engine.gamePause();
234
+ engine.__rpgMainMenuInputLock = inputLockToken;
235
+ engine.stopProcessingInput = true;
213
236
  engine.gamePause.set(true);
214
237
  return () => {
215
238
  delay(() => {
216
- engine.stopProcessingInput = false;
217
- engine.gamePause.set(false);
239
+ if (engine.__rpgMainMenuInputLock !== inputLockToken) return;
240
+ engine.__rpgMainMenuInputLock = void 0;
241
+ engine.stopProcessingInput = previousStopProcessingInput;
242
+ engine.gamePause.set(previousGamePause);
218
243
  });
219
244
  };
220
245
  });
@@ -223,177 +248,207 @@ function component($$props) {
223
248
  height: "100%",
224
249
  controls: menuControls
225
250
  }, h(DOMElement, {
226
- element: "div",
227
- attrs: { class: "rpg-ui-main-menu rpg-anim-fade-in" }
228
- }, [h(DOMElement, {
229
- element: "div",
230
- attrs: { class: "rpg-ui-main-menu-layout" }
231
- }, [h(DOMElement, {
232
- element: "div",
233
- attrs: { class: "rpg-ui-main-menu-left rpg-ui-menu rpg-ui-panel" }
234
- }, [h(DOMElement, {
235
- element: "div",
236
- attrs: { class: "rpg-ui-menu-header" },
237
- textContent: computed(() => t("rpg.menu.title"))
238
- }), h(DOMElement, {
239
- element: "div",
240
- attrs: { class: "rpg-ui-main-menu-list" }
241
- }, loop(computed(() => menuEntries()), (entry, index) => h(DOMElement, {
242
251
  element: "div",
243
252
  attrs: {
244
- class: ["rpg-ui-menu-item", computed(() => ({ disabled: isMenuDisabled(entry) }))],
245
- "data-selected": computed(() => selectedMenu() === index ? "true" : "false"),
246
- tabindex: index,
247
- click: selectMenu(index)
248
- },
249
- textContent: entry.label
250
- })))]), h(DOMElement, {
251
- element: "div",
252
- attrs: { class: "rpg-ui-main-menu-right" }
253
+ class: "rpg-ui-main-menu rpg-anim-fade-in",
254
+ click: closeMenuFromPointer
255
+ }
253
256
  }, [
254
- cond(computed(() => view() === "menu"), () => h(DOMElement, {
257
+ h(DOMElement, {
255
258
  element: "div",
256
- attrs: { class: "rpg-ui-panel" }
259
+ attrs: { class: "rpg-ui-main-menu-backdrop" }
260
+ }),
261
+ h(DOMElement, {
262
+ element: "button",
263
+ attrs: {
264
+ class: "rpg-ui-close-button",
265
+ type: "button",
266
+ title: "Close",
267
+ "aria-label": "Close menu",
268
+ click: closeMenuFromPointer
269
+ },
270
+ textContent: "x"
271
+ }),
272
+ h(DOMElement, {
273
+ element: "div",
274
+ attrs: {
275
+ class: "rpg-ui-main-menu-layout",
276
+ click: stopEvent
277
+ }
278
+ }, [h(DOMElement, {
279
+ element: "div",
280
+ attrs: { class: "rpg-ui-main-menu-left rpg-ui-menu rpg-ui-panel" }
281
+ }, [h(DOMElement, {
282
+ element: "div",
283
+ attrs: { class: "rpg-ui-menu-header" },
284
+ textContent: computed(() => t("rpg.menu.title"))
285
+ }), h(DOMElement, {
286
+ element: "div",
287
+ attrs: { class: "rpg-ui-main-menu-list" }
288
+ }, loop(computed(() => menuEntries()), (entry, index) => h(DOMElement, {
289
+ element: "div",
290
+ attrs: {
291
+ class: ["rpg-ui-menu-item", computed(() => ({ disabled: isMenuDisabled(entry) }))],
292
+ "data-selected": computed(() => selectedMenu() === index ? "true" : "false"),
293
+ tabindex: index,
294
+ click: selectMenu(index)
295
+ },
296
+ textContent: entry.label
297
+ })))]), h(DOMElement, {
298
+ element: "div",
299
+ attrs: { class: "rpg-ui-main-menu-right" }
257
300
  }, [
258
- h(DOMElement, {
259
- element: "div",
260
- attrs: { class: "rpg-ui-main-menu-section-title" },
261
- textContent: computed(() => t("rpg.menu.status"))
262
- }),
263
- h(DOMElement, {
301
+ cond(computed(() => view() === "menu"), () => h(DOMElement, {
264
302
  element: "div",
265
- attrs: { class: "rpg-ui-main-menu-status-card" }
303
+ attrs: { class: "rpg-ui-panel" }
266
304
  }, [
267
305
  h(DOMElement, {
268
306
  element: "div",
269
- attrs: { class: "rpg-ui-main-menu-status-block" }
270
- }, [h(DOMElement, {
271
- element: "div",
272
- attrs: { class: "rpg-ui-main-menu-status-label" },
273
- textContent: computed(() => t("rpg.menu.level"))
274
- }), h(DOMElement, {
275
- element: "div",
276
- attrs: { class: "rpg-ui-main-menu-status-value" },
277
- textContent: computed(() => level())
278
- })]),
307
+ attrs: { class: "rpg-ui-main-menu-section-title" },
308
+ textContent: computed(() => t("rpg.menu.status"))
309
+ }),
279
310
  h(DOMElement, {
280
311
  element: "div",
281
- attrs: { class: "rpg-ui-main-menu-status-block" }
282
- }, [h(DOMElement, {
283
- element: "div",
284
- attrs: { class: "rpg-ui-main-menu-status-label" },
285
- textContent: computed(() => t("rpg.menu.gold"))
286
- }), h(DOMElement, {
287
- element: "div",
288
- attrs: { class: "rpg-ui-main-menu-status-value" },
289
- textContent: computed(() => gold())
290
- })]),
312
+ attrs: { class: "rpg-ui-main-menu-status-card" }
313
+ }, [
314
+ h(DOMElement, {
315
+ element: "div",
316
+ attrs: { class: "rpg-ui-main-menu-status-block" }
317
+ }, [h(DOMElement, {
318
+ element: "div",
319
+ attrs: { class: "rpg-ui-main-menu-status-label" },
320
+ textContent: computed(() => t("rpg.menu.level"))
321
+ }), h(DOMElement, {
322
+ element: "div",
323
+ attrs: { class: "rpg-ui-main-menu-status-value" },
324
+ textContent: computed(() => level())
325
+ })]),
326
+ h(DOMElement, {
327
+ element: "div",
328
+ attrs: { class: "rpg-ui-main-menu-status-block" }
329
+ }, [h(DOMElement, {
330
+ element: "div",
331
+ attrs: { class: "rpg-ui-main-menu-status-label" },
332
+ textContent: computed(() => t("rpg.menu.gold"))
333
+ }), h(DOMElement, {
334
+ element: "div",
335
+ attrs: { class: "rpg-ui-main-menu-status-value" },
336
+ textContent: computed(() => gold())
337
+ })]),
338
+ h(DOMElement, {
339
+ element: "div",
340
+ attrs: { class: "rpg-ui-main-menu-status-block" }
341
+ }, [h(DOMElement, {
342
+ element: "div",
343
+ attrs: { class: "rpg-ui-main-menu-status-label" },
344
+ textContent: computed(() => "HP " + hp() + "/" + hpMax())
345
+ }), h(DOMElement, {
346
+ element: "div",
347
+ attrs: { class: "rpg-ui-main-menu-status-bar" }
348
+ }, h(DOMElement, {
349
+ element: "div",
350
+ attrs: {
351
+ class: "rpg-ui-main-menu-status-bar-fill hp",
352
+ style: { width: hpPercent }
353
+ }
354
+ }))]),
355
+ h(DOMElement, {
356
+ element: "div",
357
+ attrs: { class: "rpg-ui-main-menu-status-block" }
358
+ }, [h(DOMElement, {
359
+ element: "div",
360
+ attrs: { class: "rpg-ui-main-menu-status-label" },
361
+ textContent: computed(() => "SP " + sp() + "/" + spMax())
362
+ }), h(DOMElement, {
363
+ element: "div",
364
+ attrs: { class: "rpg-ui-main-menu-status-bar" }
365
+ }, h(DOMElement, {
366
+ element: "div",
367
+ attrs: {
368
+ class: "rpg-ui-main-menu-status-bar-fill sp",
369
+ style: { width: spPercent }
370
+ }
371
+ }))]),
372
+ h(DOMElement, {
373
+ element: "div",
374
+ attrs: {
375
+ class: "rpg-ui-main-menu-status-block",
376
+ style: { gridColumn: "span 2" }
377
+ }
378
+ }, [h(DOMElement, {
379
+ element: "div",
380
+ attrs: { class: "rpg-ui-main-menu-status-label" },
381
+ textContent: computed(() => "EXP " + exp() + "/" + expForNextlevel())
382
+ }), h(DOMElement, {
383
+ element: "div",
384
+ attrs: { class: "rpg-ui-main-menu-status-bar" }
385
+ }, h(DOMElement, {
386
+ element: "div",
387
+ attrs: {
388
+ class: "rpg-ui-main-menu-status-bar-fill exp",
389
+ style: { width: expPercent }
390
+ }
391
+ }))])
392
+ ]),
291
393
  h(DOMElement, {
292
394
  element: "div",
293
- attrs: { class: "rpg-ui-main-menu-status-block" }
294
- }, [h(DOMElement, {
295
- element: "div",
296
- attrs: { class: "rpg-ui-main-menu-status-label" },
297
- textContent: computed(() => "HP " + hp() + "/" + hpMax())
298
- }), h(DOMElement, {
299
- element: "div",
300
- attrs: { class: "rpg-ui-main-menu-status-bar" }
301
- }, h(DOMElement, {
302
- element: "div",
303
- attrs: {
304
- class: "rpg-ui-main-menu-status-bar-fill hp",
305
- style: { width: hpPercent }
306
- }
307
- }))]),
395
+ attrs: { class: "rpg-ui-main-menu-section-title" },
396
+ textContent: computed(() => t("rpg.menu.parameters"))
397
+ }),
308
398
  h(DOMElement, {
309
399
  element: "div",
310
- attrs: { class: "rpg-ui-main-menu-status-block" }
311
- }, [h(DOMElement, {
312
- element: "div",
313
- attrs: { class: "rpg-ui-main-menu-status-label" },
314
- textContent: computed(() => "SP " + sp() + "/" + spMax())
315
- }), h(DOMElement, {
316
- element: "div",
317
- attrs: { class: "rpg-ui-main-menu-status-bar" }
318
- }, h(DOMElement, {
319
- element: "div",
320
- attrs: {
321
- class: "rpg-ui-main-menu-status-bar-fill sp",
322
- style: { width: spPercent }
323
- }
324
- }))]),
325
- h(DOMElement, {
400
+ attrs: { class: "rpg-ui-main-menu-params" }
401
+ }, loop(paramsList, (param, index) => h(DOMElement, {
326
402
  element: "div",
327
- attrs: {
328
- class: "rpg-ui-main-menu-status-block",
329
- style: { gridColumn: "span 2" }
330
- }
403
+ attrs: { class: "rpg-ui-main-menu-param" }
331
404
  }, [h(DOMElement, {
332
- element: "div",
333
- attrs: { class: "rpg-ui-main-menu-status-label" },
334
- textContent: computed(() => "EXP " + exp() + "/" + expForNextlevel())
405
+ element: "span",
406
+ textContent: param.label
335
407
  }), h(DOMElement, {
336
- element: "div",
337
- attrs: { class: "rpg-ui-main-menu-status-bar" }
338
- }, h(DOMElement, {
339
- element: "div",
340
- attrs: {
341
- class: "rpg-ui-main-menu-status-bar-fill exp",
342
- style: { width: expPercent }
343
- }
344
- }))])
345
- ]),
346
- h(DOMElement, {
347
- element: "div",
348
- attrs: { class: "rpg-ui-main-menu-section-title" },
349
- textContent: computed(() => t("rpg.menu.parameters"))
350
- }),
351
- h(DOMElement, {
352
- element: "div",
353
- attrs: { class: "rpg-ui-main-menu-params" }
354
- }, loop(paramsList, (param, index) => h(DOMElement, {
355
- element: "div",
356
- attrs: { class: "rpg-ui-main-menu-param" }
357
- }, [h(DOMElement, {
358
- element: "span",
359
- textContent: param.label
360
- }), h(DOMElement, {
361
- element: "span",
362
- textContent: param.value
363
- })])))
364
- ])),
365
- cond(computed(() => view() === "items"), () => h(__ce_component$2, {
366
- data,
367
- onInteraction,
368
- onBack: goBack
369
- })),
370
- cond(computed(() => view() === "skills"), () => h(__ce_component$3, {
371
- data,
372
- onBack: goBack
373
- })),
374
- cond(computed(() => view() === "equip"), () => h(__ce_component$4, {
375
- data,
376
- onInteraction,
377
- onBack: goBack
378
- })),
379
- cond(computed(() => view() === "options"), () => h(__ce_component$5, { onBack: goBack })),
380
- cond(computed(() => view() === "exit"), () => h(__ce_component$6, {
381
- onConfirm: confirmExit,
382
- onBack: goBack
383
- }))
384
- ])]), cond(saveOverlay, () => h(DOMElement, {
385
- element: "div",
386
- attrs: { class: "rpg-ui-main-menu-overlay" }
387
- }, [h(DOMElement, {
388
- element: "div",
389
- attrs: { class: "rpg-ui-main-menu-overlay-backdrop" }
390
- }), h(DOMElement, {
391
- element: "div",
392
- attrs: { class: "rpg-ui-main-menu-overlay-content" }
393
- }, h(__ce_component$1, {
394
- data: saveLoadData,
395
- onFinish: closeSaveOverlay
396
- }))]))]));
408
+ element: "span",
409
+ textContent: param.value
410
+ })])))
411
+ ])),
412
+ cond(computed(() => view() === "items"), () => h(__ce_component$2, {
413
+ data,
414
+ onInteraction,
415
+ onBack: goBack
416
+ })),
417
+ cond(computed(() => view() === "skills"), () => h(__ce_component$3, {
418
+ data,
419
+ onBack: goBack
420
+ })),
421
+ cond(computed(() => view() === "equip"), () => h(__ce_component$4, {
422
+ data,
423
+ onInteraction,
424
+ onBack: goBack
425
+ })),
426
+ cond(computed(() => view() === "options"), () => h(__ce_component$5, { onBack: goBack })),
427
+ cond(computed(() => view() === "exit"), () => h(__ce_component$6, {
428
+ onConfirm: confirmExit,
429
+ onBack: goBack
430
+ }))
431
+ ])]),
432
+ cond(saveOverlay, () => h(DOMElement, {
433
+ element: "div",
434
+ attrs: { class: "rpg-ui-main-menu-overlay" }
435
+ }, [h(DOMElement, {
436
+ element: "div",
437
+ attrs: {
438
+ class: "rpg-ui-main-menu-overlay-backdrop",
439
+ click: closeSaveOverlayFromPointer
440
+ }
441
+ }), h(DOMElement, {
442
+ element: "div",
443
+ attrs: {
444
+ class: "rpg-ui-main-menu-overlay-content",
445
+ click: stopEvent
446
+ }
447
+ }, h(__ce_component$1, {
448
+ data: saveLoadData,
449
+ onFinish: closeSaveOverlay
450
+ }))]))
451
+ ]));
397
452
  }
398
453
  var __ce_component = component;
399
454
  //#endregion