@strixit/storyscript 0.0.0-stage → 1.0.0

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 (370) hide show
  1. package/.env +1 -0
  2. package/CodeSnippets/StoryScriptSnippets.code-snippets +573 -0
  3. package/LICENSE.txt +21 -0
  4. package/LiveTemplates/StoryScript.xml +271 -0
  5. package/README.md +9 -2
  6. package/baseViteConfig.js +112 -0
  7. package/clientFiles/currentGameName.js +1 -0
  8. package/clientFiles/gitignore +12 -0
  9. package/clientFiles/tsconfig.json +34 -0
  10. package/clientFiles/vite.config.ts +14 -0
  11. package/clientFiles/vitest.config.ts +29 -0
  12. package/dist/src/Engine/Actions/index.d.ts +2 -0
  13. package/dist/src/Engine/Actions/open.d.ts +6 -0
  14. package/dist/src/Engine/Actions/openWithKey.d.ts +7 -0
  15. package/dist/src/Engine/EntityCreatorFunctions.d.ts +18 -0
  16. package/dist/src/Engine/Interfaces/action.d.ts +37 -0
  17. package/dist/src/Engine/Interfaces/autoplayStep.d.ts +11 -0
  18. package/dist/src/Engine/Interfaces/barrier.d.ts +16 -0
  19. package/dist/src/Engine/Interfaces/barrierAction.d.ts +19 -0
  20. package/dist/src/Engine/Interfaces/character.d.ts +48 -0
  21. package/dist/src/Engine/Interfaces/combatSetup.d.ts +9 -0
  22. package/dist/src/Engine/Interfaces/combatTurn.d.ts +37 -0
  23. package/dist/src/Engine/Interfaces/combatWinnings.d.ts +6 -0
  24. package/dist/src/Engine/Interfaces/combinations/activeCombination.d.ts +14 -0
  25. package/dist/src/Engine/Interfaces/combinations/combinable.d.ts +18 -0
  26. package/dist/src/Engine/Interfaces/combinations/combinationAction.d.ts +41 -0
  27. package/dist/src/Engine/Interfaces/combinations/combinationMatchResult.d.ts +14 -0
  28. package/dist/src/Engine/Interfaces/combinations/combinations.d.ts +17 -0
  29. package/dist/src/Engine/Interfaces/combinations/combine.d.ts +22 -0
  30. package/dist/src/Engine/Interfaces/combinations/combineResult.d.ts +18 -0
  31. package/dist/src/Engine/Interfaces/combinations/gameCombinations.d.ts +40 -0
  32. package/dist/src/Engine/Interfaces/compiledLocation.d.ts +33 -0
  33. package/dist/src/Engine/Interfaces/conversations/conversation.d.ts +44 -0
  34. package/dist/src/Engine/Interfaces/conversations/conversationLogEntry.d.ts +13 -0
  35. package/dist/src/Engine/Interfaces/conversations/conversationNode.d.ts +22 -0
  36. package/dist/src/Engine/Interfaces/conversations/conversationReply.d.ts +49 -0
  37. package/dist/src/Engine/Interfaces/createCharacter/createCharacter.d.ts +20 -0
  38. package/dist/src/Engine/Interfaces/createCharacter/createCharacterAttribute.d.ts +18 -0
  39. package/dist/src/Engine/Interfaces/createCharacter/createCharacterAttributeEntry.d.ts +18 -0
  40. package/dist/src/Engine/Interfaces/createCharacter/createCharacterQuestion.d.ts +18 -0
  41. package/dist/src/Engine/Interfaces/createCharacter/createCharacterQuestionEntry.d.ts +22 -0
  42. package/dist/src/Engine/Interfaces/createCharacter/createCharacterStep.d.ts +40 -0
  43. package/dist/src/Engine/Interfaces/customCursor.d.ts +8 -0
  44. package/dist/src/Engine/Interfaces/defaultEquipment.d.ts +19 -0
  45. package/dist/src/Engine/Interfaces/definitions.d.ts +40 -0
  46. package/dist/src/Engine/Interfaces/destination.d.ts +31 -0
  47. package/dist/src/Engine/Interfaces/dynamicStyle.d.ts +10 -0
  48. package/dist/src/Engine/Interfaces/enemy.d.ts +46 -0
  49. package/dist/src/Engine/Interfaces/enumerations/actionStatus.d.ts +18 -0
  50. package/dist/src/Engine/Interfaces/enumerations/actionType.d.ts +9 -0
  51. package/dist/src/Engine/Interfaces/enumerations/equipmentType.d.ts +51 -0
  52. package/dist/src/Engine/Interfaces/enumerations/gameState.d.ts +11 -0
  53. package/dist/src/Engine/Interfaces/enumerations/playState.d.ts +10 -0
  54. package/dist/src/Engine/Interfaces/enumerations/targetType.d.ts +9 -0
  55. package/dist/src/Engine/Interfaces/equipment.d.ts +43 -0
  56. package/dist/src/Engine/Interfaces/feature.d.ts +37 -0
  57. package/dist/src/Engine/Interfaces/featureCollection.d.ts +7 -0
  58. package/dist/src/Engine/Interfaces/game.d.ts +148 -0
  59. package/dist/src/Engine/Interfaces/gameEvents.d.ts +7 -0
  60. package/dist/src/Engine/Interfaces/groupableItem.d.ts +32 -0
  61. package/dist/src/Engine/Interfaces/helpers.d.ts +50 -0
  62. package/dist/src/Engine/Interfaces/index.d.ts +78 -0
  63. package/dist/src/Engine/Interfaces/interfaceTexts.d.ts +140 -0
  64. package/dist/src/Engine/Interfaces/item.d.ts +96 -0
  65. package/dist/src/Engine/Interfaces/key.d.ts +16 -0
  66. package/dist/src/Engine/Interfaces/location.d.ts +78 -0
  67. package/dist/src/Engine/Interfaces/maps/map.d.ts +45 -0
  68. package/dist/src/Engine/Interfaces/maps/mapLocation.d.ts +23 -0
  69. package/dist/src/Engine/Interfaces/party.d.ts +33 -0
  70. package/dist/src/Engine/Interfaces/person.d.ts +25 -0
  71. package/dist/src/Engine/Interfaces/quest.d.ts +51 -0
  72. package/dist/src/Engine/Interfaces/rules/characterRules.d.ts +84 -0
  73. package/dist/src/Engine/Interfaces/rules/combatRules.d.ts +46 -0
  74. package/dist/src/Engine/Interfaces/rules/combinationRules.d.ts +15 -0
  75. package/dist/src/Engine/Interfaces/rules/demoMode.d.ts +15 -0
  76. package/dist/src/Engine/Interfaces/rules/encounterRules.d.ts +4 -0
  77. package/dist/src/Engine/Interfaces/rules/explorationRules.d.ts +42 -0
  78. package/dist/src/Engine/Interfaces/rules/generalRules.d.ts +62 -0
  79. package/dist/src/Engine/Interfaces/rules/rules.d.ts +31 -0
  80. package/dist/src/Engine/Interfaces/rules/setupRules.d.ts +56 -0
  81. package/dist/src/Engine/Interfaces/rules/titleScreen.d.ts +16 -0
  82. package/dist/src/Engine/Interfaces/saveGame.d.ts +33 -0
  83. package/dist/src/Engine/Interfaces/scoreEntry.d.ts +13 -0
  84. package/dist/src/Engine/Interfaces/services/autoplayService.d.ts +19 -0
  85. package/dist/src/Engine/Interfaces/services/characterService.d.ts +17 -0
  86. package/dist/src/Engine/Interfaces/services/combatService.d.ts +26 -0
  87. package/dist/src/Engine/Interfaces/services/combinationService.d.ts +9 -0
  88. package/dist/src/Engine/Interfaces/services/commandService.d.ts +64 -0
  89. package/dist/src/Engine/Interfaces/services/conversationService.d.ts +5 -0
  90. package/dist/src/Engine/Interfaces/services/dataSerializer.d.ts +4 -0
  91. package/dist/src/Engine/Interfaces/services/dataService.d.ts +33 -0
  92. package/dist/src/Engine/Interfaces/services/dataSynchronizer.d.ts +3 -0
  93. package/dist/src/Engine/Interfaces/services/gameService.d.ts +10 -0
  94. package/dist/src/Engine/Interfaces/services/index.d.ts +16 -0
  95. package/dist/src/Engine/Interfaces/services/itemService.d.ts +14 -0
  96. package/dist/src/Engine/Interfaces/services/localStorageService.d.ts +6 -0
  97. package/dist/src/Engine/Interfaces/services/locationService.d.ts +8 -0
  98. package/dist/src/Engine/Interfaces/services/soundService.d.ts +5 -0
  99. package/dist/src/Engine/Interfaces/services/tradeService.d.ts +9 -0
  100. package/dist/src/Engine/Interfaces/soundPlayer.d.ts +30 -0
  101. package/dist/src/Engine/Interfaces/sprite.d.ts +23 -0
  102. package/dist/src/Engine/Interfaces/stateList.d.ts +9 -0
  103. package/dist/src/Engine/Interfaces/statistics.d.ts +13 -0
  104. package/dist/src/Engine/Interfaces/stock.d.ts +39 -0
  105. package/dist/src/Engine/Interfaces/trade.d.ts +62 -0
  106. package/dist/src/Engine/ServiceFactory.d.ts +52 -0
  107. package/dist/src/Engine/Services/AutoplayService.d.ts +11 -0
  108. package/dist/src/Engine/Services/CharacterService.d.ts +21 -0
  109. package/dist/src/Engine/Services/CombatService.d.ts +16 -0
  110. package/dist/src/Engine/Services/CombinationService.d.ts +15 -0
  111. package/dist/src/Engine/Services/CommandService.d.ts +24 -0
  112. package/dist/src/Engine/Services/ConversationService.d.ts +26 -0
  113. package/dist/src/Engine/Services/DataSerializer.d.ts +17 -0
  114. package/dist/src/Engine/Services/DataService.d.ts +16 -0
  115. package/dist/src/Engine/Services/DataSynchronizer.d.ts +12 -0
  116. package/dist/src/Engine/Services/GameService.d.ts +28 -0
  117. package/dist/src/Engine/Services/HelperService.d.ts +18 -0
  118. package/dist/src/Engine/Services/ItemService.d.ts +21 -0
  119. package/dist/src/Engine/Services/LocalStorageService.d.ts +7 -0
  120. package/dist/src/Engine/Services/LocationService.d.ts +25 -0
  121. package/dist/src/Engine/Services/SoundService.d.ts +13 -0
  122. package/dist/src/Engine/Services/TradeService.d.ts +17 -0
  123. package/dist/src/Engine/Services/index.d.ts +17 -0
  124. package/dist/src/Engine/Services/serializationData.d.ts +8 -0
  125. package/dist/src/Engine/Services/sharedFunctions.d.ts +21 -0
  126. package/dist/src/Engine/arrayAndFunctionExtensions.d.ts +3 -0
  127. package/dist/src/Engine/defaultTexts.d.ts +7 -0
  128. package/dist/src/Engine/gameEvents.d.ts +10 -0
  129. package/dist/src/Engine/index.d.ts +8 -0
  130. package/dist/src/Engine/stateProperties.d.ts +6 -0
  131. package/dist/src/Engine/utilityFunctions.d.ts +25 -0
  132. package/dist/src/UI/Composables/CustomCursor.d.ts +2 -0
  133. package/dist/src/UI/Composables/LocationMap.d.ts +26 -0
  134. package/dist/src/UI/Composables/Sound.d.ts +7 -0
  135. package/dist/src/UI/Composables/TextFeatures.d.ts +8 -0
  136. package/dist/src/UI/Composables/VisualFeatures.d.ts +7 -0
  137. package/dist/src/UI/Composables/index.d.ts +7 -0
  138. package/dist/src/UI/Composables/playStateWatch.d.ts +2 -0
  139. package/dist/src/UI/StateStore.d.ts +14256 -0
  140. package/dist/src/UI/error.d.ts +6 -0
  141. package/dist/src/UI/helpers.d.ts +3 -0
  142. package/dist/src/UI/index.d.ts +6 -0
  143. package/dist/src/UI/main.d.ts +1 -0
  144. package/dist/src/UI/startup.d.ts +2 -0
  145. package/dist/src/constants.d.ts +17 -0
  146. package/dist/src/index.d.ts +3 -0
  147. package/dist/storyscript.css +9566 -0
  148. package/dist/storyscript.js +9659 -0
  149. package/dist/storyscript.js.map +1 -0
  150. package/dist/storyscript.mjs +9569 -0
  151. package/dist/storyscript.mjs.map +1 -0
  152. package/electron.cjs +44 -0
  153. package/index.html +14 -0
  154. package/package.json +118 -4
  155. package/scripts/cli.js +268 -0
  156. package/scripts/createAsset.js +117 -0
  157. package/scripts/createGame.js +40 -0
  158. package/scripts/helpers.js +21 -0
  159. package/scripts/postbuild.js +179 -0
  160. package/scripts/setupTesting.js +17 -0
  161. package/shims-vue.d.ts +1 -0
  162. package/src/Engine/Actions/index.ts +2 -0
  163. package/src/Engine/Actions/open.ts +12 -0
  164. package/src/Engine/Actions/openWithKey.ts +23 -0
  165. package/src/Engine/EntityCreatorFunctions.ts +602 -0
  166. package/src/Engine/Interfaces/action.ts +43 -0
  167. package/src/Engine/Interfaces/autoplayStep.ts +13 -0
  168. package/src/Engine/Interfaces/barrier.ts +18 -0
  169. package/src/Engine/Interfaces/barrierAction.ts +21 -0
  170. package/src/Engine/Interfaces/character.ts +58 -0
  171. package/src/Engine/Interfaces/combatSetup.ts +10 -0
  172. package/src/Engine/Interfaces/combatTurn.ts +45 -0
  173. package/src/Engine/Interfaces/combatWinnings.ts +7 -0
  174. package/src/Engine/Interfaces/combinations/activeCombination.ts +16 -0
  175. package/src/Engine/Interfaces/combinations/combinable.ts +21 -0
  176. package/src/Engine/Interfaces/combinations/combinationAction.ts +45 -0
  177. package/src/Engine/Interfaces/combinations/combinationMatchResult.ts +16 -0
  178. package/src/Engine/Interfaces/combinations/combinations.ts +19 -0
  179. package/src/Engine/Interfaces/combinations/combine.ts +25 -0
  180. package/src/Engine/Interfaces/combinations/combineResult.ts +21 -0
  181. package/src/Engine/Interfaces/combinations/gameCombinations.ts +48 -0
  182. package/src/Engine/Interfaces/compiledLocation.ts +37 -0
  183. package/src/Engine/Interfaces/conversations/conversation.ts +47 -0
  184. package/src/Engine/Interfaces/conversations/conversationLogEntry.ts +14 -0
  185. package/src/Engine/Interfaces/conversations/conversationNode.ts +26 -0
  186. package/src/Engine/Interfaces/conversations/conversationReply.ts +59 -0
  187. package/src/Engine/Interfaces/createCharacter/createCharacter.ts +23 -0
  188. package/src/Engine/Interfaces/createCharacter/createCharacterAttribute.ts +21 -0
  189. package/src/Engine/Interfaces/createCharacter/createCharacterAttributeEntry.ts +21 -0
  190. package/src/Engine/Interfaces/createCharacter/createCharacterQuestion.ts +21 -0
  191. package/src/Engine/Interfaces/createCharacter/createCharacterQuestionEntry.ts +25 -0
  192. package/src/Engine/Interfaces/createCharacter/createCharacterStep.ts +47 -0
  193. package/src/Engine/Interfaces/customCursor.ts +5 -0
  194. package/src/Engine/Interfaces/defaultEquipment.ts +32 -0
  195. package/src/Engine/Interfaces/definitions.ts +48 -0
  196. package/src/Engine/Interfaces/destination.ts +37 -0
  197. package/src/Engine/Interfaces/dynamicStyle.ts +11 -0
  198. package/src/Engine/Interfaces/enemy.ts +54 -0
  199. package/src/Engine/Interfaces/enumerations/actionStatus.ts +20 -0
  200. package/src/Engine/Interfaces/enumerations/actionType.ts +9 -0
  201. package/src/Engine/Interfaces/enumerations/equipmentType.ts +61 -0
  202. package/src/Engine/Interfaces/enumerations/gameState.ts +11 -0
  203. package/src/Engine/Interfaces/enumerations/playState.ts +10 -0
  204. package/src/Engine/Interfaces/enumerations/targetType.ts +9 -0
  205. package/src/Engine/Interfaces/equipment.ts +44 -0
  206. package/src/Engine/Interfaces/feature.ts +43 -0
  207. package/src/Engine/Interfaces/featureCollection.ts +8 -0
  208. package/src/Engine/Interfaces/game.ts +201 -0
  209. package/src/Engine/Interfaces/gameEvents.ts +11 -0
  210. package/src/Engine/Interfaces/groupableItem.ts +37 -0
  211. package/src/Engine/Interfaces/helpers.ts +55 -0
  212. package/src/Engine/Interfaces/index.ts +158 -0
  213. package/src/Engine/Interfaces/interfaceTexts.ts +142 -0
  214. package/src/Engine/Interfaces/item.ts +111 -0
  215. package/src/Engine/Interfaces/key.ts +18 -0
  216. package/src/Engine/Interfaces/location.ts +92 -0
  217. package/src/Engine/Interfaces/maps/map.ts +55 -0
  218. package/src/Engine/Interfaces/maps/mapLocation.ts +28 -0
  219. package/src/Engine/Interfaces/party.ts +40 -0
  220. package/src/Engine/Interfaces/person.ts +29 -0
  221. package/src/Engine/Interfaces/quest.ts +60 -0
  222. package/src/Engine/Interfaces/rules/characterRules.ts +96 -0
  223. package/src/Engine/Interfaces/rules/combatRules.ts +52 -0
  224. package/src/Engine/Interfaces/rules/combinationRules.ts +17 -0
  225. package/src/Engine/Interfaces/rules/demoMode.ts +18 -0
  226. package/src/Engine/Interfaces/rules/encounterRules.ts +5 -0
  227. package/src/Engine/Interfaces/rules/explorationRules.ts +47 -0
  228. package/src/Engine/Interfaces/rules/generalRules.ts +80 -0
  229. package/src/Engine/Interfaces/rules/rules.ts +46 -0
  230. package/src/Engine/Interfaces/rules/setupRules.ts +65 -0
  231. package/src/Engine/Interfaces/rules/titleScreen.ts +19 -0
  232. package/src/Engine/Interfaces/saveGame.ts +39 -0
  233. package/src/Engine/Interfaces/scoreEntry.ts +14 -0
  234. package/src/Engine/Interfaces/services/autoplayService.ts +23 -0
  235. package/src/Engine/Interfaces/services/characterService.ts +35 -0
  236. package/src/Engine/Interfaces/services/combatService.ts +30 -0
  237. package/src/Engine/Interfaces/services/combinationService.ts +10 -0
  238. package/src/Engine/Interfaces/services/commandService.ts +75 -0
  239. package/src/Engine/Interfaces/services/conversationService.ts +7 -0
  240. package/src/Engine/Interfaces/services/dataSerializer.ts +4 -0
  241. package/src/Engine/Interfaces/services/dataService.ts +39 -0
  242. package/src/Engine/Interfaces/services/dataSynchronizer.ts +9 -0
  243. package/src/Engine/Interfaces/services/gameService.ts +17 -0
  244. package/src/Engine/Interfaces/services/index.ts +33 -0
  245. package/src/Engine/Interfaces/services/itemService.ts +25 -0
  246. package/src/Engine/Interfaces/services/localStorageService.ts +6 -0
  247. package/src/Engine/Interfaces/services/locationService.ts +13 -0
  248. package/src/Engine/Interfaces/services/soundService.ts +7 -0
  249. package/src/Engine/Interfaces/services/tradeService.ts +15 -0
  250. package/src/Engine/Interfaces/soundPlayer.ts +30 -0
  251. package/src/Engine/Interfaces/sprite.ts +27 -0
  252. package/src/Engine/Interfaces/stateList.ts +13 -0
  253. package/src/Engine/Interfaces/statistics.ts +14 -0
  254. package/src/Engine/Interfaces/stock.ts +46 -0
  255. package/src/Engine/Interfaces/trade.ts +72 -0
  256. package/src/Engine/ServiceFactory.ts +167 -0
  257. package/src/Engine/Services/AutoplayService.ts +59 -0
  258. package/src/Engine/Services/CharacterService.ts +291 -0
  259. package/src/Engine/Services/CombatService.ts +266 -0
  260. package/src/Engine/Services/CombinationService.ts +197 -0
  261. package/src/Engine/Services/CommandService.ts +197 -0
  262. package/src/Engine/Services/ConversationService.ts +406 -0
  263. package/src/Engine/Services/DataSerializer.ts +326 -0
  264. package/src/Engine/Services/DataService.ts +93 -0
  265. package/src/Engine/Services/DataSynchronizer.ts +216 -0
  266. package/src/Engine/Services/GameService.ts +554 -0
  267. package/src/Engine/Services/HelperService.ts +94 -0
  268. package/src/Engine/Services/ItemService.ts +294 -0
  269. package/src/Engine/Services/LocalStorageService.ts +24 -0
  270. package/src/Engine/Services/LocationService.ts +380 -0
  271. package/src/Engine/Services/SoundService.ts +54 -0
  272. package/src/Engine/Services/TradeService.ts +176 -0
  273. package/src/Engine/Services/index.ts +17 -0
  274. package/src/Engine/Services/serializationData.ts +8 -0
  275. package/src/Engine/Services/sharedFunctions.ts +296 -0
  276. package/src/Engine/arrayAndFunctionExtensions.ts +269 -0
  277. package/src/Engine/defaultTexts.ts +162 -0
  278. package/src/Engine/gameEvents.ts +51 -0
  279. package/src/Engine/index.ts +9 -0
  280. package/src/Engine/stateProperties.ts +9 -0
  281. package/src/Engine/utilityFunctions.ts +238 -0
  282. package/src/Games/_GameTemplate/character.ts +31 -0
  283. package/src/Games/_GameTemplate/customTexts.ts +8 -0
  284. package/src/Games/_GameTemplate/interfaces/action.ts +5 -0
  285. package/src/Games/_GameTemplate/interfaces/combatSetup.ts +7 -0
  286. package/src/Games/_GameTemplate/interfaces/combatTurn.ts +8 -0
  287. package/src/Games/_GameTemplate/interfaces/destination.ts +5 -0
  288. package/src/Games/_GameTemplate/interfaces/enemy.ts +11 -0
  289. package/src/Games/_GameTemplate/interfaces/equipment.ts +5 -0
  290. package/src/Games/_GameTemplate/interfaces/feature.ts +9 -0
  291. package/src/Games/_GameTemplate/interfaces/game.ts +22 -0
  292. package/src/Games/_GameTemplate/interfaces/interfaceTexts.ts +5 -0
  293. package/src/Games/_GameTemplate/interfaces/item.ts +18 -0
  294. package/src/Games/_GameTemplate/interfaces/key.ts +10 -0
  295. package/src/Games/_GameTemplate/interfaces/location.ts +22 -0
  296. package/src/Games/_GameTemplate/interfaces/map.ts +16 -0
  297. package/src/Games/_GameTemplate/interfaces/party.ts +8 -0
  298. package/src/Games/_GameTemplate/interfaces/person.ts +11 -0
  299. package/src/Games/_GameTemplate/interfaces/quest.ts +9 -0
  300. package/src/Games/_GameTemplate/locations/Start.html +5 -0
  301. package/src/Games/_GameTemplate/locations/start.ts +12 -0
  302. package/src/Games/_GameTemplate/rules.ts +60 -0
  303. package/src/Games/_GameTemplate/types.ts +55 -0
  304. package/src/Games/_GameTemplate/ui/styles/game.css +3 -0
  305. package/src/Games/_GameTemplate/webroot/favicon.ico +0 -0
  306. package/src/Games/_GameTemplate/webroot/gameinfo.json +10 -0
  307. package/src/Games/_GameTemplate/webroot/logo192.png +0 -0
  308. package/src/Games/_GameTemplate/webroot/logo512.png +0 -0
  309. package/src/Tests/Games/_GameTemplate/specs/rules.test.ts +9 -0
  310. package/src/UI/Components/AppShell.vue +43 -0
  311. package/src/UI/Components/Autoplay.vue +32 -0
  312. package/src/UI/Components/Combinations.vue +37 -0
  313. package/src/UI/Components/Common/Collapsible.vue +50 -0
  314. package/src/UI/Components/Common/ModalDialog.vue +54 -0
  315. package/src/UI/Components/Common/Sprite.vue +53 -0
  316. package/src/UI/Components/Description.vue +23 -0
  317. package/src/UI/Components/Encounter/Combat/Combat.vue +89 -0
  318. package/src/UI/Components/Encounter/Combat/CombatActions.vue +26 -0
  319. package/src/UI/Components/Encounter/Combat/CombatParticipant.vue +22 -0
  320. package/src/UI/Components/Encounter/Combat/CombatTargetSelect.vue +55 -0
  321. package/src/UI/Components/Encounter/Combat/CombatWin.vue +33 -0
  322. package/src/UI/Components/Encounter/Conversation.vue +66 -0
  323. package/src/UI/Components/Encounter/Encounter.vue +39 -0
  324. package/src/UI/Components/Encounter/Enemy.vue +30 -0
  325. package/src/UI/Components/Encounter/Trade/Stock.vue +58 -0
  326. package/src/UI/Components/Encounter/Trade/Trade.vue +24 -0
  327. package/src/UI/Components/Exploration/ActionLog.vue +17 -0
  328. package/src/UI/Components/Exploration/Destination.vue +66 -0
  329. package/src/UI/Components/Exploration/Exploration.vue +67 -0
  330. package/src/UI/Components/Exploration/Ground.vue +22 -0
  331. package/src/UI/Components/Exploration/LocationMap.vue +42 -0
  332. package/src/UI/Components/Exploration/LocationText.vue +39 -0
  333. package/src/UI/Components/Exploration/LocationVisual.vue +38 -0
  334. package/src/UI/Components/GameContainer.vue +49 -0
  335. package/src/UI/Components/GameMenu.vue +111 -0
  336. package/src/UI/Components/GameState/GameOver.vue +20 -0
  337. package/src/UI/Components/GameState/HighScores.vue +22 -0
  338. package/src/UI/Components/GameState/Intro.vue +17 -0
  339. package/src/UI/Components/GameState/TitleScreen.vue +42 -0
  340. package/src/UI/Components/GameState/Victory.vue +28 -0
  341. package/src/UI/Components/Navigation.vue +94 -0
  342. package/src/UI/Components/Party/Backpack.vue +68 -0
  343. package/src/UI/Components/Party/BuildCharacter.vue +64 -0
  344. package/src/UI/Components/Party/CharacterSheet.vue +57 -0
  345. package/src/UI/Components/Party/CreateCharacter.vue +46 -0
  346. package/src/UI/Components/Party/Equipment.vue +48 -0
  347. package/src/UI/Components/Party/EquipmentSlot.vue +31 -0
  348. package/src/UI/Components/Party/LevelUp.vue +27 -0
  349. package/src/UI/Components/Party/Party.vue +29 -0
  350. package/src/UI/Components/Party/Quests.vue +48 -0
  351. package/src/UI/Components/Sound.vue +42 -0
  352. package/src/UI/Composables/CustomCursor.ts +60 -0
  353. package/src/UI/Composables/LocationMap.ts +315 -0
  354. package/src/UI/Composables/Sound.ts +111 -0
  355. package/src/UI/Composables/TextFeatures.ts +148 -0
  356. package/src/UI/Composables/VisualFeatures.ts +220 -0
  357. package/src/UI/Composables/index.ts +15 -0
  358. package/src/UI/Composables/playStateWatch.ts +31 -0
  359. package/src/UI/StateStore.ts +237 -0
  360. package/src/UI/error.ts +6 -0
  361. package/src/UI/helpers.ts +62 -0
  362. package/src/UI/index.ts +13 -0
  363. package/src/UI/main.ts +62 -0
  364. package/src/UI/startup.ts +58 -0
  365. package/src/UI/styles/bootstrap-storyscript.scss +31 -0
  366. package/src/UI/styles/empty.css +3 -0
  367. package/src/UI/styles/lookinglass.png +0 -0
  368. package/src/UI/styles/storyscript.css +735 -0
  369. package/typeExtensions.d.ts +25 -0
  370. package/vite-env.d.ts +1 -0
