@maka/maka-cli 5.3.16 → 5.4.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 (220) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/create.js +1 -1
  3. package/bundle/typescript/src/commands/create.js.map +1 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/archetypes.d.ts +43 -0
  5. package/bundle/typescript/src/commands/game/sideQuest/archetypes.js +131 -0
  6. package/bundle/typescript/src/commands/game/sideQuest/archetypes.js.map +1 -0
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/assense.d.ts +14 -0
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/assense.js +79 -0
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/assense.js.map +1 -0
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/attack.d.ts +42 -0
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js +224 -0
  12. package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js.map +1 -0
  13. package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.d.ts +28 -0
  14. package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js +101 -0
  15. package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js.map +1 -0
  16. package/bundle/typescript/src/commands/game/sideQuest/commands/call.d.ts +19 -0
  17. package/bundle/typescript/src/commands/game/sideQuest/commands/call.js +149 -0
  18. package/bundle/typescript/src/commands/game/sideQuest/commands/call.js.map +1 -0
  19. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.d.ts +58 -0
  20. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js +378 -0
  21. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js.map +1 -0
  22. package/bundle/typescript/src/commands/game/sideQuest/commands/command-registry.d.ts +11 -1
  23. package/bundle/typescript/src/commands/game/sideQuest/commands/command-registry.js +8 -3
  24. package/bundle/typescript/src/commands/game/sideQuest/commands/command-registry.js.map +1 -1
  25. package/bundle/typescript/src/commands/game/sideQuest/commands/command.d.ts +6 -0
  26. package/bundle/typescript/src/commands/game/sideQuest/commands/command.js +4 -0
  27. package/bundle/typescript/src/commands/game/sideQuest/commands/command.js.map +1 -1
  28. package/bundle/typescript/src/commands/game/sideQuest/commands/drone.d.ts +15 -0
  29. package/bundle/typescript/src/commands/game/sideQuest/commands/drone.js +60 -0
  30. package/bundle/typescript/src/commands/game/sideQuest/commands/drone.js.map +1 -0
  31. package/bundle/typescript/src/commands/game/sideQuest/commands/edge.d.ts +13 -0
  32. package/bundle/typescript/src/commands/game/sideQuest/commands/edge.js +31 -0
  33. package/bundle/typescript/src/commands/game/sideQuest/commands/edge.js.map +1 -0
  34. package/bundle/typescript/src/commands/game/sideQuest/commands/end-call.d.ts +6 -0
  35. package/bundle/typescript/src/commands/game/sideQuest/commands/end-call.js +27 -0
  36. package/bundle/typescript/src/commands/game/sideQuest/commands/end-call.js.map +1 -0
  37. package/bundle/typescript/src/commands/game/sideQuest/commands/equip.d.ts +4 -0
  38. package/bundle/typescript/src/commands/game/sideQuest/commands/equip.js +40 -0
  39. package/bundle/typescript/src/commands/game/sideQuest/commands/equip.js.map +1 -1
  40. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.d.ts +13 -0
  41. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js +43 -0
  42. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js.map +1 -0
  43. package/bundle/typescript/src/commands/game/sideQuest/commands/give.js +7 -1
  44. package/bundle/typescript/src/commands/game/sideQuest/commands/give.js.map +1 -1
  45. package/bundle/typescript/src/commands/game/sideQuest/commands/go.d.ts +11 -0
  46. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +115 -4
  47. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
  48. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.d.ts +25 -0
  49. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +176 -0
  50. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -0
  51. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.d.ts +12 -0
  52. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js +39 -0
  53. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js.map +1 -0
  54. package/bundle/typescript/src/commands/game/sideQuest/commands/jack.d.ts +17 -0
  55. package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js +64 -0
  56. package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js.map +1 -0
  57. package/bundle/typescript/src/commands/game/sideQuest/commands/kill.d.ts +10 -3
  58. package/bundle/typescript/src/commands/game/sideQuest/commands/kill.js +11 -33
  59. package/bundle/typescript/src/commands/game/sideQuest/commands/kill.js.map +1 -1
  60. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +35 -4
  61. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
  62. package/bundle/typescript/src/commands/game/sideQuest/commands/map.d.ts +12 -0
  63. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +46 -0
  64. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -0
  65. package/bundle/typescript/src/commands/game/sideQuest/commands/pan.d.ts +12 -0
  66. package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js +55 -0
  67. package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js.map +1 -0
  68. package/bundle/typescript/src/commands/game/sideQuest/commands/pick.d.ts +9 -0
  69. package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js +18 -0
  70. package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js.map +1 -0
  71. package/bundle/typescript/src/commands/game/sideQuest/commands/project.d.ts +19 -0
  72. package/bundle/typescript/src/commands/game/sideQuest/commands/project.js +54 -0
  73. package/bundle/typescript/src/commands/game/sideQuest/commands/project.js.map +1 -0
  74. package/bundle/typescript/src/commands/game/sideQuest/commands/read.js +6 -5
  75. package/bundle/typescript/src/commands/game/sideQuest/commands/read.js.map +1 -1
  76. package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.d.ts +12 -0
  77. package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.js +52 -0
  78. package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.js.map +1 -0
  79. package/bundle/typescript/src/commands/game/sideQuest/commands/reload.d.ts +14 -0
  80. package/bundle/typescript/src/commands/game/sideQuest/commands/reload.js +40 -0
  81. package/bundle/typescript/src/commands/game/sideQuest/commands/reload.js.map +1 -0
  82. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.d.ts +15 -0
  83. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js +59 -0
  84. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js.map +1 -0
  85. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +23 -2
  86. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
  87. package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +20 -3
  88. package/bundle/typescript/src/commands/game/sideQuest/commands/search.js.map +1 -1
  89. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.d.ts +12 -0
  90. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +49 -0
  91. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -0
  92. package/bundle/typescript/src/commands/game/sideQuest/commands/silent.d.ts +13 -0
  93. package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js +50 -0
  94. package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js.map +1 -0
  95. package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js +32 -11
  96. package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js.map +1 -1
  97. package/bundle/typescript/src/commands/game/sideQuest/commands/spells.d.ts +14 -0
  98. package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js +65 -0
  99. package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js.map +1 -0
  100. package/bundle/typescript/src/commands/game/sideQuest/commands/stance.d.ts +12 -0
  101. package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js +41 -0
  102. package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js.map +1 -0
  103. package/bundle/typescript/src/commands/game/sideQuest/commands/subdue.d.ts +21 -0
  104. package/bundle/typescript/src/commands/game/sideQuest/commands/subdue.js +43 -0
  105. package/bundle/typescript/src/commands/game/sideQuest/commands/subdue.js.map +1 -0
  106. package/bundle/typescript/src/commands/game/sideQuest/commands/surrender.d.ts +20 -0
  107. package/bundle/typescript/src/commands/game/sideQuest/commands/surrender.js +45 -0
  108. package/bundle/typescript/src/commands/game/sideQuest/commands/surrender.js.map +1 -0
  109. package/bundle/typescript/src/commands/game/sideQuest/commands/take.d.ts +8 -0
  110. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js +80 -1
  111. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js.map +1 -1
  112. package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js +1 -0
  113. package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js.map +1 -1
  114. package/bundle/typescript/src/commands/game/sideQuest/commands/use.d.ts +24 -0
  115. package/bundle/typescript/src/commands/game/sideQuest/commands/use.js +101 -1
  116. package/bundle/typescript/src/commands/game/sideQuest/commands/use.js.map +1 -1
  117. package/bundle/typescript/src/commands/game/sideQuest/factories/item-factory.js +2 -1
  118. package/bundle/typescript/src/commands/game/sideQuest/factories/item-factory.js.map +1 -1
  119. package/bundle/typescript/src/commands/game/sideQuest/factories/npc-factory.js +7 -2
  120. package/bundle/typescript/src/commands/game/sideQuest/factories/npc-factory.js.map +1 -1
  121. package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js +2 -1
  122. package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js.map +1 -1
  123. package/bundle/typescript/src/commands/game/sideQuest/factories/room-factory.js +2 -0
  124. package/bundle/typescript/src/commands/game/sideQuest/factories/room-factory.js.map +1 -1
  125. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.d.ts +8 -1
  126. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js +138 -21
  127. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js.map +1 -1
  128. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.d.ts +119 -0
  129. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js +816 -0
  130. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js.map +1 -0
  131. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +70 -9
  132. package/bundle/typescript/src/commands/game/sideQuest/game.js +403 -164
  133. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  134. package/bundle/typescript/src/commands/game/sideQuest/minigames/hack-minigame.d.ts +16 -0
  135. package/bundle/typescript/src/commands/game/sideQuest/minigames/hack-minigame.js +101 -0
  136. package/bundle/typescript/src/commands/game/sideQuest/minigames/hack-minigame.js.map +1 -0
  137. package/bundle/typescript/src/commands/game/sideQuest/minigames/lockpick-minigame.d.ts +15 -0
  138. package/bundle/typescript/src/commands/game/sideQuest/minigames/lockpick-minigame.js +95 -0
  139. package/bundle/typescript/src/commands/game/sideQuest/minigames/lockpick-minigame.js.map +1 -0
  140. package/bundle/typescript/src/commands/game/sideQuest/models/door.d.ts +10 -0
  141. package/bundle/typescript/src/commands/game/sideQuest/models/door.js +15 -2
  142. package/bundle/typescript/src/commands/game/sideQuest/models/door.js.map +1 -1
  143. package/bundle/typescript/src/commands/game/sideQuest/models/inventory.d.ts +10 -0
  144. package/bundle/typescript/src/commands/game/sideQuest/models/inventory.js +54 -4
  145. package/bundle/typescript/src/commands/game/sideQuest/models/inventory.js.map +1 -1
  146. package/bundle/typescript/src/commands/game/sideQuest/models/item.d.ts +41 -0
  147. package/bundle/typescript/src/commands/game/sideQuest/models/item.js +106 -3
  148. package/bundle/typescript/src/commands/game/sideQuest/models/item.js.map +1 -1
  149. package/bundle/typescript/src/commands/game/sideQuest/models/npc.d.ts +25 -0
  150. package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +220 -47
  151. package/bundle/typescript/src/commands/game/sideQuest/models/npc.js.map +1 -1
  152. package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +213 -0
  153. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +525 -9
  154. package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
  155. package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.d.ts +75 -1
  156. package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js +174 -6
  157. package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js.map +1 -1
  158. package/bundle/typescript/src/commands/game/sideQuest/models/room.d.ts +20 -0
  159. package/bundle/typescript/src/commands/game/sideQuest/models/room.js +39 -18
  160. package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
  161. package/bundle/typescript/src/commands/game/sideQuest/models/scene.d.ts +69 -0
  162. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +175 -2
  163. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
  164. package/bundle/typescript/src/commands/game/sideQuest/scenes/scene1.json +80 -1
  165. package/bundle/typescript/src/commands/game/sideQuest/scenes/scene2.json +7 -2
  166. package/bundle/typescript/src/commands/game/sideQuest/types/player-equipment.d.ts +1 -0
  167. package/bundle/typescript/src/commands/game/sideQuest/types/seed/exit-seed.d.ts +1 -0
  168. package/bundle/typescript/src/commands/game/sideQuest/types/seed/item-seed.d.ts +1 -0
  169. package/bundle/typescript/src/commands/game/sideQuest/types/seed/npc-seed.d.ts +1 -0
  170. package/bundle/typescript/src/commands/game/sideQuest/types/seed/player-seed.d.ts +34 -0
  171. package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.d.ts +15 -1
  172. package/bundle/typescript/src/commands/game/sideQuest/types/seed/room-seed.d.ts +3 -0
  173. package/bundle/typescript/src/commands/game/sideQuest/types/seed/scene-seed.d.ts +5 -0
  174. package/bundle/typescript/src/commands/game/sideQuest/types/seed/win-condition-seed.d.ts +15 -0
  175. package/bundle/typescript/src/commands/game/sideQuest/types/seed/win-condition-seed.js +2 -0
  176. package/bundle/typescript/src/commands/game/sideQuest/types/seed/win-condition-seed.js.map +1 -0
  177. package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.d.ts +1 -0
  178. package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js +5 -0
  179. package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js.map +1 -1
  180. package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.d.ts +1 -0
  181. package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.js +1 -0
  182. package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.js.map +1 -1
  183. package/bundle/typescript/src/commands/game/sideQuest/ui.d.ts +3 -0
  184. package/bundle/typescript/src/commands/game/sideQuest/ui.js +95 -5
  185. package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
  186. package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.d.ts +60 -0
  187. package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.js +138 -0
  188. package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.js.map +1 -0
  189. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.d.ts +143 -0
  190. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js +328 -0
  191. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js.map +1 -0
  192. package/bundle/typescript/src/commands/game/sideQuest/utilities/comm-style.d.ts +2 -0
  193. package/bundle/typescript/src/commands/game/sideQuest/utilities/comm-style.js +12 -0
  194. package/bundle/typescript/src/commands/game/sideQuest/utilities/comm-style.js.map +1 -0
  195. package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.d.ts +22 -0
  196. package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.js +34 -0
  197. package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.js.map +1 -0
  198. package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.d.ts +36 -0
  199. package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js +92 -0
  200. package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js.map +1 -0
  201. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.d.ts +44 -0
  202. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +193 -0
  203. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js.map +1 -0
  204. package/bundle/typescript/src/commands/game/sideQuest/utilities/pursuit.d.ts +16 -0
  205. package/bundle/typescript/src/commands/game/sideQuest/utilities/pursuit.js +36 -0
  206. package/bundle/typescript/src/commands/game/sideQuest/utilities/pursuit.js.map +1 -0
  207. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +54 -7
  208. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
  209. package/bundle/typescript/src/commands/set/global.sub.cmd.js +59 -5
  210. package/bundle/typescript/src/commands/set/global.sub.cmd.js.map +1 -1
  211. package/bundle/typescript/src/tools/ai/ai.class.d.ts +35 -0
  212. package/bundle/typescript/src/tools/ai/ai.class.js +112 -0
  213. package/bundle/typescript/src/tools/ai/ai.class.js.map +1 -0
  214. package/bundle/typescript/src/tools/fsi/fsi.interfaces.d.ts +1 -0
  215. package/bundle/typescript/src/tools/fsi/fsi.interfaces.js.map +1 -1
  216. package/bundle/typescript/src/tools/https/https.class.d.ts +2 -1
  217. package/bundle/typescript/src/tools/https/https.class.js +43 -0
  218. package/bundle/typescript/src/tools/https/https.class.js.map +1 -1
  219. package/bundle/typescript/src/tools/https/https.interface.d.ts +8 -0
  220. package/package.json +1 -1
