@maka/maka-cli 5.117.0 → 5.119.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 (159) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js +6 -1
  3. package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js.map +1 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js +9 -2
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js.map +1 -1
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/compile.js +3 -0
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/compile.js.map +1 -1
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/deck.d.ts +14 -2
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js +73 -38
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js.map +1 -1
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/decompile.js +3 -6
  12. package/bundle/typescript/src/commands/game/sideQuest/commands/decompile.js.map +1 -1
  13. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js +1 -1
  14. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js.map +1 -1
  15. package/bundle/typescript/src/commands/game/sideQuest/commands/download.js +4 -3
  16. package/bundle/typescript/src/commands/game/sideQuest/commands/download.js.map +1 -1
  17. package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.d.ts +1 -1
  18. package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.js +10 -8
  19. package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.js.map +1 -1
  20. package/bundle/typescript/src/commands/game/sideQuest/commands/equip.js +17 -7
  21. package/bundle/typescript/src/commands/game/sideQuest/commands/equip.js.map +1 -1
  22. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.d.ts +10 -0
  23. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js +72 -20
  24. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js.map +1 -1
  25. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +8 -3
  26. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
  27. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +30 -14
  28. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -1
  29. package/bundle/typescript/src/commands/game/sideQuest/commands/haggle.js +14 -2
  30. package/bundle/typescript/src/commands/game/sideQuest/commands/haggle.js.map +1 -1
  31. package/bundle/typescript/src/commands/game/sideQuest/commands/hop.d.ts +16 -0
  32. package/bundle/typescript/src/commands/game/sideQuest/commands/hop.js +95 -0
  33. package/bundle/typescript/src/commands/game/sideQuest/commands/hop.js.map +1 -0
  34. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js +6 -0
  35. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js.map +1 -1
  36. package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js +3 -1
  37. package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js.map +1 -1
  38. package/bundle/typescript/src/commands/game/sideQuest/commands/jackpoint.js +5 -7
  39. package/bundle/typescript/src/commands/game/sideQuest/commands/jackpoint.js.map +1 -1
  40. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +24 -4
  41. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
  42. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +1 -1
  43. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -1
  44. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js +20 -6
  45. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js.map +1 -1
  46. package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.js +7 -6
  47. package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.js.map +1 -1
  48. package/bundle/typescript/src/commands/game/sideQuest/commands/reload.js +6 -3
  49. package/bundle/typescript/src/commands/game/sideQuest/commands/reload.js.map +1 -1
  50. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js +3 -0
  51. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js.map +1 -1
  52. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +8 -5
  53. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
  54. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +4 -3
  55. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
  56. package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js +11 -3
  57. package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js.map +1 -1
  58. package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js +5 -3
  59. package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js.map +1 -1
  60. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js +20 -2
  61. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js.map +1 -1
  62. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js +1 -0
  63. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js.map +1 -1
  64. package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js +2 -5
  65. package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js.map +1 -1
  66. package/bundle/typescript/src/commands/game/sideQuest/engine-version.d.ts +1 -1
  67. package/bundle/typescript/src/commands/game/sideQuest/engine-version.js +17 -1
  68. package/bundle/typescript/src/commands/game/sideQuest/engine-version.js.map +1 -1
  69. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.d.ts +6 -0
  70. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js +17 -4
  71. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js.map +1 -1
  72. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +1 -0
  73. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
  74. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js +2 -0
  75. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js.map +1 -1
  76. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +22 -0
  77. package/bundle/typescript/src/commands/game/sideQuest/game.js +132 -29
  78. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  79. package/bundle/typescript/src/commands/game/sideQuest/models/host.d.ts +80 -0
  80. package/bundle/typescript/src/commands/game/sideQuest/models/host.js +98 -0
  81. package/bundle/typescript/src/commands/game/sideQuest/models/host.js.map +1 -0
  82. package/bundle/typescript/src/commands/game/sideQuest/models/item.d.ts +50 -1
  83. package/bundle/typescript/src/commands/game/sideQuest/models/item.js +78 -2
  84. package/bundle/typescript/src/commands/game/sideQuest/models/item.js.map +1 -1
  85. package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +133 -3
  86. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +381 -85
  87. package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
  88. package/bundle/typescript/src/commands/game/sideQuest/models/room.d.ts +40 -9
  89. package/bundle/typescript/src/commands/game/sideQuest/models/room.js +73 -12
  90. package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
  91. package/bundle/typescript/src/commands/game/sideQuest/models/scene.d.ts +3 -0
  92. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +3 -0
  93. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
  94. package/bundle/typescript/src/commands/game/sideQuest/qualities.d.ts +34 -1
  95. package/bundle/typescript/src/commands/game/sideQuest/qualities.js +58 -26
  96. package/bundle/typescript/src/commands/game/sideQuest/qualities.js.map +1 -1
  97. package/bundle/typescript/src/commands/game/sideQuest/types/player-equipment.d.ts +8 -12
  98. package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +14 -1
  99. package/bundle/typescript/src/commands/game/sideQuest/types/seed/room-seed.d.ts +1 -0
  100. package/bundle/typescript/src/commands/game/sideQuest/types/seed/scene-seed.d.ts +2 -0
  101. package/bundle/typescript/src/commands/game/sideQuest/types/shared/equipment-enum.d.ts +22 -16
  102. package/bundle/typescript/src/commands/game/sideQuest/types/shared/equipment-enum.js +22 -16
  103. package/bundle/typescript/src/commands/game/sideQuest/types/shared/equipment-enum.js.map +1 -1
  104. package/bundle/typescript/src/commands/game/sideQuest/ui.js +2 -2
  105. package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
  106. package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.js +13 -8
  107. package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.js.map +1 -1
  108. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.d.ts +1 -1
  109. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.js +8 -7
  110. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.js.map +1 -1
  111. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js +61 -16
  112. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js.map +1 -1
  113. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.d.ts +23 -0
  114. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.js +111 -11
  115. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.js.map +1 -1
  116. package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.d.ts +5 -1
  117. package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.js +5 -27
  118. package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.js.map +1 -1
  119. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-reach.js +2 -1
  120. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-reach.js.map +1 -1
  121. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.d.ts +11 -0
  122. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js +56 -8
  123. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js.map +1 -1
  124. package/bundle/typescript/src/commands/game/sideQuest/utilities/grids.d.ts +72 -0
  125. package/bundle/typescript/src/commands/game/sideQuest/utilities/grids.js +100 -0
  126. package/bundle/typescript/src/commands/game/sideQuest/utilities/grids.js.map +1 -0
  127. package/bundle/typescript/src/commands/game/sideQuest/utilities/harm-note.d.ts +25 -0
  128. package/bundle/typescript/src/commands/game/sideQuest/utilities/harm-note.js +10 -0
  129. package/bundle/typescript/src/commands/game/sideQuest/utilities/harm-note.js.map +1 -0
  130. package/bundle/typescript/src/commands/game/sideQuest/utilities/harm-settlement.d.ts +29 -0
  131. package/bundle/typescript/src/commands/game/sideQuest/utilities/harm-settlement.js +64 -0
  132. package/bundle/typescript/src/commands/game/sideQuest/utilities/harm-settlement.js.map +1 -0
  133. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic-actors.d.ts +9 -0
  134. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic-actors.js +98 -0
  135. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic-actors.js.map +1 -0
  136. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.d.ts +3 -2
  137. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.js +34 -6
  138. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.js.map +1 -1
  139. package/bundle/typescript/src/commands/game/sideQuest/utilities/marks.d.ts +42 -2
  140. package/bundle/typescript/src/commands/game/sideQuest/utilities/marks.js +75 -4
  141. package/bundle/typescript/src/commands/game/sideQuest/utilities/marks.js.map +1 -1
  142. package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-roster.d.ts +62 -0
  143. package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-roster.js +97 -0
  144. package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-roster.js.map +1 -0
  145. package/bundle/typescript/src/commands/game/sideQuest/utilities/overwatch.js +3 -3
  146. package/bundle/typescript/src/commands/game/sideQuest/utilities/overwatch.js.map +1 -1
  147. package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.d.ts +1 -3
  148. package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js +85 -7
  149. package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js.map +1 -1
  150. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.d.ts +10 -0
  151. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +39 -23
  152. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js.map +1 -1
  153. package/bundle/typescript/src/commands/game/sideQuest/utilities/programs.d.ts +16 -0
  154. package/bundle/typescript/src/commands/game/sideQuest/utilities/programs.js +12 -0
  155. package/bundle/typescript/src/commands/game/sideQuest/utilities/programs.js.map +1 -1
  156. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.d.ts +2 -0
  157. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.js +23 -4
  158. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.js.map +1 -1
  159. package/package.json +1 -1
