@maka/maka-cli 5.64.0 → 5.65.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/backlog.d.ts +29 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js +146 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.d.ts +40 -13
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js +107 -25
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.d.ts +11 -15
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js +13 -16
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/buy.d.ts +8 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/buy.js +30 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/buy.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.d.ts +40 -49
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js +121 -160
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.d.ts +7 -8
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js +13 -13
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.d.ts +30 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.js +65 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/dispel.d.ts +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/dispel.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/dispel.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +25 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.d.ts +2 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js +2 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +58 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +18 -4
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/move.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.d.ts +2 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/posture.d.ts +45 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/posture.js +115 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/posture.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +35 -24
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/take.js +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/take.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.d.ts +17 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.js +136 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.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 +15 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.d.ts +82 -43
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +419 -263
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js +82 -84
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.d.ts +23 -4
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js +95 -79
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/seed-migration.d.ts +30 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/seed-migration.js +176 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/seed-migration.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/game.js +11 -5
- package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/headless.js +24 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/_index.d.ts +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/_index.js +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/_index.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/device.d.ts +121 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/device.js +145 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/device.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/door.d.ts +27 -8
- package/bundle/typescript/src/commands/game/sideQuest/models/door.js +15 -10
- package/bundle/typescript/src/commands/game/sideQuest/models/door.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.d.ts +81 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +132 -21
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +68 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js +102 -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 +32 -46
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js +38 -63
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.d.ts +1 -4
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +0 -22
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/scenes/scene1.json +78 -109
- package/bundle/typescript/src/commands/game/sideQuest/scenes/scene2.json +4 -101
- package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +24 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/device-seed.d.ts +52 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/device-seed.js +2 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/device-seed.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/legacy-puzzle-seed.d.ts +63 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/legacy-puzzle-seed.js +2 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/legacy-puzzle-seed.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/player-seed.d.ts +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/room-seed.d.ts +4 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/scene-seed.d.ts +3 -2
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.d.ts +2 -28
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js +1 -14
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/ui.js +24 -0
- package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/affordances.d.ts +55 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/affordances.js +36 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/affordances.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-review.d.ts +45 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-review.js +116 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-review.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.d.ts +67 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.js +56 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js +37 -4
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/credentials.d.ts +26 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/credentials.js +48 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/credentials.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/devices.d.ts +23 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/devices.js +55 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/devices.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.d.ts +57 -2
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js +46 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/log-style.d.ts +16 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/log-style.js +18 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/log-style.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js +68 -38
- package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.d.ts +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.d.ts +36 -12
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +101 -27
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/use-target.d.ts +88 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/use-target.js +113 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/use-target.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +54 -5
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
- package/bundle/typescript/src/maka.js +1 -1
- package/bundle/typescript/src/maka.js.map +1 -1
- package/bundle/typescript/src/tools/sdk-loader/relocate.d.ts +19 -2
- package/bundle/typescript/src/tools/sdk-loader/relocate.js +22 -2
- package/bundle/typescript/src/tools/sdk-loader/relocate.js.map +1 -1
- package/package.json +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.d.ts +0 -6
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js +0 -72
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js.map +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.d.ts +0 -6
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js +0 -26
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js.map +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.d.ts +0 -152
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js +0 -393
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js.map +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.d.ts +0 -28
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.js +0 -2
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.js.map +0 -1
|
@@ -11,6 +11,14 @@ export declare class BuyCommand extends Command implements ICommand {
|
|
|
11
11
|
protected static verb: string;
|
|
12
12
|
protected static description: string;
|
|
13
13
|
execute(args?: string[]): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* The shelf, flattened in PRINT ORDER across every vendor in the room
|
|
16
|
+
* -- the list "buy <n>" indexes into. One function so the numbers a
|
|
17
|
+
* player reads and the numbers the parser honours cannot drift apart:
|
|
18
|
+
* browse() and purchase() both call it rather than each walking the
|
|
19
|
+
* vendors themselves.
|
|
20
|
+
*/
|
|
21
|
+
private shelf;
|
|
14
22
|
private browse;
|
|
15
23
|
/** Is what they asked for inside a present contact's TRADE (the same
|
|
16
24
|
* domain list their AI is briefed on in npc.ts)? Returns the item
|
|
@@ -2,6 +2,8 @@ import { Command } from './command.js';
|
|
|
2
2
|
import { hint } from '../utilities/hints.js';
|
|
3
3
|
import { priceOf, vendorsInRoom, waresOf, shelfNote } from '../utilities/commerce.js';
|
|
4
4
|
import { findCatalogItem, ROLE_DOMAINS } from '../utilities/catalog.js';
|
|
5
|
+
import { optionMark } from '../utilities/log-style.js';
|
|
6
|
+
import { fuzzyPickName } from '../utilities/fuzzy-match.js';
|
|
5
7
|
/**
|
|
6
8
|
* Diegetic shopping: "browse" (or bare "buy") in a vendor's room reads
|
|
7
9
|
* their shelves with live prices; "buy <item>" slides the nuyen across
|
|
@@ -31,19 +33,36 @@ export class BuyCommand extends Command {
|
|
|
31
33
|
}
|
|
32
34
|
return this.purchase(args.join(' '), vendors);
|
|
33
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* The shelf, flattened in PRINT ORDER across every vendor in the room
|
|
38
|
+
* -- the list "buy <n>" indexes into. One function so the numbers a
|
|
39
|
+
* player reads and the numbers the parser honours cannot drift apart:
|
|
40
|
+
* browse() and purchase() both call it rather than each walking the
|
|
41
|
+
* vendors themselves.
|
|
42
|
+
*/
|
|
43
|
+
shelf(vendors) {
|
|
44
|
+
const out = [];
|
|
45
|
+
for (const vendor of vendors) {
|
|
46
|
+
for (const item of waresOf(this.actor.currentLocation, vendor.name))
|
|
47
|
+
out.push(item);
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
34
51
|
browse(vendors, room) {
|
|
35
52
|
const lines = [];
|
|
53
|
+
let nth = 0;
|
|
36
54
|
for (const vendor of vendors) {
|
|
37
55
|
const wares = waresOf(this.actor.currentLocation, vendor.name);
|
|
38
56
|
lines.push(`${vendor.name}'s wares:`);
|
|
39
57
|
for (const item of wares) {
|
|
58
|
+
nth += 1;
|
|
40
59
|
const price = priceOf(item);
|
|
41
60
|
const dots = '.'.repeat(Math.max(2, 28 - item.name.length));
|
|
42
|
-
lines.push(
|
|
61
|
+
lines.push(`${optionMark(nth)}${item.name} ${dots} ${price} nuyen${shelfNote(item)}`);
|
|
43
62
|
}
|
|
44
63
|
}
|
|
45
64
|
lines.push('');
|
|
46
|
-
lines.push(`You're carrying ${this.actor.currency} nuyen.${hint(` "buy <item>"
|
|
65
|
+
lines.push(`You're carrying ${this.actor.currency} nuyen.${hint(` "buy <item>" -- or "buy <number>" off this list.`)}`);
|
|
47
66
|
this.logger.write(`BuyCommand: ${this.actor.name} browsed in ${room.name}.`);
|
|
48
67
|
return lines.join('\n');
|
|
49
68
|
}
|
|
@@ -71,6 +90,15 @@ export class BuyCommand extends Command {
|
|
|
71
90
|
purchase(wanted, vendors) {
|
|
72
91
|
const actor = this.actor;
|
|
73
92
|
const room = actor.currentLocation;
|
|
93
|
+
// "buy 3" -- the row browse() printed. Resolved through the shared
|
|
94
|
+
// resolver against the same flattened shelf, so the index can only
|
|
95
|
+
// ever mean what was on screen. A name that IS a number still wins
|
|
96
|
+
// (see fuzzy-match.ts), and an out-of-range number falls through to
|
|
97
|
+
// the ordinary not-on-the-shelf refusal.
|
|
98
|
+
const shelf = this.shelf(vendors);
|
|
99
|
+
const byIndex = fuzzyPickName(wanted, shelf.map(i => i.name), { index: true });
|
|
100
|
+
if (byIndex)
|
|
101
|
+
wanted = byIndex;
|
|
74
102
|
const item = room.inventory.getItem(wanted) ?? undefined;
|
|
75
103
|
if (!item) {
|
|
76
104
|
// NOT ON THE SHELF IS NOT THE SAME AS NOT AVAILABLE (playtest
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buy.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/buy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"buy.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/buy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,61 +1,52 @@
|
|
|
1
1
|
import { Command, ICommand } from './command.js';
|
|
2
|
-
import {
|
|
3
|
-
import { PuzzleTarget } from '../models/room.js';
|
|
2
|
+
import { Device } from '../models/device.js';
|
|
4
3
|
/**
|
|
5
|
-
* Shared implementation for pick/hack/cast/
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
4
|
+
* Shared implementation for pick/breach/hack/cast/dispel -- FORCING a
|
|
5
|
+
* device rather than opening it the way it was meant to open.
|
|
6
|
+
*
|
|
7
|
+
* The gate check (is it already open? does this verb even bite on this
|
|
8
|
+
* kind of thing?) always runs first and synchronously, so a doomed
|
|
9
|
+
* attempt never makes the player sit through an interactive challenge
|
|
10
|
+
* they were never going to be allowed to attempt. Each concrete command
|
|
11
|
+
* differs in its verb, the kind of device it works, the "nothing to do
|
|
12
|
+
* that to" message, how the outcome gets determined (see
|
|
13
|
+
* determineOutcome() -- every real one overrides it with a skill roll),
|
|
14
|
+
* and what failure costs beyond the noise (onForceFailure()).
|
|
15
|
+
*
|
|
16
|
+
* WHAT LEFT WITH THE PUZZLE MECHANIC: there is no burned route any
|
|
17
|
+
* more. A lock you failed to pick is a lock you can try again, which is
|
|
18
|
+
* what a lock IS -- the one-shot shortcut was a property of a riddle
|
|
19
|
+
* pretending to be an object. Failure is still loud and still raises
|
|
20
|
+
* the world; it just doesn't spend the thing.
|
|
14
21
|
*/
|
|
15
22
|
export declare abstract class BypassCommand extends Command implements ICommand {
|
|
16
|
-
|
|
17
|
-
protected abstract
|
|
23
|
+
/** The kind of device this verb works. */
|
|
24
|
+
protected abstract deviceKind: Device['kind'];
|
|
25
|
+
protected abstract noDeviceMessage: string;
|
|
18
26
|
/** The word the player typed -- used in disambiguation prompts. Two
|
|
19
|
-
* commands can share a
|
|
20
|
-
*
|
|
27
|
+
* commands can share a kind (pick and breach both work a lock), so
|
|
28
|
+
* this can't be derived from it. */
|
|
21
29
|
protected abstract verbName: string;
|
|
22
|
-
/** Optional: replaces the
|
|
23
|
-
*
|
|
24
|
-
*
|
|
30
|
+
/** Optional: replaces the stock per-kind failure line -- for a verb
|
|
31
|
+
* that shares a kind but fails differently (a breach doesn't snap a
|
|
32
|
+
* pick). */
|
|
25
33
|
protected failureFlavor?: string;
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* breach used to re-refuse a breach with the snapped-pick line -- a
|
|
29
|
-
* pick the player never owned (playtest 2026-08-27). A verb that
|
|
30
|
-
* shares a bypassType but burns differently says so here. */
|
|
31
|
-
protected burnedFlavor?: string;
|
|
32
|
-
/** Fallback: a flat coin flip. Every real bypass overrides this with a
|
|
33
|
-
* skill roll (pick: Agility+locksmith, hack: Logic+hacking, bluff:
|
|
34
|
-
* Charisma+con, cast: the casting pool). */
|
|
34
|
+
/** Fallback: a flat coin flip. Every real one overrides this with a
|
|
35
|
+
* skill roll. */
|
|
35
36
|
protected determineOutcome(): Promise<boolean>;
|
|
37
|
+
/** Type-specific teeth for a failed forcing, beyond the noise.
|
|
38
|
+
* Returns narration lines. */
|
|
39
|
+
protected onForceFailure(): Promise<string[]>;
|
|
40
|
+
/** Type-specific consequences of a forcing that WORKED, before the
|
|
41
|
+
* success message renders (see breach.ts: smashing through is loud
|
|
42
|
+
* whether or not it gives). */
|
|
43
|
+
protected onForceSuccess(device: Device): Promise<string[]>;
|
|
36
44
|
/**
|
|
37
|
-
*
|
|
38
|
-
* the
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* runs through the real damage tracks and can still knock out or kill.
|
|
43
|
-
*/
|
|
44
|
-
protected onBypassFailure(): Promise<string[]>;
|
|
45
|
-
/**
|
|
46
|
-
* Type-specific consequences of a bypass that WORKED, before the success
|
|
47
|
-
* message renders. Default: nothing -- picking, hacking, and bluffing
|
|
48
|
-
* are quiet when they land. The forceful bypass overrides this (see
|
|
49
|
-
* breach.ts): smashing through a barrier is loud whether or not it
|
|
50
|
-
* gives, so success still raises the world and ends any sneak.
|
|
51
|
-
*/
|
|
52
|
-
protected onBypassSuccess(target: PuzzleTarget): Promise<string[]>;
|
|
53
|
-
/**
|
|
54
|
-
* There's no typed answer here to disambiguate with (unlike solve.ts),
|
|
55
|
-
* so with more than one barrier in the room the player has to name which
|
|
56
|
-
* one: a direction ("pick north", for a locked door) or a word from the
|
|
57
|
-
* barrier's own name ("pick maglock"). With only one candidate, a bare
|
|
58
|
-
* "pick" still works exactly as before.
|
|
45
|
+
* There's no typed answer here to disambiguate with, so with more
|
|
46
|
+
* than one device in the room the player has to name which one: a
|
|
47
|
+
* direction ("pick north", for a device holding a door) or a word
|
|
48
|
+
* from its own name ("pick maglock"). With only one candidate, a bare
|
|
49
|
+
* "pick" still works.
|
|
59
50
|
*/
|
|
60
51
|
private resolveTarget;
|
|
61
52
|
execute(args: string[]): Promise<string>;
|
|
@@ -1,64 +1,55 @@
|
|
|
1
1
|
import { Command } from './command.js';
|
|
2
2
|
import { exitSpot, ensureAtSpot } from '../utilities/spots.js';
|
|
3
|
+
import { applyDeviceOpened } from '../utilities/devices.js';
|
|
3
4
|
/**
|
|
4
|
-
* Shared implementation for pick/hack/cast/
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
5
|
+
* Shared implementation for pick/breach/hack/cast/dispel -- FORCING a
|
|
6
|
+
* device rather than opening it the way it was meant to open.
|
|
7
|
+
*
|
|
8
|
+
* The gate check (is it already open? does this verb even bite on this
|
|
9
|
+
* kind of thing?) always runs first and synchronously, so a doomed
|
|
10
|
+
* attempt never makes the player sit through an interactive challenge
|
|
11
|
+
* they were never going to be allowed to attempt. Each concrete command
|
|
12
|
+
* differs in its verb, the kind of device it works, the "nothing to do
|
|
13
|
+
* that to" message, how the outcome gets determined (see
|
|
14
|
+
* determineOutcome() -- every real one overrides it with a skill roll),
|
|
15
|
+
* and what failure costs beyond the noise (onForceFailure()).
|
|
16
|
+
*
|
|
17
|
+
* WHAT LEFT WITH THE PUZZLE MECHANIC: there is no burned route any
|
|
18
|
+
* more. A lock you failed to pick is a lock you can try again, which is
|
|
19
|
+
* what a lock IS -- the one-shot shortcut was a property of a riddle
|
|
20
|
+
* pretending to be an object. Failure is still loud and still raises
|
|
21
|
+
* the world; it just doesn't spend the thing.
|
|
13
22
|
*/
|
|
14
23
|
export class BypassCommand extends Command {
|
|
15
|
-
/** Optional: replaces the
|
|
16
|
-
*
|
|
17
|
-
*
|
|
24
|
+
/** Optional: replaces the stock per-kind failure line -- for a verb
|
|
25
|
+
* that shares a kind but fails differently (a breach doesn't snap a
|
|
26
|
+
* pick). */
|
|
18
27
|
failureFlavor;
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
* breach used to re-refuse a breach with the snapped-pick line -- a
|
|
22
|
-
* pick the player never owned (playtest 2026-08-27). A verb that
|
|
23
|
-
* shares a bypassType but burns differently says so here. */
|
|
24
|
-
burnedFlavor;
|
|
25
|
-
/** Fallback: a flat coin flip. Every real bypass overrides this with a
|
|
26
|
-
* skill roll (pick: Agility+locksmith, hack: Logic+hacking, bluff:
|
|
27
|
-
* Charisma+con, cast: the casting pool). */
|
|
28
|
+
/** Fallback: a flat coin flip. Every real one overrides this with a
|
|
29
|
+
* skill roll. */
|
|
28
30
|
async determineOutcome() {
|
|
29
31
|
return Math.random() < 0.5;
|
|
30
32
|
}
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
* lines. Default: nothing extra -- the cost of a snapped pick or a blown
|
|
35
|
-
* story is the burned shortcut and a district that heard about it. The
|
|
36
|
-
* spell bypass overrides this with ward backlash (see cast.ts), which
|
|
37
|
-
* runs through the real damage tracks and can still knock out or kill.
|
|
38
|
-
*/
|
|
39
|
-
async onBypassFailure() {
|
|
33
|
+
/** Type-specific teeth for a failed forcing, beyond the noise.
|
|
34
|
+
* Returns narration lines. */
|
|
35
|
+
async onForceFailure() {
|
|
40
36
|
return [];
|
|
41
37
|
}
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
* gives, so success still raises the world and ends any sneak.
|
|
48
|
-
*/
|
|
49
|
-
async onBypassSuccess(target) {
|
|
50
|
-
void target;
|
|
38
|
+
/** Type-specific consequences of a forcing that WORKED, before the
|
|
39
|
+
* success message renders (see breach.ts: smashing through is loud
|
|
40
|
+
* whether or not it gives). */
|
|
41
|
+
async onForceSuccess(device) {
|
|
42
|
+
void device;
|
|
51
43
|
return [];
|
|
52
44
|
}
|
|
53
45
|
/**
|
|
54
|
-
* There's no typed answer here to disambiguate with
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* "pick" still works
|
|
46
|
+
* There's no typed answer here to disambiguate with, so with more
|
|
47
|
+
* than one device in the room the player has to name which one: a
|
|
48
|
+
* direction ("pick north", for a device holding a door) or a word
|
|
49
|
+
* from its own name ("pick maglock"). With only one candidate, a bare
|
|
50
|
+
* "pick" still works.
|
|
59
51
|
*/
|
|
60
|
-
resolveTarget(args,
|
|
61
|
-
// "cast at hatch" / "pick at the maglock" -- connectives are free.
|
|
52
|
+
resolveTarget(args, devices) {
|
|
62
53
|
let words = [...args];
|
|
63
54
|
if (words[0]?.toLowerCase() === 'at')
|
|
64
55
|
words = words.slice(1);
|
|
@@ -66,160 +57,130 @@ export class BypassCommand extends Command {
|
|
|
66
57
|
words = words.slice(1);
|
|
67
58
|
const raw = words.join(' ').trim().toLowerCase();
|
|
68
59
|
if (!raw) {
|
|
69
|
-
if (
|
|
70
|
-
return {
|
|
71
|
-
const options =
|
|
60
|
+
if (devices.length === 1)
|
|
61
|
+
return { device: devices[0] };
|
|
62
|
+
const options = devices.map(d => d.opensExit ?? d.name).join(', ');
|
|
72
63
|
return { error: `There's more than one thing to ${this.verbName} at here -- say which: ${options}.` };
|
|
73
64
|
}
|
|
74
65
|
if (this.isValidDirection(raw)) {
|
|
75
|
-
const match =
|
|
76
|
-
return match ? {
|
|
66
|
+
const match = devices.find(d => d.opensExit === raw);
|
|
67
|
+
return match ? { device: match } : { error: `There's nothing to force in that direction.` };
|
|
77
68
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// (a real session tried "cast manabolt at hatch" three ways and
|
|
81
|
-
// bounced every time).
|
|
82
|
-
const matches = targets.filter(t => t.label.toLowerCase().includes(raw)
|
|
83
|
-
|| (t.puzzle.riddle ?? '').toLowerCase().includes(raw));
|
|
69
|
+
const matches = devices.filter(d => d.name.toLowerCase().includes(raw)
|
|
70
|
+
|| d.description.toLowerCase().includes(raw));
|
|
84
71
|
if (matches.length === 1)
|
|
85
|
-
return {
|
|
72
|
+
return { device: matches[0] };
|
|
86
73
|
if (matches.length > 1)
|
|
87
74
|
return { error: `That could mean more than one thing here -- be more specific.` };
|
|
88
|
-
// Generic
|
|
89
|
-
if (
|
|
90
|
-
return {
|
|
75
|
+
// Generic words land when there's only one thing here anyway.
|
|
76
|
+
if (devices.length === 1 && /^(lock|door|ward|barrier|seal|gate|hatch|glyph|field|sigil|way|node|terminal|panel|keypad)$/.test(raw)) {
|
|
77
|
+
return { device: devices[0] };
|
|
91
78
|
}
|
|
92
79
|
return { error: `There's nothing here called "${raw}".` };
|
|
93
80
|
}
|
|
94
81
|
async execute(args) {
|
|
95
82
|
const room = this.actor.currentLocation;
|
|
96
|
-
const
|
|
83
|
+
const all = room?.openableDevices() ?? [];
|
|
97
84
|
// THE ONLY HONEST "nothing here" (blocker 2026-08-27, "the barrier
|
|
98
85
|
// isn't allowing me to hack/pick/breach it"): the room holds no
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// every refusal goes through the gate.
|
|
107
|
-
if (allTargets.length === 0) {
|
|
108
|
-
return this.noPuzzleMessage;
|
|
86
|
+
// device at all. Filtering by KIND first made a wrong verb
|
|
87
|
+
// indistinguishable from an empty room, so a ward answered every
|
|
88
|
+
// physical verb by denying the door the player was staring at
|
|
89
|
+
// existed. Now the filter only picks a PREFERRED target and every
|
|
90
|
+
// refusal goes through canForce().
|
|
91
|
+
if (all.length === 0) {
|
|
92
|
+
return this.noDeviceMessage;
|
|
109
93
|
}
|
|
110
|
-
// WHO PICKS THE TARGET depends on whether the player named one.
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
//
|
|
116
|
-
// But "pick terminal" NAMES a thing, and the name settles which
|
|
117
|
-
// object is meant before the verb gets a say. Resolving that
|
|
118
|
-
// against same-type targets only was quietly wrong: resolveTarget's
|
|
119
|
-
// generic-noun fallback ("lock", "door", "terminal"...) fires
|
|
120
|
-
// whenever the candidate list has exactly one entry, so naming the
|
|
121
|
-
// terminal in a mixed room picked the MAGLOCK instead -- the right
|
|
122
|
-
// verb aimed at the wrong barrier, and it opened. Named targets
|
|
123
|
-
// therefore resolve against every barrier here; the gate below
|
|
124
|
-
// decides whether the verb suits the thing the player pointed at.
|
|
125
|
-
const mine = allTargets.filter(t => t.puzzle.bypassType === this.bypassType);
|
|
94
|
+
// WHO PICKS THE TARGET depends on whether the player named one. A
|
|
95
|
+
// bare "pick" in a room holding a maglock and a ward means the
|
|
96
|
+
// maglock. But "pick terminal" NAMES a thing, and the name settles
|
|
97
|
+
// which object is meant before the verb gets a say.
|
|
98
|
+
const mine = all.filter(d => d.kind === this.deviceKind);
|
|
126
99
|
const named = args.length > 0;
|
|
127
|
-
const primary = named ?
|
|
128
|
-
const {
|
|
129
|
-
let
|
|
130
|
-
if (!
|
|
131
|
-
|
|
132
|
-
// own barriers, which keeps the generic-noun convenience alive
|
|
133
|
-
// ("pick door" with one lock and one terminal still means the
|
|
134
|
-
// lock) without letting it hijack a name that DID match.
|
|
135
|
-
target = this.resolveTarget(args, mine).target;
|
|
100
|
+
const primary = named ? all : (mine.length > 0 ? mine : all);
|
|
101
|
+
const { device: preferred, error } = this.resolveTarget(args, primary);
|
|
102
|
+
let device = preferred;
|
|
103
|
+
if (!device && named && mine.length > 0) {
|
|
104
|
+
device = this.resolveTarget(args, mine).device;
|
|
136
105
|
}
|
|
137
|
-
if (!
|
|
138
|
-
return error ?? this.
|
|
106
|
+
if (!device) {
|
|
107
|
+
return error ?? this.noDeviceMessage;
|
|
139
108
|
}
|
|
140
|
-
// GATE BEFORE THE WALK
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
const gate = target.puzzle.checkBypassGate(this.bypassType);
|
|
109
|
+
// GATE BEFORE THE WALK: the gate is pure and synchronous, so a
|
|
110
|
+
// doomed attempt costs nothing at all -- and marching the player
|
|
111
|
+
// across the room only to tell them the verb was wrong is its own
|
|
112
|
+
// small insult.
|
|
113
|
+
const gate = device.canForce(this.verbName);
|
|
146
114
|
if (!gate.allowed) {
|
|
147
|
-
if (gate.reason === 'burned' && this.burnedFlavor)
|
|
148
|
-
return this.burnedFlavor;
|
|
149
115
|
return gate.message ?? `You can't do that here.`;
|
|
150
116
|
}
|
|
151
|
-
// "At" spots
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
117
|
+
// "At" spots: a device has a PLACE -- either its own atSpot, or the
|
|
118
|
+
// exit it holds. Out of combat you simply walk over; mid-exchange
|
|
119
|
+
// the crossing refuses.
|
|
120
|
+
// ATSPOT FIRST -- coordinator ruling 2026-08-27, reversing the
|
|
121
|
+
// original spec (`exitSpot(...) ?? atSpot`).
|
|
122
|
+
//
|
|
123
|
+
// atSpot is an AUTHOR'S EXPLICIT PLACEMENT; exitSpot is INFERRED.
|
|
124
|
+
// The migration only fills a device's atSpot from its exit's when
|
|
125
|
+
// the device had none of its own, so a device carrying BOTH means
|
|
126
|
+
// the seed said two different things -- and preferring the
|
|
127
|
+
// inference over the statement inverts the point of having the
|
|
128
|
+
// field. Generation starts emitting both once the generator moves
|
|
129
|
+
// to devices, so this is a decision about the future, not about
|
|
130
|
+
// the three seeds that exist today.
|
|
131
|
+
//
|
|
132
|
+
// It also keeps the refusal and the walk from contradicting each
|
|
133
|
+
// other: a locked door's refusal names WHERE THE MECHANISM IS, so
|
|
134
|
+
// walking the player somewhere else to touch it would say two
|
|
135
|
+
// things in one breath.
|
|
136
|
+
//
|
|
137
|
+
// NOT the pre-flip code's rule. bypass-command used to branch on
|
|
138
|
+
// door-ness (`door && direction ? exitSpot(...) : atSpot`); both
|
|
139
|
+
// call sites now ??-chain and agree with EACH OTHER, and with
|
|
140
|
+
// neither the old code nor the original spec. Do not "fix" one to
|
|
141
|
+
// match something older.
|
|
142
|
+
const where = device.atSpot
|
|
143
|
+
?? (device.opensExit ? exitSpot(room, device.opensExit) : undefined);
|
|
144
|
+
const reach = ensureAtSpot(this.actor, where);
|
|
159
145
|
if (reach.refusal)
|
|
160
146
|
return reach.refusal;
|
|
161
147
|
const crossNote = reach.line ? `${reach.line}\n` : '';
|
|
162
148
|
const succeeded = await this.determineOutcome();
|
|
163
|
-
const result =
|
|
149
|
+
const result = device.force(succeeded);
|
|
164
150
|
if (!result.success && this.failureFlavor) {
|
|
165
151
|
result.message = this.failureFlavor;
|
|
166
152
|
}
|
|
167
|
-
let
|
|
153
|
+
let consequence = [];
|
|
168
154
|
if (result.success) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
else if (target.puzzle.rewardItem) {
|
|
176
|
-
this.actor.inventory.addItem(target.puzzle.rewardItem);
|
|
177
|
-
this.scene.addWorldEvent(`${this.actor.name} bypassed "${target.puzzle.name}" (${this.bypassType}) in ${room.name}.`);
|
|
178
|
-
this.scene.updateInventory(this.scene.getPlayer().inventory);
|
|
179
|
-
}
|
|
180
|
-
// ROOM GRIDS (spatial wave 2026-08-25): the same terrain-clearing
|
|
181
|
-
// solve.ts does -- a bypass is just the risky route to the same
|
|
182
|
-
// outcome. A silent no-op for the overwhelming majority of
|
|
183
|
-
// puzzles that never synthesized blocking terrain.
|
|
184
|
-
const opened = room.clearTerrainFor(target.puzzle.name);
|
|
185
|
-
if (opened) {
|
|
186
|
-
successConsequence.push(`The ${opened} comes apart -- the way through is open.`);
|
|
187
|
-
this.scene.addWorldEvent(`${this.actor.name} cleared ${opened} in ${room.name} by bypassing "${target.puzzle.name}".`);
|
|
188
|
-
}
|
|
155
|
+
consequence = await this.onForceSuccess(device);
|
|
156
|
+
// ONE HOME FOR WHAT HAPPENS WHEN A DEVICE OPENS (see
|
|
157
|
+
// utilities/devices.ts). This and use.ts used to hand-roll the
|
|
158
|
+
// same four side effects and had already drifted apart.
|
|
159
|
+
consequence.push(...applyDeviceOpened(this.scene, this.actor, room, device, this.verbName));
|
|
189
160
|
}
|
|
190
161
|
if (result.alarmed) {
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
this.scene.addWorldEvent(`${this.actor.name}'s ${this.
|
|
195
|
-
|
|
196
|
-
this.game?.addHeat(2, `${this.bypassType} alarm on "${target.puzzle.name}"`);
|
|
162
|
+
// NPCs already listen for world events (scene.ts's
|
|
163
|
+
// getWorldEventsSummary()), so this alone lets them react without
|
|
164
|
+
// a dedicated alarm subsystem.
|
|
165
|
+
this.scene.addWorldEvent(`${this.actor.name}'s ${this.verbName} attempt on "${device.name}" in ${room.name} went loud.`);
|
|
166
|
+
this.game?.addHeat(2, `${this.verbName} alarm on "${device.name}"`);
|
|
197
167
|
}
|
|
198
|
-
this.logger.write(`${this.actor.name} attempted to ${this.
|
|
199
|
-
// The VERB, not the shared bypassType (2026-08-24 playtest: a
|
|
200
|
-
// BREACH was announced as "lockpicked" -- breach and pick share the
|
|
201
|
-
// 'lockpick' type but not the fiction).
|
|
168
|
+
this.logger.write(`${this.actor.name} attempted to ${this.verbName} "${device.name}": ${result.success ? 'success' : 'failure'}${result.alarmed ? ' (alarmed)' : ''}`);
|
|
202
169
|
this.actor.performAction(this.verbName, result.message);
|
|
203
|
-
// A failed bypass used to be instant, unrecoverable death by fiat --
|
|
204
|
-
// no dice, no damage, just endGame(). Replaced (after a real session
|
|
205
|
-
// died to it) with consequences that run through the systems that now
|
|
206
|
-
// exist: the route BURNS (puzzle.bypassBurned -- this trick never works
|
|
207
|
-
// on this barrier again; the findable answer still does), the alarm
|
|
208
|
-
// world event above puts every NPC on notice, any sneak is over, and
|
|
209
|
-
// the type-specific teeth in onBypassFailure() (spell backlash damage,
|
|
210
|
-
// see cast.ts) can still put you down -- but through the damage
|
|
211
|
-
// tracks, resisted and narrated, not by administrative decree.
|
|
212
170
|
if (result.alarmed) {
|
|
213
171
|
this.actor.sneaking = false;
|
|
214
|
-
const
|
|
172
|
+
const teeth = await this.onForceFailure();
|
|
215
173
|
this.scene.updateStatus();
|
|
216
174
|
return crossNote + [
|
|
217
175
|
result.message,
|
|
218
|
-
|
|
219
|
-
|
|
176
|
+
// NO BURN LINE any more: the route is not spent. Say what IS
|
|
177
|
+
// true -- it held, and the noise carried -- rather than
|
|
178
|
+
// promising a permanence that no longer exists.
|
|
179
|
+
` It holds. You can try again, but the noise has already carried.`,
|
|
180
|
+
...teeth,
|
|
220
181
|
].join('\n');
|
|
221
182
|
}
|
|
222
|
-
return crossNote + [result.message, ...
|
|
183
|
+
return crossNote + [result.message, ...consequence].join('\n');
|
|
223
184
|
}
|
|
224
185
|
}
|
|
225
186
|
//# sourceMappingURL=bypass-command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bypass-command.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/bypass-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"bypass-command.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/bypass-command.ts"],"names":[],"mappings":"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"}
|