@@ -4,4 +4,28 @@ export declare class UseCommand extends Command implements ICommand {
4
4
  protected static description: string;
5
5
  execute(args: string[]): Promise<string>;
6
6
  private use;
7
+ /**
8
+ * Healing, matching combat's texture (see commands/attack.ts): a visible
9
+ * first-aid dice pool scaled by the item's quality, applied to the
10
+ * condition monitor. Pool is 2 * (1 + quality) d6 (a common medkit rolls
11
+ * 2d6, a military-grade one 10d6) and the recovery is hits + 1 + quality
12
+ * -- the floor guarantees even an all-miss roll isn't a wasted kit, and
13
+ * quality dominates, since gear is the game's whole progression system.
14
+ * Single-use: the kit is consumed. Healing also restores wound-modifier
15
+ * dice, since those derive from current damage.
16
+ *
17
+ * Deliberately refuses BEFORE consuming when there's nothing to heal --
18
+ * burning a medkit at full health would just be a trap -- and when the
19
+ * user is already down: death is death, not a big wound.
20
+ */
21
+ private applyFirstAid;
22
+ /**
23
+ * Stim patches are the STUN answer (spell drain fills stun; medkits only
24
+ * touch physical): same quality-scaled pool and consumable economy as a
25
+ * medkit, but with the classic stim tradeoff -- the CRASH. After the
26
+ * lift, 1 box of real physical damage lands. Slapping a stim while
27
+ * already bleeding out can genuinely kill you; that's the gamble, and
28
+ * the reason a safe rest (see rest.ts) exists as the free alternative.
29
+ */
30
+ private applyStim;
7
31
  }