@@ -14,7 +14,47 @@ export declare const MAX_MARKS = 3;
14
14
  /** Everything this placer has marked, gone at once -- their reboot,
15
15
  * jack-out, or GOD convergence (all reboot the persona). */
16
16
  export declare function clearMarksPlacedBy(scene: Scene, placerName: string): void;
17
- /** A target rebooting shakes every mark off itself. */
18
- export declare function clearMarksOn(actor: Player): number;
17
+ /**
18
+ * A target rebooting shakes every mark off itself -- "all of your marks,
19
+ * as well as the ones others may have put on your icon, are erased"
20
+ * (p.242, RAG-checked 2026-09-02). With a scene that is every persona on
21
+ * the PAN ledger AND every host's entry for this persona (web report:
22
+ * after a jack-out the ledger still read "The Circuit Bazaar host x2").
23
+ * Returns how many placers were shaken off.
24
+ */
25
+ export declare function clearMarksOn(actor: Player, scene?: Scene): number;
26
+ /**
27
+ * THE REBOOT, as far as marks go -- one door for every route that reboots
28
+ * the persona: "reboot", jack-out (p.240 reboots the device), a forced
29
+ * dump, GOD's convergence. Both ledgers go (p.242) and the sheet hears it.
30
+ */
31
+ export declare function rebootWipe(scene: Scene, actor: Player): {
32
+ placed: void;
33
+ on: number;
34
+ };
19
35
  /** The placer's standing marks, for the bare "mark" listing. */
20
36
  export declare function describeMarks(scene: Scene, placerName: string): string[];
