@maka/maka-cli 5.183.0 → 5.184.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/ar.js +6 -6
- package/bundle/typescript/src/commands/game/sideQuest/commands/delay.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/disable.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/download.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/end-turn.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.js +11 -13
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +7 -7
- package/bundle/typescript/src/commands/game/sideQuest/commands/hop.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +5 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sprites.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js +7 -7
- package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/game.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js +2 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-turn.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-reach.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js +14 -14
- package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-style.js +8 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/overwatch.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.js +2 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maka/maka-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.184.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
|
|
6
6
|
"description": "A command line tool for scaffolding Meteor 3.x applications using React.",
|
|
@@ -64,14 +64,14 @@ export class ArCommand extends Command {
|
|
|
64
64
|
return `Overlay back on -- over nothing. No commlink, no deck, no AR: you're reading the street with your eyes like it's 2050.`;
|
|
65
65
|
}
|
|
66
66
|
const tags = aroTags(this.scene, actor, actor.currentLocation);
|
|
67
|
-
const head = `{
|
|
67
|
+
const head = `{lightblue-fg}The overlay blinks back in.{/lightblue-fg}`;
|
|
68
68
|
// Turning AR back on while silent is the other moment the question
|
|
69
69
|
// lands -- you have just done the thing you were unsure was allowed.
|
|
70
70
|
const note = silentAndSeeingNote(actor);
|
|
71
71
|
if (tags.length === 0) {
|
|
72
|
-
return [head, `{
|
|
72
|
+
return [head, `{lightblue-fg}Nothing here is talking -- a dead patch of street.{/lightblue-fg}`, note].filter(Boolean).join('\n');
|
|
73
73
|
}
|
|
74
|
-
return [head, ...tags.map(t => ` {
|
|
74
|
+
return [head, ...tags.map(t => ` {lightblue-fg}${t}{/lightblue-fg}`), note].filter(Boolean).join('\n');
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
@@ -105,11 +105,11 @@ export class ArosCommand extends Command {
|
|
|
105
105
|
const note = silentAndSeeingNote(actor);
|
|
106
106
|
const tags = aroTags(this.scene, actor, actor.currentLocation);
|
|
107
107
|
if (tags.length === 0) {
|
|
108
|
-
return [`{
|
|
108
|
+
return [`{lightblue-fg}Nothing here is talking -- a dead patch of street.{/lightblue-fg}`, note].filter(Boolean).join('\n');
|
|
109
109
|
}
|
|
110
110
|
return [
|
|
111
|
-
`{
|
|
112
|
-
...tags.map(t => ` {
|
|
111
|
+
`{lightblue-fg}AR OVERLAY:{/lightblue-fg}`,
|
|
112
|
+
...tags.map(t => ` {lightblue-fg}${t}{/lightblue-fg}`),
|
|
113
113
|
note,
|
|
114
114
|
].filter(Boolean).join('\n');
|
|
115
115
|
}
|
|
@@ -25,7 +25,7 @@ export class DelayCommand extends Command {
|
|
|
25
25
|
return `Too late to delay -- you've already acted this phase (${budget.ledger()}). "end turn" instead.`;
|
|
26
26
|
}
|
|
27
27
|
if (this.scene.isHumanControlled(actor)) {
|
|
28
|
-
this.logger.log(`{
|
|
28
|
+
this.logger.log(`{yellow-fg}You hold your action, watching.{/yellow-fg}`, { actor: actor.name });
|
|
29
29
|
}
|
|
30
30
|
await enc.delayPhase(actor);
|
|
31
31
|
return this.scene.isHumanControlled(actor) ? '' : `${actor.name} holds their action.`;
|
|
@@ -180,7 +180,7 @@ export class DisableCommand extends Command {
|
|
|
180
180
|
const defence = this.defence(t);
|
|
181
181
|
const defenceRoll = rollPool(defence.pool);
|
|
182
182
|
const net = roll.hits - defenceRoll.hits;
|
|
183
|
-
actor.performAction('takes control of a device', name);
|
|
183
|
+
actor.performAction('takes control of a device', name, { quiet: this.scene.isHumanControlled(actor) });
|
|
184
184
|
if (this.scene.isHumanControlled(actor)) {
|
|
185
185
|
this.logger.meta(`Control Device (Electronic Warfare + Intuition [Sleaze])${gridNote(grid)}: ${formatRoll(roll)}`);
|
|
186
186
|
this.logger.meta(`${defence.label}: ${formatRoll(defenceRoll)} -- net ${net >= 0 ? '+' : ''}${net}`);
|
|
@@ -236,7 +236,7 @@ export class DisableCommand extends Command {
|
|
|
236
236
|
const defence = this.defence(t);
|
|
237
237
|
const defenceRoll = rollPool(defence.pool);
|
|
238
238
|
const net = roll.hits - defenceRoll.hits;
|
|
239
|
-
actor.performAction('throws a Data Spike', name);
|
|
239
|
+
actor.performAction('throws a Data Spike', name, { quiet: this.scene.isHumanControlled(actor) });
|
|
240
240
|
if (this.scene.isHumanControlled(actor)) {
|
|
241
241
|
this.logger.meta(`Data Spike (Cybercombat + Logic [Attack ${limit}])${gridNote(grid)}: ${formatRoll(roll)}`);
|
|
242
242
|
this.logger.meta(`${defence.label}: ${formatRoll(defenceRoll)} -- net ${net >= 0 ? '+' : ''}${net}`);
|
|
@@ -92,7 +92,7 @@ export class DownloadCommand extends Command {
|
|
|
92
92
|
// is that nobody could find the file should say what it can see.
|
|
93
93
|
const query = args.join(' ').trim();
|
|
94
94
|
if (query.length === 0) {
|
|
95
|
-
const lines = [`{
|
|
95
|
+
const lines = [`{lightblue-fg}Within reach to pull down:{/lightblue-fg}`];
|
|
96
96
|
for (const i of loose)
|
|
97
97
|
lines.push(` ${planeTintItemName(i, actor.plane)} -- loose on the grid here`);
|
|
98
98
|
for (const c of carried)
|
|
@@ -134,11 +134,11 @@ export class DownloadCommand extends Command {
|
|
|
134
134
|
this.scene.updateStatus();
|
|
135
135
|
return fromSprite
|
|
136
136
|
? [
|
|
137
|
-
`{
|
|
137
|
+
`{lightblue-fg}${fromSprite.npc.name} opens its hands and the data pours out of them.{/lightblue-fg}`,
|
|
138
138
|
`You pull {bold}{underline}${item.name}{/underline}{/bold} down onto a chip -- meat-world cargo now.${hint(` (You can "give ${item.name}" to somebody standing in front of you.)`)}`,
|
|
139
139
|
].join('\n')
|
|
140
140
|
: [
|
|
141
|
-
`{
|
|
141
|
+
`{lightblue-fg}You pull {bold}{underline}${item.name}{/underline}{/bold} down off the grid -- written to a chip.{/lightblue-fg}`,
|
|
142
142
|
hint(`(Meat-world cargo now: carry it, stash it, or "give" it to somebody.)`),
|
|
143
143
|
].join('\n');
|
|
144
144
|
}
|
|
@@ -49,7 +49,7 @@ export class EndTurnCommand extends Command {
|
|
|
49
49
|
// Logged now rather than returned: the phases that follow announce
|
|
50
50
|
// themselves while this command is still running, and a return
|
|
51
51
|
// value would land under them, out of order.
|
|
52
|
-
this.logger.log(`{
|
|
52
|
+
this.logger.log(`{yellow-fg}You end your Action Phase${budget && budget.spent.length > 0 ? ` -- ${ledger}` : ' -- nothing spent'}.{/yellow-fg}`, { actor: actor.name });
|
|
53
53
|
}
|
|
54
54
|
await enc.endPhase(actor);
|
|
55
55
|
return this.scene.isHumanControlled(actor) ? '' : `${actor.name} ends their Action Phase.`;
|
|
@@ -64,7 +64,7 @@ export class EnterHostCommand extends Command {
|
|
|
64
64
|
const marks = target.hostMarksBy.get(actor.name) ?? 0;
|
|
65
65
|
if (marks < 1 && !target.hostCracked && !target.hostSanctioned) {
|
|
66
66
|
return [
|
|
67
|
-
`{
|
|
67
|
+
`{lightblue-fg}${hostLabel(target, { capital: true })} doesn't know you. Its architecture has no door shaped like your icon.{/lightblue-fg}`,
|
|
68
68
|
hint(`A host opens to anyone holding a MARK on it (p.239) -- "mark ${target.name}" softens it, or "hack" takes one by force.`),
|
|
69
69
|
].join('\n');
|
|
70
70
|
}
|
|
@@ -79,14 +79,15 @@ export class EnterHostCommand extends Command {
|
|
|
79
79
|
// you there). currentLocation is never written -- it is the body's.
|
|
80
80
|
actor.matrixPosition = { kind: 'host', host: target.host, from: actor.currentGrid };
|
|
81
81
|
movePersonaWith(this.game ?? undefined, actor);
|
|
82
|
-
actor.performAction('enters a host', `icon crossing into ${target.name}'s architecture
|
|
82
|
+
actor.performAction('enters a host', `icon crossing into ${target.name}'s architecture`, { quiet: this.scene.isHumanControlled(actor) });
|
|
83
83
|
this.logger.write(`${actor.name} entered the host at ${target.name}.`);
|
|
84
84
|
this.scene.updateStatus();
|
|
85
|
+
// ONE LINE (2026-09-13, "too much text"): the crossing, and the
|
|
86
|
+
// coaching behind the hints toggle.
|
|
85
87
|
return [
|
|
86
|
-
`{
|
|
87
|
-
`
|
|
88
|
-
|
|
89
|
-
].join('\n');
|
|
88
|
+
`{lightblue-fg}You cross into ${hostLabel(target, { capital: false })} -- the outside grid folds shut behind you.{/lightblue-fg}`,
|
|
89
|
+
hint(`(In here there is only what the host keeps. "look" reads it; "exit" puts you back on the grid.)`),
|
|
90
|
+
].filter(Boolean).join('\n');
|
|
90
91
|
}
|
|
91
92
|
/**
|
|
92
93
|
* The host this verb means. Bare `enter` takes the one under your feet
|
|
@@ -109,14 +110,14 @@ export class EnterHostCommand extends Command {
|
|
|
109
110
|
const over = hostOver(gridVicinity(this.actor)) ?? hostOver(here);
|
|
110
111
|
if (over)
|
|
111
112
|
return over;
|
|
112
|
-
return `{
|
|
113
|
+
return `{lightblue-fg}Thin grid here -- no host stands over ${gridVicinity(this.actor).name}.{/lightblue-fg} ${hint(`Overhead: ${roster} -- "enter <name>" crosses into any of them from here.`)}`;
|
|
113
114
|
}
|
|
114
115
|
const host = resolveHostInReach(rooms, this.actor, named);
|
|
115
116
|
if (host)
|
|
116
117
|
return host;
|
|
117
118
|
const street = Object.values(rooms).find(r => r.name.toLowerCase() === named.toLowerCase());
|
|
118
119
|
if (street)
|
|
119
|
-
return `{
|
|
120
|
+
return `{lightblue-fg}${street.name} has no host over it -- nothing to enter. Overhead: ${roster}.{/lightblue-fg}`;
|
|
120
121
|
return `No host called "${named}" overhead. ${hint(`Overhead: ${roster}.`)}`;
|
|
121
122
|
}
|
|
122
123
|
}
|
|
@@ -148,13 +149,10 @@ export class ExitHostCommand extends Command {
|
|
|
148
149
|
const from = actor.matrixPosition?.kind === 'host' ? actor.matrixPosition.from : undefined;
|
|
149
150
|
actor.matrixPosition = { kind: 'grid', grid: from };
|
|
150
151
|
movePersonaWith(this.game ?? undefined, actor);
|
|
151
|
-
actor.performAction('exits a host', `icon surfacing out of ${host.name}'s architecture
|
|
152
|
+
actor.performAction('exits a host', `icon surfacing out of ${host.name}'s architecture`, { quiet: this.scene.isHumanControlled(actor) });
|
|
152
153
|
this.logger.write(`${actor.name} exited the host at ${host.name}.`);
|
|
153
154
|
this.scene.updateStatus();
|
|
154
|
-
return
|
|
155
|
-
`{cyan-fg}You step back out of ${hostLabel(host, { capital: false })} and onto the grid -- your body still sits in ${actor.currentLocation.name}.{/cyan-fg}`,
|
|
156
|
-
`{cyan-fg}The host seals behind you: one icon again, whatever you saw in there now on the other side of its wall.{/cyan-fg}`,
|
|
157
|
-
].join('\n');
|
|
155
|
+
return `{lightblue-fg}You step back out of ${hostLabel(host, { capital: false })} onto the grid; the host seals behind you. Your body still sits in ${actor.currentLocation.name}.{/lightblue-fg}`;
|
|
158
156
|
}
|
|
159
157
|
}
|
|
160
158
|
//# sourceMappingURL=enter-host.js.map
|
|
@@ -173,7 +173,7 @@ export class HackCommand extends BypassCommand {
|
|
|
173
173
|
const burned = this.actor.burnedAttributeRefusal(mode === 'attack' ? 'attack' : 'sleaze');
|
|
174
174
|
if (burned)
|
|
175
175
|
return burned;
|
|
176
|
-
this.actor.performAction('hacks the host', room.name);
|
|
176
|
+
this.actor.performAction('hacks the host', room.name, { quiet: this.scene.isHumanControlled(this.actor) });
|
|
177
177
|
const attempt = await this.hostIntrusionRoll(mode, declared, room);
|
|
178
178
|
const success = attempt.success;
|
|
179
179
|
// GOD BILLS THE DEFENDER'S HITS (p.231-232): "your OS increases by
|
|
@@ -276,7 +276,7 @@ export class HackCommand extends BypassCommand {
|
|
|
276
276
|
if (marksNow >= 1)
|
|
277
277
|
lines.push(` One mark is the door: "enter" walks your persona inside (p.239).`);
|
|
278
278
|
if (perception > 0)
|
|
279
|
-
lines.push(` {
|
|
279
|
+
lines.push(` {lightblue-fg}And you read it on the way past -- ${perception} Matrix Perception hit${perception === 1 ? '' : 's'} of what this node is (p.240).{/lightblue-fg}`);
|
|
280
280
|
if (forcedDv > 0)
|
|
281
281
|
lines.push(` The forcing burns ${forcedDv} DV into the architecture -- a host has no boards to brick, so it only announces you louder.`);
|
|
282
282
|
lines.push(` ${MAX_MARKS - marksNow} more and its architecture stops asking who you are.${hint(` ("hack for ${MAX_MARKS - marksNow}" reaches for the rest at once -- ${declarationPenalty(MAX_MARKS - marksNow, this.actor.hasQuality(GO_BIG_QUALITY))} dice.)`)}`);
|
|
@@ -340,13 +340,13 @@ export class HackCommand extends BypassCommand {
|
|
|
340
340
|
lines.push(` ${iconLocks.length} ${iconLocks.length === 1 ? 'lock hangs' : 'locks hang'} off it, still sealed -- each its own icon behind its own rating: ${iconLocks.map(d => d.name).join(', ')}.${hint(` ("hack <lock>" from in here keys one; the host's key is not the door's.)`)}`);
|
|
341
341
|
}
|
|
342
342
|
if (vaultedFiles.length > 0) {
|
|
343
|
-
lines.push(` {
|
|
343
|
+
lines.push(` {lightblue-fg}The data vault unseals -- ${vaultedFiles.map(i => i.name).join(', ')} spill${vaultedFiles.length === 1 ? 's' : ''} into the open.${hint(` Yours to "take".`)}{/lightblue-fg}`);
|
|
344
344
|
}
|
|
345
345
|
// AND WHAT THE CRACK DID NOT REACH: a wired site's data sits on an
|
|
346
346
|
// air-gapped box the host never held (p.233) -- say so, or the next
|
|
347
347
|
// "take" reads as a contradiction.
|
|
348
348
|
if (room.offlineServer && room.inventory.getAllItems().some(i => i.plane === 'matrix')) {
|
|
349
|
-
lines.push(` {
|
|
349
|
+
lines.push(` {lightblue-fg}Nothing on the grid side of the vault -- whatever this place keeps sits on the ${room.offlineServer}, an air-gapped box with no Matrix presence. Your BODY has to be in ${room.name} to cable in (p.233).{/lightblue-fg}`);
|
|
350
350
|
}
|
|
351
351
|
// THE FEEDS ARE A REAL GAIN AND WERE NEVER MENTIONED
|
|
352
352
|
// (BpR5cjhYuvgCyDSZc, 7aNWnDSHeZMYmS2De: "what have I gained?").
|
|
@@ -540,7 +540,7 @@ export class HackCommand extends BypassCommand {
|
|
|
540
540
|
? Math.max(1, actor.getAttackPool() + silence + actor.bonus('matrix-attack') + declarePenalty)
|
|
541
541
|
: Math.max(1, actor.logic + actor.skillRating('hacking') + actor.bonus('hacking') + actor.bonus('matrix-sleaze')
|
|
542
542
|
+ silence + actor.woundModifier - actor.sustainingPenalty + declarePenalty);
|
|
543
|
-
actor.performAction('works a slaved icon', device.name);
|
|
543
|
+
actor.performAction('works a slaved icon', device.name, { quiet: this.scene.isHumanControlled(actor) });
|
|
544
544
|
const roll = rollPool(pool, limit, { gremlins: actor.deckGremlins });
|
|
545
545
|
// From the grid the slave borrows its master's numbers where they are
|
|
546
546
|
// higher (p.233); inside, it stands alone (Data Trails p.87-88).
|
|
@@ -606,7 +606,7 @@ export class HackCommand extends BypassCommand {
|
|
|
606
606
|
else {
|
|
607
607
|
const perception = freeMatrixPerceptionHits(netHits);
|
|
608
608
|
if (perception > 0)
|
|
609
|
-
lines.push(` {
|
|
609
|
+
lines.push(` {lightblue-fg}And you read it on the way past -- ${perception} Matrix Perception hit${perception === 1 ? '' : 's'} of what it guards (p.240).{/lightblue-fg}`);
|
|
610
610
|
}
|
|
611
611
|
// TWO MARKS COMMAND IT (p.238 Control Device: 1 mark for a Free
|
|
612
612
|
// action, 2 for a Simple, 3 for a Complex -- and unlocking a maglock
|
|
@@ -765,7 +765,7 @@ export class HackCommand extends BypassCommand {
|
|
|
765
765
|
// Intuition + Firewall against a sleaze, Willpower + Firewall
|
|
766
766
|
// against a smash (p.240 / p.238), and no limit on either.
|
|
767
767
|
const defense = rollPool(target.getPanDefensePool(mode === 'attack' ? 'attack' : 'sleaze'));
|
|
768
|
-
actor.performAction('runs a PAN intrusion', target.name);
|
|
768
|
+
actor.performAction('runs a PAN intrusion', target.name, { quiet: this.scene.isHumanControlled(actor) });
|
|
769
769
|
this.logger.write(`${actor.name} PAN-hacks ${target.name}: ${attack.hits} vs ${defense.hits} (silent=${target.runningSilent}).`);
|
|
770
770
|
// Dice anatomy to the Mechanics ticker (readability pass) --
|
|
771
771
|
// player-gated like every roll site: an NPC's probe isn't your dice.
|
|
@@ -53,7 +53,7 @@ export class HopCommand extends Command {
|
|
|
53
53
|
actor.performAction('hops grids', `persona blinking across to ${target.name}`);
|
|
54
54
|
this.logger.write(`${actor.name} hopped to ${target.key} (legal, ${tier}).`);
|
|
55
55
|
this.scene.updateStatus();
|
|
56
|
-
return `{
|
|
56
|
+
return `{lightblue-fg}The sky changes texture and you're on ${target.name}.{/lightblue-fg}${target.userPenalty ? ` ${hint(`Public grid: -2 on everything you do out here.`)}` : ''}`;
|
|
57
57
|
}
|
|
58
58
|
// ILLEGAL HOP (p.240): Hack on the Fly against the grid itself.
|
|
59
59
|
const burned = actor.burnedAttributeRefusal('sleaze');
|
|
@@ -87,7 +87,7 @@ export class HopCommand extends Command {
|
|
|
87
87
|
this.logger.write(`${actor.name} hopped to ${target.key} (illegal, ${attempt.hits} v ${defence.hits}).`);
|
|
88
88
|
this.scene.updateStatus();
|
|
89
89
|
return [
|
|
90
|
-
`{
|
|
90
|
+
`{lightblue-fg}You slip through a seam nobody sold you and come up on ${target.name}.{/lightblue-fg}`,
|
|
91
91
|
...bill.lines,
|
|
92
92
|
].join('\n');
|
|
93
93
|
}
|
|
@@ -379,7 +379,7 @@ export class LookCommand extends Command {
|
|
|
379
379
|
const dim = this.scene.getActorsInRoom(far)
|
|
380
380
|
.find(a => a !== this.actor && a.name.toLowerCase() === target.toLowerCase() && this.actor.canPerceive(a));
|
|
381
381
|
if (dim)
|
|
382
|
-
return `${this.inspectPersona(dim)}\n{
|
|
382
|
+
return `${this.inspectPersona(dim)}\n{lightblue-fg} -- a far icon, ${far.name}${noiseNote(noise)}{/lightblue-fg}`;
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
// 3. THE HOST, as a thing you can name. gridIcons already renders it
|
|
@@ -396,8 +396,8 @@ export class LookCommand extends Command {
|
|
|
396
396
|
// `deck` reads out your own array.
|
|
397
397
|
const a = namedHost.hostAttributes();
|
|
398
398
|
return [
|
|
399
|
-
`{
|
|
400
|
-
`{
|
|
399
|
+
`{lightblue-fg}${hostIcon}{/lightblue-fg}`,
|
|
400
|
+
`{lightblue-fg} Attack ${a.attack} Sleaze ${a.sleaze} Data Processing ${a.dataProcessing} Firewall ${a.firewall}{/lightblue-fg}`,
|
|
401
401
|
].join('\n');
|
|
402
402
|
}
|
|
403
403
|
}
|
|
@@ -409,7 +409,7 @@ export class LookCommand extends Command {
|
|
|
409
409
|
if (matchesCameraName(target)) {
|
|
410
410
|
const eye = gridIcons(this.scene, this.actor, room).find(i => i.startsWith('◎'));
|
|
411
411
|
if (eye)
|
|
412
|
-
return `{
|
|
412
|
+
return `{lightblue-fg}${eye}{/lightblue-fg}`;
|
|
413
413
|
// Named correctly, and there is simply nothing here to name.
|
|
414
414
|
// Worth its own line: the old answer said the WORDS were wrong,
|
|
415
415
|
// which sent the player hunting for a synonym that never
|
|
@@ -525,7 +525,7 @@ export class LookCommand extends Command {
|
|
|
525
525
|
* there's a deck anywhere in the shape of it.
|
|
526
526
|
*/
|
|
527
527
|
inspectPersona(target) {
|
|
528
|
-
const lines = [`{
|
|
528
|
+
const lines = [`{lightblue-fg}◆ ${target.name} -- a persona on this grid.{/lightblue-fg}`];
|
|
529
529
|
const companion = this.scene.ownerGame?.companions.find(c => c.npc === target);
|
|
530
530
|
if (companion) {
|
|
531
531
|
lines.push(`Yours -- it goes where you go, and it answers when you speak.`);
|
|
@@ -93,7 +93,7 @@ export class MapCommand extends Command {
|
|
|
93
93
|
actor.insideHost
|
|
94
94
|
? `THE GRID -- INSIDE ${hostLabel(actor.insideHost, { capital: true }).toUpperCase()}`
|
|
95
95
|
: `THE GRID -- ${actor.currentGrid ? `on ${actor.currentGrid.name}, ` : ''}jacked in from ${body.name}`,
|
|
96
|
-
`{
|
|
96
|
+
`{lightblue-fg}Black flatland under a black sky. No streets out here -- only icons. The hosts hang overhead; ${actor.insideHost ? '"exit" puts you back under them' : '"go <host>" (or "go <number>") crosses into one you hold a mark on, from anywhere'}.{/lightblue-fg}`,
|
|
97
97
|
];
|
|
98
98
|
if (hosts.length === 0) {
|
|
99
99
|
lines.push(' Nothing overhead -- no host stands over this district.');
|
|
@@ -51,7 +51,7 @@ export class MarkCommand extends Command {
|
|
|
51
51
|
screen: this.screen,
|
|
52
52
|
game: this.game,
|
|
53
53
|
}).execute(args);
|
|
54
|
-
return `{
|
|
54
|
+
return `{lightblue-fg}Placing a mark IS ${action} -- running it (p.238/p.240).{/lightblue-fg}\n${result}`;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
//# sourceMappingURL=mark.js.map
|
|
@@ -175,7 +175,7 @@ export class SearchCommand extends Command {
|
|
|
175
175
|
// seconds spent is what makes the next illegal action pay for them.
|
|
176
176
|
if (actor.overwatchLastTick > 0)
|
|
177
177
|
actor.overwatchLastTick -= seconds * 1000;
|
|
178
|
-
actor.performAction('runs a Matrix Search', host ? `inside ${hostLabel(where)}` : `across ${where.name}'s grid
|
|
178
|
+
actor.performAction('runs a Matrix Search', host ? `inside ${hostLabel(where)}` : `across ${where.name}'s grid`, { quiet: this.scene.isHumanControlled(actor) });
|
|
179
179
|
const files = where.offlineServer ? [] : where.inventory.getAllItems().filter(i => i.plane === 'matrix');
|
|
180
180
|
const clock = `(${seconds}s of Matrix time${browse ? ', Browse cutting it' : ''})`;
|
|
181
181
|
if (roll.hits < row.threshold) {
|
|
@@ -313,8 +313,8 @@ export class SearchCommand extends Command {
|
|
|
313
313
|
// tells a player standing next to an offline server that it is
|
|
314
314
|
// there and what it wants from them.
|
|
315
315
|
description += room.offlineServer
|
|
316
|
-
? `\n{
|
|
317
|
-
: `\n{
|
|
316
|
+
? `\n{lightblue-fg}A ${room.offlineServer} sits here, dark and off the network -- no aerial, no marquee, nothing broadcasting. Whatever it holds comes out through a cable and no other way.${hint(` "jack in" RIGHT HERE to touch its files.`)}{/lightblue-fg}`
|
|
317
|
+
: `\n{lightblue-fg}The node here hums with locked files -- whatever's worth taking lives on the grid, inside the host.${hint(` "jack in", then "enter" the host.`)}{/lightblue-fg}`;
|
|
318
318
|
}
|
|
319
319
|
description += describeContainers(room, this.actor);
|
|
320
320
|
description += describeBarriers(room, this.actor);
|
|
@@ -49,7 +49,7 @@ export class SnoopCommand extends Command {
|
|
|
49
49
|
this.logger.write(`Snoop: ${actor.name} watching ${target.name} via camera feed.`);
|
|
50
50
|
const lines = [`CAMERA FEED: ${target.name.toUpperCase()}`];
|
|
51
51
|
if (!camerasLive(allRooms, target)) {
|
|
52
|
-
lines.push(`{
|
|
52
|
+
lines.push(`{lightblue-fg}(Security sees a loop of empty hallways -- these eyes answer only to you now.){/lightblue-fg}`);
|
|
53
53
|
}
|
|
54
54
|
const seen = this.scene.getActorsInRoom(target)
|
|
55
55
|
.filter(a => a !== actor && a.plane === 'meat' && !a.sneaking);
|
|
@@ -73,7 +73,7 @@ export class SpritesCommand extends Command {
|
|
|
73
73
|
const name = type?.name ?? set.spriteKey;
|
|
74
74
|
const isMine = mineType === set.spriteKey;
|
|
75
75
|
const powers = powersForSprite(set.spriteKey);
|
|
76
|
-
lines.push(`${name.toUpperCase()} SPRITE${isMine ? ' {
|
|
76
|
+
lines.push(`${name.toUpperCase()} SPRITE${isMine ? ' {lightblue-fg}(yours){/lightblue-fg}' : ''}${type ? ` -- ${type.blurb}` : ''}`);
|
|
77
77
|
lines.push(` Skills: ${skillsForSprite(set.spriteKey).join(', ')}${hint(` (${set.page})`)}`);
|
|
78
78
|
if (!detailed) {
|
|
79
79
|
// The names alone, which is the comparison view.
|
|
@@ -158,9 +158,9 @@ export class TapCommand extends Command {
|
|
|
158
158
|
}
|
|
159
159
|
this.logger.write(`${actor.name} now holds ${now} mark(s) on ${host.name} via the ${room.name} cameras.`);
|
|
160
160
|
const lines = [
|
|
161
|
-
`{
|
|
162
|
-
` {
|
|
163
|
-
` {
|
|
161
|
+
`{lightblue-fg}The filament finds the connector and the camera stops being a camera -- it's a device, and it's talking to you.{/lightblue-fg}`,
|
|
162
|
+
` {lightblue-fg}It never gets to hide behind ${hostLabel(host)}: a cable doesn't ask the network for permission, so the lens has to defend itself with what a lens has. It doesn't have much.{/lightblue-fg}`,
|
|
163
|
+
` {lightblue-fg}MARK PLACED -- and it lands on the host too. The camera answers to ${host.name}, and anything ${host.name} trusts to speak for it just handed you a key. [${now}/${MAX_MARKS}]{/lightblue-fg}`,
|
|
164
164
|
];
|
|
165
165
|
if (mode === 'attack') {
|
|
166
166
|
lines.push(` The housing is visibly forced -- the host FELT that one, even if nothing saw your face.`);
|
|
@@ -169,15 +169,15 @@ export class TapCommand extends Command {
|
|
|
169
169
|
lines.push(` Nothing logged, nothing flagged. You were never here.`);
|
|
170
170
|
}
|
|
171
171
|
if (host === room) {
|
|
172
|
-
lines.push(` {
|
|
172
|
+
lines.push(` {lightblue-fg}${now >= MAX_MARKS
|
|
173
173
|
? `The host thinks you belong now -- "hack" walks straight in.`
|
|
174
|
-
: `${hostLabel(host, { capital: true })} cracks easier with every key you hold${hint(` -- "jack in" and "hack", or come back for another lens`)}.`}{/
|
|
174
|
+
: `${hostLabel(host, { capital: true })} cracks easier with every key you hold${hint(` -- "jack in" and "hack", or come back for another lens`)}.`}{/lightblue-fg}`);
|
|
175
175
|
}
|
|
176
176
|
else {
|
|
177
|
-
lines.push(` {
|
|
177
|
+
lines.push(` {lightblue-fg}These lenses ride the site network, so the key fits ${hostLabel(host)}${hint(` -- "jack in", "go ${host.name}", "hack"`)}.{/lightblue-fg}`);
|
|
178
178
|
}
|
|
179
179
|
// A mark is all canSnoopFeeds ever wanted (surveillance.ts).
|
|
180
|
-
lines.push(` {
|
|
180
|
+
lines.push(` {lightblue-fg}And the eyes are half yours already${hint(` -- jacked in, "snoop <room>" rides any feed on this network`)}.{/lightblue-fg}`);
|
|
181
181
|
lines.push(...godLines);
|
|
182
182
|
this.scene.updateStatus();
|
|
183
183
|
return lines.join('\n');
|
|
@@ -67,7 +67,7 @@ export class ThreadCommand extends Command {
|
|
|
67
67
|
const lines = [`COMPLEX FORMS (thread <form> <level>)`];
|
|
68
68
|
for (const f of FORMS) {
|
|
69
69
|
const held = actor.sustainedForms.some(s => s.key === f.key);
|
|
70
|
-
lines.push(` ${f.name.padEnd(16)} ${f.kind === 'sustained' ? '[sustained]' : '[instant] '} ${f.blurb}${held ? ' {
|
|
70
|
+
lines.push(` ${f.name.padEnd(16)} ${f.kind === 'sustained' ? '[sustained]' : '[instant] '} ${f.blurb}${held ? ' {lightblue-fg}(HELD){/lightblue-fg}' : ''}`);
|
|
71
71
|
}
|
|
72
72
|
if (actor.sustainedForms.length > 0) {
|
|
73
73
|
lines.push('', ` Holding ${actor.sustainedForms.length} form${actor.sustainedForms.length === 1 ? '' : 's'} (${sustainTotal(actor.sustainedLedger().filter(w => w.kind === 'form'))}).${hint(` ("thread drop <form>" releases.)`)}`);
|
|
@@ -5665,7 +5665,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
|
|
|
5665
5665
|
// works the grid while you're back in the meat (the AR-drop exit).
|
|
5666
5666
|
const remoteAgent = this.companions.find(c => c.kind === 'agent');
|
|
5667
5667
|
if (remoteAgent && player.plane !== 'matrix') {
|
|
5668
|
-
lines.push(`{
|
|
5668
|
+
lines.push(`{lightblue-fg}▣ DECK IN AR -- ${remoteAgent.npc.name} on the grid${remoteAgent.npc.objective ? ', working its directive' : ''}${hint(' ("jack in" to rejoin it, "recall" to fold it home)')}{/lightblue-fg}`);
|
|
5669
5669
|
}
|
|
5670
5670
|
// Off-plane context: which reality you're in, your persona's Matrix
|
|
5671
5671
|
// track (cold-sim damage lands there), and where your empty body lies.
|
|
@@ -5684,7 +5684,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
|
|
|
5684
5684
|
const track = jackedDeck
|
|
5685
5685
|
? ` Deck A${jackedDeck.attack} S${jackedDeck.sleaze} D${jackedDeck.dataProcessing} F${jackedDeck.firewall} ${jackedDeck.deckSummary()}${player.simMode === 'hot' ? ' +biofeedback' : ''}${pgms}`
|
|
5686
5686
|
: ` (living persona -- damage is REAL stun)`;
|
|
5687
|
-
lines.push(`{
|
|
5687
|
+
lines.push(`{lightblue-fg}▣ MATRIX ${(player.simMode ?? 'cold').toUpperCase()}-SIM${track} -- body at ${player.bodyRoom?.name ?? '???'}{/lightblue-fg}`);
|
|
5688
5688
|
}
|
|
5689
5689
|
else if (player.plane === 'astral') {
|
|
5690
5690
|
lines.push(`{magenta-fg}✧ ASTRAL -- ${player.astralTicks} move${player.astralTicks === 1 ? '' : 's'} out -- body at ${player.bodyRoom?.name ?? '???'}{/magenta-fg}`);
|
|
@@ -5776,7 +5776,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
|
|
|
5776
5776
|
const dockW = mapWidth ?? 15;
|
|
5777
5777
|
const lines = hosts.length > 0
|
|
5778
5778
|
? hosts.map(h => hostDockLine(h, this.player, dockW))
|
|
5779
|
-
: ['{
|
|
5779
|
+
: ['{lightblue-fg}nothing overhead{/lightblue-fg}'];
|
|
5780
5780
|
lines.push(caption(this.player.insideHost ? `inside ${this.player.insideHost.name}` : `on the grid from ${gridVicinity(this.player).name}`, mapWidth));
|
|
5781
5781
|
this.setMapOverlay(lines);
|
|
5782
5782
|
if (onTheGrid) {
|
|
@@ -8,6 +8,7 @@ import { hint } from '../utilities/hints.js';
|
|
|
8
8
|
import { Category } from '../types/shared/item-enum.js';
|
|
9
9
|
import { Logger } from '../utilities/logger.js';
|
|
10
10
|
import { CALL_ICON, CALL_COLOR } from '../utilities/comm-style.js';
|
|
11
|
+
import { FEED_COLOR } from '../utilities/matrix-style.js';
|
|
11
12
|
// The Physical limit already lives here (subduing, p.195) -- imported
|
|
12
13
|
// rather than re-derived so meat combat and the grapple cannot drift
|
|
13
14
|
// into two different formulas for the same canon number.
|
|
@@ -2851,7 +2852,7 @@ export class Player extends AbstractPlayer {
|
|
|
2851
2852
|
// as before -- only the human's log line is dropped.
|
|
2852
2853
|
if (quiet)
|
|
2853
2854
|
return;
|
|
2854
|
-
this.logger.logWithColor(`${actor.name} ${verb} ${details}`,
|
|
2855
|
+
this.logger.logWithColor(`${actor.name} ${verb} ${details}`, FEED_COLOR);
|
|
2855
2856
|
}
|
|
2856
2857
|
}
|
|
2857
2858
|
performAction(verb, details, opts) {
|
|
@@ -256,7 +256,7 @@ export function aroBlock(scene, actor, room) {
|
|
|
256
256
|
const tags = aroTags(scene, actor, room);
|
|
257
257
|
if (tags.length === 0)
|
|
258
258
|
return '';
|
|
259
|
-
return `{
|
|
259
|
+
return `{lightblue-fg}AR OVERLAY:{/lightblue-fg}\n${tags.map(t => ` {lightblue-fg}${t}{/lightblue-fg}`).join('\n')}`;
|
|
260
260
|
}
|
|
261
261
|
/** Gear that talks to the grid on its own, lying LOOSE in the room.
|
|
262
262
|
* Weapons are absent here because a carried one is handled above, as
|
|
@@ -475,7 +475,7 @@ export class CombatEncounter {
|
|
|
475
475
|
// A persona has no metres to spend: the grid sees no distance.
|
|
476
476
|
const ground = this.arena.kind === 'room' ? `; ${this.movementLine(p.actor)}` : '';
|
|
477
477
|
const budgetLine = `Your Action Phase -- Combat Turn ${this.turn}, pass ${this.pass}, Initiative ${p.score}. ${this.budget.describe()}${ground}. "end turn" when you're done.`;
|
|
478
|
-
this.logger.log(`\n{
|
|
478
|
+
this.logger.log(`\n{yellow-fg}${budgetLine}{/yellow-fg}`, { actor: p.actor.name });
|
|
479
479
|
this.scene.updateStatus();
|
|
480
480
|
this.onHumanPhase?.(p.actor, this);
|
|
481
481
|
return;
|
|
@@ -742,7 +742,7 @@ export class CombatEncounter {
|
|
|
742
742
|
return undefined;
|
|
743
743
|
if (this.phaseActor === player && this.budget) {
|
|
744
744
|
const ground = this.arena.kind === 'room' ? ` · ${player.movementLeftMeters} m` : '';
|
|
745
|
-
return `{
|
|
745
|
+
return `{yellow-fg}⏱ YOUR PHASE{/yellow-fg} T${this.turn}/P${this.pass} Init ${p.score} · ${this.budget.describe()}${ground} · "end turn"`;
|
|
746
746
|
}
|
|
747
747
|
const who = this.phaseActor ? `${this.phaseActor.name} acting` : 'resolving';
|
|
748
748
|
return `⏱ COMBAT T${this.turn}/P${this.pass} Init ${p.score} · ${who}${p.fullDefenseTurn === this.turn ? ' · FULL DEFENSE' : ''}`;
|
|
@@ -106,6 +106,6 @@ export function hostDockLine(room, actor, width) {
|
|
|
106
106
|
const tag = room.hostCracked ? ' open' : marks > 0 ? ` ${marks}/3` : '';
|
|
107
107
|
const raw = `${inside ? '▣' : '●'} ${room.name} HR${room.hostRating}${tag}`;
|
|
108
108
|
const cut = [...raw].slice(0, Math.max(4, width)).join('');
|
|
109
|
-
return `{
|
|
109
|
+
return `{lightblue-fg}${cut}{/lightblue-fg}`;
|
|
110
110
|
}
|
|
111
111
|
//# sourceMappingURL=grid-reach.js.map
|
|
@@ -440,20 +440,20 @@ export function gridSculpt(actor, room) {
|
|
|
440
440
|
const purpose = room.host?.purpose;
|
|
441
441
|
const sculpt = room.host?.sculpt;
|
|
442
442
|
return [
|
|
443
|
-
`{
|
|
444
|
-
`{
|
|
443
|
+
`{lightblue-fg}INSIDE :: ${hostLabel(room, { capital: true }).toUpperCase()} [HR ${room.hostRating}]${purpose ? ` -- ${purpose}` : ''}{/lightblue-fg}`,
|
|
444
|
+
`{lightblue-fg}${sculpt ?? 'Architecture all the way around -- the outside grid is a wall away and might as well be weather.'}{/lightblue-fg}`,
|
|
445
445
|
].join('\n');
|
|
446
446
|
}
|
|
447
447
|
// ON THE GRID (SR5 pp.217-218): no street under the persona -- a black
|
|
448
448
|
// flatland, the body's room named only because that is where the
|
|
449
449
|
// signal comes from. A host directly overhead gets a line of its own.
|
|
450
450
|
const body = actor.bodyRoom ?? room;
|
|
451
|
-
const header = `{
|
|
451
|
+
const header = `{lightblue-fg}THE GRID :: jacked in from ${body.name.toUpperCase()}{/lightblue-fg}`;
|
|
452
452
|
const grid = actor.currentGrid;
|
|
453
|
-
const flat = `{
|
|
453
|
+
const flat = `{lightblue-fg}Black flatland under a black sky -- the icons are the only things out here.${grid ? ` Riding ${grid.name}${grid.userPenalty ? ' (-2 on everything you do, p.233)' : ''}.` : ''}{/lightblue-fg}`;
|
|
454
454
|
if (!room.hasNode)
|
|
455
455
|
return `${header}\n${flat}`;
|
|
456
|
-
return `${header}\n${flat}\n{
|
|
456
|
+
return `${header}\n${flat}\n{lightblue-fg}${hostLabel(room, { capital: true })} hangs directly overhead, sealed. What it holds is inside it.{/lightblue-fg}`;
|
|
457
457
|
}
|
|
458
458
|
/**
|
|
459
459
|
* The icons rendered as the standard cyan block, or the thin-grid line.
|
|
@@ -482,19 +482,19 @@ export function gridIconBlock(scene, actor, room, rooms) {
|
|
|
482
482
|
if (actor.insideHost || !rooms) {
|
|
483
483
|
const icons = gridIcons(scene, actor, room);
|
|
484
484
|
if (icons.length === 0) {
|
|
485
|
-
return `{
|
|
485
|
+
return `{lightblue-fg}Thin grid out here -- background noise, nothing worth cracking.{/lightblue-fg}`;
|
|
486
486
|
}
|
|
487
|
-
return `{
|
|
487
|
+
return `{lightblue-fg}ICONS IN REACH:{/lightblue-fg}\n${icons.map(i => ` {lightblue-fg}${i}{/lightblue-fg}`).join('\n')}`;
|
|
488
488
|
}
|
|
489
489
|
const out = [];
|
|
490
490
|
const hosts = hostsInReach(rooms, actor);
|
|
491
491
|
out.push(hosts.length > 0
|
|
492
|
-
? `{
|
|
493
|
-
: `{
|
|
492
|
+
? `{lightblue-fg}HOSTS OVERHEAD:{/lightblue-fg}\n${hosts.map(h => ` {lightblue-fg}${hostLine(h, actor)}{/lightblue-fg}`).join('\n')}`
|
|
493
|
+
: `{lightblue-fg}Nothing overhead -- no host stands over this district.{/lightblue-fg}`);
|
|
494
494
|
const near = gridIcons(scene, actor, gridVicinity(actor)).filter(i => !isHostLine(i));
|
|
495
495
|
out.push(near.length > 0
|
|
496
|
-
? `{
|
|
497
|
-
: `{
|
|
496
|
+
? `{lightblue-fg}ICONS IN REACH:{/lightblue-fg}\n${near.map(i => ` {lightblue-fg}${i}{/lightblue-fg}`).join('\n')}`
|
|
497
|
+
: `{lightblue-fg}Nothing near -- background noise around your signal.{/lightblue-fg}`);
|
|
498
498
|
// FARTHER OUT, WITHOUT AN ADDRESS (SR5 p.235, p.243): Matrix Perception
|
|
499
499
|
// never tells you where a device physically sits -- that is Trace Icon,
|
|
500
500
|
// two marks and an opposed test. So far icons are listed by the noise
|
|
@@ -519,9 +519,9 @@ export function gridIconBlock(scene, actor, room, rooms) {
|
|
|
519
519
|
byBand.set(noise, list);
|
|
520
520
|
}
|
|
521
521
|
const far = [...byBand.entries()].sort((a, b) => a[0] - b[0])
|
|
522
|
-
.map(([noise, names]) => ` {
|
|
522
|
+
.map(([noise, names]) => ` {lightblue-fg}· dim, noise -${noise}: ${names.join(', ')}{/lightblue-fg}`);
|
|
523
523
|
if (far.length > 0)
|
|
524
|
-
out.push(`{
|
|
524
|
+
out.push(`{lightblue-fg}FARTHER OUT -- dimmer with distance:{/lightblue-fg}\n${far.join('\n')}`);
|
|
525
525
|
// A blank line between the distance bands (user, 2026-09-02): three
|
|
526
526
|
// sections read as three when they do not touch.
|
|
527
527
|
return out.join('\n\n');
|
|
@@ -536,7 +536,7 @@ export function gridIconBlock(scene, actor, room, rooms) {
|
|
|
536
536
|
* the other personas, and the files. Cut to the dock's rows and columns.
|
|
537
537
|
*/
|
|
538
538
|
export function hostInteriorPanel(scene, actor, host, rows, cols) {
|
|
539
|
-
const cut = (raw) => `{
|
|
539
|
+
const cut = (raw) => `{lightblue-fg}${[...raw].slice(0, Math.max(4, cols)).join('')}{/lightblue-fg}`;
|
|
540
540
|
const lines = [];
|
|
541
541
|
lines.push(cut(`INSIDE ${host.name}`));
|
|
542
542
|
if (host.purpose)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const MATRIX_COLOR = 'lightblue';
|
|
2
|
+
export const FEED_COLOR = 'white';
|
|
3
|
+
export const TURN_COLOR = 'yellow';
|
|
4
|
+
/** Matrix-plane prose, tagged. */
|
|
5
|
+
export function mx(text) {
|
|
6
|
+
return `{${MATRIX_COLOR}-fg}${text}{/${MATRIX_COLOR}-fg}`;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=matrix-style.js.map
|
|
@@ -58,10 +58,10 @@ export function accrueOverwatch(scene, actor, defenseHits, why) {
|
|
|
58
58
|
// The grid's built-in warning system (p.221): subtle ripples, once
|
|
59
59
|
// per band -- the only free hint the player ever gets.
|
|
60
60
|
if (before < 30 && actor.overwatchScore >= 30) {
|
|
61
|
-
return { lines: [`{
|
|
61
|
+
return { lines: [`{lightblue-fg}The grid RIPPLES -- hard, close, and looking. Something vast has nearly found the thread you're hanging by. ("reboot" is a clean slate.){/lightblue-fg}`], converged: false };
|
|
62
62
|
}
|
|
63
63
|
if (before < 20 && actor.overwatchScore >= 20) {
|
|
64
|
-
return { lines: [`{
|
|
64
|
+
return { lines: [`{lightblue-fg}A ripple crosses the grid -- subtle, wrong, deliberate. Somewhere above, an eye has started counting your fingerprints.{/lightblue-fg}`], converged: false };
|
|
65
65
|
}
|
|
66
66
|
return { lines: [], converged: false };
|
|
67
67
|
}
|
|
@@ -107,7 +107,7 @@ export function enterMatrix(scene, actor, mode) {
|
|
|
107
107
|
// half-done, which would be a fresh canon violation wearing a
|
|
108
108
|
// feature's clothes. See the PR for CgJ6uTfEvTd8JXdDN.
|
|
109
109
|
actor.activeDeck = actor.isTechnomancer() ? undefined : actor.getCyberdeck();
|
|
110
|
-
actor.performAction('jacks in', `slumping where they stand, eyes flickering (${mode}-sim)
|
|
110
|
+
actor.performAction('jacks in', `slumping where they stand, eyes flickering (${mode}-sim)`, { quiet: scene.isHumanControlled?.(actor) ?? false });
|
|
111
111
|
scene.addWorldEvent(`${actor.name} jacked into the Matrix in ${actor.bodyRoom.name}.`);
|
|
112
112
|
Logger.getInstance().write(`${actor.name} entered the Matrix (${mode}-sim, ${actor.activeDeck?.name ?? (actor.isTechnomancer() ? 'living persona' : 'no deck?!')}) from ${actor.bodyRoom.name}.`);
|
|
113
113
|
const hotWarning = mode === 'hot'
|
|
@@ -267,7 +267,7 @@ export function leaveMatrix(scene, actor, opts) {
|
|
|
267
267
|
actor.bodyRoom = undefined;
|
|
268
268
|
lines.push(`You're back in your body in ${body.name}.`);
|
|
269
269
|
}
|
|
270
|
-
actor.performAction('jacks out', 'stirring awake');
|
|
270
|
+
actor.performAction('jacks out', 'stirring awake', { quiet: scene.isHumanControlled?.(actor) ?? false });
|
|
271
271
|
scene.addWorldEvent(`${actor.name} jacked out of the Matrix.`);
|
|
272
272
|
scene.updateStatus();
|
|
273
273
|
return lines;
|
|
@@ -449,7 +449,7 @@ export function fileReach(actor, room) {
|
|
|
449
449
|
*/
|
|
450
450
|
export function planeTintItemName(item, viewerPlane) {
|
|
451
451
|
if (item.plane === 'matrix') {
|
|
452
|
-
return `{
|
|
452
|
+
return `{lightblue-fg}${item.name} [data]{/lightblue-fg}`;
|
|
453
453
|
}
|
|
454
454
|
if (item.plane === 'astral') {
|
|
455
455
|
return `{magenta-fg}${item.name} [astral]{/magenta-fg}`;
|
|
@@ -24,6 +24,7 @@ import { join, dirname } from 'node:path';
|
|
|
24
24
|
import { Logger } from './logger.js';
|
|
25
25
|
import { hint } from './hints.js';
|
|
26
26
|
import { CALL_ICON, CALL_COLOR, END_CALL_SENTINEL } from './comm-style.js';
|
|
27
|
+
import { FEED_COLOR } from './matrix-style.js';
|
|
27
28
|
import { ENGINE_VERSION } from '../engine-version.js';
|
|
28
29
|
import { authToken, fetchSave } from './cloud-saves.js';
|
|
29
30
|
import { saveSlug, restorePlayer, writeSaveAtomic } from './persistence.js';
|
|
@@ -1143,7 +1144,7 @@ export class SharedRunSession {
|
|
|
1143
1144
|
break;
|
|
1144
1145
|
}
|
|
1145
1146
|
for (const line of ev.text.split('\n'))
|
|
1146
|
-
g.logBox?.pushLine(`{
|
|
1147
|
+
g.logBox?.pushLine(`{${FEED_COLOR}-fg}${line}{/${FEED_COLOR}-fg}`);
|
|
1147
1148
|
Logger.getInstance().transcript(ev.text);
|
|
1148
1149
|
g.followLog?.();
|
|
1149
1150
|
if (ev.kind === 'death' && ev.data?.player === g.player.name) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maka/maka-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.184.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
|
|
6
6
|
"description": "A command line tool for scaffolding Meteor 3.x applications using React.",
|