@@ -1,7 +1,9 @@
1
1
  import { Command } from './command.js';
2
+ import { Category } from '../types/shared/item-enum.js';
3
+ import { rollPool, formatRoll } from '../utilities/dice.js';
2
4
  export class UseCommand extends Command {
3
5
  static verb = 'use';
4
- static description = 'Use an item.';
6
+ static description = 'Use an item. A Medical item (medkit, stim patch) heals your wounds and is consumed.';
5
7
  async execute(args) {
6
8
  return this.use(args);
7
9
  }
@@ -18,6 +20,12 @@ export class UseCommand extends Command {
18
20
  this.logger.write(`UseCommand: ${itemName} not retrieved from ${this.actor.name}'s inventory.`);
19
21
  return `You don't have the ${itemName} to use.`;
20
22
  }
23
+ if (itemToUse.category === Category.Medical) {
24
+ return this.applyFirstAid(itemToUse);
25
+ }
26
+ if (itemToUse.category === Category.StimPatch) {
27
+ return this.applyStim(itemToUse);
28
+ }
21
29
  // If the item has a 'use' method, call it and use the return value in the response.
22
30
  if (typeof itemToUse.use === 'function') {
23
31
  const result = itemToUse.use();
@@ -30,5 +38,97 @@ export class UseCommand extends Command {
30
38
  return `You can't use the ${itemName} in this way.`;
31
39
  }
32
40
  }
41
+ /**
42
+ * Healing, matching combat's texture (see commands/attack.ts): a visible
43
+ * first-aid dice pool scaled by the item's quality, applied to the
44
+ * condition monitor. Pool is 2 * (1 + quality) d6 (a common medkit rolls
45
+ * 2d6, a military-grade one 10d6) and the recovery is hits + 1 + quality
46
+ * -- the floor guarantees even an all-miss roll isn't a wasted kit, and
47
+ * quality dominates, since gear is the game's whole progression system.
48
+ * Single-use: the kit is consumed. Healing also restores wound-modifier
49
+ * dice, since those derive from current damage.
50
+ *
51
+ * Deliberately refuses BEFORE consuming when there's nothing to heal --
52
+ * burning a medkit at full health would just be a trap -- and when the
53
+ * user is already down: death is death, not a big wound.
54
+ */
55
+ applyFirstAid(kit) {
56
+ if (this.actor.isDown()) {
57
+ return `You're past the help of a ${kit.name}.`;
58
+ }
59
+ if (this.actor.damageTaken === 0) {
60
+ return `You're not hurt -- save the ${kit.name} for when you're bleeding.`;
61
+ }
62
+ // First aid is a LOGIC test aided by the kit (Logic + 2/quality tier);
63
+ // a logic-3 medic with a standard kit rolls the same 5-ish dice the old
64
+ // pure-gear formula gave.
65
+ const quality = kit.qualityBonus;
66
+ const roll = rollPool(this.actor.logic + 2 * quality);
67
+ const healed = this.actor.healDamage(roll.hits + 1 + quality);
68
+ this.actor.inventory.removeItem(kit.name);
69
+ this.logger.write(`UseCommand: ${this.actor.name} used ${kit.name} and healed ${healed} boxes (${this.actor.damageTaken}/${this.actor.maxConditionBoxes}).`);
70
+ this.actor.performAction('uses', kit.name);
71
+ this.scene.addWorldEvent(`${this.actor.name} patched themselves up with ${kit.name}.`);
72
+ this.scene.updateInventory(this.scene.getPlayer().inventory);
73
+ this.scene.updateStatus();
74
+ return [
75
+ `You use the ${kit.name}:`,
76
+ ` First aid: ${formatRoll(roll)}`,
77
+ ` You recover ${healed} box${healed === 1 ? '' : 'es'}: ${this.actor.conditionSummary()}`,
78
+ ` (The ${kit.name} is spent.)`,
79
+ ].join('\n');
80
+ }
81
+ /**
82
+ * Stim patches are the STUN answer (spell drain fills stun; medkits only
83
+ * touch physical): same quality-scaled pool and consumable economy as a
84
+ * medkit, but with the classic stim tradeoff -- the CRASH. After the
85
+ * lift, 1 box of real physical damage lands. Slapping a stim while
86
+ * already bleeding out can genuinely kill you; that's the gamble, and
87
+ * the reason a safe rest (see rest.ts) exists as the free alternative.
88
+ */
89
+ applyStim(patch) {
90
+ if (this.actor.isIncapacitated()) {
91
+ return `You're past the help of a ${patch.name}.`;
92
+ }
93
+ if (this.actor.stunTaken === 0) {
94
+ return `You're not winded -- save the ${patch.name} for when the drain's caught up with you.`;
95
+ }
96
+ const quality = patch.qualityBonus;
97
+ const roll = rollPool(2 * (1 + quality));
98
+ const recovered = this.actor.healStun(roll.hits + 1 + quality);
99
+ this.actor.inventory.removeItem(patch.name);
100
+ this.actor.performAction('uses', patch.name);
101
+ this.scene.addWorldEvent(`${this.actor.name} slapped on a ${patch.name}.`);
102
+ const lines = [
103
+ `You slap on the ${patch.name}:`,
104
+ ` Stim: ${formatRoll(roll)}`,
105
+ ` The fog burns off -- ${recovered} stun recovered: ${this.actor.stunSummary()}`,
106
+ ];
107
+ // The crash: chemicals collect their fee in real damage.
108
+ this.actor.takeDamage(1);
109
+ this.logger.write(`UseCommand: ${this.actor.name} used ${patch.name}: +${recovered} stun, crash 1 physical (${this.actor.damageTaken}/${this.actor.maxConditionBoxes}).`);
110
+ lines.push(` ...then the crash bites: 1 box physical: ${this.actor.conditionSummary()}`);
111
+ lines.push(` (The ${patch.name} is spent.)`);
112
+ if (this.actor.isDown()) {
113
+ // Stimming while nearly bled out finished the job -- same GAME
114
+ // OVER/removal flows every other death uses (see kill.ts).
115
+ const isPlayer = this.actor === this.scene.getPlayer();
116
+ this.scene.addWorldEvent(`${this.actor.name} collapsed dead from a stim crash.`);
117
+ if (isPlayer) {
118
+ void this.scene.endGame().then(() => {
119
+ this.logger.logWithColor(`💀 GAME OVER: ${this.actor.name}'s heart gave out under the stim crash.`, 'red');
120
+ this.logger.logWithColor(`Press ctrl-c to quit.`, 'red');
121
+ });
122
+ lines.push('', `Your chest seizes. The lift was a lie -- the crash takes everything.`);
123
+ }
124
+ else {
125
+ this.scene.removeActor(this.actor.name);
126
+ lines.push('', `${this.actor.name} seizes and drops -- the stim took more than it gave.`);
127
+ }
128
+ }
129
+ this.scene.updateInventory(this.scene.getPlayer().inventory);
130
+ this.scene.updateStatus();
131
+ return lines.join('\n');
132
+ }
33
133
  }