37
+ /**
38
+ * The marks this persona HOLDS, for the live sheet (contract 2026-09-02,
39
+ * web accepts first): every host and PAN it has marked, named the way
40
+ * describeMarks prints them, count 1..3. Read at beat time, so the reboot
41
+ * clear and convergence show on the next beat with no clear-site wiring.
42
+ * The site caps the list at 24 entries.
43
+ */
44
+ export declare function marksPlaced(scene: Scene, placerName: string): {
45
+ target: string;
46
+ count: number;
47
+ }[];
48
+ /**
49
+ * WHO HOLDS MARKS ON THIS PERSONA, one row each, for the live sheet
50
+ * (contract 2026-09-02). Every host in the scene that MADE the persona --
51
+ * not only the one it stands inside: a host's mark on you outlives your
52
+ * exit and dies with your reboot (p.236 -- marks last the session; the
53
+ * ledger is Host.marksOn, cleared by clearMarksOn). A session log showed
54
+ * three marks across two hosts while the inside-host number could show
55
+ * one host's worth. Plus every persona on the PAN ledger.
56
+ */
57
+ export declare function marksOnYou(scene: Scene, player: Player): {
58
+ placer: string;
59
+ count: number;
60
+ }[];
@@ -27,12 +27,40 @@ export function clearMarksPlacedBy(scene, placerName) {
27
27
  Logger.getInstance().write(`Marks: ${placerName}'s ${cleared} marked icon(s) cleared (persona reboot).`);
28
28
  }
29
29
  }
