@maka/maka-cli 5.77.0 → 5.79.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.
- package/bundle/typescript/package.json +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js +8 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js +8 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/climb.js +9 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/climb.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.js +14 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/jack.d.ts +19 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js +68 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +9 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.js +9 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.d.ts +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.js +11 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +20 -0
- package/bundle/typescript/src/commands/game/sideQuest/game.js +87 -3
- package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/headless.js +0 -3
- package/bundle/typescript/src/commands/game/sideQuest/headless.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +33 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js +42 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/room.d.ts +18 -7
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js +37 -7
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.d.ts +180 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.js +534 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.d.ts +34 -4
- package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +78 -47
- package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/repro-launch.js +30 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/repro-launch.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.d.ts +31 -28
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js +59 -32
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.d.ts +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +14 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js.map +1 -1
- package/bundle/typescript/src/tools/sdk-loader/runtime-fetch.d.ts +24 -2
- package/bundle/typescript/src/tools/sdk-loader/runtime-fetch.js +87 -4
- package/bundle/typescript/src/tools/sdk-loader/runtime-fetch.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
import { rollPool, formatRoll } from './dice.js';
|
|
2
|
+
import { MAX_MARKS } from './marks.js';
|
|
3
|
+
/**
|
|
4
|
+
* INTRUSION COUNTERMEASURES -- the host's side of the roll (SR5 p.247-248).
|
|
5
|
+
*
|
|
6
|
+
* This closes the standing note on Room.hostAttributes(): "the only
|
|
7
|
+
* mechanical use SR5 gives a Host Rating is IC rolling Host Rating x 2
|
|
8
|
+
* (p.247-248), and this engine has no IC -- `hostAlert` is a flag and
|
|
9
|
+
* 'ice hunting' is prose; nothing rolls on the host's side anywhere."
|
|
10
|
+
* A host now rolls. hostRating is no longer read by nothing.
|
|
11
|
+
*
|
|
12
|
+
* PHASE 1 SHIPS TWO TYPES: Patrol and Probe. The other ten citable types
|
|
13
|
+
* (Killer, Sparky, Black, Blaster, Acid, Binder, Jammer, Marker,
|
|
14
|
+
* Scramble, Track) land in later phases, and are deliberately ABSENT
|
|
15
|
+
* from the table below rather than present-and-inert -- a host must not
|
|
16
|
+
* advertise ice it cannot run, which is the same rule
|
|
17
|
+
* commands/advertised-verbs.test.ts enforces for verbs.
|
|
18
|
+
*
|
|
19
|
+
* TAR BABY and CRASH IC ARE LEFT OUT ON PURPOSE, and this is a canon
|
|
20
|
+
* statement rather than a backlog note: they appear in published host
|
|
21
|
+
* lists (False Flag p.31-32, p.37-38; Data Trails p.100) but the
|
|
22
|
+
* rulebooks give no mechanics for either. Three differently-phrased
|
|
23
|
+
* retrievals found none. Data Trails p.56-57 describes a "Tarball"
|
|
24
|
+
* CYBERPROGRAM -- a decker's program, not the IC -- and reaching for it
|
|
25
|
+
* would be inventing an ability, which CLAUDE.md rates worse than a
|
|
26
|
+
* missing one. If a page turns up, they are a table row each.
|
|
27
|
+
*/
|
|
28
|
+
/** What the host rolls, for every IC that attacks: Host Rating x 2,
|
|
29
|
+
* LIMITED by the host's Attack (p.247-248). The bracket is a cap on
|
|
30
|
+
* hits and never a die in the pool -- see dice.ts. */
|
|
31
|
+
export function icAttackPool(room) {
|
|
32
|
+
return { pool: room.hostRating * 2, limit: room.hostAttributes().attack };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The target's defence against an attacking IC: INTUITION + FIREWALL
|
|
36
|
+
* (p.248, named identically on Black, Killer and Probe).
|
|
37
|
+
*
|
|
38
|
+
* Built from Player.panDefence()'s components rather than its total, on
|
|
39
|
+
* purpose. That method's `silent`/`scrub`/`sneak` terms exist because a
|
|
40
|
+
* hidden PAN must be FOUND before it can be hit; IC inside the host has
|
|
41
|
+
* already found you -- it is attacking, not searching -- and canon
|
|
42
|
+
* writes this defence as the two attributes flat. Taking the total would
|
|
43
|
+
* hand the defender up to +5 dice the book does not give them.
|
|
44
|
+
*
|
|
45
|
+
* Reusing the components keeps the technomancer rule (a living persona's
|
|
46
|
+
* Firewall is Willpower, p.251) and the correction that Firewall is a
|
|
47
|
+
* WHOLE attribute here, both of which panDefence already carries.
|
|
48
|
+
*/
|
|
49
|
+
export function icDefencePool(actor) {
|
|
50
|
+
const d = actor.panDefence('sleaze');
|
|
51
|
+
return Math.max(0, d.attribute + d.firewall);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* HOW OFTEN PATROL LOOKS, before it suspects anyone (Data Trails p.86).
|
|
55
|
+
* The interval is in Combat Turns and is rolled fresh each time.
|
|
56
|
+
*
|
|
57
|
+
* CANON'S TABLE STARTS AT RATING 3. Ratings 1-2 exist (p.247 rates hosts
|
|
58
|
+
* 1-12) and the interval table simply does not cover them. Rather than
|
|
59
|
+
* invent a sixth band this takes the nearest published one, and says so:
|
|
60
|
+
* an ENGINE DECISION extending 3-4 downward, not a citation. The
|
|
61
|
+
* alternative -- a rating-1 host that never patrols at all -- would be
|
|
62
|
+
* inventing a rule too, and a more surprising one.
|
|
63
|
+
*/
|
|
64
|
+
const PATROL_INTERVAL = [
|
|
65
|
+
{ maxRating: 2, dice: 1, plus: 0 }, // engine decision -- see above
|
|
66
|
+
{ maxRating: 4, dice: 1, plus: 0 },
|
|
67
|
+
{ maxRating: 6, dice: 1, plus: 2 },
|
|
68
|
+
{ maxRating: 8, dice: 2, plus: 0 },
|
|
69
|
+
{ maxRating: 10, dice: 2, plus: 2 },
|
|
70
|
+
{ maxRating: 12, dice: 3, plus: 0 },
|
|
71
|
+
];
|
|
72
|
+
/** A fresh interval in Combat Turns for this host's next sweep. */
|
|
73
|
+
export function rollPatrolInterval(hostRating) {
|
|
74
|
+
const band = PATROL_INTERVAL.find(b => hostRating <= b.maxRating)
|
|
75
|
+
?? PATROL_INTERVAL[PATROL_INTERVAL.length - 1];
|
|
76
|
+
// rollPool's faces, so the audited roller stays the only place dice
|
|
77
|
+
// are made. Hits are irrelevant here; the pips are the interval.
|
|
78
|
+
const faces = rollPool(band.dice).rolls.reduce((a, b) => a + b, 0);
|
|
79
|
+
return Math.max(1, faces + band.plus);
|
|
80
|
+
}
|
|
81
|
+
/** How the reducers name the attribute they are eating, for the log. */
|
|
82
|
+
const ATTR_LABEL = {
|
|
83
|
+
attack: 'Attack', sleaze: 'Sleaze', dataProcessing: 'Data Processing', firewall: 'Firewall',
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* LAUNCH ORDER. Canon fixes the RATE (one per Combat Turn) and the CAPS
|
|
87
|
+
* (up to Host Rating running; never two of one type) but says nothing
|
|
88
|
+
* about which program a host reaches for first. Patrol leads here for a
|
|
89
|
+
* reason canon does give: "most hosts have Patrol IC running at all
|
|
90
|
+
* times" (p.248), so on any host that has noticed you, Patrol is the one
|
|
91
|
+
* already up rather than one it had to launch.
|
|
92
|
+
*/
|
|
93
|
+
export const IC_TYPES = [
|
|
94
|
+
{ name: 'Patrol IC', kind: 'patrol', attacks: false, hurtByFailure: false },
|
|
95
|
+
{ name: 'Probe IC', kind: 'probe', attacks: true, hurtByFailure: true },
|
|
96
|
+
{ name: 'Killer IC', kind: 'damage', attacks: true, hurtByFailure: true },
|
|
97
|
+
// "Psycho Killer" -- an upgraded Killer, same damage line plus
|
|
98
|
+
// biofeedback (p.248).
|
|
99
|
+
{ name: 'Sparky IC', kind: 'damage', attacks: true, hurtByFailure: true, biofeedback: true },
|
|
100
|
+
// "Also known as Grey IC" -- biofeedback that can only ever be Stun,
|
|
101
|
+
// plus a link-lock (p.248).
|
|
102
|
+
{ name: 'Blaster IC', kind: 'damage', attacks: true, hurtByFailure: true, biofeedback: true, stunOnly: true, linkLock: true },
|
|
103
|
+
// The nastiest thing on the table: full biofeedback AND a link-lock,
|
|
104
|
+
// so it hurts you and holds you there to keep doing it (p.248).
|
|
105
|
+
{ name: 'Black IC', kind: 'damage', attacks: true, hurtByFailure: true, biofeedback: true, linkLock: true },
|
|
106
|
+
// THE FOUR REDUCERS -- one mechanic, four rows. Each eats a different
|
|
107
|
+
// Matrix attribute by 1 per successful attack, cumulatively, until you
|
|
108
|
+
// reboot; once that attribute is at 0 they deal 1 DV per net hit
|
|
109
|
+
// instead (p.248).
|
|
110
|
+
{ name: 'Acid IC', kind: 'reducer', attacks: true, hurtByFailure: true, reduces: 'firewall' },
|
|
111
|
+
{ name: 'Binder IC', kind: 'reducer', attacks: true, hurtByFailure: true, reduces: 'dataProcessing' },
|
|
112
|
+
{ name: 'Jammer IC', kind: 'reducer', attacks: true, hurtByFailure: true, reduces: 'attack' },
|
|
113
|
+
{ name: 'Marker IC', kind: 'reducer', attacks: true, hurtByFailure: true, reduces: 'sleaze' },
|
|
114
|
+
// THE TWO CONDITIONALS -- they do nothing at all until the host has
|
|
115
|
+
// collected enough marks, which is what Probe IC is for.
|
|
116
|
+
{ name: 'Track IC', kind: 'track', attacks: true, hurtByFailure: true, marksNeeded: 2 },
|
|
117
|
+
{ name: 'Scramble IC', kind: 'scramble', attacks: true, hurtByFailure: true, marksNeeded: 3 },
|
|
118
|
+
];
|
|
119
|
+
const empty = () => ({ lines: [], meta: [], world: [] });
|
|
120
|
+
/**
|
|
121
|
+
* Does this host act at all this turn?
|
|
122
|
+
*
|
|
123
|
+
* `hostAlert` IS canon's launch condition, already set in the right
|
|
124
|
+
* place: hack.ts sets it exactly when a blown sleaze gets the intruder
|
|
125
|
+
* MADE, which is p.247's "the host launches IC when it notices someone
|
|
126
|
+
* doing something unauthorized". No new trigger is invented here -- the
|
|
127
|
+
* world event hack.ts already prints promises "ice hunting", and this is
|
|
128
|
+
* the code that finally pays that promise.
|
|
129
|
+
*
|
|
130
|
+
* A CRACKED HOST STOPS: room.ts documents cracking as mooting the alert,
|
|
131
|
+
* and a host whose security "hangs in shreds" fielding fresh ice would
|
|
132
|
+
* contradict the line the player was already given.
|
|
133
|
+
*/
|
|
134
|
+
export function hostIsHunting(room, actor) {
|
|
135
|
+
return actor.plane === 'matrix'
|
|
136
|
+
&& room.hasNode
|
|
137
|
+
&& room.hostAlert
|
|
138
|
+
&& !room.hostCracked;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* IS THIS PERSONA A LEGITIMATE USER? (p.248, Patrol.)
|
|
142
|
+
*
|
|
143
|
+
* Marks are what tell a host you belong -- Patrol's own entry is where
|
|
144
|
+
* the rules tie marks to being a legitimate user, and hack.ts already
|
|
145
|
+
* says the same thing from the other side ("enough marks and the host
|
|
146
|
+
* thinks they belong"). So a persona holding at least one mark on this
|
|
147
|
+
* host is not what Patrol is hunting for, and the `mark` verb finally
|
|
148
|
+
* buys something defensive rather than only softening a later crack.
|
|
149
|
+
*/
|
|
150
|
+
export function looksLegitimate(room, actor) {
|
|
151
|
+
return (room.hostMarksBy.get(actor.name) ?? 0) > 0;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* AMBIENT PATROL -- the host's own eyes, before anyone has been made.
|
|
155
|
+
*
|
|
156
|
+
* This is the half of Patrol IC that Phase 1 could not reach, and
|
|
157
|
+
* without it the ice was very nearly unreachable: the only way to wake
|
|
158
|
+
* it was to fail a sleaze, and against a flat threshold of 2 a competent
|
|
159
|
+
* decker essentially never does. Measured on the Phase 1 build: twelve
|
|
160
|
+
* runs, twelve cracked hosts, zero sightings. Canon puts the detection
|
|
161
|
+
* on the host (p.248: "most hosts have Patrol IC running at all times",
|
|
162
|
+
* and it is the program that hunts illegal activity), so a Patrol that
|
|
163
|
+
* only ran AFTER you were spotted was a partial implementation of the
|
|
164
|
+
* one program whose whole job is spotting.
|
|
165
|
+
*
|
|
166
|
+
* WHAT IT ROLLS. Canon does not print Patrol's dice pool, and this says
|
|
167
|
+
* so rather than pretending: the pool is the general IC rule (Host
|
|
168
|
+
* Rating x 2, p.247) and the bracket is the one the Matrix Perception
|
|
169
|
+
* action carries ([Data Processing], p.241). Both halves are cited; the
|
|
170
|
+
* combination is the engine's, because the book never spells it out.
|
|
171
|
+
*
|
|
172
|
+
* WHAT IT TAKES TO BE SEEN, which canon IS explicit about (p.235): an
|
|
173
|
+
* icon that is not running silent is spotted AUTOMATICALLY, with no test
|
|
174
|
+
* at all. Running silent turns it into an Opposed test against Logic +
|
|
175
|
+
* Sleaze (p.236/241), and a tie goes to the hider.
|
|
176
|
+
*/
|
|
177
|
+
export function ambientPatrol(room, actor) {
|
|
178
|
+
const out = empty();
|
|
179
|
+
if (actor.plane !== 'matrix' || !room.hasNode)
|
|
180
|
+
return out;
|
|
181
|
+
// Already made, or already open: Phase 1's turn owns those.
|
|
182
|
+
if (room.hostAlert || room.hostCracked)
|
|
183
|
+
return out;
|
|
184
|
+
if (looksLegitimate(room, actor))
|
|
185
|
+
return out;
|
|
186
|
+
// The sweep is on a clock (Data Trails p.86) -- it is not looking
|
|
187
|
+
// every single moment until it has reason to.
|
|
188
|
+
const due = (room.patrolCountdown ?? rollPatrolInterval(room.hostRating)) - 1;
|
|
189
|
+
if (due > 0) {
|
|
190
|
+
room.patrolCountdown = due;
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
193
|
+
room.patrolCountdown = rollPatrolInterval(room.hostRating);
|
|
194
|
+
let spotted;
|
|
195
|
+
if (!actor.runningSilent) {
|
|
196
|
+
// p.235: no test. A visible icon in the host is simply seen.
|
|
197
|
+
spotted = true;
|
|
198
|
+
out.meta.push(`Patrol IC -- sweep: icon not running silent, spotted automatically (no test, p.235)`);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
const look = rollPool(room.hostRating * 2, room.hostAttributes().dataProcessing);
|
|
202
|
+
const hide = rollPool(actor.logic + actor.matrixAttribute('sleaze'));
|
|
203
|
+
// p.236: a tie goes to the hider.
|
|
204
|
+
spotted = look.hits > hide.hits;
|
|
205
|
+
out.meta.push(`Patrol IC -- Matrix Perception (Host Rating x2 [Data Processing]): ${formatRoll(look)} v. Logic + Sleaze: ${formatRoll(hide)}`);
|
|
206
|
+
}
|
|
207
|
+
if (!spotted) {
|
|
208
|
+
out.lines.push(` Something quarters the datastream around you and moves on. Your silence held.`);
|
|
209
|
+
return out;
|
|
210
|
+
}
|
|
211
|
+
room.hostAlert = true;
|
|
212
|
+
actor.sneaking = false;
|
|
213
|
+
out.lines.push(` {red-fg}Patrol IC finds you -- an unmarked icon where none should be. The host knows it has an intruder.{/red-fg}`);
|
|
214
|
+
out.world.push(`${room.name}'s Patrol IC made ${actor.name} on a routine sweep -- alarm flagged, ice hunting.`);
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* THE HOST'S WHOLE TURN: its eyes if it has not made you, its ice if it
|
|
219
|
+
* has. One entry point, so the caller never has to know which half of
|
|
220
|
+
* the host is awake.
|
|
221
|
+
*/
|
|
222
|
+
export function runHostTurn(room, actor) {
|
|
223
|
+
if (hostIsHunting(room, actor))
|
|
224
|
+
return runICTurn(room, actor);
|
|
225
|
+
return ambientPatrol(room, actor);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* ONE COMBAT TURN of the host's ice.
|
|
229
|
+
*
|
|
230
|
+
* THE TURN MAPPING IS AN ENGINE MAPPING, NOT A RULE, and is labelled so
|
|
231
|
+
* deliberately. Canon paces IC in Combat Turns -- one program launched
|
|
232
|
+
* per turn, at the beginning of it. sideQuest has no Matrix initiative
|
|
233
|
+
* structure to hang that on, so ONE PLAYER ACTION TAKEN INSIDE AN
|
|
234
|
+
* ALERTED HOST counts as one Combat Turn. That is the closest structural
|
|
235
|
+
* analogue available; it is not something the book says, and it is not
|
|
236
|
+
* dressed up as a citation.
|
|
237
|
+
*/
|
|
238
|
+
export function runICTurn(room, actor) {
|
|
239
|
+
if (!hostIsHunting(room, actor))
|
|
240
|
+
return empty();
|
|
241
|
+
const out = empty();
|
|
242
|
+
// LAUNCH: one program per Combat Turn (p.247), up to (Host Rating)
|
|
243
|
+
// running at once, and never more than one of each type.
|
|
244
|
+
if (room.runningIC.length < room.hostRating) {
|
|
245
|
+
const next = IC_TYPES.find(t => !room.runningIC.includes(t.name));
|
|
246
|
+
if (next) {
|
|
247
|
+
room.runningIC.push(next.name);
|
|
248
|
+
out.lines.push(next.kind === 'patrol'
|
|
249
|
+
? ` {red-fg}${next.name} is already walking the host -- it never had to be launched.{/red-fg}`
|
|
250
|
+
: ` {red-fg}The host launches ${next.name}.{/red-fg}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Every running program acts. An IC attack is a Complex Action
|
|
254
|
+
// (p.247), which is one program's whole turn.
|
|
255
|
+
for (const name of room.runningIC) {
|
|
256
|
+
const type = IC_TYPES.find(t => t.name === name);
|
|
257
|
+
if (!type)
|
|
258
|
+
continue;
|
|
259
|
+
if (type.kind === 'patrol')
|
|
260
|
+
patrolActs(room, actor, out);
|
|
261
|
+
else if (type.kind === 'probe')
|
|
262
|
+
probeActs(room, actor, out);
|
|
263
|
+
else if (type.kind === 'damage')
|
|
264
|
+
damageActs(room, actor, type, out);
|
|
265
|
+
else
|
|
266
|
+
reducerOrConditionalActs(room, actor, type, out);
|
|
267
|
+
}
|
|
268
|
+
return out;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* The opposed attack every attacking IC makes: Host Rating x 2 [Attack]
|
|
272
|
+
* v. Intuition + Firewall (p.248). Returns the net hits; 0 or less is a
|
|
273
|
+
* miss. Shared so the four reducers, Track and Scramble cannot drift
|
|
274
|
+
* from Killer's version of the same roll.
|
|
275
|
+
*/
|
|
276
|
+
function icAttack(room, actor, type, out) {
|
|
277
|
+
const { pool, limit } = icAttackPool(room);
|
|
278
|
+
const attack = rollPool(pool, limit);
|
|
279
|
+
const defence = rollPool(icDefencePool(actor));
|
|
280
|
+
const net = attack.hits - defence.hits;
|
|
281
|
+
out.meta.push(`${type.name} -- Host Rating x2 [Attack ${limit}]: ${formatRoll(attack)} v. Intuition + Firewall: ${formatRoll(defence)} (net ${net})`);
|
|
282
|
+
return net;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* ACID / BINDER / JAMMER / MARKER, and the two mark-gated programs.
|
|
286
|
+
*
|
|
287
|
+
* THE FOUR REDUCERS ARE ONE MECHANIC (p.248), written four times in the
|
|
288
|
+
* book with a different attribute each: "when it gets 1 or more net hits
|
|
289
|
+
* on its attack, it reduces your (attribute) by 1. If your (attribute)
|
|
290
|
+
* has been reduced to 0 already, it causes 1 DV Matrix damage per net
|
|
291
|
+
* hit on the attack. The reduction is cumulative and lasts until you
|
|
292
|
+
* reboot the targeted device." So this is a table with four rows rather
|
|
293
|
+
* than four functions -- and a uniform approximation would have been a
|
|
294
|
+
* deviation, but a uniform RULE is just the rule.
|
|
295
|
+
*
|
|
296
|
+
* The reduction bites through Player.matrixAttribute, which is the one
|
|
297
|
+
* place all four are read -- so Acid really does thin your defence pool
|
|
298
|
+
* against the next IC, and Jammer really does lower the ceiling on your
|
|
299
|
+
* own Brute Force.
|
|
300
|
+
*/
|
|
301
|
+
function reducerOrConditionalActs(room, actor, type, out) {
|
|
302
|
+
const net = icAttack(room, actor, type, out);
|
|
303
|
+
if (net <= 0) {
|
|
304
|
+
out.lines.push(` ${type.name} probes at your icon and finds no purchase.`);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (type.kind === 'reducer' && type.reduces) {
|
|
308
|
+
const attr = type.reduces;
|
|
309
|
+
const label = ATTR_LABEL[attr];
|
|
310
|
+
if (actor.matrixAttribute(attr) > 0) {
|
|
311
|
+
actor.matrixAttrLoss[attr] += 1;
|
|
312
|
+
out.lines.push(` {red-fg}${type.name} eats into your ${label} -- down to ${actor.matrixAttribute(attr)} until you reboot.{/red-fg}`);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
// AT ZERO IT STOPS REDUCING AND STARTS BURNING: 1 DV per net hit.
|
|
316
|
+
const soak = rollPool(actor.getSoakPool());
|
|
317
|
+
const dealt = Math.max(0, net - soak.hits);
|
|
318
|
+
out.meta.push(`${type.name} -- ${label} already 0, ${net} DV v. Device Rating + Firewall: ${formatRoll(soak)} -> ${dealt}`);
|
|
319
|
+
if (dealt <= 0) {
|
|
320
|
+
out.lines.push(` {red-fg}${type.name} claws at a ${label} that is already gone, and finds nothing left to take.{/red-fg}`);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
applyMatrixDamage(actor, dealt, type, out);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
// MARK-GATED. Both check what the HOST holds on you -- the counter
|
|
327
|
+
// Probe IC spends its turns building, which is why a host fields Probe
|
|
328
|
+
// alongside these rather than instead of them.
|
|
329
|
+
const marks = room.hostMarksOn.get(actor.name) ?? 0;
|
|
330
|
+
const needed = type.marksNeeded ?? 0;
|
|
331
|
+
if (marks < needed) {
|
|
332
|
+
out.lines.push(` ${type.name} closes on you and cannot get a grip -- it needs ${needed} mark${needed === 1 ? '' : 's'} on you and the host has ${marks}.`);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (type.kind === 'track') {
|
|
336
|
+
// p.249: "the host (and its owners) discover your physical location,
|
|
337
|
+
// which is usually reported to real-world authorities immediately."
|
|
338
|
+
out.lines.push(` {red-fg}${type.name} rides your datastream back to the meat. They have your PHYSICAL LOCATION -- and that goes straight to the authorities.{/red-fg}`);
|
|
339
|
+
out.world.push(`${room.name}'s Track IC pinned ${actor.name}'s real-world location and called it in.`);
|
|
340
|
+
out.traced = true;
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
// SCRAMBLE (p.248): "if the host has three marks on you when this IC
|
|
344
|
+
// hits you, you reboot immediately, taking dumpshock if you were in
|
|
345
|
+
// VR." Reported, not performed -- leaveMatrix needs the Scene.
|
|
346
|
+
out.lines.push(` {red-fg}${type.name} nukes your connection outright --{/red-fg}`);
|
|
347
|
+
out.world.push(`${room.name}'s Scramble IC force-rebooted ${actor.name}.`);
|
|
348
|
+
out.scrambled = true;
|
|
349
|
+
}
|
|
350
|
+
/** Matrix damage onto the right track: the deck, or a technomancer's
|
|
351
|
+
* own head (p.229). Shared by the damage IC and the reducers-at-zero. */
|
|
352
|
+
function applyMatrixDamage(actor, dealt, type, out) {
|
|
353
|
+
if (actor.isTechnomancer()) {
|
|
354
|
+
actor.takeStun(dealt);
|
|
355
|
+
out.lines.push(` {red-fg}${type.name} tears through your living persona -- ${dealt} stun: ${actor.stunSummary()}{/red-fg}`);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
actor.takeMatrixDamage(dealt);
|
|
359
|
+
out.lines.push(` {red-fg}${type.name} burns ${dealt} box${dealt === 1 ? '' : 'es'} off your deck: ${actor.matrixSummary()}{/red-fg}`);
|
|
360
|
+
if (actor.matrixCrashed) {
|
|
361
|
+
out.lines.push(` {red-fg}The deck BRICKS under it --{/red-fg}`);
|
|
362
|
+
out.bricked = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* KILLER IC and SPARKY IC (p.248).
|
|
367
|
+
*
|
|
368
|
+
* Both roll Host Rating x 2 [Attack] v. Intuition + Firewall and deal
|
|
369
|
+
* "(Attack) DV Matrix damage, +1 DV per net hit and +2 DV per mark on
|
|
370
|
+
* the target". Sparky -- "Psycho Killer", an upgraded Killer -- adds
|
|
371
|
+
* biofeedback; Killer does not.
|
|
372
|
+
*
|
|
373
|
+
* THE MARKS IN THE DV ARE THE HOST'S, not the player's: "per mark on the
|
|
374
|
+
* target" is what the host holds ON you, which is hostMarksOn and which
|
|
375
|
+
* Probe IC spends its turns building. That coupling is canon's own, and
|
|
376
|
+
* it is why Probe is worth a slot on a host that also fields a Killer.
|
|
377
|
+
*
|
|
378
|
+
* A FAILED IC ATTACK SHOULD DAMAGE THE IC (p.247) AND DOES NOT YET,
|
|
379
|
+
* stated here rather than left for the next reader to discover. Modelling
|
|
380
|
+
* it needs a condition monitor per program AND a way for the player to
|
|
381
|
+
* attack ice, and neither exists: there is no cybercombat path against
|
|
382
|
+
* IC in this engine at all. Half of it -- ice that hurts itself while
|
|
383
|
+
* the player still cannot swing back -- would be worse than neither
|
|
384
|
+
* half. It lands with the verb.
|
|
385
|
+
*/
|
|
386
|
+
function damageActs(room, actor, type, out) {
|
|
387
|
+
const { limit } = icAttackPool(room);
|
|
388
|
+
const net = icAttack(room, actor, type, out);
|
|
389
|
+
if (net <= 0) {
|
|
390
|
+
out.lines.push(` ${type.name} lunges at your icon and closes on nothing.`);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
// Before the damage, so a clean soak is not an escape -- see the note
|
|
394
|
+
// on applyLinkLock.
|
|
395
|
+
applyLinkLock(actor, type, out);
|
|
396
|
+
const marks = room.hostMarksOn.get(actor.name) ?? 0;
|
|
397
|
+
const dv = limit + net + (2 * marks);
|
|
398
|
+
// MATRIX DAMAGE IS RESISTED WITH DEVICE RATING + FIREWALL (p.228), and
|
|
399
|
+
// getSoakPool() is already exactly that on the matrix plane -- whole
|
|
400
|
+
// Firewall, technomancer living-persona rule and Armor program
|
|
401
|
+
// included. Not recomputed here; one formula, one place.
|
|
402
|
+
const soak = rollPool(actor.getSoakPool());
|
|
403
|
+
const dealt = Math.max(0, dv - soak.hits);
|
|
404
|
+
out.meta.push(`${type.name} -- ${dv} DV (Attack ${limit} +${net} net${marks > 0 ? ` +${2 * marks} for ${marks} mark${marks === 1 ? '' : 's'}` : ''}) v. Device Rating + Firewall: ${formatRoll(soak)} -> ${dealt}`);
|
|
405
|
+
if (dealt <= 0) {
|
|
406
|
+
out.lines.push(` {red-fg}${type.name} bites and your firewall holds -- barely.{/red-fg}`);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
// p.229: a technomancer has no Matrix condition monitor and takes
|
|
410
|
+
// Matrix damage as Stun. Shared with the reducers-at-zero path.
|
|
411
|
+
applyMatrixDamage(actor, dealt, type, out);
|
|
412
|
+
if (type.biofeedback)
|
|
413
|
+
dealBiofeedback(actor, dealt, type, out);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* THE LINK-LOCK LANDS ON A SUCCESSFUL ATTACK (p.248): "a single
|
|
417
|
+
* successful attack also link-locks the target".
|
|
418
|
+
*
|
|
419
|
+
* Tied to the attack CONNECTING, not to how much damage got through --
|
|
420
|
+
* so a hit soaked down to zero boxes still holds you. That is the whole
|
|
421
|
+
* horror of Black IC: it does not have to hurt you this turn to make
|
|
422
|
+
* sure you are still here next turn. Called before the damage is
|
|
423
|
+
* resolved for exactly that reason; putting it after the "soaked to
|
|
424
|
+
* nothing" early return would have quietly made a clean soak an escape.
|
|
425
|
+
*/
|
|
426
|
+
function applyLinkLock(actor, type, out) {
|
|
427
|
+
if (!type.linkLock || actor.linkLockedBy.has(type.name))
|
|
428
|
+
return;
|
|
429
|
+
actor.linkLockedBy.add(type.name);
|
|
430
|
+
out.lines.push(` {red-fg}${type.name} sinks keep-alive hooks into your connection -- you are LINK-LOCKED. "jack out" is a fight now, not a decision.{/red-fg}`);
|
|
431
|
+
out.world.push(`${actor.name}'s persona is link-locked by ${type.name}.`);
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* BIOFEEDBACK (p.229) -- a SECOND, SEPARATE hit on the user, applied
|
|
435
|
+
* after the Matrix damage is resolved, not instead of it.
|
|
436
|
+
*
|
|
437
|
+
* The worked example at p.245 sets the amount: a spider's 8 DV becomes 4
|
|
438
|
+
* boxes after the deck resists, and the decker then resists **4P** of
|
|
439
|
+
* biofeedback. So the biofeedback DV is the Matrix damage that actually
|
|
440
|
+
* LANDED, not the DV that was thrown. Sparky's own entry says only "with
|
|
441
|
+
* biofeedback damage" and does not quantify it; Black IC's says "an
|
|
442
|
+
* equal amount", which agrees with the worked example. That is the
|
|
443
|
+
* reading used here, and it is an inference from two cited passages
|
|
444
|
+
* rather than a line anybody printed about Sparky.
|
|
445
|
+
*
|
|
446
|
+
* Resisted with WILLPOWER + FIREWALL (p.229). Hot-sim makes it PHYSICAL,
|
|
447
|
+
* cold-sim makes it STUN (p.230) -- which is the whole price of hot-sim,
|
|
448
|
+
* and the game already tells players that when they jack in.
|
|
449
|
+
*/
|
|
450
|
+
function dealBiofeedback(actor, dv, type, out) {
|
|
451
|
+
const resist = rollPool(actor.willpower + actor.matrixAttribute('firewall'));
|
|
452
|
+
const dealt = Math.max(0, dv - resist.hits);
|
|
453
|
+
// BLASTER IS THE EXCEPTION (p.248): "the biofeedback from a Blaster
|
|
454
|
+
// program can only cause Stun damage" -- even in hot-sim, where every
|
|
455
|
+
// other source turns Physical. It is the whole difference between Grey
|
|
456
|
+
// IC and Black, and the reason a Blaster is survivable.
|
|
457
|
+
const hot = actor.simMode === 'hot' && !type.stunOnly;
|
|
458
|
+
out.meta.push(`${type.name} -- biofeedback ${dv} DV v. Willpower + Firewall: ${formatRoll(resist)} -> ${dealt}${hot ? ' PHYSICAL (hot-sim)' : ' stun'}`);
|
|
459
|
+
if (dealt <= 0) {
|
|
460
|
+
out.lines.push(` The feedback surge breaks against you and dies.`);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
if (hot) {
|
|
464
|
+
actor.takeDamage(dealt);
|
|
465
|
+
out.lines.push(` {red-fg}Hot-sim carries it into the MEAT -- ${dealt} physical: ${actor.conditionSummary()}{/red-fg}`);
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
actor.takeStun(dealt);
|
|
469
|
+
out.lines.push(` {red-fg}Feedback burns -- ${dealt} stun: ${actor.stunSummary()}{/red-fg}`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* PATROL IC (p.248): makes NO attack test. It runs Matrix Perception on
|
|
474
|
+
* the personas in the host hunting illegal activity, has no Attack
|
|
475
|
+
* rating, shares what it finds with the host, and takes no Matrix damage
|
|
476
|
+
* when it fails.
|
|
477
|
+
*
|
|
478
|
+
* CADENCE: Data Trails p.86 spaces Patrol's perception tests by Host
|
|
479
|
+
* Rating (3-4: 1D6 Combat Turns, up to 11-12: 3D6) -- BUT that is the
|
|
480
|
+
* unsuspecting case, and the same passage says that once the Patrol IC
|
|
481
|
+
* or a spider suspects an intruder it runs Matrix Perception EVERY
|
|
482
|
+
* ACTION. This engine only reaches this code once the host has already
|
|
483
|
+
* made someone (hostAlert), so every-action is the branch that applies
|
|
484
|
+
* and the dice interval is deliberately not modelled. When ambient
|
|
485
|
+
* pre-alert patrolling exists, the interval table is what it needs.
|
|
486
|
+
*/
|
|
487
|
+
function patrolActs(room, actor, out) {
|
|
488
|
+
// No Attack rating means no bracket to cap the hits with.
|
|
489
|
+
const roll = rollPool(room.hostRating * 2);
|
|
490
|
+
out.meta.push(`Patrol IC -- Matrix Perception (Host Rating x2): ${formatRoll(roll)}`);
|
|
491
|
+
if (roll.hits > 0) {
|
|
492
|
+
out.lines.push(` {red-fg}Patrol IC sweeps your icon and hands what it sees to the host.{/red-fg}`);
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
// "Does not take Matrix damage when it fails" -- a whiff costs it
|
|
496
|
+
// nothing, which is why Patrol is the one thing always running.
|
|
497
|
+
out.lines.push(` Patrol IC quarters the datastream around you and comes up empty -- this pass.`);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* PROBE IC (p.248): Host Rating x 2 [Attack] v. Intuition + Firewall.
|
|
502
|
+
* "Each successful attack gives the host and its IC one mark on the
|
|
503
|
+
* target, up to a maximum of three marks."
|
|
504
|
+
*
|
|
505
|
+
* MARKS RUN THE OTHER WAY FROM Room.hostMarksBy, and the distinction is
|
|
506
|
+
* the whole reason hostMarksOn exists. hostMarksBy counts marks the
|
|
507
|
+
* PLAYER holds on the HOST (they soften a crack). Probe places marks the
|
|
508
|
+
* HOST holds on the PLAYER, which is a different quantity pointing the
|
|
509
|
+
* other direction -- and the one Scramble (3 marks) and Track (2 marks)
|
|
510
|
+
* read in Phase 4. The engine previously modelled the host's side as the
|
|
511
|
+
* single boolean `hostAlert`, which cannot answer "how many".
|
|
512
|
+
*/
|
|
513
|
+
function probeActs(room, actor, out) {
|
|
514
|
+
const { pool, limit } = icAttackPool(room);
|
|
515
|
+
const attack = rollPool(pool, limit);
|
|
516
|
+
const defence = rollPool(icDefencePool(actor));
|
|
517
|
+
const net = attack.hits - defence.hits;
|
|
518
|
+
out.meta.push(`Probe IC -- Host Rating x2 [Attack ${limit}]: ${formatRoll(attack)} v. Intuition + Firewall: ${formatRoll(defence)} (net ${net})`);
|
|
519
|
+
const held = room.hostMarksOn.get(actor.name) ?? 0;
|
|
520
|
+
if (net <= 0) {
|
|
521
|
+
out.lines.push(` Probe IC tests your edges and finds nothing to hold onto.`);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (held >= MAX_MARKS) {
|
|
525
|
+
// Canon caps Probe's marks at three; a fourth is not a thing.
|
|
526
|
+
out.lines.push(` {red-fg}Probe IC crawls over marks it already owns -- it can hold no more of you.{/red-fg}`);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const now = held + 1;
|
|
530
|
+
room.hostMarksOn.set(actor.name, now);
|
|
531
|
+
out.lines.push(` {red-fg}Probe IC gets a grip -- the host holds ${now} mark${now === 1 ? '' : 's'} on you now${now >= MAX_MARKS ? ', all it can carry' : ''}.{/red-fg}`);
|
|
532
|
+
out.world.push(`${room.name}'s ice tightened its hold on ${actor.name}.`);
|
|
533
|
+
}
|
|
534
|
+
//# sourceMappingURL=ic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ic.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/ic.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,34 @@ export declare function planeLabel(actor: Player): string;
|
|
|
25
25
|
/** Every off-plane actor whose empty body lies in this room. */
|
|
26
26
|
export declare function shellsInRoom(scene: Scene, room: Room): (Player | NPC)[];
|
|
27
27
|
export declare function enterMatrix(scene: Scene, actor: Player, mode: SimMode): string[];
|
|
28
|
+
/**
|
|
29
|
+
* DUMPSHOCK (SR5 p.229) -- ONE RULE, ONE PLACE.
|
|
30
|
+
*
|
|
31
|
+
* "When you're disconnected from the Matrix while in VR without
|
|
32
|
+
* gracefully switching to AR first... The Damage Value for dumpshock is
|
|
33
|
+
* 6S if you're in cold-sim and 6P if you're in hot-sim. Dumpshock is
|
|
34
|
+
* biofeedback damage, so you resist it with Willpower + Firewall...
|
|
35
|
+
* you're also disoriented and take a -2 dice pool modifier on all of
|
|
36
|
+
* your actions for (10 - Willpower) minutes. Remember that if you're
|
|
37
|
+
* being dumped because your deck just got bricked, you don't have a
|
|
38
|
+
* functional Firewall attribute any more, so only use your Willpower."
|
|
39
|
+
*
|
|
40
|
+
* EXTRACTED BECAUSE THE TWO COPIES HAD ALREADY DRIFTED. leaveMatrix and
|
|
41
|
+
* leaveDrone each rolled their own dumpshock: both used a DV of 4, which
|
|
42
|
+
* is not a number the book has, and both resisted on Willpower alone,
|
|
43
|
+
* which is missing a term -- but only the DRONE one applied the
|
|
44
|
+
* disorientation, so a decker dumped out of the Matrix walked away
|
|
45
|
+
* sharper than a rigger dumped out of a drone, for no reason anybody
|
|
46
|
+
* wrote down. Correcting one and not the other would have widened that
|
|
47
|
+
* gap instead of closing it. A rigger jumped into a drone is in VR, so
|
|
48
|
+
* it is the same rule and now it is the same code.
|
|
49
|
+
*
|
|
50
|
+
* The Biofeedback Filter's +2 (p.245) rides along and is simply absent
|
|
51
|
+
* for a rigger with no active deck, which is the right answer anyway.
|
|
52
|
+
*/
|
|
53
|
+
export declare function applyDumpshock(actor: Player, reason: string): string[];
|
|
54
|
+
/** p.229. Was 4 in two places; the book says 6. */
|
|
55
|
+
export declare const DUMPSHOCK_DV = 6;
|
|
28
56
|
export declare function leaveMatrix(scene: Scene, actor: Player, opts?: {
|
|
29
57
|
forced?: boolean;
|
|
30
58
|
reason?: string;
|
|
@@ -41,10 +69,12 @@ export declare function leaveMatrix(scene: Scene, actor: Player, opts?: {
|
|
|
41
69
|
export declare function enterDrone(scene: Scene, actor: Player, drone: Item, mode: SimMode): string[];
|
|
42
70
|
/**
|
|
43
71
|
* Jumping out -- clean when voluntary; a WRECKED airframe is a forced
|
|
44
|
-
* dump
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
72
|
+
* dump, and a rigger jumped into a drone is in VR, so the dump is
|
|
73
|
+
* ORDINARY DUMPSHOCK: see applyDumpshock, which both this and the Matrix
|
|
74
|
+
* exit now share. It used to be spelled out here with a DV of 4 and a
|
|
75
|
+
* Willpower-only resist -- the same softening the Matrix side had, minus
|
|
76
|
+
* the Firewall term, plus the only correct half either copy had (the
|
|
77
|
+
* p.229 disorientation, which the Matrix side was missing entirely).
|
|
48
78
|
*/
|
|
49
79
|
export declare function leaveDrone(scene: Scene, actor: Player, opts?: {
|
|
50
80
|
forced?: boolean;
|