34
134
  //# sourceMappingURL=use.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/use.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,cAAc,CAAC;AAEjD,MAAM,OAAO,UAAW,SAAQ,OAAO;IAC3B,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;IACpB,MAAM,CAAC,WAAW,GAAG,cAAc,CAAC;IAE9C,KAAK,CAAC,OAAO,CAAC,IAAc;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAEO,GAAG,CAAC,IAAc;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAE9C,qDAAqD;QACrD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,IAAI,qBAAqB,QAAQ,oCAAoC,CAAC,CAAC;YACnH,OAAO,sBAAsB,QAAQ,UAAU,CAAC;QAClD,CAAC;QAED,uCAAuC;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEzD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,QAAQ,uBAAuB,IAAI,CAAC,KAAK,CAAC,IAAI,eAAe,CAAC,CAAC;YAChG,OAAO,sBAAsB,QAAQ,UAAU,CAAC;QAClD,CAAC;QAED,oFAAoF;QACpF,IAAI,OAAO,SAAS,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,QAAQ,GAAG,CAAC,CAAC;YACtE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACxC,OAAO,MAAM,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,QAAQ,6BAA6B,CAAC,CAAC;YACxE,OAAO,qBAAqB,QAAQ,eAAe,CAAC;QACtD,CAAC;IACH,CAAC"}
