@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,294 @@
1
+ import {
2
+ EquipmentType,
3
+ ICharacter,
4
+ IEnemy,
5
+ IGame,
6
+ IGroupableItem,
7
+ IInterfaceTexts,
8
+ IItem,
9
+ IItemService,
10
+ IRules,
11
+ removeItemFromItemsAndEquipment
12
+ } from 'storyScript';
13
+ import {getEquipmentType} from "src/Engine/utilityFunctions";
14
+
15
+ export class ItemService implements IItemService {
16
+
17
+ constructor(private _game: IGame, private _rules: IRules, private _texts: IInterfaceTexts) {
18
+ }
19
+
20
+ getItemName = (item: IItem): string => {
21
+ if (!item) {
22
+ return undefined;
23
+ }
24
+
25
+ if (this._rules.general.getItemName) {
26
+ return this._rules.general.getItemName(item, this._texts);
27
+ }
28
+
29
+ const groupableItem = item as IGroupableItem<IItem>
30
+
31
+ if (!groupableItem.members?.length) {
32
+ return item.name;
33
+ }
34
+
35
+ return this._texts.format(groupableItem.groupName, [(groupableItem.members.length + 1).toString()]);
36
+ }
37
+
38
+ pickupItem = (character: ICharacter, item: IItem): boolean => {
39
+ const isCombining = this._game.combinations?.activeCombination;
40
+
41
+ if (isCombining) {
42
+ this._game.combinations.tryCombine(item)
43
+ return false;
44
+ }
45
+
46
+ if (this._rules.character.beforePickup && !this._rules.character.beforePickup(this._game, character, item)) {
47
+ return false;
48
+ }
49
+
50
+ this._game.currentLocation.items.delete(item);
51
+ character.items.add(item);
52
+
53
+ return true;
54
+ }
55
+
56
+ canGroupItem = (character: ICharacter, group: IGroupableItem<IItem>, item: IGroupableItem<IItem>): boolean => {
57
+ if (!item || !item.isGroupable || item.members?.length) {
58
+ return false;
59
+ }
60
+
61
+ if (group) {
62
+ if (!group.isGroupable) {
63
+ return false;
64
+ }
65
+
66
+ if ((group.members?.length ?? 0) >= group.maxSize - 1) {
67
+ return false;
68
+ }
69
+
70
+ if (group.id !== item.id && (!group.groupTypes || group.groupTypes.indexOf(item.id) === -1)) {
71
+ return false;
72
+ }
73
+ }
74
+
75
+ const anyGroupableItem = character.items.find(i => {
76
+ if (i === item) {
77
+ return false;
78
+ }
79
+
80
+ const groupable = i as IGroupableItem<IItem>;
81
+ return groupable.isGroupable && (!groupable.maxSize || ((groupable.members?.length ?? 0) < groupable.maxSize - 1))
82
+ });
83
+
84
+ if (!anyGroupableItem) {
85
+ return false;
86
+ }
87
+
88
+ if (this._rules.general.canGroupItem) {
89
+ return this._rules.general.canGroupItem(character, group, item);
90
+ }
91
+
92
+ return true;
93
+ };
94
+
95
+ groupItem = (character: ICharacter, group: IGroupableItem<IItem>, item: IGroupableItem<IItem>): boolean => {
96
+ if (group && group !== item) {
97
+ group.members ??= [];
98
+ group.members.add(item);
99
+ character.items.delete(item);
100
+ return true;
101
+ }
102
+
103
+ return false;
104
+ }
105
+
106
+ splitItemGroup = (character: ICharacter, item: IGroupableItem<IItem>): void => {
107
+ if (item?.members?.length > 0) {
108
+ item.members.forEach((item: IItem) => {
109
+ character.items.add(item);
110
+ });
111
+
112
+ item.members = undefined;
113
+ }
114
+ }
115
+
116
+ useItem = (character: ICharacter, item: IItem, target?: IEnemy): Promise<void> | void => {
117
+ const useItem = (this._rules.exploration?.onUseItem?.(this._game, character, item) && item.use) ?? item.use;
118
+
119
+ if (useItem) {
120
+ const promise = item.use(this._game, character, item, target);
121
+
122
+ return Promise.resolve(promise).then(() => {
123
+ if (item.charges !== undefined) {
124
+ if (!isNaN(item.charges)) {
125
+ item.charges--;
126
+ }
127
+
128
+ if (item.charges <= 0) {
129
+ removeItemFromItemsAndEquipment(character, item);
130
+ }
131
+ }
132
+ });
133
+ }
134
+ }
135
+
136
+ isEquippable = (item: IItem, character?: ICharacter): boolean => {
137
+ if (item.equipmentType === EquipmentType.Miscellaneous) {
138
+ return false;
139
+ }
140
+
141
+ if (this._rules.character.canEquip) {
142
+ return this._rules.character.canEquip(item, character);
143
+ }
144
+
145
+ return true;
146
+ };
147
+
148
+ equipItem = (character: ICharacter, item: IItem): boolean => {
149
+ const equipmentTypes = Array.isArray(item.equipmentType) ? <EquipmentType[]>item.equipmentType : [<EquipmentType>item.equipmentType];
150
+
151
+ const slotsAvailable = this.makeSlotAvailable(character, item, equipmentTypes);
152
+
153
+ if (slotsAvailable.length === 0) {
154
+ return false;
155
+ }
156
+
157
+ if (this._rules.character.beforeEquip) {
158
+ if (!this._rules.character.beforeEquip(this._game, character, item)) {
159
+ return false;
160
+ }
161
+ }
162
+
163
+ if (item.equip) {
164
+ if (!item.equip(character, item, this._game)) {
165
+ return false;
166
+ }
167
+ }
168
+
169
+ for (const n in slotsAvailable) {
170
+ character.equipment[slotsAvailable[n]] = item;
171
+ }
172
+
173
+ character.items.splice(character.items.indexOf(item), 1);
174
+ return true;
175
+ }
176
+
177
+ unequipItem = (character: ICharacter, item: IItem): boolean => {
178
+ return this.unequip(character, item);
179
+ }
180
+
181
+ canDrop = (item: IItem): boolean => {
182
+ let canDrop: boolean;
183
+
184
+ if (typeof item.canDrop === 'function') {
185
+ canDrop = item.canDrop(this._game, item);
186
+ } else if (item.canDrop === undefined) {
187
+ canDrop = true;
188
+ } else {
189
+ canDrop = item.canDrop;
190
+ }
191
+
192
+ return canDrop
193
+ };
194
+
195
+ dropItem = (character: ICharacter, item: IItem): void => {
196
+ if (!item) {
197
+ return;
198
+ }
199
+
200
+ let drop = true;
201
+
202
+ if (this._rules.character.beforeDrop) {
203
+ drop = this._rules.character.beforeDrop(this._game, character, item);
204
+ }
205
+
206
+ if (drop) {
207
+ character.items.delete(item);
208
+ this._game.currentLocation.items.add(item);
209
+ }
210
+ }
211
+
212
+ private makeSlotAvailable(character: ICharacter, item: IItem, equipmentTypes: EquipmentType[]): string[] {
213
+ if (!item.usesMultipleSlots) {
214
+ return this.findAvailableSlot(character, equipmentTypes);
215
+ }
216
+
217
+ const availableSlots: string[] = [];
218
+
219
+ for (const n in equipmentTypes) {
220
+ const type = getEquipmentType(equipmentTypes[n]);
221
+ const slotItem = character.equipment[type];
222
+
223
+ if (slotItem) {
224
+ const unequipped = this.unequip(character, slotItem);
225
+
226
+ if (!unequipped) {
227
+ return [];
228
+ }
229
+ }
230
+
231
+ availableSlots.push(type);
232
+ }
233
+
234
+ return availableSlots;
235
+ }
236
+
237
+ private findAvailableSlot(character: ICharacter, equipmentTypes: EquipmentType[]) {
238
+ // If the item uses only one of the slots specified, see if a slot is available first.
239
+ const occupiedSlots: string[] = [];
240
+ const emptySlots: string[] = [];
241
+
242
+ for (const n in equipmentTypes) {
243
+ const type = getEquipmentType(equipmentTypes[n]);
244
+
245
+ if (character.equipment[type]) {
246
+ occupiedSlots.push(type);
247
+ } else {
248
+ emptySlots.push(type);
249
+ }
250
+ }
251
+
252
+ if (emptySlots.length === 0) {
253
+ const slotToUnequip = occupiedSlots[occupiedSlots.length - 1];
254
+ const unequipped = this.unequip(character, character.equipment[slotToUnequip]);
255
+ return !unequipped ? [] : [slotToUnequip];
256
+ }
257
+
258
+ return [emptySlots[0]];
259
+ }
260
+
261
+ private unequip = (character: ICharacter, equippedItem: IItem): boolean => {
262
+ if (!equippedItem) {
263
+ return true;
264
+ }
265
+
266
+ if (this._rules.character.beforeUnequip) {
267
+ if (!this._rules.character.beforeUnequip(this._game, character, equippedItem)) {
268
+ return false;
269
+ }
270
+ }
271
+
272
+ if (equippedItem.unequip) {
273
+ if (!equippedItem.unequip(character, equippedItem, this._game)) {
274
+ return false;
275
+ }
276
+ }
277
+
278
+ if (equippedItem?.equipmentType && character.items.indexOf(equippedItem) < 0) {
279
+ character.items.push(equippedItem);
280
+ }
281
+
282
+ const slotsToUnEquip = Array.isArray(equippedItem.equipmentType)
283
+ ? equippedItem.equipmentType
284
+ : [equippedItem.equipmentType];
285
+
286
+ slotsToUnEquip.forEach(t => {
287
+ const itemType = getEquipmentType(t);
288
+ const slotItem = character.equipment[itemType];
289
+ character.equipment[itemType] = slotItem === equippedItem ? null : slotItem;
290
+ });
291
+
292
+ return true;
293
+ }
294
+ }
@@ -0,0 +1,24 @@
1
+ import {ILocalStorageService} from 'storyScript';
2
+
3
+ const StoryScriptPrefix: string = 'StoryScript_';
4
+
5
+ export class LocalStorageService implements ILocalStorageService {
6
+ get = (key: string): any => localStorage.getItem(StoryScriptPrefix + key);
7
+
8
+ set = (key: string, value: any): void => localStorage.setItem(StoryScriptPrefix + key, value);
9
+
10
+ remove = (key: string): void => localStorage.removeItem(StoryScriptPrefix + key);
11
+
12
+ getKeys = (prefix: string): string[] => {
13
+ const result = [];
14
+ prefix = StoryScriptPrefix + prefix;
15
+
16
+ Object.keys(localStorage).forEach(k => {
17
+ if (k.startsWith(prefix)) {
18
+ result.push(k.replace(prefix, ''));
19
+ }
20
+ });
21
+
22
+ return result;
23
+ }
24
+ }
@@ -0,0 +1,380 @@
1
+ import {
2
+ ActionType,
3
+ gameEvents,
4
+ IAction,
5
+ ICompiledLocation,
6
+ IDefinitions,
7
+ IDestination,
8
+ IGame,
9
+ IGameEvents,
10
+ IKey,
11
+ ILocation,
12
+ ILocationService,
13
+ IRules,
14
+ parseGamePropertiesInTemplate
15
+ } from 'storyScript';
16
+ import {addHtmlSpaces, getId, parseHtmlDocumentFromString} from 'src/Engine/utilityFunctions';
17
+ import {getBasicFeatureData, setDestination} from "src/Engine/EntityCreatorFunctions";
18
+
19
+ export class LocationService implements ILocationService {
20
+ constructor(
21
+ private readonly _definitions: IDefinitions,
22
+ private readonly _rules: IRules,
23
+ private readonly _game: IGame,
24
+ private readonly _gameEvents: IGameEvents,
25
+ ) {
26
+ }
27
+
28
+ init = (): void => {
29
+ this._game.currentLocation = null;
30
+ this._game.previousLocation = null;
31
+
32
+ if (!this._game.locations) {
33
+ // When we don't have any locations yet, we're starting a new game. Use the definitions to build
34
+ // all the locations. Also build the maps, if present.
35
+ this._game.locations = {};
36
+ this._definitions.locations.forEach(l => this._game.locations[getId(l)] = <ICompiledLocation>l());
37
+ }
38
+
39
+ if (!this._game.maps && this._definitions.maps) {
40
+ this._game.maps = {};
41
+ // When we have no maps, it could be that maps were added later and that they are not in the saved
42
+ // data yet. Add the maps available now.
43
+ this._definitions.maps?.forEach(m => this._game.maps[getId(m)] = m());
44
+ }
45
+
46
+ this.setupLocations();
47
+
48
+ this._gameEvents.subscribe(['add-character-items', 'delete-character-items', 'add-location-items'], (game: IGame, _) => {
49
+ game.currentLocation?.destinations.forEach(d => {
50
+ this.addKeyAction(game, d);
51
+ })
52
+ }, false);
53
+ }
54
+
55
+ changeLocation = (location: string | (() => ILocation), travel: boolean, game: IGame): void => {
56
+ // Clear the play state on travel.
57
+ game.playState = null;
58
+ this._rules.exploration?.leaveLocation?.(game, game.currentLocation, getId(location), travel);
59
+ this.playEvents(game, 'leaveEvents');
60
+
61
+ // If there is no location, we are starting a new game. We're done here.
62
+ if (!this.switchLocation(game, location)) {
63
+ return;
64
+ }
65
+
66
+ this.processDestinations(game);
67
+ this._game.party.currentLocationId = game.currentLocation.id;
68
+ this._game.party.previousLocationId = game.previousLocation?.id;
69
+ this._rules.exploration?.enterLocation?.(game, game.currentLocation, game.previousLocation?.id, travel);
70
+ this.loadLocationDescriptions(game);
71
+ this.initTrade(game);
72
+ this.playEvents(game, 'enterEvents');
73
+ this.markCurrentLocationAsVisited(game);
74
+ }
75
+
76
+ executeAction = (action: [string, IAction]): void => {
77
+ const execute = action[1]?.execute;
78
+
79
+ if (execute) {
80
+ let result = true;
81
+
82
+ if (typeof execute === 'function') {
83
+ const actionResult = execute(this._game);
84
+ result = actionResult === true;
85
+ } else {
86
+ gameEvents.publish(execute, action);
87
+ }
88
+
89
+ const typeAndIndex = this.getActionIndex(this._game, action);
90
+
91
+ if (!result && typeAndIndex.index !== -1) {
92
+ if (typeAndIndex.type === ActionType.Regular && this._game.currentLocation.actions) {
93
+ const currentAction = this._game.currentLocation.actions[typeAndIndex.index];
94
+ this._game.currentLocation.actions.delete(currentAction);
95
+ } else if (typeAndIndex.type === ActionType.Combat && this._game.currentLocation.combatActions) {
96
+ const currentCombatAction = this._game.currentLocation.combatActions[typeAndIndex.index];
97
+ this._game.currentLocation.combatActions.delete(currentCombatAction);
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ loadLocationDescriptions = (game: IGame): void => {
104
+ if (this.selectLocationDescription(game)) {
105
+ parseGamePropertiesInTemplate(game.currentLocation.description, this._game);
106
+ this.processTextFeatures(game.currentLocation);
107
+ }
108
+ }
109
+
110
+ initDestinations = (location: ICompiledLocation): void => {
111
+ // Add a proxy to the destination collection add and delete functions, to replace the target function pointers
112
+ // with the target id when adding or deleting destinations at runtime.
113
+ location.destinations.add = location.destinations.add.proxy(this.addDestination, this._game);
114
+
115
+ Object.defineProperty(location, 'activeDestinations', {
116
+ get: function () {
117
+ return location.destinations.filter(e => {
118
+ return !e.inactive;
119
+ });
120
+ }
121
+ });
122
+ }
123
+
124
+ processDestinations = (game: IGame) => {
125
+ if (game.previousLocation?.destinations.length) {
126
+ // Remove the isPreviousLocation and visited markers from the previous location's destinations.
127
+ game.previousLocation.destinations.forEach((d: any) => {
128
+ delete d.isPreviousLocation;
129
+ delete d.visited;
130
+ });
131
+ }
132
+
133
+ if (game.currentLocation.destinations.length) {
134
+ // 1. Mark the previous location in the current location's destinations to allow
135
+ // the player to more easily backtrack his last step.
136
+ // 2. Mark the destination as visited when the player has already visited the location it leads to.
137
+ // 3. Check if the user has the key for one or more barriers at this location, and add the key actions
138
+ // if that is the case.
139
+ game.currentLocation.destinations.forEach((d: any) => {
140
+ if (d.target == game.previousLocation?.id) {
141
+ d.isPreviousLocation = true;
142
+ }
143
+
144
+ const targetLocation = game.locations[d.target];
145
+ const visitedRule = this._rules.exploration?.hasVisitedLocation;
146
+
147
+ if (targetLocation && visitedRule) {
148
+ d.visited = visitedRule(game, targetLocation);
149
+ } else {
150
+ d.visited = targetLocation?.hasVisited;
151
+ }
152
+
153
+ this.addKeyAction(game, d);
154
+ });
155
+ }
156
+ }
157
+
158
+ private readonly setupLocations = () => {
159
+ Object.values(this._game.locations).forEach(l => {
160
+ const compiledLocation = <ICompiledLocation>l;
161
+ this.initDestinations(compiledLocation);
162
+ let selector = compiledLocation.descriptionSelector;
163
+
164
+ Object.defineProperty(compiledLocation, 'descriptionSelector', {
165
+ enumerable: true,
166
+ get: () => selector,
167
+ set: (value) => {
168
+ selector = value;
169
+ this.selectLocationDescription(this._game);
170
+ }
171
+ });
172
+ });
173
+
174
+ this.addLocationGet(this._game.locations);
175
+ }
176
+
177
+ private readonly addLocationGet = (locations: Record<string, ICompiledLocation>) => {
178
+ Object.defineProperty(locations, 'get', {
179
+ enumerable: false,
180
+ value: function (id?: string | (() => ILocation) | ICompiledLocation): ICompiledLocation {
181
+ if (!id) {
182
+ return undefined;
183
+ }
184
+
185
+ if (typeof id === 'string') {
186
+ return locations[id.toLowerCase()];
187
+ } else if (typeof id === 'function') {
188
+ return locations[id.name.toLowerCase()];
189
+ } else {
190
+ return locations[id.id]
191
+ }
192
+ }
193
+ });
194
+ }
195
+
196
+ private readonly switchLocation = (game: IGame, location: string | (() => ILocation)): boolean => {
197
+ let presentLocation: ICompiledLocation;
198
+
199
+ // If no location is specified, go to the previous location.
200
+ if (!location) {
201
+ const tempLocation = game.currentLocation;
202
+ game.currentLocation = game.previousLocation;
203
+ game.previousLocation = tempLocation;
204
+ presentLocation = game.currentLocation;
205
+ }
206
+ // If currently at a location, make this the previous location.
207
+ else if (game.currentLocation) {
208
+ game.previousLocation = game.currentLocation;
209
+ }
210
+
211
+ if (!location && !presentLocation) {
212
+ return false;
213
+ }
214
+
215
+ const key = getId(location) ?? presentLocation.id;
216
+ game.currentLocation = game.locations.get(key);
217
+ return true;
218
+ }
219
+
220
+ private readonly markCurrentLocationAsVisited = (game: IGame): void => {
221
+ if (!game.currentLocation.hasVisited) {
222
+ game.currentLocation.hasVisited = true;
223
+ game.statistics.LocationsVisited = game.statistics.LocationsVisited || 0;
224
+ game.statistics.LocationsVisited += 1;
225
+ }
226
+ }
227
+
228
+ private readonly initTrade = (game: IGame): void => {
229
+ if (game.currentLocation.trade?.length > 0) {
230
+ game.currentLocation.trade.forEach(t => {
231
+ if (!game.currentLocation.actions.find(([k, v]) => v.actionType === ActionType.Trade && k === t.id)) {
232
+ game.currentLocation.actions.add([t.id, {
233
+ text: t.name,
234
+ actionType: ActionType.Trade,
235
+ execute: 'trade'
236
+ }]);
237
+ }
238
+ });
239
+ }
240
+ }
241
+
242
+ private readonly addDestination = (originalScope: any, originalFunction: Function, destination: IDestination, game: IGame): void => {
243
+ setDestination(destination);
244
+ this.addKeyAction(game, destination);
245
+ originalFunction.call(originalScope, destination);
246
+ }
247
+
248
+ private readonly playEvents = (game: IGame, eventProperty: string): void => {
249
+ if (!game.currentLocation?.[eventProperty]) {
250
+ return;
251
+ }
252
+
253
+ // Keep a reference to the location being processed. When the location is changed in the
254
+ // event, we want to still update the events in the originating location.
255
+ const location = game.currentLocation;
256
+ const events = [...location[eventProperty]];
257
+
258
+ events.forEach(e => {
259
+ const result = e[1]?.(game);
260
+
261
+ if (!result) {
262
+ location[eventProperty].delete(e);
263
+ }
264
+ });
265
+ }
266
+
267
+ private readonly processTextFeatures = (location: ICompiledLocation): void => {
268
+ if (!location.description) {
269
+ return;
270
+ }
271
+
272
+ const htmlDoc = parseHtmlDocumentFromString(location.description);
273
+ const featureNodes = <HTMLCollectionOf<HTMLElement>>htmlDoc.getElementsByTagName('feature');
274
+
275
+ for (const element of featureNodes) {
276
+ const feature = getBasicFeatureData(location, element);
277
+
278
+ // If the feature is not present in code, clean the node html as the feature is either
279
+ // not yet added (the feature tag is a placeholder for a feature added at runtime) or it
280
+ // was deleted. Clean the node html to not show the feature text in case it was deleted.
281
+ if (!feature) {
282
+ element.innerHTML = '';
283
+ } else {
284
+ feature.description = element.innerHTML || feature.description;
285
+ element.innerHTML = addHtmlSpaces(feature.description);
286
+ }
287
+ }
288
+
289
+ location.description = htmlDoc.body.innerHTML;
290
+ }
291
+
292
+
293
+ private readonly selectLocationDescription = (game: IGame): boolean => {
294
+ let selector = null;
295
+
296
+ if (!game.currentLocation.descriptions) {
297
+ game.currentLocation.description = null;
298
+ return false;
299
+ }
300
+
301
+ let description: string;
302
+ const defaultDescription = game.currentLocation.descriptions['default'] || game.currentLocation.descriptions[Object.keys(game.currentLocation.descriptions)[0]];
303
+
304
+ // A location can specify how to select the proper selection using a descriptor selection function. If it is not specified,
305
+ // use the default description selector function.
306
+ if (game.currentLocation.descriptionSelector) {
307
+ selector = typeof game.currentLocation.descriptionSelector == 'function' ? game.currentLocation.descriptionSelector(game) : game.currentLocation.descriptionSelector;
308
+ description = game.currentLocation.descriptions[selector];
309
+ }
310
+
311
+ if (!description && this._rules.exploration?.descriptionSelector && (selector = this._rules.exploration.descriptionSelector(game))) {
312
+ description = game.currentLocation.descriptions[selector];
313
+ }
314
+
315
+ description ??= defaultDescription;
316
+ game.currentLocation.description = description;
317
+ return true;
318
+ }
319
+
320
+ private readonly addKeyAction = (game: IGame, destination: IDestination) => {
321
+ destination.barriers?.forEach(([_, b]) => {
322
+ if (b.key) {
323
+ const key = typeof b.key === 'function' ?
324
+ b.key()
325
+ : <IKey>this._definitions.items.get(b.key)();
326
+
327
+ let existingAction = null;
328
+
329
+ if (b.actions) {
330
+ b.actions.forEach(([k, v]) => {
331
+ if (k === key.id) {
332
+ existingAction = v;
333
+ }
334
+ });
335
+ } else {
336
+ b.actions = [];
337
+ }
338
+
339
+ if (existingAction) {
340
+ b.actions.splice(b.actions.indexOf(existingAction), 1);
341
+ }
342
+
343
+ let partyKey = null;
344
+
345
+ game.party.characters.forEach(c => {
346
+ partyKey = partyKey ?? c.items.get(key.id);
347
+ });
348
+
349
+ const barrierKey = <IKey>(partyKey || game.currentLocation.items.get(key.id));
350
+
351
+ if (barrierKey) {
352
+ b.actions.push([barrierKey.id, barrierKey.open]);
353
+ }
354
+ }
355
+ });
356
+ }
357
+
358
+ private getActionIndex = (game: IGame, action: [string, IAction]): { type: ActionType, index: number } => {
359
+ let index = -1;
360
+ let type = ActionType.Regular;
361
+
362
+ game.currentLocation.actions.forEach(([k, v], i) => {
363
+ if (k === action[0]) {
364
+ index = i;
365
+ type = ActionType.Regular;
366
+ }
367
+ });
368
+
369
+ if (index == -1) {
370
+ game.currentLocation.combatActions.forEach(([k, v], i) => {
371
+ if (k === action[0]) {
372
+ index = i;
373
+ type = ActionType.Combat;
374
+ }
375
+ });
376
+ }
377
+
378
+ return {type, index};
379
+ }
380
+ }