@@ -0,0 +1,315 @@
1
+ import {useStateStore} from "ui/StateStore";
2
+ import {storeToRefs} from "pinia";
3
+ import {computed, onMounted, onUpdated, Ref, ref, watch} from "vue";
4
+ import {IMap} from 'storyScript';
5
+ import {isTouchDevice} from 'src/constants';
6
+
7
+ export function useLocationMap(mapImageRef: Ref<HTMLImageElement>, mapDialogRef: Ref<HTMLDialogElement>) {
8
+ const visible: string = 'visible';
9
+ const hidden: string = 'hidden';
10
+ const reachable: string = 'reachable';
11
+ const visited: string = 'visited';
12
+ const labelClass: string = 'map-location-label';
13
+ const imageClass: string = 'map-location-image';
14
+
15
+ const store = useStateStore();
16
+ const {game} = storeToRefs(store);
17
+ const {texts} = store.services;
18
+
19
+ const map = computed(() => game.value.currentMap);
20
+ const location = computed(() => game.value.currentLocation);
21
+
22
+ const fullScreen = ref(false);
23
+ const firstShowFullScreen = ref(true);
24
+ const touchMarkersVisible = ref(false);
25
+ const mapDialog = mapDialogRef;
26
+ const currentMap = mapImageRef;
27
+ const currentFullScreenMap = ref<HTMLImageElement>(null);
28
+
29
+ watch(() => location.value, () => {
30
+ navigateMap(map.value, currentMap.value, false);
31
+
32
+ if (fullScreen.value) {
33
+ navigateMap(map.value, currentFullScreenMap.value, false);
34
+ }
35
+ });
36
+
37
+ onMounted(() => {
38
+ prepareMap(map.value, false);
39
+ });
40
+
41
+ onUpdated(() => {
42
+ prepareMap(map.value, true);
43
+ });
44
+
45
+ const toggleTouchMarkersVisible = () => {
46
+ if (!isTouchDevice) {
47
+ return;
48
+ }
49
+
50
+ touchMarkersVisible.value = !touchMarkersVisible.value;
51
+
52
+ if (map.value.showMarkersOnKeyPress) {
53
+ const mapContainer = (fullScreen.value ? currentFullScreenMap.value : currentMap.value).parentElement;
54
+ const labelElements = mapContainer.getElementsByClassName(labelClass);
55
+ const markerElements = mapContainer.getElementsByClassName(imageClass);
56
+ setMarkerVisibility(labelElements, markerElements, touchMarkersVisible.value ? visible : hidden);
57
+ }
58
+ }
59
+
60
+ function toggleFullScreen() {
61
+ fullScreen.value = !fullScreen.value;
62
+
63
+ if (fullScreen.value) {
64
+ mapDialog.value.showModal();
65
+ navigateMap(map.value, currentFullScreenMap.value, firstShowFullScreen.value);
66
+ firstShowFullScreen.value = false;
67
+ currentFullScreenMap.value.focus();
68
+ } else {
69
+ mapDialog.value.close();
70
+ }
71
+ }
72
+
73
+ function prepareMap(newMap: IMap, cleanup: boolean) {
74
+ if (!newMap) {
75
+ return;
76
+ }
77
+
78
+ const mapContainer = currentMap.value.parentElement;
79
+
80
+ if (cleanup) {
81
+ firstShowFullScreen.value = true;
82
+ currentMap.value.onload = null;
83
+ mapContainer.onkeydown = null;
84
+ mapContainer.onkeyup = null;
85
+ const labelElements = Array.prototype.slice.call(mapContainer.getElementsByClassName(labelClass));
86
+ labelElements.forEach(l => l.remove());
87
+ const markerElements = Array.prototype.slice.call(mapContainer.getElementsByClassName(imageClass));
88
+ markerElements.forEach(l => l.remove());
89
+ mapDialog.value.onkeydown = null;
90
+ mapDialog.value.onkeyup = null;
91
+ mapDialog.value.replaceChildren();
92
+ }
93
+
94
+ if (newMap.toggleFullScreen === true) {
95
+ let fullScreenMap = getMapElement(mapDialog.value);
96
+
97
+ if (!fullScreenMap) {
98
+ for (const n in Object.keys(mapContainer.children)) {
99
+ const child = mapContainer.children[n];
100
+ mapDialog.value.appendChild(child.cloneNode(true));
101
+ }
102
+
103
+ const closeToggle = mapDialog.value.getElementsByClassName('map-full-screen-toggle')[0] as HTMLSpanElement;
104
+ closeToggle.innerText = texts.closeFullScreenMap;
105
+ closeToggle.onclick = () => toggleFullScreen();
106
+
107
+ const showMarkersToggle = (mapDialog.value.querySelector('.show-marker-instructions') as HTMLElement);
108
+ showMarkersToggle.onclick = () => toggleTouchMarkersVisible();
109
+ }
110
+
111
+ currentFullScreenMap.value = getMapElement(mapDialog.value);
112
+ initMap(currentFullScreenMap.value);
113
+ }
114
+
115
+ initMap(currentMap.value);
116
+ }
117
+
118
+ function initMap(mapElement: HTMLElement) {
119
+ if (!map) {
120
+ return;
121
+ }
122
+
123
+ mapElement.onkeydown = null;
124
+ mapElement.onkeyup = null;
125
+
126
+ map.value.locations.forEach(l => {
127
+ const textLabel = l.markerImage ? null : l.textLabel ?? (map.value.locationNamesAsTextMarkers ? game.value.locations[l.location as string].name : null);
128
+ const id = l.location as string;
129
+
130
+ if (textLabel) {
131
+ l.markerElement = addElement(mapElement, l.coords, id, labelClass, 'span', textLabel);
132
+ }
133
+
134
+ const markerImage = l.markerImage ?? map.value.locationMarkerImage;
135
+
136
+ if (markerImage) {
137
+ l.markerElement = addElement(mapElement, l.coords, id, imageClass, 'img', markerImage);
138
+ }
139
+ });
140
+
141
+ if (map.value.showMarkersOnKeyPress) {
142
+ const mapContainer = mapElement.parentElement;
143
+ const labelElements = mapElement.parentElement.getElementsByClassName(labelClass);
144
+ const markerElements = mapElement.parentElement.getElementsByClassName(imageClass);
145
+
146
+ mapContainer.onkeydown = e => {
147
+ if (e.key === map.value.showMarkersOnKeyPress) {
148
+ setMarkerVisibility(labelElements, markerElements, visible);
149
+ }
150
+ };
151
+
152
+ mapContainer.onkeyup = e => {
153
+ if (e.key === map.value.showMarkersOnKeyPress) {
154
+ setMarkerVisibility(labelElements, markerElements, hidden);
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ function showMap() {
161
+ navigateMap(map.value, currentMap.value, true);
162
+ }
163
+
164
+ function navigateMap(map: IMap, mapElement: HTMLElement, show: boolean) {
165
+ const parentElement = mapElement.parentElement;
166
+ const coordString = map.locations.find(l => l.location === location.value.id)?.coords;
167
+ const avatar = parentElement.getElementsByClassName('avatar-image')[0] as HTMLImageElement;
168
+ let mapMargins: { x: number, y: number };
169
+
170
+ if (coordString) {
171
+ const coords = getCoords(coordString);
172
+ mapMargins = {
173
+ x: getMapMargin(mapElement, coords.x, 'width'),
174
+ y: getMapMargin(mapElement, coords.y, 'height')
175
+ };
176
+ mapElement.style.marginLeft = `-${mapMargins.x}px`;
177
+ mapElement.style.marginTop = `-${mapMargins.y}px`;
178
+
179
+ if (avatar) {
180
+ const avatarLeft = coords.x - mapMargins.x - avatar.width / 2;
181
+ const avatarTop = coords.y - mapMargins.y - avatar.height / 2;
182
+ setCoordinates(avatar, avatarLeft, avatarTop);
183
+ }
184
+ }
185
+
186
+ const labelElements = parentElement.getElementsByClassName(labelClass);
187
+ const markerElements = parentElement.getElementsByClassName(imageClass);
188
+ moveMarker(labelElements, mapMargins);
189
+ moveMarker(markerElements, mapMargins);
190
+
191
+ if (show) {
192
+ showElements(avatar, labelElements, markerElements);
193
+ }
194
+
195
+ parentElement.focus();
196
+ }
197
+
198
+ function setCoordinates(element: HTMLElement, left: number, top: number) {
199
+ element.style.top = `${top}px`;
200
+ element.style.left = `${left}px`;
201
+ }
202
+
203
+ function addElement(mapElement: HTMLElement, coordsString: string, location: string, className: string, elementType: string, elementValue: string): HTMLElement {
204
+ const coords = getCoords(coordsString);
205
+ const labelElement = document.createElement("div");
206
+ labelElement.setAttribute("class", className);
207
+ labelElement.style.visibility = hidden;
208
+ labelElement.setAttribute("data-top", coords.x.toString());
209
+ labelElement.setAttribute("data-left", coords.y.toString());
210
+ labelElement.setAttribute("data-locationid", location);
211
+ const valueElement = document.createElement(elementType);
212
+
213
+ if (elementType === 'span') {
214
+ (<HTMLSpanElement>valueElement).innerText = elementValue;
215
+ } else if (elementType === 'img') {
216
+ (<HTMLImageElement>valueElement).src = `resources/${elementValue}`;
217
+ }
218
+
219
+ labelElement.appendChild(valueElement);
220
+ mapElement.parentElement.appendChild(labelElement);
221
+ return labelElement;
222
+ }
223
+
224
+ function moveMarker(markerElements: HTMLCollection, mapMargins: { x: number, y: number }) {
225
+ if (!mapMargins) {
226
+ return;
227
+ }
228
+
229
+ for (const n in Object.keys(markerElements)) {
230
+ const markerElement = markerElements[n] as HTMLElement;
231
+ const currentLeft = parseInt(markerElement.dataset.top) - markerElement.clientWidth / 2 - mapMargins.x;
232
+ const currentTop = parseInt(markerElement.dataset.left) - markerElement.clientHeight / 2 - mapMargins.y;
233
+ const locationId = markerElement.dataset.locationid;
234
+ setCoordinates(markerElement, currentLeft, currentTop);
235
+
236
+ const isVisited = game.value.locations.get(locationId)?.hasVisited;
237
+ markerElement.classList.remove(visited);
238
+
239
+ if (isVisited) {
240
+ markerElement.classList.add(visited);
241
+ }
242
+
243
+ if (map.value.clickable === true) {
244
+ const isReachable = location.value.destinations.find(d => d.target === locationId);
245
+
246
+ markerElement.onclick = null;
247
+ markerElement.classList.remove(reachable);
248
+
249
+ if (isReachable) {
250
+ markerElement.classList.add(reachable);
251
+ markerElement.onclick = () => {
252
+ game.value.commands.go(locationId);
253
+ }
254
+ } else if (location.value.id === locationId) {
255
+ markerElement.classList.add(reachable);
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ function showElements(avatar: HTMLElement, labelElements: HTMLCollection, markerElements: HTMLCollection) {
262
+ setTimeout(() => {
263
+ if (avatar) {
264
+ avatar.style.visibility = visible;
265
+ }
266
+
267
+ if (!map.value.showMarkersOnKeyPress) {
268
+ setMarkerVisibility(labelElements, markerElements, visible);
269
+ }
270
+
271
+ }, map.value.transitionTime ?? 1000);
272
+ }
273
+
274
+ function setMarkerVisibility(labelElements: HTMLCollection, markerElements: HTMLCollection, visibility: string) {
275
+ for (const n in Object.keys(labelElements)) {
276
+ const labelElement = labelElements[n] as HTMLElement;
277
+ labelElement.style.visibility = visibility;
278
+ }
279
+
280
+ for (const n in Object.keys(markerElements)) {
281
+ const markerElement = markerElements[n] as HTMLElement;
282
+ markerElement.style.visibility = visibility;
283
+ }
284
+ }
285
+
286
+ function getCoords(coordString: string) {
287
+ const coords = coordString.split(',');
288
+ const coordLeft = parseInt(coords[0]);
289
+ const coordTop = parseInt(coords[1]);
290
+ return {x: coordLeft, y: coordTop};
291
+ }
292
+
293
+ function getMapMargin(mapImage: any, coord: number, dimension: string): number {
294
+ const mapContainer = mapImage.parentElement;
295
+ const clientDimension = 'client' + dimension.substring(0, 1).toUpperCase() + dimension.substring(1)
296
+ const mapDimension = mapContainer[clientDimension];
297
+ const viewPortCenter = mapDimension / 2;
298
+ const maxMargin = mapImage[dimension] - mapDimension;
299
+ let mapMargin = coord > viewPortCenter ? coord - viewPortCenter : 0;
300
+ mapMargin = mapMargin > maxMargin ? maxMargin : mapMargin;
301
+ return mapMargin;
302
+ }
303
+
304
+ function getMapElement(parentElement: HTMLElement): HTMLImageElement {
305
+ return parentElement.getElementsByClassName('map-image')[0] as HTMLImageElement;
306
+ }
307
+
308
+ return {
309
+ map,
310
+ prepareMap,
311
+ showMap,
312
+ toggleFullScreen,
313
+ toggleTouchMarkersVisible
314
+ }
315
+ }
@@ -0,0 +1,111 @@
1
+ import {useStateStore} from "ui/StateStore";
2
+ import {Ref, ref, watch} from "vue";
3
+ import {storeToRefs} from "pinia";
4
+
5
+ export function useSound(musicPlayerRef: Ref<HTMLAudioElement>) {
6
+ const store = useStateStore();
7
+ const {game} = storeToRefs(store);
8
+ const {rules, soundService} = store.services;
9
+
10
+ const musicPlayer = musicPlayerRef;
11
+
12
+ const canPlay = ref<boolean>(null);
13
+ const fadeInterval = ref<NodeJS.Timeout>(null);
14
+ const fadingMusic = ref(false);
15
+ const currentMusic = ref<string>(null);
16
+ const currentVolume = ref(1);
17
+
18
+ let audioContext: AudioContext;
19
+ const soundQueue: [number, string][] = [];
20
+
21
+ document.addEventListener('click', async () => {
22
+ if (!audioContext) {
23
+ audioContext = new window.AudioContext();
24
+ canPlay.value = true;
25
+
26
+ if (musicPlayer.value) {
27
+ await musicPlayer.value.play();
28
+ }
29
+ }
30
+ }, { once: true });
31
+
32
+ watch(musicPlayerRef, (newValue) => {
33
+ if (newValue && canPlay.value === null) {
34
+ canPlay.value = Boolean(audioContext);
35
+ }
36
+ }, { immediate: true });
37
+
38
+ const getSoundQueue = (): [number, string][] => {
39
+ Array.from(game.value.sounds.soundQueue).forEach(e => {
40
+ if (!e[1].playing) {
41
+ soundQueue.push([e[0], e[1].value]);
42
+ e[1].playing = true;
43
+ }
44
+ });
45
+
46
+ return soundQueue;
47
+ }
48
+
49
+ const getCurrentMusic = (): string => {
50
+ const music = soundService.getCurrentMusic();
51
+
52
+ if (rules.setup.fadeMusicInterval) {
53
+
54
+ if (!currentMusic.value) {
55
+ currentMusic.value = music;
56
+ }
57
+
58
+ if (!fadingMusic.value && music != currentMusic.value) {
59
+ fadingMusic.value = true;
60
+ fadeInterval.value = setInterval(() => fade(music), rules.setup.fadeMusicInterval);
61
+ }
62
+
63
+ return currentMusic.value;
64
+ }
65
+
66
+ return music;
67
+ }
68
+
69
+ const soundCompleted = (soundKey: number) => {
70
+ const sound = game.value.sounds.soundQueue.get(soundKey);
71
+
72
+ if (sound) {
73
+ sound.completeCallBack?.();
74
+ game.value.sounds.soundQueue.delete(soundKey);
75
+ }
76
+
77
+ const queueEntry = soundQueue.find(([k, _]) => soundKey === k);
78
+
79
+ if (!queueEntry) {
80
+ return;
81
+ }
82
+
83
+ const index = soundQueue.indexOf(queueEntry);
84
+
85
+ if (index > -1) {
86
+ soundQueue.splice(index, 1);
87
+ }
88
+ }
89
+
90
+ const fade = (newMusic: string) => {
91
+ const newVolume = currentVolume.value - 0.1;
92
+
93
+ if (newVolume >= 0) {
94
+ currentVolume.value = newVolume;
95
+ } else {
96
+ clearInterval(fadeInterval.value);
97
+ currentVolume.value = 1;
98
+ currentMusic.value = newMusic;
99
+ fadingMusic.value = false;
100
+ }
101
+
102
+ musicPlayer.value.volume = currentVolume.value;
103
+ }
104
+
105
+ return {
106
+ canPlay,
107
+ getSoundQueue,
108
+ getCurrentMusic,
109
+ soundCompleted
110
+ }
111
+ }
@@ -0,0 +1,148 @@
1
+ import {addHtmlSpaces} from "src/Engine/utilityFunctions";
2
+ import {IFeature} from 'storyScript';
3
+ import {useStateStore} from "ui/StateStore";
4
+ import {Ref, watch} from "vue";
5
+ import {storeToRefs} from "pinia";
6
+ import {isTouchDevice} from 'src/constants';
7
+
8
+ export function useTextFeatures(descriptionRef: Ref<HTMLDivElement>) {
9
+ const activeTriggerClass = 'trigger-active';
10
+
11
+ const store = useStateStore();
12
+ const {game} = storeToRefs(store);
13
+ const {combinationService} = store.services;
14
+
15
+ const description = descriptionRef;
16
+
17
+ watch(() => game.value.combinations.activeCombination?.selectedTool, () => {
18
+ refreshFeatures();
19
+ });
20
+
21
+ const refreshFeatures = () => {
22
+ // Show the text of added features.
23
+ const featureArray = Array.from(description.value?.getElementsByTagName('feature'));
24
+
25
+ if (featureArray.length === 0) {
26
+ return;
27
+ }
28
+
29
+ featureArray.filter(e => e.innerHTML.trim() === '')
30
+ .forEach((e) => {
31
+ const feature = game.value.currentLocation.features.get(e.getAttribute('name'));
32
+
33
+ if (feature) {
34
+ game.value.currentLocation.description = game.value.currentLocation.description.replace(new RegExp('<feature name="' + feature.id + '">\s*<\/feature>', 'i'), '<feature name="' + feature.id + '">' + addHtmlSpaces(feature.description) + '<\/feature>');
35
+ }
36
+ });
37
+
38
+ // Remove the text of deleted features.
39
+ featureArray.filter(e => e.innerHTML.trim() !== '')
40
+ .forEach((e) => {
41
+ const featureName = e.getAttribute('name')?.toLowerCase();
42
+
43
+ if (featureName && game.value.combinations.combinationResult.featuresToRemove.find(f => f === featureName)) {
44
+ e.innerHTML = '';
45
+ }
46
+ });
47
+
48
+ featureArray.forEach((e) => {
49
+ const feature = game.value.currentLocation.features.get(e.getAttribute('name'));
50
+
51
+ if (feature && game.value.combinations.activeCombination?.selectedTool?.id === feature.id) {
52
+ return;
53
+ }
54
+
55
+ e.classList.remove('combine-active-selected', 'combine-selectable', 'feature-cursor');
56
+ e.classList.add('feature-cursor');
57
+
58
+ if (game.value.combinations.activeCombination) {
59
+ e.classList.add('combine-selectable');
60
+ }
61
+ });
62
+ };
63
+
64
+ const click = (ev: PointerEvent) => {
65
+ const triggerElement = getTriggerElement(ev.target as HTMLElement);
66
+
67
+ if (triggerElement && isTouchDevice) {
68
+ const activate = !triggerElement.classList.contains(activeTriggerClass);
69
+
70
+ Array.from(description.value.querySelectorAll('[data-trigger]')).forEach((el) => {
71
+ toggleTrigger(el as any, false);
72
+ });
73
+
74
+ toggleTrigger(triggerElement, activate);
75
+ }
76
+
77
+ const feature = getFeature(ev);
78
+
79
+ if (feature) {
80
+ const result = game.value.combinations.tryCombine(feature);
81
+ const className = combinationService.getCombineClass(feature);
82
+
83
+ if (className) {
84
+ const featureElement = getFeatureElement(ev);
85
+ featureElement.classList.add(className);
86
+ }
87
+
88
+ if (result.success) {
89
+ refreshFeatures();
90
+ }
91
+ }
92
+ }
93
+
94
+ const mouseOver = (ev: MouseEvent) => {
95
+ if (isTouchDevice) {
96
+ return;
97
+ }
98
+
99
+ toggleTrigger(getTriggerElement(ev?.target as HTMLElement), true);
100
+ };
101
+
102
+ const mouseOut = (ev: MouseEvent) => {
103
+ if (isTouchDevice) {
104
+ return;
105
+ }
106
+
107
+ toggleTrigger(getTriggerElement(ev?.target as HTMLElement), false);
108
+ };
109
+
110
+ const toggleTrigger = (element: HTMLElement, active: boolean) => {
111
+ if (!element) {
112
+ return;
113
+ }
114
+
115
+ const data = element.dataset
116
+ const event = game.value.currentLocation.triggeredActions?.find(([k, _]) => k === data.trigger)?.[1];
117
+
118
+ if (active) {
119
+ element.classList.add(activeTriggerClass);
120
+ event?.(game.value, active, data);
121
+ } else {
122
+ element.classList.remove(activeTriggerClass);
123
+ event?.(game.value, active, data);
124
+ }
125
+ }
126
+
127
+ const getTriggerElement = (element: HTMLElement): HTMLElement => {
128
+ return element?.closest('[data-trigger]') as HTMLElement;
129
+ }
130
+
131
+ const getFeatureElement = (ev: MouseEvent) => {
132
+ return (ev.target as HTMLElement).closest('feature');
133
+ }
134
+
135
+ const getFeature = (ev: MouseEvent): IFeature => {
136
+ const featureElement = getFeatureElement(ev);
137
+ const featureName = featureElement?.getAttribute('name');
138
+ return featureName ? game.value.currentLocation.features.get(featureName) : null;
139
+ }
140
+
141
+ return {
142
+ description,
143
+ refreshFeatures,
144
+ click,
145
+ mouseOver,
146
+ mouseOut
147
+ }
148
+ }