1
+ {"version":3,"file":"use.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/use.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,8 @@ export class ItemFactory {
14
14
  weight: json.weight,
15
15
  details: json.details,
16
16
  satisfiesLifestyle: json.satisfiesLifestyle,
17
- transferable: json.transferable
17
+ transferable: json.transferable,
18
+ plane: json.plane
18
19
  });
19
20
  if (json.currencyAmount && item.isCurrencyCarrier()) {
20
21
  item.addCurrency(json.currencyAmount);
@@ -1 +1 @@
1
- {"version":3,"file":"item-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/item-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEtE,MAAM,OAAO,WAAW;IACtB,KAAK,CAAC,kBAAkB,CAAC,IAAmB;QAC1C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;YACpB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACrB,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YACpD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
1
+ {"version":3,"file":"item-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/item-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEtE,MAAM,OAAO,WAAW;IACtB,KAAK,CAAC,kBAAkB,CAAC,IAAmB;QAC1C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;YACpB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACrB,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YACpD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -11,11 +11,15 @@ export class NPCFactory {
11
11
  }
12
12
  const playerConstructorConfig = this.convertPlayerSeedToConstructorConfig(json.player);
13
13
  const commandRegistry = new CommandRegistry(this.scene);
14
- return new NPC({
14
+ const npc = new NPC({
15
15
  dialog: json.dialogue ?? ["..."],
16
16
  description: json.description ?? "Not interesting",
17
17
  playerConstructorConfig
18
18
  }, commandRegistry);
19
+ // Native off-plane residents: ice lives on the Matrix, spirits on the
20
+ // astral. They have no body to leave behind -- the plane IS their home.
21
+ npc.plane = json.plane ?? 'meat';
22
+ return npc;
19
23
  }
20
24
  convertPlayerSeedToConstructorConfig(seed) {
21
25
  if (!seed.name) {
@@ -28,7 +32,8 @@ export class NPCFactory {
28
32
  return {
29
33
  playerName: seed.name,
30
34
  lifestyleChoices: seed.lifestyleChoices,
31
- startLocation
35
+ startLocation,
36
+ combat: seed.combat
32
37
  };
33
38
  }
34
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"npc-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/npc-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAIvC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,OAAO,UAAU;IACb,KAAK,CAAQ;IAErB,YAAY,KAAY;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,IAAkB;QACxC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,uBAAuB,GAAG,IAAI,CAAC,oCAAoC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvF,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExD,OAAO,IAAI,GAAG,CAAC;YACb,MAAM,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC;YAChC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,iBAAiB;YAClD,uBAAuB;SACxB,EAAE,eAAe,CAAC,CAAC;IACtB,CAAC;IAEO,oCAAoC,CAAC,IAA4B;QACvE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7D,OAAO;YACL,UAAU,EAAE,IAAI,CAAC,IAAI;YACrB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,aAAa;SACd,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"npc-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/npc-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAIvC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,OAAO,UAAU;IACb,KAAK,CAAQ;IAErB,YAAY,KAAY;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,IAAkB;QACxC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,uBAAuB,GAAG,IAAI,CAAC,oCAAoC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvF,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC;YAClB,MAAM,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC;YAChC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,iBAAiB;YAClD,uBAAuB;SACxB,EAAE,eAAe,CAAC,CAAC;QACpB,sEAAsE;QACtE,wEAAwE;QACxE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC;QACjC,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,oCAAoC,CAAC,IAA4B;QACvE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7D,OAAO;YACL,UAAU,EAAE,IAAI,CAAC,IAAI;YACrB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,aAAa;YACb,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;CACF"}
@@ -17,7 +17,8 @@ export class PuzzleFactory {
17
17
  rewardItem,
18
18
  successMessage: json.successMessage,
19
19
  failureMessage: json.failureMessage,
20
- hobbyTags: json.hobbyTags
20
+ hobbyTags: json.hobbyTags,
21
+ bypassType: json.bypassType
21
22
  });
22
23
  }
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"puzzle-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/puzzle-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,oBAAoB,CAAC,IAAqB,EAAE,OAA0B;QAC1E,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9E,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,YAAY,2BAA2B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAC9F,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,CAAC,UAAU,2BAA2B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAC1F,CAAC;QAED,OAAO,IAAI,MAAM,CAAC;YAChB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,YAAY;YACZ,UAAU;YACV,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"puzzle-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/puzzle-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,oBAAoB,CAAC,IAAqB,EAAE,OAA0B;QAC1E,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9E,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,YAAY,2BAA2B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAC9F,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,CAAC,UAAU,2BAA2B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAC1F,CAAC;QAED,OAAO,IAAI,MAAM,CAAC;YAChB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,YAAY;YACZ,UAAU;YACV,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -12,6 +12,8 @@ export class RoomFactory {
12
12
  isStartRoom: roomJson.isStartRoom,
13
13
  roomType: roomJson.roomType,
14
14
  tags: roomJson.tags ?? [],
15
+ hasNode: roomJson.hasNode,
16
+ warded: roomJson.warded,
15
17
  supportedLifestyles: roomJson.supportedLifestyles
16
18
  };
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"room-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/room-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA0B,MAAM,qBAAqB,CAAC;AAGnE,MAAM,OAAO,WAAW;IACtB,KAAK,CAAC,kBAAkB,CAAC,MAAqB;QAC5C,MAAM,UAAU,GAA2B,IAAI,CAAC,2BAA2B,CAAC,MAAM,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,2BAA2B,CAAC,QAAuB;QACzD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,EAAE;YACzB,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB;SAClD,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"room-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/room-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA0B,MAAM,qBAAqB,CAAC;AAGnE,MAAM,OAAO,WAAW;IACtB,KAAK,CAAC,kBAAkB,CAAC,MAAqB;QAC5C,MAAM,UAAU,GAA2B,IAAI,CAAC,2BAA2B,CAAC,MAAM,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,2BAA2B,CAAC,QAAuB;QACzD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,EAAE;YACzB,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB;SAClD,CAAC;IACJ,CAAC;CACF"}
@@ -2,5 +2,12 @@ import { Scene } from '../models/scene.js';
2
2
  import { Player } from '../models/player.js';
3
3
  import { ISceneSeedJson } from '../types/seed/scene-seed.js';
4
4
  export declare class SceneSynthesizer {
5
- static synthesizeFromJson(json: ISceneSeedJson, player: Player, _useAi: boolean): Promise<Scene>;
5
+ /**
6
+ * `grantStartingItems` defaults to true (a fresh game). Pass false when
7
+ * synthesizing a "continue"d job onto a long-lived Player who already has
8
+ * gear from prior jobs -- otherwise a whole new starter kit (commlink,
9
+ * armor, etc.) gets dumped into their inventory on top of what they
10
+ * already earned, unexplained.
11
+ */
12
+ static synthesizeFromJson(json: ISceneSeedJson, player: Player, useAi: boolean, grantStartingItems?: boolean): Promise<Scene>;
6
13
  }
@@ -1,11 +1,20 @@
1
1
  import { Scene } from '../models/scene.js';
2
+ import { Door } from '../models/door.js';
2
3
  import { RoomFactory } from './room-factory.js';
3
4
  import { NPCFactory } from './npc-factory.js';
4
5
  import { ItemFactory } from './item-factory.js';
5
6
  import { PuzzleFactory } from './puzzle-factory.js';
7
+ import { Category } from '../types/shared/item-enum.js';
6
8
  import { Logger } from '../utilities/logger.js';
7
9
  export class SceneSynthesizer {
8
- static async synthesizeFromJson(json, player, _useAi) {
10
+ /**
11
+ * `grantStartingItems` defaults to true (a fresh game). Pass false when
12
+ * synthesizing a "continue"d job onto a long-lived Player who already has
13
+ * gear from prior jobs -- otherwise a whole new starter kit (commlink,
14
+ * armor, etc.) gets dumped into their inventory on top of what they
15
+ * already earned, unexplained.
16
+ */
17
+ static async synthesizeFromJson(json, player, useAi, grantStartingItems = true) {
9
18
  const logger = Logger.getInstance();
10
19
  // Step 1: Create the Scene using the JSON’s room configuration
11
20
  logger.write(`Initilizing Scene`);
@@ -18,12 +27,25 @@ export class SceneSynthesizer {
18
27
  residenceTiers: json.residenceTiers,
19
28
  story: json.story,
20
29
  });
30
+ // Shared context handed to every ensureAI*() call below, so room
31
+ // descriptions, NPC appearances, and puzzle riddles all stay
32
+ // consistent with the same scene tone.
33
+ const sceneContext = `
34
+ Scene: ${json.name}
35
+ Story: ${json.story}
36
+ Currency: ${json.currency.type}
37
+ Residence Tiers: ${json.residenceTiers.join(', ')}
38
+ Key Locations: ${json.rooms.map(r => r.name).join(', ')}
39
+ `.trim();
21
40
  // Step 2: Create and Register Rooms using RoomFactory
22
41
  logger.write(`Creating Rooms`);
23
42
  const roomFactory = new RoomFactory();
24
43
  for (const roomJson of json.rooms) {
25
44
  const room = await roomFactory.createRoomFromJson(roomJson);
26
45
  scene.addRoom(room); // Assumes you have a method like this on Scene
46
+ if (useAi) {
47
+ await room.ensureAIDescription(sceneContext);
48
+ }
27
49
  }
28
50
  // Step 2.5: Wire exits between rooms
29
51
  logger.write(`Adding Exits`);
@@ -50,6 +72,9 @@ export class SceneSynthesizer {
50
72
  scene.addActor(npc);
51
73
  scene.setCharacterLocation(npc, npcJson.player.startLocation);
52
74
  npc.scene = scene;
75
+ if (useAi) {
76
+ await npc.ensureAIAppearance(sceneContext);
77
+ }
53
78
  }
54
79
  // Step 4: Add Items
55
80
  const itemFactory = new ItemFactory();
@@ -71,32 +96,124 @@ export class SceneSynthesizer {
71
96
  // throw new Error(`Item "${itemJson.name}" must have either 'room' or 'heldBy'.`);
72
97
  }
73
98
  }
74
- // Step 4.1: Add Starting Items for the Player
75
- logger.write(`Assigning starting items to player: ${json.player.name}`);
76
- for (const startingItemJson of json.player.startingItems ?? []) {
77
- const item = await itemFactory.createItemFromJson(startingItemJson);
78
- player.addInventory(item);
79
- itemMap.set(item.name, item); // So it can still be referenced later if needed
80
- item.owner = player.name;
81
- logger.write(`Gave player starting item: ${item.name}`);
99
+ // Step 4.05: NPCs wear their gear. "heldBy" only puts items in an NPC's
100
+ // inventory, but combat pools (see Player.getWeaponProfile /
101
+ // getArmorValue) read from EQUIPPED slots -- without this, an enforcer
102
+ // "holding" an assault rifle and an armored jacket would fight
103
+ // bare-fisted in street clothes. Only weapon/armor categories are
104
+ // auto-equipped: plot items (datachips, books, keys) stay in inventory
105
+ // where "give"/death-drops expect them. Failures are non-fatal -- a
106
+ // second weapon just stays holstered in inventory.
107
+ const combatCategories = new Set([
108
+ Category.Weapon, Category.MeleeWeapon, Category.RangedWeapon,
109
+ Category.Armor, Category.BodyArmor, Category.ArmorClothing, Category.Shield,
110
+ Category.Helmet, Category.ArmArmor, Category.LegArmor, Category.Boots, Category.Gloves,
111
+ ]);
112
+ for (const npcJson of json.npcs ?? []) {
113
+ const npc = scene.getActor(npcJson.player.name);
114
+ if (!npc)
115
+ continue;
116
+ for (const item of [...npc.inventory.getAllItems()]) {
117
+ if (combatCategories.has(item.category)) {
118
+ npc.equip(item);
119
+ }
120
+ }
121
+ }
122
+ // Step 4.1: Add Starting Items for the Player (skipped when continuing
123
+ // a long-lived player who already has gear from a prior job)
124
+ if (grantStartingItems) {
125
+ logger.write(`Assigning starting items to player: ${json.player.name}`);
126
+ for (const startingItemJson of json.player.startingItems ?? []) {
127
+ const item = await itemFactory.createItemFromJson(startingItemJson);
128
+ player.addInventory(item);
129
+ itemMap.set(item.name, item); // So it can still be referenced later if needed
130
+ item.owner = player.name;
131
+ logger.write(`Gave player starting item: ${item.name}`);
132
+ }
133
+ }
134
+ else {
135
+ logger.write(`Skipping starting items for ${json.player.name} -- continuing with existing gear.`);
136
+ }
137
+ // Step 4.2: Resolve the win condition (if any), now that items/npcs exist
138
+ if (json.winCondition) {
139
+ const wc = json.winCondition;
140
+ if (!itemMap.has(wc.item)) {
141
+ throw new Error(`Win condition references item "${wc.item}", which is not in "items".`);
142
+ }
143
+ if (wc.type === 'give') {
144
+ if (!wc.toNpc) {
145
+ throw new Error(`Win condition type "give" requires "toNpc".`);
146
+ }
147
+ if (!scene.getActor(wc.toNpc)) {
148
+ throw new Error(`Win condition references NPC "${wc.toNpc}", which is not in "npcs".`);
149
+ }
150
+ }
151
+ let rewardItem;
152
+ if (wc.rewardItem) {
153
+ rewardItem = itemMap.get(wc.rewardItem);
154
+ if (!rewardItem) {
155
+ throw new Error(`Win condition reward item "${wc.rewardItem}" is not in "items".`);
156
+ }
157
+ }
158
+ scene.setWinCondition({
159
+ type: wc.type,
160
+ item: wc.item,
161
+ toNpc: wc.toNpc,
162
+ rewardItem,
163
+ completionMessage: wc.completionMessage,
164
+ payout: wc.payout
165
+ });
82
166
  }
83
167
  // Step 5: Add Puzzles
84
168
  const puzzleFactory = new PuzzleFactory();
169
+ const puzzleMap = new Map();
85
170
  for (const puzzleJson of json.puzzles ?? []) {
86
171
  const puzzle = await puzzleFactory.createPuzzleFromJson(puzzleJson, itemMap);
87
- scene.addPuzzleToRoom(puzzle, puzzleJson.room);
172
+ puzzleMap.set(puzzle.name, puzzle);
173
+ // A door-guarding puzzle (see exits[].puzzle below) has no "room" of
174
+ // its own -- it belongs to the connection between two rooms, not
175
+ // either one.
176
+ if (puzzleJson.room) {
177
+ scene.addPuzzleToRoom(puzzle, puzzleJson.room);
178
+ }
179
+ if (useAi) {
180
+ await puzzle.ensureAIRiddle(sceneContext, puzzleJson.room);
181
+ }
182
+ }
183
+ // Step 5.1: Wire puzzle prerequisites, now that every puzzle in the
184
+ // scene exists -- a puzzle's requiresPuzzle may point at one created
185
+ // later in the array above, so this has to be a separate pass.
186
+ for (const puzzleJson of json.puzzles ?? []) {
187
+ if (!puzzleJson.requiresPuzzle)
188
+ continue;
189
+ const puzzle = puzzleMap.get(puzzleJson.name);
190
+ const prerequisite = puzzleMap.get(puzzleJson.requiresPuzzle);
191
+ if (!prerequisite) {
192
+ throw new Error(`Puzzle "${puzzleJson.name}" requires puzzle "${puzzleJson.requiresPuzzle}", which doesn't exist in this scene.`);
193
+ }
194
+ if (puzzle === prerequisite) {
195
+ throw new Error(`Puzzle "${puzzleJson.name}" cannot require itself.`);
196
+ }
197
+ puzzle.setRequiresPuzzle(prerequisite, puzzleJson.lockedMessage);
198
+ }
199
+ // Step 5.2: Wire door-guarding puzzles onto their exits, now that every
200
+ // puzzle exists -- a puzzle referenced by "exits[].puzzle" may be
201
+ // defined anywhere in "puzzles[]", built above in this same pass.
202
+ for (const roomJson of json.rooms) {
203
+ for (const exit of roomJson.exits ?? []) {
204
+ if (!exit.puzzle)
205
+ continue;
206
+ const puzzle = puzzleMap.get(exit.puzzle);
207
+ if (!puzzle) {
208
+ throw new Error(`Exit from "${roomJson.name}" to "${exit.targetRoom}" references puzzle "${exit.puzzle}", which doesn't exist in this scene.`);
209
+ }
210
+ const sourceRoom = scene.getRoom(roomJson.name);
211
+ const doorExit = sourceRoom?.getExit(exit.direction.toLowerCase());
212
+ if (doorExit instanceof Door) {
213
+ doorExit.attachPuzzle(puzzle);
214
+ }
215
+ }
88
216
  }
89
- // // Step 6: Sync AI descriptions for all rooms
90
- // const sceneContext = `
91
- // Scene: ${scene.name}
92
- // Currency: ${json.currency.type}
93
- // Residence Tiers: ${json.residenceTiers.join(', ')}
94
- // Key Locations: ${json.rooms.map(r => r.name).join(', ')}
95
- // `;
96
- //
97
- // for (const room of Object.values(scene.getRooms())) {
98
- // await room.ensureAIDescription(sceneContext);
99
- // }
100
217
  // Step 7: Assign ownership to rooms and items
101
218
  logger.write(`Assigning Ownership`);
102
219
  for (const roomJson of json.rooms) {
@@ -1 +1 @@
1
- {"version":3,"file":"scene-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/scene-factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene-factory.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/factories/scene-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import { ISceneSeedJson } from '../types/seed/scene-seed.js';
2
+ export declare const FIXER_NAME = "Mr. Johnson";
3
+ export declare class SceneSeedGenerator {
4
+ private static readonly maxAttempts;
5
+ /**
6
+ * `tier` is 1 for a first job, 2+ for each successive "continue" --
7
+ * scales both the scope guidance in the prompt and, indirectly, the
8
+ * story's stakes. `previousFixerName`, when given, tells the model to
9
+ * keep using the same job-giver identity rather than inventing a new one
10
+ * every time "continue" is used.
11
+ */
12
+ static generate(logFilePath: string, tier?: number, previousFixerName?: string): Promise<ISceneSeedJson | null>;
13
+ /**
14
+ * Saves a validated scene alongside that session's game log (same
15
+ * directory as `logFilePath`) so a run can be inspected or replayed later
16
+ * -- AI-generated scenes previously only existed in memory for the
17
+ * process that generated them.
18
+ */
19
+ private static saveSeedToDisk;
20
+ private static requestCandidate;
21
+ /**
22
+ * Runs the candidate through the exact same synthesis pipeline a real
23
+ * session would use, purely to surface referential-integrity errors
24
+ * (missing room/item/npc names) before committing to it. Discards the
25
+ * resulting Scene either way -- the real session re-synthesizes fresh
26
+ * (with AI flavor enabled) once this seed is handed off.
27
+ */
28
+ private static dryRunValidate;
29
+ /**
30
+ * The one structural guarantee every other check assumes: every room,
31
+ * NPC, and item actually has a real, non-blank "name". Nothing about the
32
+ * JSON shape stops a model from emitting `"name": ""` or omitting the
33
+ * field outright, and synthesis doesn't validate it either -- it just
34
+ * uses whatever's there as a map key and crashes with an opaque error the
35
+ * moment something tries to look it up.
36
+ */
37
+ private static validateBasicStructure;
38
+ /**
39
+ * A puzzle must belong to exactly one place: a room (via "puzzles[].room")
40
+ * or a door (via some "exits[].puzzle" naming it) -- see DOORS AS PUZZLES.
41
+ * Synthesis itself doesn't catch either failure mode: an orphaned puzzle
42
+ * (neither) silently never appears anywhere in the world, and a
43
+ * double-placed one (both) would exist as two disconnected instances of
44
+ * "the same" barrier -- solvable in the room without ever needing to open
45
+ * the door, or vice versa.
46
+ */
47
+ private static validatePuzzlePlacement;
48
+ /**
49
+ * The schema says a reward item must have neither "room" nor "heldBy" --
50
+ * solving the puzzle (or completing the win condition) is what's supposed
51
+ * to bring it into existence for the player -- but nothing ever actually
52
+ * enforced that. Found via a real session where a puzzle's rewardItem was
53
+ * ALSO "heldBy" the very NPC guarding it: solving the puzzle granted a
54
+ * second, phantom copy of the item while the NPC's own real one stayed
55
+ * put (and later dropped normally when killed) -- so the player ended up
56
+ * with two disconnected copies of "the same" item, and the NPC's own
57
+ * dialogue reflected the same confused premise (accusing the player of
58
+ * theft for solving a puzzle it had just dared them to solve).
59
+ */
60
+ private static validateRewardItemPlacement;
61
+ /**
62
+ * Maps every item that has a concrete location (room, or heldBy an NPC
63
+ * whose startLocation gives it one) to that room's name. Shared by the
64
+ * reachability BFS and the win-condition checks below.
65
+ */
66
+ private static buildItemLocationMap;
67
+ /**
68
+ * Lock-and-key reachability BFS from the start room: a room becomes
69
+ * reachable once some already-reachable room has an unlocked exit to it,
70
+ * or a locked exit whose key has already been found in a reachable
71
+ * location. Rooms marked "reachable: false" are excluded from this
72
+ * traversal on purpose -- see validateDoorKeys.
73
+ */
74
+ private static computeReachableRooms;
75
+ /**
76
+ * Synthesis itself doesn't catch a locked door whose "keyRequired" names
77
+ * an item that doesn't exist, or one that's placed somewhere only
78
+ * reachable by first passing through that same door -- both leave the
79
+ * player permanently stuck with no way to unlock it (the real bug this
80
+ * guards against, found via a real session where a player was stonewalled
81
+ * behind a locked door for an entire play session). Also enforces the
82
+ * "reachable: false" contract (used for a fixer's inaccessible hideout,
83
+ * say): such a room must never connect to a normally-reachable one, in
84
+ * either direction, and nothing the player needs to retrieve may live
85
+ * inside one.
86
+ */
87
+ private static validateDoorKeys;
88
+ /**
89
+ * requiresPuzzle references are structurally valid JSON either way (a
90
+ * bad name or a cycle won't make synthesis itself throw), so this walks
91
+ * each puzzle's prerequisite chain looking for a reference to a puzzle
92
+ * that doesn't exist or a cycle. Chains of any length are fine -- only
93
+ * missing references and cycles are rejected.
94
+ */
95
+ private static validatePuzzleChain;
96
+ /**
97
+ * Every AI-generated scene must have a completable win condition -- this
98
+ * is what the "continue into a new job" loop hooks into. Also guards
99
+ * against a win condition item that's already sitting in the target
100
+ * NPC's own inventory, which would make the "find and deliver it"
101
+ * premise nonsensical.
102
+ */
103
+ private static validateWinCondition;
104
+ /**
105
+ * Enforces the "always some way to find the solution" guarantee: every
106
+ * puzzle must have a discoverable clue, placed in a different room. None
107
+ * of this is caught by synthesis (a puzzle with no clue, or an empty one,
108
+ * is still structurally valid), so it's checked separately and treated
109
+ * the same as any other validation failure -- it triggers a retry.
110
+ *
111
+ * Two patterns both count. Found via a real generation that kept getting
112
+ * rejected despite being genuinely solvable: a riddle whose answer is a
113
+ * real item's own name (e.g. "obsidian keycard", matching an actual item
114
+ * called "Obsidian Keycard" sitting in another room) needs no separate
115
+ * documentation -- finding it and seeing its name on screen already
116
+ * reveals the answer. A Book clue is still required for anything else.
117
+ */
118
+ private static validateClueItems;
119
+ }