@maka/maka-cli 5.63.1 → 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/ar.js +29 -8
- package/bundle/typescript/src/commands/game/sideQuest/commands/ar.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/ask.d.ts +42 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/ask.js +86 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/ask.js.map +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 +151 -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/call.js +29 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.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/contacts.js +22 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/contacts.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 +18 -10
- package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/journal.d.ts +44 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/journal.js +136 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/journal.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.d.ts +20 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +157 -5
- 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/players.js +8 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/players.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 +46 -12
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +30 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js +11 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.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/talk.d.ts +47 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/talk.js +91 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/talk.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.d.ts +20 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.js +61 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.js.map +1 -0
- 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 +128 -44
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +551 -254
- 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.d.ts +104 -0
- package/bundle/typescript/src/commands/game/sideQuest/game.js +268 -16
- package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/headless-harness.d.ts +78 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless-harness.js +188 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless-harness.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless.d.ts +5 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless.js +78 -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 +143 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +253 -30
- 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 +80 -34
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js +126 -54
- 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/ar.d.ts +22 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js +26 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-dump.js +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-dump.js.map +1 -1
- 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 +73 -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 +38 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/log-style.js +42 -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 +72 -17
- package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/playtester.d.ts +50 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/playtester.js +43 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/playtester.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.d.ts +14 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js +45 -31
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js +66 -8
- 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 +81 -15
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +142 -33
- 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/utilities/world-clock.d.ts +83 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/world-clock.js +106 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/world-clock.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 -143
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js +0 -366
- 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
|
@@ -1,18 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PuzzleBypassType } from '../types/seed/puzzle-seed.js';
|
|
1
|
+
import { Command, ICommand } from './command.js';
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
3
|
+
* BLUFF IS SOCIAL, AND SOCIAL MEANS A PERSON (player ruling 2026-08-27:
|
|
4
|
+
* "'bluff' shouldn't work on Barriers like locks/wards/etc. Bluff is a
|
|
5
|
+
* social workaround. The real barrier, in this case, should be Coyote --
|
|
6
|
+
* NPCs can be barriers (can't move through them)").
|
|
7
|
+
*
|
|
8
|
+
* This used to be a BypassCommand: bluff was a bypassType on the barrier
|
|
9
|
+
* itself, so a keypad could be "really a doorman" and you talked the
|
|
10
|
+
* keypad round. That was a category error in two directions at once. A
|
|
11
|
+
* lock has no opinion to change, so there was nothing for the con to
|
|
12
|
+
* work on; and modelling the DOORMAN as a Puzzle to get the social route
|
|
13
|
+
* gave a human being a shortcut that could be BURNED, a coin flip in
|
|
14
|
+
* place of an opposed test, and a "BARRIER:" label in search.
|
|
15
|
+
*
|
|
16
|
+
* So bluff no longer touches barriers at all. What it does instead is
|
|
17
|
+
* the thing the ruling asked for: an OPPOSED SOCIAL TEST against a
|
|
18
|
+
* person who is holding a doorway. An obstructive NPC is one whose
|
|
19
|
+
* `guarding` flag makes utilities/spots.ts holdsGround() keep the way
|
|
20
|
+
* shut; winning clears it and they step aside.
|
|
21
|
+
*
|
|
22
|
+
* Charisma + con against their Willpower + Intuition -- the will not to
|
|
23
|
+
* be moved, and the read on you. Not a coin flip, because a coin flip is
|
|
24
|
+
* what you roll against a mechanism.
|
|
25
|
+
*
|
|
26
|
+
* Losing does NOT burn anything. They remember the story and won't hear
|
|
27
|
+
* it twice from you (conAttemptedBy), but they can still be leaned on,
|
|
28
|
+
* bought, or fought. That distinction is the ruling in miniature: a
|
|
29
|
+
* barrier gets burned, a person just doesn't buy it.
|
|
30
|
+
*
|
|
31
|
+
* Every refusal here NAMES THE ROUTE THAT WOULD WORK, per the standing
|
|
32
|
+
* rule from v5.63/v5.64 -- a bare denial in front of an obvious obstacle
|
|
33
|
+
* is what made a real session conclude the barrier was broken. Typing
|
|
34
|
+
* "bluff" at a maglock says the maglock was never the kind of thing you
|
|
35
|
+
* talk to, and points at what is.
|
|
9
36
|
*/
|
|
10
|
-
export declare class BluffCommand extends
|
|
37
|
+
export declare class BluffCommand extends Command implements ICommand {
|
|
11
38
|
protected static verb: string;
|
|
12
39
|
protected static description: string;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
40
|
+
execute(args?: string[]): Promise<string>;
|
|
41
|
+
/** Is there a barrier in this room at all? Only used to word the
|
|
42
|
+
* refusal correctly -- a player who typed "bluff" at a lock deserves
|
|
43
|
+
* to be pointed at the verbs that do work on it. */
|
|
44
|
+
private roomHasBarrier;
|
|
18
45
|
}
|
|
@@ -1,19 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Command } from './command.js';
|
|
2
|
+
import { hint } from '../utilities/hints.js';
|
|
3
|
+
import { sameSpot, spotOf } from '../utilities/spots.js';
|
|
2
4
|
import { rollPool, formatRoll } from '../utilities/dice.js';
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* BLUFF IS SOCIAL, AND SOCIAL MEANS A PERSON (player ruling 2026-08-27:
|
|
7
|
+
* "'bluff' shouldn't work on Barriers like locks/wards/etc. Bluff is a
|
|
8
|
+
* social workaround. The real barrier, in this case, should be Coyote --
|
|
9
|
+
* NPCs can be barriers (can't move through them)").
|
|
10
|
+
*
|
|
11
|
+
* This used to be a BypassCommand: bluff was a bypassType on the barrier
|
|
12
|
+
* itself, so a keypad could be "really a doorman" and you talked the
|
|
13
|
+
* keypad round. That was a category error in two directions at once. A
|
|
14
|
+
* lock has no opinion to change, so there was nothing for the con to
|
|
15
|
+
* work on; and modelling the DOORMAN as a Puzzle to get the social route
|
|
16
|
+
* gave a human being a shortcut that could be BURNED, a coin flip in
|
|
17
|
+
* place of an opposed test, and a "BARRIER:" label in search.
|
|
18
|
+
*
|
|
19
|
+
* So bluff no longer touches barriers at all. What it does instead is
|
|
20
|
+
* the thing the ruling asked for: an OPPOSED SOCIAL TEST against a
|
|
21
|
+
* person who is holding a doorway. An obstructive NPC is one whose
|
|
22
|
+
* `guarding` flag makes utilities/spots.ts holdsGround() keep the way
|
|
23
|
+
* shut; winning clears it and they step aside.
|
|
24
|
+
*
|
|
25
|
+
* Charisma + con against their Willpower + Intuition -- the will not to
|
|
26
|
+
* be moved, and the read on you. Not a coin flip, because a coin flip is
|
|
27
|
+
* what you roll against a mechanism.
|
|
28
|
+
*
|
|
29
|
+
* Losing does NOT burn anything. They remember the story and won't hear
|
|
30
|
+
* it twice from you (conAttemptedBy), but they can still be leaned on,
|
|
31
|
+
* bought, or fought. That distinction is the ruling in miniature: a
|
|
32
|
+
* barrier gets burned, a person just doesn't buy it.
|
|
33
|
+
*
|
|
34
|
+
* Every refusal here NAMES THE ROUTE THAT WOULD WORK, per the standing
|
|
35
|
+
* rule from v5.63/v5.64 -- a bare denial in front of an obvious obstacle
|
|
36
|
+
* is what made a real session conclude the barrier was broken. Typing
|
|
37
|
+
* "bluff" at a maglock says the maglock was never the kind of thing you
|
|
38
|
+
* talk to, and points at what is.
|
|
9
39
|
*/
|
|
10
|
-
export class BluffCommand extends
|
|
40
|
+
export class BluffCommand extends Command {
|
|
11
41
|
static verb = 'bluff';
|
|
12
|
-
static description = 'Talk
|
|
13
|
-
|
|
14
|
-
verbName = 'bluff';
|
|
15
|
-
noPuzzleMessage = `There's nobody here to bluff past.`;
|
|
16
|
-
async execute(args) {
|
|
42
|
+
static description = 'Talk a PERSON round -- Charisma + con. Locks, wards and terminals have no opinion to change; work those with "pick", "hack" or "cast".';
|
|
43
|
+
async execute(args = []) {
|
|
17
44
|
// Fast-talk needs a face and a voice on the scene -- your meat ones.
|
|
18
45
|
if (this.actor.plane === 'matrix') {
|
|
19
46
|
return `Your silver tongue is meat-side, slumped with the rest of you. "jack out" to run your game in person.`;
|
|
@@ -24,25 +51,80 @@ export class BluffCommand extends BypassCommand {
|
|
|
24
51
|
if (this.actor.plane === 'drone') {
|
|
25
52
|
return `Nobody buys a story from a hovering drone with a tinny speaker -- a con needs a FACE. "jump" back to yours.`;
|
|
26
53
|
}
|
|
54
|
+
const room = this.actor.currentLocation;
|
|
55
|
+
const here = room
|
|
56
|
+
? this.scene.getActorsInRoom(room).filter((a) => a !== this.actor && !a.isIncapacitated())
|
|
57
|
+
: [];
|
|
58
|
+
// NAME THE PEOPLE, because "bluff" is now a question about people and
|
|
59
|
+
// the honest answer to "who?" is a list of who is actually here.
|
|
60
|
+
if (here.length === 0) {
|
|
61
|
+
return `There's nobody here to work. A con needs an audience -- ${room && this.roomHasBarrier() ? `and whatever's blocking you isn't one. It's a THING: work it with "pick", "hack" or "cast", or find the answer and "solve" it.` : `find someone who can say yes.`}`;
|
|
62
|
+
}
|
|
63
|
+
const named = args.join(' ').trim();
|
|
64
|
+
const target = named
|
|
65
|
+
? here.find(a => a.name.toLowerCase().includes(named.toLowerCase()))
|
|
66
|
+
: undefined;
|
|
67
|
+
if (named && !target) {
|
|
68
|
+
return `You don't see anyone called "${named}" to work. Here: ${here.map(a => a.name).join(', ')}.`;
|
|
69
|
+
}
|
|
27
70
|
// Working a mark out loud is the opposite of sneaking (see sneak.ts).
|
|
28
71
|
this.actor.sneaking = false;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
72
|
+
const who = target ?? here[0];
|
|
73
|
+
if (!sameSpot(this.actor, who)) {
|
|
74
|
+
const spot = spotOf(who);
|
|
75
|
+
return `A story needs to be told close. ${who.name} is at the ${spot ?? 'other side of the room'} -- "move to ${spot ?? who.name}" first.`;
|
|
76
|
+
}
|
|
77
|
+
if (!who.guarding) {
|
|
78
|
+
return [
|
|
79
|
+
`You size ${who.name} up for a story -- but they aren't in your way. A con needs something to BE talked past.`,
|
|
80
|
+
hint(` (Say your piece with "talk-to ${who.name} <what you tell them>", or lean on them with "persuade"/"intimidate".)`),
|
|
81
|
+
].join('');
|
|
82
|
+
}
|
|
83
|
+
// A MARK REMEMBERS. Not a burned route -- the distinction is the
|
|
84
|
+
// whole ruling. They didn't buy your story; they can still be leaned
|
|
85
|
+
// on, bought, or fought.
|
|
86
|
+
if (who.conAttemptedBy.has(this.actor.name)) {
|
|
87
|
+
return `${who.name} has heard your story once already, and they didn't buy it the first time. Try something that isn't talk.`;
|
|
88
|
+
}
|
|
89
|
+
who.conAttemptedBy.add(this.actor.name);
|
|
90
|
+
// OPPOSED, against the PERSON -- not a coin flip against a lock.
|
|
91
|
+
// Their Willpower + Intuition is what sees through a story: the will
|
|
92
|
+
// not to be moved, and the read on you.
|
|
35
93
|
const skill = this.actor.skillRating('con');
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
// a face that can't claim to be someone else (capped at -2).
|
|
94
|
+
// Public Awareness cuts AGAINST a con: a face people can place is a
|
|
95
|
+
// face that can't claim to be someone else (capped at -2).
|
|
39
96
|
const fame = Math.min(2, this.actor.publicAwareness);
|
|
40
|
-
const pool = Math.max(1, this.actor.charisma + (skill > 0 ? skill : -1)
|
|
41
|
-
|
|
97
|
+
const pool = Math.max(1, this.actor.charisma + (skill > 0 ? skill : -1)
|
|
98
|
+
+ this.actor.consumeLiquidCourage() + this.actor.consumeFirstImpression()
|
|
99
|
+
+ this.actor.augBonus('social') - fame
|
|
100
|
+
+ this.actor.woundModifier - this.actor.sustainingPenalty);
|
|
101
|
+
const theirs = Math.max(1, who.willpower + who.intuition);
|
|
102
|
+
const mine = rollPool(pool);
|
|
103
|
+
const resist = rollPool(theirs);
|
|
42
104
|
if (this.scene.isHumanControlled(this.actor)) {
|
|
43
|
-
this.logger.meta(`Con: ${formatRoll(
|
|
105
|
+
this.logger.meta(`Con: ${formatRoll(mine)}`);
|
|
106
|
+
this.logger.meta(` ${who.name} sees through it: ${formatRoll(resist)}`);
|
|
44
107
|
}
|
|
45
|
-
|
|
108
|
+
this.actor.performAction('spins a story for', who.name);
|
|
109
|
+
this.logger.write(`Bluff: ${this.actor.name} vs ${who.name} -- ${mine.hits} vs ${resist.hits} (guarding).`);
|
|
110
|
+
if (mine.hits <= resist.hits) {
|
|
111
|
+
void Promise.resolve(who.hear(this.actor, `[System note: ${this.actor.name} just tried to talk their way past you and you DIDN'T buy it. You are still holding this doorway. Say so, in your own voice, in one short line.]`)).catch(() => undefined);
|
|
112
|
+
return `${who.name} lets you finish, then doesn't move. "Nice try."`;
|
|
113
|
+
}
|
|
114
|
+
// They stand down -- for everyone, deliberately (see Player.guarding).
|
|
115
|
+
who.guarding = false;
|
|
116
|
+
void Promise.resolve(who.hear(this.actor, `[System note: ${this.actor.name} just talked you round and you're STEPPING ASIDE -- you bought the story. One short line as you move, in your own voice. Don't re-block the way.]`)).catch(() => undefined);
|
|
117
|
+
return [
|
|
118
|
+
`${who.name} weighs it, decides you're somebody's problem but not theirs, and steps out of the way.`,
|
|
119
|
+
hint(` (The way is open while they stay stood down.)`),
|
|
120
|
+
].join('');
|
|
121
|
+
}
|
|
122
|
+
/** Is there a barrier in this room at all? Only used to word the
|
|
123
|
+
* refusal correctly -- a player who typed "bluff" at a lock deserves
|
|
124
|
+
* to be pointed at the verbs that do work on it. */
|
|
125
|
+
roomHasBarrier() {
|
|
126
|
+
const room = this.actor.currentLocation;
|
|
127
|
+
return (room?.openableDevices?.() ?? []).length > 0;
|
|
46
128
|
}
|
|
47
129
|
}
|
|
48
130
|
//# sourceMappingURL=bluff.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bluff.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/bluff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"bluff.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/bluff.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +1,30 @@
|
|
|
1
1
|
import { BypassCommand } from './bypass-command.js';
|
|
2
|
-
import {
|
|
3
|
-
import { PuzzleTarget } from '../models/room.js';
|
|
2
|
+
import { Device } from '../models/device.js';
|
|
4
3
|
/**
|
|
5
4
|
* The FORCEFUL route past a physical barrier (player ruling: "solve" was
|
|
6
5
|
* too broad -- a maglock wants finesse OR muscle, and muscle deserves its
|
|
7
|
-
* own verb). Same
|
|
6
|
+
* own verb). Same device kind as "pick" (a lock), opposite
|
|
8
7
|
* philosophy: raw Strength + Body instead of Agility + locksmith, and it
|
|
9
8
|
* is LOUD no matter what -- a successful breach still raises the world
|
|
10
9
|
* and ends any sneak (onBypassSuccess), where a clean pick stays quiet.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* noticed being told about a pick they never owned (2026-08-27). Hence
|
|
18
|
-
* burnedFlavor below: same flag, own fiction. Do not reinstate the wart.
|
|
10
|
+
* NOTHING BURNS ANY MORE. Both verbs used to share the barrier's one
|
|
11
|
+
* "burned" flag -- a failed attempt spent the shortcut for good -- and
|
|
12
|
+
* that flag went with the puzzle mechanic. A lock you failed to force
|
|
13
|
+
* is a lock you can throw yourself at again, which is what a lock is.
|
|
14
|
+
* The trade against "pick" is undiminished: breach is loud whether or
|
|
15
|
+
* not it works, and that is what you are choosing.
|
|
19
16
|
*/
|
|
20
17
|
export declare class BreachCommand extends BypassCommand {
|
|
21
18
|
protected static verb: string;
|
|
22
19
|
protected static description: string;
|
|
23
|
-
protected
|
|
20
|
+
protected deviceKind: "lock";
|
|
24
21
|
protected verbName: string;
|
|
25
|
-
protected
|
|
22
|
+
protected noDeviceMessage: string;
|
|
26
23
|
protected failureFlavor: string;
|
|
27
|
-
protected burnedFlavor: string;
|
|
28
24
|
execute(args: string[]): Promise<string>;
|
|
29
25
|
protected determineOutcome(): Promise<boolean>;
|
|
30
26
|
/** Breaching is loud when it WORKS, too -- the defining trade against
|
|
31
27
|
* pick. The world event lets every listening NPC react (same channel
|
|
32
28
|
* the failure alarm uses); the sneak is over either way. */
|
|
33
|
-
protected
|
|
29
|
+
protected onForceSuccess(device: Device): Promise<string[]>;
|
|
34
30
|
}
|
|
@@ -3,27 +3,24 @@ import { rollPool, formatRoll } from '../utilities/dice.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* The FORCEFUL route past a physical barrier (player ruling: "solve" was
|
|
5
5
|
* too broad -- a maglock wants finesse OR muscle, and muscle deserves its
|
|
6
|
-
* own verb). Same
|
|
6
|
+
* own verb). Same device kind as "pick" (a lock), opposite
|
|
7
7
|
* philosophy: raw Strength + Body instead of Agility + locksmith, and it
|
|
8
8
|
* is LOUD no matter what -- a successful breach still raises the world
|
|
9
9
|
* and ends any sneak (onBypassSuccess), where a clean pick stays quiet.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* noticed being told about a pick they never owned (2026-08-27). Hence
|
|
17
|
-
* burnedFlavor below: same flag, own fiction. Do not reinstate the wart.
|
|
10
|
+
* NOTHING BURNS ANY MORE. Both verbs used to share the barrier's one
|
|
11
|
+
* "burned" flag -- a failed attempt spent the shortcut for good -- and
|
|
12
|
+
* that flag went with the puzzle mechanic. A lock you failed to force
|
|
13
|
+
* is a lock you can throw yourself at again, which is what a lock is.
|
|
14
|
+
* The trade against "pick" is undiminished: breach is loud whether or
|
|
15
|
+
* not it works, and that is what you are choosing.
|
|
18
16
|
*/
|
|
19
17
|
export class BreachCommand extends BypassCommand {
|
|
20
18
|
static verb = 'breach';
|
|
21
|
-
static description = 'Force a physical barrier open with raw muscle -- Strength + Body, no skill needed. Loud EVEN WHEN IT WORKS: the crash carries and any sneak is over. Fail
|
|
22
|
-
|
|
19
|
+
static description = 'Force a physical barrier open with raw muscle -- Strength + Body, no skill needed. Loud EVEN WHEN IT WORKS: the crash carries and any sneak is over. Fail and it holds -- try again if you like, but the boom has already carried. "breach north" or "breach <name>" if there\'s more than one.';
|
|
20
|
+
deviceKind = 'lock';
|
|
23
21
|
verbName = 'breach';
|
|
24
|
-
|
|
22
|
+
noDeviceMessage = "There's nothing here to breach -- no physical barrier holds this room.";
|
|
25
23
|
failureFlavor = `You slam into it and it HOLDS -- the frame seizes solid, and the boom rolls down every corridor on the floor.`;
|
|
26
|
-
burnedFlavor = `The frame is sprung and jammed hard in its seat -- you've already thrown everything you have at it, and it won't give twice. Only the real code opens it now.`;
|
|
27
24
|
async execute(args) {
|
|
28
25
|
// Shoulders are meat -- same plane fiction as pick.ts.
|
|
29
26
|
if (this.actor.plane === 'matrix') {
|
|
@@ -51,11 +48,11 @@ export class BreachCommand extends BypassCommand {
|
|
|
51
48
|
/** Breaching is loud when it WORKS, too -- the defining trade against
|
|
52
49
|
* pick. The world event lets every listening NPC react (same channel
|
|
53
50
|
* the failure alarm uses); the sneak is over either way. */
|
|
54
|
-
async
|
|
51
|
+
async onForceSuccess(device) {
|
|
55
52
|
this.actor.sneaking = false;
|
|
56
|
-
this.scene.addWorldEvent(`${this.actor.name} breached "${
|
|
53
|
+
this.scene.addWorldEvent(`${this.actor.name} breached "${device.name}" in ${this.actor.currentLocation.name} -- the crash carried.`);
|
|
57
54
|
// A breach is loud past the walls too (heat -- SINs & getting caught).
|
|
58
|
-
this.game?.addHeat(2, `breached "${
|
|
55
|
+
this.game?.addHeat(2, `breached "${device.name}"`);
|
|
59
56
|
return [` The crash CARRIES -- anyone nearby knows exactly where you are now.`];
|
|
60
57
|
}
|
|
61
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"breach.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/breach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"breach.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/breach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,aAAc,SAAQ,aAAa;IACpC,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;IACvB,MAAM,CAAC,WAAW,GAAG,iSAAiS,CAAC;IACvT,UAAU,GAAG,MAAe,CAAC;IAC7B,QAAQ,GAAG,QAAQ,CAAC;IACpB,eAAe,GAAG,wEAAwE,CAAC;IAC3F,aAAa,GAAG,+GAA+G,CAAC;IAE1I,KAAK,CAAC,OAAO,CAAC,IAAc;QAC1B,uDAAuD;QACvD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,+DAA+D,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,IAAI,cAAc,uCAAuC,CAAC;QAC3J,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,uGAAuG,CAAC;QACjH,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YACjC,OAAO,4EAA4E,CAAC;QACtF,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAES,KAAK,CAAC,gBAAgB;QAC9B,kEAAkE;QAClE,qEAAqE;QACrE,6BAA6B;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC1H,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IACxB,CAAC;IAED;;gEAE4D;IAClD,KAAK,CAAC,cAAc,CAAC,MAAc;QAC3C,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,MAAM,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,wBAAwB,CAAC,CAAC;QACrI,uEAAuE;QACvE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,aAAa,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QACnD,OAAO,CAAC,uEAAuE,CAAC,CAAC;IACnF,CAAC"}
|
|
@@ -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>;
|