30
- /** A target rebooting shakes every mark off itself. */
31
- export function clearMarksOn(actor) {
32
- const had = actor.panMarksBy.size;
33
- actor.panMarksBy.clear();
30
+ /**
31
+ * A target rebooting shakes every mark off itself -- "all of your marks,
32
+ * as well as the ones others may have put on your icon, are erased"
33
+ * (p.242, RAG-checked 2026-09-02). With a scene that is every persona on
34
+ * the PAN ledger AND every host's entry for this persona (web report:
35
+ * after a jack-out the ledger still read "The Circuit Bazaar host x2").
36
+ * Returns how many placers were shaken off.
37
+ */
38
+ export function clearMarksOn(actor, scene) {
39
+ // Optional chaining: test stubs stand in for a Player here (link-lock.test.ts).
40
+ let had = [...(actor.panMarksBy?.values() ?? [])].filter(n => n > 0).length;
41
+ actor.panMarksBy?.clear();
42
+ if (scene) {
43
+ for (const room of Object.values(scene.getRooms())) {
44
+ if ((room.host?.marksOn.get(actor.name) ?? 0) > 0)
45
+ had++;
46
+ room.host?.marksOn.delete(actor.name);
47
+ }
48
+ }
34
49
  return had;
35
50
  }
51
+ /**
52
+ * THE REBOOT, as far as marks go -- one door for every route that reboots
53
+ * the persona: "reboot", jack-out (p.240 reboots the device), a forced
54
+ * dump, GOD's convergence. Both ledgers go (p.242) and the sheet hears it.
55
+ */
56
+ export function rebootWipe(scene, actor) {
57
+ const placed = clearMarksPlacedBy(scene, actor.name);
58
+ const on = clearMarksOn(actor, scene);
59
+ if (on > 0)
60
+ Logger.getInstance().write(`Marks: ${on} placer(s) shaken off ${actor.name} (persona reboot).`);
61
+ actor.noteConditionChanged?.();
62
+ return { placed, on };
63
+ }
36
64
  /** The placer's standing marks, for the bare "mark" listing. */
37
65
  export function describeMarks(scene, placerName) {
38
66
  const lines = [];
@@ -48,4 +76,47 @@ export function describeMarks(scene, placerName) {
48
76
  }
49
77
  return lines;
50
78
  }
79
+ /**
80
+ * The marks this persona HOLDS, for the live sheet (contract 2026-09-02,
81
+ * web accepts first): every host and PAN it has marked, named the way
82
+ * describeMarks prints them, count 1..3. Read at beat time, so the reboot
83
+ * clear and convergence show on the next beat with no clear-site wiring.
84
+ * The site caps the list at 24 entries.
85
+ */
86
+ export function marksPlaced(scene, placerName) {
87
+ const out = [];
88
+ for (const room of Object.values(scene.getRooms())) {
89
+ const n = room.hostMarksBy.get(placerName) ?? 0;
90
+ if (n > 0)
91
+ out.push({ target: hostLabel(room, { capital: true }), count: n });
92
+ }
93
+ for (const a of scene.allActors) {
94
+ const n = a.panMarksBy.get(placerName) ?? 0;
95
+ if (n > 0)
96
+ out.push({ target: `${a.name}'s PAN`, count: n });
97
+ }
98
+ return out.slice(0, 24);
99
+ }
100
+ /**
101
+ * WHO HOLDS MARKS ON THIS PERSONA, one row each, for the live sheet
102
+ * (contract 2026-09-02). Every host in the scene that MADE the persona --
103
+ * not only the one it stands inside: a host's mark on you outlives your
104
+ * exit and dies with your reboot (p.236 -- marks last the session; the
105
+ * ledger is Host.marksOn, cleared by clearMarksOn). A session log showed
106
+ * three marks across two hosts while the inside-host number could show
107
+ * one host's worth. Plus every persona on the PAN ledger.
108
+ */
109
+ export function marksOnYou(scene, player) {
110
+ const out = [];
111
+ for (const room of Object.values(scene.getRooms())) {
112
+ const n = room.host?.marksOn.get(player.name) ?? 0;
113
+ if (n > 0)
114
+ out.push({ placer: hostLabel(room, { capital: true }), count: n });
115
+ }
116
+ for (const [placer, count] of player.panMarksBy.entries()) {
117
+ if (count > 0)
118
+ out.push({ placer, count });
119
+ }
120
+ return out.slice(0, 24);
121
+ }
51
122
  //# sourceMappingURL=marks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"marks.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/marks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAE3B;6DAC6D;AAC7D,MAAM,UAAU,kBAAkB,CAAC,KAAY,EAAE,UAAkB;IACjE,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;QACnD,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,OAAO,EAAE,CAAC;IACrD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,OAAO,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,UAAU,UAAU,MAAM,OAAO,2CAA2C,CAAC,CAAC;IAC3G,CAAC;AACH,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;IAClC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACzB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,UAAkB;IAC5D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvJ,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"marks.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/marks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import type { Player } from '../models/player.js';
2
+ import type { Item } from '../models/item.js';
3
+ import type { Room } from '../models/room.js';
4
+ import { NPC } from '../models/npc.js';
5
+ import type { Scene } from '../models/scene.js';
6
+ import type { Host } from '../models/host.js';
7
+ /**
8
+ * WHO A PERSONA CAN REACH (increment 2 of the Matrix position model,
9
+ * 2026-09-02). The persona's position is `Player.matrixPosition` -- on a
10
+ * grid, or inside a Host -- and its body stays in `currentLocation` on
11
+ * every plane. So a persona inside a host is NOT in the host room's
12
+ * actor set any more, and the nine verbs that used to read
13
+ * `getActorsInRoom(room)` + `sameHostSide` for Matrix targets read these
14
+ * instead. One utility, one answer, both sides of the wall (SR5 p.246:
15
+ * inside a host you see and touch only what is inside it; outside, you
16
+ * cannot touch the interior).
17
+ */
18
+ /** The wall test: same host, or both out on a grid, or both off-Matrix (undefined === undefined stays deliberately harmless). */
19
+ export declare function sameMatrixSide(a: Player, b: Player): boolean;
20
+ /** Everyone whose persona is inside this host -- players, ice, sprites, agents. */
21
+ export declare function personasInside(scene: Scene, host: Host): (Player | NPC)[];
22
+ /** Matrix-plane actors on the persona's side of the wall, excluding the persona. */
23
+ export declare function personasOnMySide(scene: Scene, actor: Player): (Player | NPC)[];
24
+ /** Constructs a spike or a decompile can reach: NPC icons on my side, still running. */
25
+ export declare function matrixConstructsInReach(scene: Scene, actor: Player): NPC[];
26
+ /** Cybercombat targets: icons on my side that share the combat plane. */
27
+ export declare function cybercombatCandidates(scene: Scene, actor: Player): (Player | NPC)[];
28
+ /** Who hears a persona speak: every persona on its side of the wall. Bodies hear nothing. */
29
+ export declare function speechAudience(scene: Scene, actor: Player): (Player | NPC)[];
30
+ /** Delivers a persona's words to its audience, the way Room.say delivers a body's. */
31
+ export declare function speakOnTheGrid(scene: Scene, actor: Player, message: string): (Player | NPC)[];
32
+ /**
33
+ * The combat exchange's "same place": on the matrix plane it is the
34
+ * same side of the host wall (distance is noise, not range); in the meat
35
+ * it is the same room, as it always was.
36
+ */
37
+ export declare function samePlace(a: Player, b: Player): boolean;
38
+ /**
39
+ * Sprites and agents ride with their owner's persona: across a host wall
40
+ * on enter/exit, and between grids on a hop. Bodies do not move.
41
+ */
42
+ export declare function movePersonaWith(game: {
43
+ companions: {
44
+ kind: string;
45
+ npc: NPC;
46
+ }[];
47
+ } | undefined, actor: Player): NPC[];
48
+ /**
49
+ * WHERE A NAMED THING IS, when it is not where the persona stands: the
50
+ * first room in reach holding an item by that name, and what stands
51
+ * between the persona and it. 'offline' = an air-gapped server (only a
52
+ * body in that room reaches it, p.233); 'host' = inside a host's vault
53
+ * (enter first, p.246); 'open' = loose on the grid, a dim icon at the
54
+ * noise the distance costs; 'meat' = a physical thing, not an icon.
55
+ */
56
+ export declare function whereIsThat(rooms: Record<string, Room>, actor: Player, name: string): {
57
+ room: Room;
58
+ item: Item;
59
+ reach: 'offline' | 'host' | 'open' | 'meat';
60
+ noise: number;
61
+ remembered: boolean;
62
+ } | undefined;
@@ -0,0 +1,97 @@
1
+ import { roomsInReach } from './grid-reach.js';
2
+ import { NPC } from '../models/npc.js';
3
+ /**
4
+ * WHO A PERSONA CAN REACH (increment 2 of the Matrix position model,
5
+ * 2026-09-02). The persona's position is `Player.matrixPosition` -- on a
6
+ * grid, or inside a Host -- and its body stays in `currentLocation` on
7
+ * every plane. So a persona inside a host is NOT in the host room's
8
+ * actor set any more, and the nine verbs that used to read
9
+ * `getActorsInRoom(room)` + `sameHostSide` for Matrix targets read these
10
+ * instead. One utility, one answer, both sides of the wall (SR5 p.246:
11
+ * inside a host you see and touch only what is inside it; outside, you
12
+ * cannot touch the interior).
13
+ */
14
+ /** The wall test: same host, or both out on a grid, or both off-Matrix (undefined === undefined stays deliberately harmless). */
15
+ export function sameMatrixSide(a, b) {
16
+ return a.hostInside === b.hostInside;
17
+ }
18
+ /** Everyone whose persona is inside this host -- players, ice, sprites, agents. */
19
+ export function personasInside(scene, host) {
20
+ return scene.allActors.filter(a => a.plane === 'matrix' && a.hostInside === host);
21
+ }
22
+ /** Matrix-plane actors on the persona's side of the wall, excluding the persona. */
23
+ export function personasOnMySide(scene, actor) {
24
+ return scene.allActors.filter(a => a !== actor && a.plane === 'matrix' && sameMatrixSide(actor, a));
25
+ }
26
+ /** Constructs a spike or a decompile can reach: NPC icons on my side, still running. */
27
+ export function matrixConstructsInReach(scene, actor) {
28
+ return personasOnMySide(scene, actor).filter((a) => a instanceof NPC && !a.deathClaimed);
29
+ }
30
+ /** Cybercombat targets: icons on my side that share the combat plane. */
31
+ export function cybercombatCandidates(scene, actor) {
32
+ return personasOnMySide(scene, actor).filter(a => a.sharesCombatPlane(actor));
33
+ }
34
+ /** Who hears a persona speak: every persona on its side of the wall. Bodies hear nothing. */
35
+ export function speechAudience(scene, actor) {
36
+ return personasOnMySide(scene, actor);
37
+ }
38
+ /** Delivers a persona's words to its audience, the way Room.say delivers a body's. */
39
+ export function speakOnTheGrid(scene, actor, message) {
40
+ const audience = speechAudience(scene, actor);
41
+ for (const recipient of audience) {
42
+ void Promise.resolve(recipient.hear(actor, message, { broadcast: true })).catch(() => undefined);
43
+ }
44
+ return audience;
45
+ }
46
+ /**
47
+ * The combat exchange's "same place": on the matrix plane it is the
48
+ * same side of the host wall (distance is noise, not range); in the meat
49
+ * it is the same room, as it always was.
50
+ */
51
+ export function samePlace(a, b) {
52
+ if (a.plane === 'matrix' || b.plane === 'matrix') {
53
+ return a.plane === b.plane && sameMatrixSide(a, b);
54
+ }
55
+ return a.currentLocation === b.currentLocation;
56
+ }
57
+ /**
58
+ * Sprites and agents ride with their owner's persona: across a host wall
59
+ * on enter/exit, and between grids on a hop. Bodies do not move.
60
+ */
61
+ export function movePersonaWith(game, actor) {
62
+ const moved = [];
63
+ for (const c of game?.companions ?? []) {
64
+ if ((c.kind === 'sprite' || c.kind === 'agent') && c.npc.plane === 'matrix') {
65
+ c.npc.matrixPosition = actor.matrixPosition;
66
+ moved.push(c.npc);
67
+ }
68
+ }
69
+ return moved;
70
+ }
71
+ /**
72
+ * WHERE A NAMED THING IS, when it is not where the persona stands: the
73
+ * first room in reach holding an item by that name, and what stands
74
+ * between the persona and it. 'offline' = an air-gapped server (only a
75
+ * body in that room reaches it, p.233); 'host' = inside a host's vault
76
+ * (enter first, p.246); 'open' = loose on the grid, a dim icon at the
77
+ * noise the distance costs; 'meat' = a physical thing, not an icon.
78
+ */
79
+ export function whereIsThat(rooms, actor, name) {
80
+ const q = name.trim().toLowerCase();
81
+ for (const { room, noise } of roomsInReach(rooms, actor)) {
82
+ const item = room.inventory.getAllItems().find(i => i.name.toLowerCase() === q)
83
+ ?? room.inventory.getAllItems().find(i => i.name.toLowerCase().includes(q));
84
+ if (!item)
85
+ continue;
86
+ const reach = item.plane !== 'matrix' ? 'meat'
87
+ : room.offlineServer ? 'offline'
88
+ : room.host && !room.host.cracked ? 'host'
89
+ : 'open';
90
+ // A room is named only from MEMORY (p.243: the grid does not give away
91
+ // a device's address): the runner has stood in it, or searched it.
92
+ const remembered = room.visitedBy.has(actor.name) || room.searchedBy.has(actor.name) || room === actor.currentLocation;
93
+ return { room, item, reach, noise, remembered };
94
+ }
95
+ return undefined;
96
+ }
97
+ //# sourceMappingURL=matrix-roster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix-roster.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/matrix-roster.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { Logger } from './logger.js';
2
2
  import { rollPool, formatRoll } from './dice.js';
3
- import { clearMarksPlacedBy } from './marks.js';
3
+ import { rebootWipe } from './marks.js';
4
4
  /**
5
5
  * GOD -- the Grid Overwatch Division (canon p.221/231-232, player go
6
6
  * 2026-08-23). Every illegal Matrix action (Attack or Sleaze) leaves
@@ -102,8 +102,8 @@ function converge(scene, actor) {
102
102
  lines.push(` You shed the hammerblow -- barely.`);
103
103
  }
104
104
  resetOverwatch(actor, 'convergence force-reboot');
105
- // "Erasing all of your marks" (p.231-232) -- now literal.
106
- clearMarksPlacedBy(scene, actor.name);
105
+ // "Erasing all of your marks" (p.231-232) -- and the ones on you (p.242).
106
+ rebootWipe(scene, actor);
107
107
  actor.addNotoriety(`GOD converged on their persona -- location burned to the authorities`);
108
108
  scene.addWorldEvent(`GOD converged on ${actor.name} -- their physical location in ${actor.bodyRoom?.name ?? actor.currentLocation.name} is burned to the authorities.`);
109
109
  // "Reported to the authorities" now MEANS something: the district's
@@ -1 +1 @@
1
- {"version":3,"file":"overwatch.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/overwatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"overwatch.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/overwatch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC;AAC5B,oEAAoE;AACpE,yBAAyB;AACzB,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B,SAAS,EAAE;IACT,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,4EAA4E;AAC5E,SAAS,QAAQ,CAAC,KAAa;IAC7B,IAAI,KAAK,CAAC,cAAc,IAAI,CAAC,IAAI,KAAK,CAAC,iBAAiB,KAAK,CAAC;QAAE,OAAO;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACxG,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,cAAc,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;IACpE,KAAK,CAAC,iBAAiB,IAAI,KAAK,GAAG,OAAO,CAAC;IAC3C,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,cAAc,KAAK,CAAC,IAAI,gBAAgB,KAAK,kBAAkB,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC;AACrH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAY,EAAE,KAAa,EAAE,WAAmB,EAAE,GAAW;IAC3F,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,KAAK,CAAC,iBAAiB,KAAK,CAAC;QAAE,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACxE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;IACpC,KAAK,CAAC,cAAc,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,GAAG,WAAW,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC;IAE9G,IAAI,KAAK,CAAC,cAAc,IAAI,cAAc,EAAE,CAAC;QAC3C,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC5D,CAAC;IACD,mEAAmE;IACnE,uDAAuD;IACvD,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK,CAAC,cAAc,IAAI,EAAE,EAAE,CAAC;QAC9C,OAAO,EAAE,KAAK,EAAE,CAAC,6JAA6J,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACtM,CAAC;IACD,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK,CAAC,cAAc,IAAI,EAAE,EAAE,CAAC;QAC9C,OAAO,EAAE,KAAK,EAAE,CAAC,4IAA4I,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACrL,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACzC,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChB,OAAO,KAAK,CAAC,cAAc,CAAC;AAC9B,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,GAAW;IACvD,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,cAAc,KAAK,CAAC,IAAI,kBAAkB,KAAK,CAAC,cAAc,KAAK,GAAG,IAAI,CAAC,CAAC;IACzG,CAAC;IACD,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC;IACzB,KAAK,CAAC,iBAAiB,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;qEACqE;AACrE,SAAS,QAAQ,CAAC,KAAY,EAAE,KAAa;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,CAAC,yIAAyI,CAAC,CAAC;IAC1J,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,gCAAgC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,IAAI,KAAK,CAAC,OAAO,KAAK,KAAK,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;YACtD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,8CAA8C,KAAK,wBAAwB,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC/G,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,mCAAmC,KAAK,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QACjH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACrD,CAAC;IACD,cAAc,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC;IAClD,0EAA0E;IAC1E,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACzB,KAAK,CAAC,YAAY,CAAC,sEAAsE,CAAC,CAAC;IAC3F,KAAK,CAAC,aAAa,CAAC,oBAAoB,KAAK,CAAC,IAAI,kCAAkC,KAAK,CAAC,QAAQ,EAAE,IAAI,IAAI,KAAK,CAAC,eAAe,CAAC,IAAI,gCAAgC,CAAC,CAAC;IACxK,oEAAoE;IACpE,qEAAqE;IACrE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,sBAAsB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,KAAK,CAAC,IAAI,CAAC,sHAAsH,CAAC,CAAC;IACnI,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -88,9 +88,7 @@ export declare function serializeItem(item: Item): ISavedItem;
88
88
  export declare function restoreItem(json: ISavedItem): Item;
89
89
  type EquipmentShape = Player['equipment'];
90
90
  export declare function serializeEquipment(eq: EquipmentShape): ISavedEquipment;
91
- /** Clears EVERY slot first (an NPC auto-equips at synthesis; the save
92
- * is authoritative), then lays in the saved blobs. */
93
- export declare function restoreEquipment(eq: EquipmentShape, saved: ISavedEquipment): void;
91
+ export declare function restoreEquipment(eq: EquipmentShape, saved: ISavedEquipment, spill?: (item: Item) => void): void;
94
92
  export declare function replaceInventory(inv: Inventory, items: ISavedItem[]): void;
95
93
  export declare function serializePlayer(p: Player): ISavedPlayer;
96
94
  /**
@@ -1,4 +1,5 @@
1
1
  import * as fs from 'fs';
2
+ import { normalizeStance } from '../models/player.js';
2
3
  import { resolveSpot } from './spots.js';
3
4
  import { isAspectKey } from '../aspects.js';
4
5
  import * as path from 'path';
@@ -157,6 +158,8 @@ export function serializeItem(item) {
157
158
  out.quantity = item.quantity;
158
159
  if (item.isFirearm() && item.ammo !== Item.MAGAZINE_CAPACITY)
159
160
  out.ammo = item.ammo;
161
+ if (item.loadedAmmo)
162
+ out.loadedAmmo = item.loadedAmmo;
160
163
  if (item.jammed)
161
164
  out.jammed = true;
162
165
  if (item.deckDamage > 0)
@@ -165,6 +168,12 @@ export function serializeItem(item) {
165
168
  out.droneDamage = item.droneDamage;
166
169
  if (item.loadedPrograms.length > 0)
167
170
  out.loadedPrograms = [...item.loadedPrograms];
171
+ if (item.storedPrograms.length > 0)
172
+ out.storedPrograms = [...item.storedPrograms];
173
+ if (item.papers.length > 0)
174
+ out.papers = item.papers.map(serializeItem);
175
+ if (item.linkedSin)
176
+ out.linkedSin = item.linkedSin;
168
177
  if (item.isCyberdeck() && item.deckOrder.join() !== '0,1,2,3')
169
178
  out.deckOrder = item.deckOrder;
170
179
  return out;
@@ -200,6 +209,8 @@ export function restoreItem(json) {
200
209
  item.quantity = json.quantity;
201
210
  if (json.ammo !== undefined)
202
211
  item.ammo = json.ammo;
212
+ if (json.loadedAmmo)
213
+ item.loadedAmmo = json.loadedAmmo;
203
214
  if (json.jammed)
204
215
  item.jammed = true;
205
216
  if (json.deckDamage)
@@ -208,6 +219,16 @@ export function restoreItem(json) {
208
219
  item.takeDroneDamage(json.droneDamage);
209
220
  if (json.loadedPrograms)
210
221
  item.loadedPrograms = [...json.loadedPrograms];
222
+ if (json.storedPrograms)
223
+ item.storedPrograms = [...json.storedPrograms];
224
+ if (json.papers)
225
+ item.papers = json.papers.map(restoreItem);
226
+ if (json.linkedSin)
227
+ item.linkedSin = json.linkedSin;
228
+ // A running program is in storage by definition -- saves from before
229
+ // storage existed carried only the running set.
230
+ for (const k of item.loadedPrograms)
231
+ item.installProgram(k);
211
232
  if (json.deckOrder)
212
233
  item.configureDeck(json.deckOrder);
213
234
  return item;
@@ -226,7 +247,27 @@ export function serializeEquipment(eq) {
226
247
  }
227
248
  /** Clears EVERY slot first (an NPC auto-equips at synthesis; the save
228
249
  * is authoritative), then lays in the saved blobs. */
229
- export function restoreEquipment(eq, saved) {
250
+ /**
251
+ * The paired slots collapsed to one per region on 2026-09-02 (canon has no
252
+ * sides). A save from before carries the old keys; each lands on the new
253
+ * slot, and a second item for the same region goes to the bag via `spill`
254
+ * rather than to nowhere.
255
+ */
256
+ /** The three skillsoft rows pulled from the shelf on 2026-09-02, at the price they sold for. */
257
+ const SKILLSOFT_REFUNDS = [
258
+ { test: /^Activesoft/i, nuyen: 15000 },
259
+ { test: /^Knowsoft/i, nuyen: 6000 },
260
+ { test: /^Linguasoft/i, nuyen: 3000 },
261
+ ];
262
+ const LEGACY_SLOTS = {
263
+ 'torso.leftShoulder': 'torso.shoulder', 'torso.rightShoulder': 'torso.shoulder',
264
+ 'legs.leftHip': 'legs.hip', 'legs.rightHip': 'legs.hip',
265
+ 'feet.leftAnkle': 'feet.ankle', 'feet.rightAnkle': 'feet.ankle',
266
+ 'arms.leftForearm': 'arms.forearm', 'arms.rightForearm': 'arms.forearm',
267
+ 'arms.leftBicept': 'arms.bicep', 'arms.rightBicept': 'arms.bicep',
268
+ 'gloves.leftWrist': 'gloves.wrist', 'gloves.rightWrist': 'gloves.wrist',
269
+ };
270
+ export function restoreEquipment(eq, saved, spill) {
230
271
  for (const group of Object.values(eq)) {
231
272
  if (!group)
232
273
  continue;
@@ -237,13 +278,23 @@ export function restoreEquipment(eq, saved) {
237
278
  for (const [pathKey, savedItem] of Object.entries(saved)) {
238
279
  if (!savedItem)
239
280
  continue;
240
- const [groupKey, slotKey] = pathKey.split('.');
281
+ let key = LEGACY_SLOTS[pathKey] ?? pathKey;
282
+ // A pair of gloves used to sit on the wrist; it has its own slot now.
283
+ if (key === 'gloves.wrist' && savedItem.category === 'Gloves')
284
+ key = 'gloves.gloves';
285
+ const [groupKey, slotKey] = key.split('.');
241
286
  const group = eq[groupKey];
242
287
  if (!group || !(slotKey in group)) {
243
288
  Logger.getInstance().write(`restoreEquipment: unknown slot "${pathKey}" -- item "${savedItem.name}" dropped to nowhere, skipping.`);
244
289
  continue;
245
290
  }
246
- group[slotKey] = restoreItem(savedItem);
291
+ const item = restoreItem(savedItem);
292
+ if (group[slotKey]) {
293
+ Logger.getInstance().write(`restoreEquipment: "${item.name}" (${pathKey}) -- ${key} already holds ${group[slotKey].name}; ${spill ? 'bagged' : 'dropped'}.`);
294
+ spill?.(item);
295
+ continue;
296
+ }
297
+ group[slotKey] = item;
247
298
  }
248
299
  }
249
300
  export function replaceInventory(inv, items) {
@@ -287,6 +338,7 @@ export function serializePlayer(p) {
287
338
  augmentations: [...p.augmentations],
288
339
  augmentationGrades: [...p.augGrades.entries()],
289
340
  qualities: [...p.qualities],
341
+ qualityRatings: [...p.qualityRatings.entries()],
290
342
  activeSin: p.activeSin,
291
343
  metamagics: [...p.metamagics],
292
344
  initiationGrade: p.initiationGrade,
@@ -318,8 +370,11 @@ export function serializePlayer(p) {
318
370
  */
319
371
  export function restorePlayer(p, s) {
320
372
  const logger = Logger.getInstance();
373
+ // Ratings ride beside the keys (contract 2026-09-02); a legacy "<key>-1"
374
+ // resolves inside addQuality to the rated key at 1.
375
+ const ratings = new Map(s.qualityRatings ?? []);
321
376
  for (const q of s.qualities)
322
- p.addQuality(q);
377
+ p.addQuality(q, ratings.get(q));
323
378
  p.activeSin = s.activeSin;
324
379
  p.baseMagic = s.baseMagic;
325
380
  p.baseResonance = s.baseResonance;
@@ -459,7 +514,7 @@ export function restorePlayer(p, s) {
459
514
  p.sleepStreak = s.needs.sleepStreak;
460
515
  p.edgeRemaining = s.edgeRemaining;
461
516
  p.haggledThisJob = s.haggledThisJob;
462
- p.autoStance = s.autoStance;
517
+ p.autoStance = normalizeStance(s.autoStance);
463
518
  if (s.archetypeName)
464
519
  p.archetypeName = s.archetypeName;
465
520
  if (s.gender)
@@ -470,7 +525,30 @@ export function restorePlayer(p, s) {
470
525
  for (const name of s.visitedRooms ?? [])
471
526
  p.visitedRooms.add(name);
472
527
  replaceInventory(p.inventory, s.inventory);
473
- restoreEquipment(p.equipment, s.equipment);
528
+ // PROGRAMS LIVE ON THE DECK (p.227; 2026-09-02): a save from before
529
+ // carried its library as loose chips. They move into the carried deck
530
+ // here, once, and the log says how many.
531
+ // SKILLSOFTS BOUGHT BEFORE THE SHELF WAS FIXED are refunded at the price
532
+ // paid: nothing in the engine could ever run them (catalog-data.ts note).
533
+ for (const chip of [...p.inventory.getAllItems()]) {
534
+ const refund = SKILLSOFT_REFUNDS.find(r => chip.category === Category.Software && r.test.test(chip.name));
535
+ if (!refund)
536
+ continue;
537
+ p.inventory.removeItem(chip.name);
538
+ p.adjustCurrency(refund.nuyen);
539
+ Logger.getInstance().write(`restorePlayer: ${chip.name} refunded (${refund.nuyen} nuyen) -- no skillwires or skilljack exist to run it.`);
540
+ }
541
+ // PAPERS LIVE ON THE COMMLINK (p.443; 2026-09-02): a save from before
542
+ // carried fake SINs and licenses loose in the pack. They move onto the
543
+ // carried commlink (or deck) here, once; a loose license links to the
544
+ // best fake SIN, and the log says what moved.
545
+ const papers = p.sweepPapersOntoDevice();
546
+ if (papers > 0)
547
+ Logger.getInstance().write(`restorePlayer: ${papers} paper(s) moved onto ${p.paperDevice()?.name ?? 'the device'} (papers live on the commlink now).`);
548
+ const swept = p.sweepProgramChipsIntoDeck();
549
+ if (swept > 0)
550
+ Logger.getInstance().write(`restorePlayer: ${swept} program chip(s) installed into ${p.getAnyCyberdeck()?.name ?? 'the deck'} (programs live in deck storage now).`);
551
+ restoreEquipment(p.equipment, s.equipment, item => p.addInventory(item));
474
552
  }
475
553
  // ============================= Hub world =============================
476
554
  function serializeRoomOverlay(room, player) {
@@ -669,7 +747,7 @@ export function applyHubOverlay(scene, saved, player, homeRoom) {
669
747
  npc.setObjective(overlay.objective);
670
748
  npc.restoreHistory(overlay.history);
671
749
  replaceInventory(npc.inventory, overlay.inventory);
672
- restoreEquipment(npc.equipment, overlay.equipment);
750
+ restoreEquipment(npc.equipment, overlay.equipment, item => npc.inventory.addItem(item));
673
751
  }
674
752
  // 4. Devices: the one flag -- door lock state was restored in step 2,
675
753
  // so a door relocked after its device opened stays relocked.