@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
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utilities/logger.js';
|
|
2
|
-
import { Item } from './item.js';
|
|
3
|
-
import { Inventory } from './inventory.js';
|
|
4
|
-
import { PuzzleBypassType } from '../types/seed/puzzle-seed.js';
|
|
5
|
-
import { AbstractPuzzle } from '../types/shared/abstracts.js';
|
|
6
|
-
/**
|
|
7
|
-
* Why a bypass was refused, so the CALLING command can re-voice a
|
|
8
|
-
* message the puzzle can't word correctly on its own: two verbs share
|
|
9
|
-
* one bypassType (pick/breach both work 'lockpick'), and the puzzle
|
|
10
|
-
* only knows the type. See BypassCommand.burnedFlavor.
|
|
11
|
-
*/
|
|
12
|
-
export type BypassRefusal = 'solved' | 'locked' | 'mismatch' | 'burned';
|
|
13
|
-
export interface BypassGate {
|
|
14
|
-
allowed: boolean;
|
|
15
|
-
reason?: BypassRefusal;
|
|
16
|
-
message?: string;
|
|
17
|
-
}
|
|
18
|
-
export interface IPuzzleConstructorConfig {
|
|
19
|
-
name: string;
|
|
20
|
-
requiredItem?: Item;
|
|
21
|
-
requiredPhrase?: string;
|
|
22
|
-
riddle?: string;
|
|
23
|
-
rewardItem?: Item;
|
|
24
|
-
successMessage?: string;
|
|
25
|
-
failureMessage?: string;
|
|
26
|
-
hobbyTags?: string[];
|
|
27
|
-
bypassType?: PuzzleBypassType;
|
|
28
|
-
atSpot?: string;
|
|
29
|
-
}
|
|
30
|
-
export declare class Puzzle extends AbstractPuzzle {
|
|
31
|
-
protected logger: Logger;
|
|
32
|
-
protected solved: boolean;
|
|
33
|
-
private hasAIRiddle;
|
|
34
|
-
name: string;
|
|
35
|
-
requiredItem?: Item;
|
|
36
|
-
requiredPhrase?: string;
|
|
37
|
-
riddle?: string;
|
|
38
|
-
rewardItem?: Item;
|
|
39
|
-
atSpot?: string;
|
|
40
|
-
successMessage: string;
|
|
41
|
-
failureMessage: string;
|
|
42
|
-
hobbyTags?: string[];
|
|
43
|
-
requiresPuzzle?: Puzzle;
|
|
44
|
-
lockedMessage: string;
|
|
45
|
-
bypassType?: PuzzleBypassType;
|
|
46
|
-
private static readonly BYPASS_SUCCESS_CHANCE;
|
|
47
|
-
bypassBurned: boolean;
|
|
48
|
-
constructor(config: IPuzzleConstructorConfig);
|
|
49
|
-
/**
|
|
50
|
-
* Player-facing hint that a risky bypass exists, without which nothing
|
|
51
|
-
* in the game ever tells the player "pick"/"hack"/"cast" is even an
|
|
52
|
-
* option here -- found via a real session where a player had no idea
|
|
53
|
-
* what they were supposed to "pick".
|
|
54
|
-
*/
|
|
55
|
-
/** Just the bypass verb ("pick"/"hack"/"cast"/"bluff"), for refusal
|
|
56
|
-
* one-liners that need to NAME the mechanism without the full
|
|
57
|
-
* coaching text getBypassHint() carries. */
|
|
58
|
-
getBypassVerb(): string | undefined;
|
|
59
|
-
/**
|
|
60
|
-
* EVERY verb that works this barrier, not just the canonical one --
|
|
61
|
-
* one bypassType can have two (pick/breach both work a lockpick;
|
|
62
|
-
* cast/dispel both work a ward). For telling the player exactly what
|
|
63
|
-
* they may type (item B, 2026-08-27: "the 'thing' to
|
|
64
|
-
* hack/breach/pick/dispell needs to be very very clear"), where
|
|
65
|
-
* naming only half the routes is its own small lie.
|
|
66
|
-
*/
|
|
67
|
-
getBypassVerbs(): string[];
|
|
68
|
-
getBypassHint(): string | undefined;
|
|
69
|
-
/**
|
|
70
|
-
* Wired in after all puzzles in a scene exist (scene-factory.ts), since
|
|
71
|
-
* a prerequisite may not have been constructed yet at this puzzle's own
|
|
72
|
-
* construction time.
|
|
73
|
-
*/
|
|
74
|
-
setRequiresPuzzle(prerequisite: Puzzle, lockedMessage?: string): void;
|
|
75
|
-
/**
|
|
76
|
-
* Persistence-only (utilities/persistence.ts): flags in, nothing out --
|
|
77
|
-
* no reward items, no success message, no door side effects (door lock
|
|
78
|
-
* state is restored independently, so a solved-then-relocked door stays
|
|
79
|
-
* relocked on load).
|
|
80
|
-
*/
|
|
81
|
-
restoreState(state: {
|
|
82
|
-
solved: boolean;
|
|
83
|
-
bypassBurned: boolean;
|
|
84
|
-
}): void;
|
|
85
|
-
isSolved(): boolean;
|
|
86
|
-
/**
|
|
87
|
-
* Rewrites the riddle's presentation once per scene load, while keeping
|
|
88
|
-
* `requiredPhrase` (the exact-match answer key used by `solve()`) fixed --
|
|
89
|
-
* so the correctness gate never drifts from what the player was actually
|
|
90
|
-
* asked.
|
|
91
|
-
*/
|
|
92
|
-
ensureAIRiddle(sceneContext: string, roomName?: string, kind?: 'device' | 'terrain'): Promise<void>;
|
|
93
|
-
hasRequiredItem(playerInventory: Inventory): boolean;
|
|
94
|
-
/**
|
|
95
|
-
* Clue items are only required to CONTAIN the answer somewhere in their
|
|
96
|
-
* text (e.g. "kill the power to bypass security" for a required phrase
|
|
97
|
-
* of "kill the power"), so a player who reasonably quotes the clue back
|
|
98
|
-
* verbatim types more words than the exact answer. Strict equality
|
|
99
|
-
* rejected that. Normalizing punctuation/whitespace and accepting the
|
|
100
|
-
* required phrase as a substring of the input (not just an exact match)
|
|
101
|
-
* fixes it without loosening things enough for a wrong guess to pass.
|
|
102
|
-
*/
|
|
103
|
-
matchesRequiredPhrase(inputPhrase: string): boolean;
|
|
104
|
-
solve(providedAnswer: string, playerInventory: Inventory): {
|
|
105
|
-
success: boolean;
|
|
106
|
-
message: string;
|
|
107
|
-
};
|
|
108
|
-
/**
|
|
109
|
-
* The risky alternate route never requires knowing requiredPhrase. Split
|
|
110
|
-
* into a gate check (run first, before any outcome is determined -- an
|
|
111
|
-
* already-solved, blocked, or type-mismatched puzzle should never make
|
|
112
|
-
* the player sit through an interactive minigame they were never going
|
|
113
|
-
* to be allowed to attempt) and applying an already-determined outcome.
|
|
114
|
-
* A failed attempt BURNS the route (see bypassBurned) -- the gate
|
|
115
|
-
* refuses retries with the burned flavor -- but never touches the safe
|
|
116
|
-
* solve() path: finding the actual answer remains deterministic. Further
|
|
117
|
-
* consequences (the alarm world event, spell backlash) belong to the
|
|
118
|
-
* calling command (see commands/bypass-command.ts).
|
|
119
|
-
*/
|
|
120
|
-
checkBypassGate(type: PuzzleBypassType): BypassGate;
|
|
121
|
-
/**
|
|
122
|
-
* The wrong-verb answer, spoken in the barrier's OWN fiction. Keyed on
|
|
123
|
-
* this.bypassType (what the thing IS), never on the verb attempted --
|
|
124
|
-
* see the note on BYPASS_FLAVOR.resists. Always names a route that
|
|
125
|
-
* works, so a player never gets a dead end in front of a visible
|
|
126
|
-
* barrier; a barrier with no shortcut at all says so plainly instead
|
|
127
|
-
* of pretending not to exist, which is what a solve-only puzzle used
|
|
128
|
-
* to do (it was filtered out before this gate ever ran).
|
|
129
|
-
*/
|
|
130
|
-
private wrongRouteMessage;
|
|
131
|
-
/**
|
|
132
|
-
* Applies an outcome already determined elsewhere (a coin flip, or a live
|
|
133
|
-
* minigame's win/loss) to this puzzle. Assumes checkBypassGate() already
|
|
134
|
-
* passed -- doesn't re-check it.
|
|
135
|
-
*/
|
|
136
|
-
resolveBypass(type: PuzzleBypassType, succeeded: boolean): {
|
|
137
|
-
success: boolean;
|
|
138
|
-
message: string;
|
|
139
|
-
alarmed: boolean;
|
|
140
|
-
};
|
|
141
|
-
/**
|
|
142
|
-
* Convenience wrapper: gate check + a flat coin-flip outcome. Used for
|
|
143
|
-
* any bypass type without its own interactive minigame yet -- see
|
|
144
|
-
* BypassCommand.determineOutcome(), which lockpicking overrides to run a
|
|
145
|
-
* real player-skill challenge instead of this coin flip.
|
|
146
|
-
*/
|
|
147
|
-
attemptBypass(type: PuzzleBypassType): {
|
|
148
|
-
success: boolean;
|
|
149
|
-
message: string;
|
|
150
|
-
alarmed: boolean;
|
|
151
|
-
};
|
|
152
|
-
}
|
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utilities/logger.js';
|
|
2
|
-
import { hint } from '../utilities/hints.js';
|
|
3
|
-
import { AI } from '../../../../tools/ai/ai.class.js';
|
|
4
|
-
import { AbstractPuzzle } from '../types/shared/abstracts.js';
|
|
5
|
-
/**
|
|
6
|
-
* `resists` is the WRONG-VERB voice, and it is keyed on what the barrier
|
|
7
|
-
* IS, never on what the player typed (blocker 2026-08-27, "the barrier
|
|
8
|
-
* isn't allowing me to hack/pick/breach it"): a player who reaches for
|
|
9
|
-
* the wrong route is not making an error to be reported, they are asking
|
|
10
|
-
* what this thing is. So the line says what it is, why the attempted
|
|
11
|
-
* route finds no purchase on it, and which verb DOES bite -- the same
|
|
12
|
-
* job spots.ts:terrainRefusal() does for a blocked crossing. Never a
|
|
13
|
-
* bare denial: a denial in front of an obvious door is what made a real
|
|
14
|
-
* session conclude the barrier was broken.
|
|
15
|
-
*/
|
|
16
|
-
const BYPASS_FLAVOR = {
|
|
17
|
-
lockpick: {
|
|
18
|
-
verb: 'pick',
|
|
19
|
-
verbs: ['pick', 'breach'],
|
|
20
|
-
resists: `It's a mechanism, not a system -- no console to intrude on, no weave to unpick, nobody to talk round. It gives to HANDS: "pick" it quietly, or "breach" it with your shoulder.`,
|
|
21
|
-
failureMessage: `Your pick snaps in the mechanism -- and the lock's alarm isn't silent anymore.`,
|
|
22
|
-
hint: `This looks forceable -- "pick" works it quietly (Agility + locksmith); "breach" forces it with raw muscle (Strength + Body, LOUD even when it works). Fail either way and the mechanism seizes for good -- and the noise carries.`,
|
|
23
|
-
burnedMessage: `The mechanism is seized solid around your snapped pick -- no tool opens it now. Only the real code will.`,
|
|
24
|
-
},
|
|
25
|
-
hack: {
|
|
26
|
-
verb: 'hack',
|
|
27
|
-
verbs: ['hack'],
|
|
28
|
-
resists: `No keyway, no seam, no tumblers to feel for -- it's a sealed SYSTEM, and it only argues with a deck. "hack" it.`,
|
|
29
|
-
failureMessage: `Your intrusion trips a countermeasure -- the system logs the attempt and pings whoever's watching.`,
|
|
30
|
-
hint: `This looks hackable -- try "hack" to skip finding the code (Logic + hacking). Fail, and the system locks you out for good -- and pings whoever's watching.`,
|
|
31
|
-
burnedMessage: `The system remembers your intrusion -- hard lockout, your signature blacklisted. Only the real code opens it now.`,
|
|
32
|
-
},
|
|
33
|
-
spell: {
|
|
34
|
-
verb: 'cast',
|
|
35
|
-
verbs: ['cast', 'dispel'],
|
|
36
|
-
resists: `Your hands find nothing to work and your tools find nothing to bite -- the barrier isn't matter. It answers to the Art: "cast" at it, or "dispel" it.`,
|
|
37
|
-
failureMessage: `The weave slips through your fingers -- backlash crackles outward, and something out there felt it.`,
|
|
38
|
-
hint: `This could be unwoven magically -- try "dispel" (Magic + counterspelling) or "cast" (the casting pool) to skip finding the code. Fail, and the backlash BITES -- and the barrier seals against you for good.`,
|
|
39
|
-
burnedMessage: `The barrier has sealed itself against your signature -- no working of yours touches it again. Only the real answer opens it now.`,
|
|
40
|
-
},
|
|
41
|
-
// The Face's route: a barrier that's really a PERSON or a voice-gate --
|
|
42
|
-
// a doorman, an intercom challenge, a receptionist with a checklist.
|
|
43
|
-
// Born from a real generated scene that emitted bypassType "con" for a
|
|
44
|
-
// keypad "used by trusted business partners" before the type existed
|
|
45
|
-
// (and crashed search doing it) -- the model wanted social engineering,
|
|
46
|
-
// so now it's real. See commands/bluff.ts.
|
|
47
|
-
con: {
|
|
48
|
-
verb: 'bluff',
|
|
49
|
-
verbs: ['bluff'],
|
|
50
|
-
resists: `There's no lock here at all. There's a PERSON -- and people don't open to tools, they open to a story. "bluff" your way past.`,
|
|
51
|
-
failureMessage: `The story comes apart mid-sentence -- and now they KNOW someone's running a game on them.`,
|
|
52
|
-
hint: `This could be TALKED past -- try "bluff" to fast-talk through without the code (Charisma + con). Blow the story, and they'll never buy another word from you.`,
|
|
53
|
-
burnedMessage: `They've made you -- no story you tell holds water here anymore. Only the real credential works now.`,
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
export class Puzzle extends AbstractPuzzle {
|
|
57
|
-
logger = Logger.getInstance();
|
|
58
|
-
solved = false;
|
|
59
|
-
hasAIRiddle = false;
|
|
60
|
-
name;
|
|
61
|
-
requiredItem;
|
|
62
|
-
requiredPhrase;
|
|
63
|
-
riddle;
|
|
64
|
-
// Optional: a room-anchored puzzle typically grants one, but a door-
|
|
65
|
-
// guarding puzzle (see Door.puzzle) usually doesn't need one -- opening
|
|
66
|
-
// the door already IS the reward.
|
|
67
|
-
rewardItem;
|
|
68
|
-
// See IPuzzleConstructorConfig.atSpot.
|
|
69
|
-
atSpot;
|
|
70
|
-
successMessage;
|
|
71
|
-
failureMessage;
|
|
72
|
-
hobbyTags;
|
|
73
|
-
// Points only at this puzzle's immediate predecessor -- chains of any
|
|
74
|
-
// length fall out of that naturally, since a puzzle can't become solved
|
|
75
|
-
// until its own prerequisite is, which cascades transitively up the
|
|
76
|
-
// chain with no special traversal needed at solve() time.
|
|
77
|
-
requiresPuzzle;
|
|
78
|
-
lockedMessage;
|
|
79
|
-
// The riddle/requiredPhrase path above is the "first layer" -- a lock,
|
|
80
|
-
// code, or passphrase that exists to be found and always works once
|
|
81
|
-
// known. bypassType is a SEPARATE, optional route past that same barrier
|
|
82
|
-
// that never requires knowing the answer, matching the barrier's actual
|
|
83
|
-
// in-fiction nature (a lock, a terminal, a ward) -- rolled on the
|
|
84
|
-
// matching skill by the bypass command, and failure isn't quiet: it
|
|
85
|
-
// BURNS the route (see bypassBurned) and raises the world. See
|
|
86
|
-
// resolveBypass().
|
|
87
|
-
bypassType;
|
|
88
|
-
static BYPASS_SUCCESS_CHANCE = 0.5;
|
|
89
|
-
// One shot at the shortcut: a failed bypass seizes the mechanism /
|
|
90
|
-
// blacklists the intruder / seals the ward / burns the cover story.
|
|
91
|
-
// The safe solve() route (the findable answer) is deliberately never
|
|
92
|
-
// touched by this -- "no second chances" applies to the trick, not to
|
|
93
|
-
// the barrier.
|
|
94
|
-
bypassBurned = false;
|
|
95
|
-
constructor(config) {
|
|
96
|
-
super();
|
|
97
|
-
this.name = config.name;
|
|
98
|
-
this.requiredItem = config.requiredItem;
|
|
99
|
-
this.requiredPhrase = config.requiredPhrase;
|
|
100
|
-
this.riddle = config.riddle;
|
|
101
|
-
this.successMessage = config.successMessage || 'You solved the puzzle!';
|
|
102
|
-
this.failureMessage = config.failureMessage || `You don't have the necessary item or the correct phrase to solve the puzzle.`;
|
|
103
|
-
this.hobbyTags = config.hobbyTags ?? [];
|
|
104
|
-
this.lockedMessage = `Something else needs to happen first.`;
|
|
105
|
-
this.bypassType = config.bypassType;
|
|
106
|
-
this.atSpot = config.atSpot;
|
|
107
|
-
this.rewardItem = config.rewardItem;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Player-facing hint that a risky bypass exists, without which nothing
|
|
111
|
-
* in the game ever tells the player "pick"/"hack"/"cast" is even an
|
|
112
|
-
* option here -- found via a real session where a player had no idea
|
|
113
|
-
* what they were supposed to "pick".
|
|
114
|
-
*/
|
|
115
|
-
/** Just the bypass verb ("pick"/"hack"/"cast"/"bluff"), for refusal
|
|
116
|
-
* one-liners that need to NAME the mechanism without the full
|
|
117
|
-
* coaching text getBypassHint() carries. */
|
|
118
|
-
getBypassVerb() {
|
|
119
|
-
return this.bypassType ? BYPASS_FLAVOR[this.bypassType]?.verb : undefined;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* EVERY verb that works this barrier, not just the canonical one --
|
|
123
|
-
* one bypassType can have two (pick/breach both work a lockpick;
|
|
124
|
-
* cast/dispel both work a ward). For telling the player exactly what
|
|
125
|
-
* they may type (item B, 2026-08-27: "the 'thing' to
|
|
126
|
-
* hack/breach/pick/dispell needs to be very very clear"), where
|
|
127
|
-
* naming only half the routes is its own small lie.
|
|
128
|
-
*/
|
|
129
|
-
getBypassVerbs() {
|
|
130
|
-
if (!this.bypassType)
|
|
131
|
-
return [];
|
|
132
|
-
return BYPASS_FLAVOR[this.bypassType]?.verbs ?? [];
|
|
133
|
-
}
|
|
134
|
-
getBypassHint() {
|
|
135
|
-
if (!this.bypassType)
|
|
136
|
-
return undefined;
|
|
137
|
-
// DEFENSIVE lookup: bypassType ultimately comes from generated JSON,
|
|
138
|
-
// and an unknown value here used to crash every "search" in the room
|
|
139
|
-
// (real session: five straight TypeErrors on an unvalidated type).
|
|
140
|
-
// Generation now validates the value too, but static seeds and old
|
|
141
|
-
// saved scenes don't re-validate -- unknown types read as "no bypass".
|
|
142
|
-
const flavor = BYPASS_FLAVOR[this.bypassType];
|
|
143
|
-
if (!flavor)
|
|
144
|
-
return undefined;
|
|
145
|
-
// A burned route stops advertising itself -- the hint becomes the
|
|
146
|
-
// reminder of what the failed attempt cost.
|
|
147
|
-
if (this.bypassBurned) {
|
|
148
|
-
return `${flavor.burnedMessage}`;
|
|
149
|
-
}
|
|
150
|
-
// The clue reminder is a real promise -- generation validates that
|
|
151
|
-
// every puzzle's answer IS discoverable somewhere else (see
|
|
152
|
-
// scene-seed-generator.validateClueItems). A real session took the
|
|
153
|
-
// risky gamble first and only found the written-down code afterward.
|
|
154
|
-
// The whole block is COACHING (the barrier itself still shows) --
|
|
155
|
-
// behind the hints toggle since a real session's "hints off" left
|
|
156
|
-
// this printing anyway.
|
|
157
|
-
const text = hint(`${flavor.hint}\n(The safe route: the answer is recorded somewhere out in the world -- case the other rooms before you gamble.)`);
|
|
158
|
-
return text.length > 0 ? text : undefined;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Wired in after all puzzles in a scene exist (scene-factory.ts), since
|
|
162
|
-
* a prerequisite may not have been constructed yet at this puzzle's own
|
|
163
|
-
* construction time.
|
|
164
|
-
*/
|
|
165
|
-
setRequiresPuzzle(prerequisite, lockedMessage) {
|
|
166
|
-
this.requiresPuzzle = prerequisite;
|
|
167
|
-
if (lockedMessage) {
|
|
168
|
-
this.lockedMessage = lockedMessage;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Persistence-only (utilities/persistence.ts): flags in, nothing out --
|
|
173
|
-
* no reward items, no success message, no door side effects (door lock
|
|
174
|
-
* state is restored independently, so a solved-then-relocked door stays
|
|
175
|
-
* relocked on load).
|
|
176
|
-
*/
|
|
177
|
-
restoreState(state) {
|
|
178
|
-
this.solved = state.solved;
|
|
179
|
-
this.bypassBurned = state.bypassBurned;
|
|
180
|
-
}
|
|
181
|
-
isSolved() {
|
|
182
|
-
return this.solved;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Rewrites the riddle's presentation once per scene load, while keeping
|
|
186
|
-
* `requiredPhrase` (the exact-match answer key used by `solve()`) fixed --
|
|
187
|
-
* so the correctness gate never drifts from what the player was actually
|
|
188
|
-
* asked.
|
|
189
|
-
*/
|
|
190
|
-
async ensureAIRiddle(sceneContext, roomName, kind = 'device') {
|
|
191
|
-
if (this.hasAIRiddle)
|
|
192
|
-
return;
|
|
193
|
-
if (!AI.isConfigured())
|
|
194
|
-
return;
|
|
195
|
-
if (!this.riddle || !this.requiredPhrase)
|
|
196
|
-
return;
|
|
197
|
-
// TERRAIN framing (spatial wave 2026-08-25, closing a real-session
|
|
198
|
-
// complaint: a barrier's prose read "way too insightful on how
|
|
199
|
-
// Doc Halloran is feeling" and exposed history no BARRIER should
|
|
200
|
-
// know -- "it's a BARRIER, not a book"): a terrain-kind puzzle
|
|
201
|
-
// seals a PASSAGE, not a device, so the rewrite must say what
|
|
202
|
-
// physically blocks the way and how it might yield, never lean on
|
|
203
|
-
// scene lore for color.
|
|
204
|
-
const framing = kind === 'terrain'
|
|
205
|
-
? `This barrier is IMPASSABLE TERRAIN blocking a passage -- rubble, a collapsed structure, a security shutter -- NOT a device with a credential. State WHAT physically blocks the way and HOW it looks like it might yield (cut apart, hauled aside, powered down, dispelled). Never a book, riddle, or poem, and never lean on the scene's story or any character's feelings/history for color -- describe the physical obstacle only.`
|
|
206
|
-
: `You are a game narrator rewriting what a player sees when they search a room and find a
|
|
207
|
-
barrier (a lock, scanner, terminal, or ward) -- NOT a riddle or poem.`;
|
|
208
|
-
const prompt = `
|
|
209
|
-
${framing}
|
|
210
|
-
|
|
211
|
-
Scene context: ${sceneContext}
|
|
212
|
-
${roomName ? `This puzzle is found in: ${roomName}` : ''}
|
|
213
|
-
${this.bypassType ? `This barrier is physically a: ${this.bypassType === 'lockpick' ? 'mechanical lock or maglock' : this.bypassType === 'hack' ? 'electronic terminal, console, or scanner' : this.bypassType === 'con' ? 'person or voice-gate that must be talked past (a doorman, an intercom challenge, a checkpoint)' : 'magical ward or sigil'}` : ''}
|
|
214
|
-
|
|
215
|
-
The exact credential that opens it MUST remain: "${this.requiredPhrase}"
|
|
216
|
-
The existing description is: "${this.riddle}"
|
|
217
|
-
|
|
218
|
-
Write a NEW version, evocative but PLAIN. Start with "You see", "You find", or similar,
|
|
219
|
-
and name the barrier concretely -- e.g. "You see a maglock safe." or "You see a biometric
|
|
220
|
-
scanner beside the door." -- then say what it demands (a code, a passphrase, a name, a
|
|
221
|
-
fingerprint), the way an NPC would actually describe it. Describe the OBSTACLE only --
|
|
222
|
-
never write people, guards, or dialogue into it, and never state a character's feelings
|
|
223
|
-
or private history; anyone standing watch does their own talking in play. Do not phrase
|
|
224
|
-
it as a riddle, wordplay, or puzzle to decode, and do not state the credential itself
|
|
225
|
-
outright.
|
|
226
|
-
|
|
227
|
-
THE CREDENTIAL YOU DESCRIBE MUST MATCH THE ONE ABOVE IN KIND. The exact credential is
|
|
228
|
-
"${this.requiredPhrase}" -- ${/^\d+$/.test((this.requiredPhrase ?? '').trim())
|
|
229
|
-
? `that is a NUMBER, so describe something that takes a number: a keypad, a dial, a numeric counter.`
|
|
230
|
-
: `that is a PHRASE OF WORDS, so describe something that takes words: an intercom, a voice-gate, a sign asking for a passphrase. Do NOT describe a numeric keypad, a digit pad, or a combination dial -- a player who reads "keypad" hunts for a number that does not exist, and the words in their pocket stop looking like the answer.`}
|
|
231
|
-
Write NO other number into the description either -- no unit number, model number, or
|
|
232
|
-
serial. Every code-shaped string a player reads is one they will go and type, and a second
|
|
233
|
-
plausible number is indistinguishable from the real one.
|
|
234
|
-
|
|
235
|
-
No more than 3 sentences. Respond with ONLY the description text.`;
|
|
236
|
-
try {
|
|
237
|
-
const reply = await AI.ask(prompt);
|
|
238
|
-
this.riddle = reply;
|
|
239
|
-
this.hasAIRiddle = true;
|
|
240
|
-
this.logger.write(`Generated AI riddle for puzzle "${this.name}"`);
|
|
241
|
-
}
|
|
242
|
-
catch (err) {
|
|
243
|
-
this.logger.write(`AI fallback for riddle (${this.name}): ${err}`);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
hasRequiredItem(playerInventory) {
|
|
247
|
-
if (this.requiredItem) {
|
|
248
|
-
return playerInventory.hasItem(this.requiredItem.name);
|
|
249
|
-
}
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Clue items are only required to CONTAIN the answer somewhere in their
|
|
254
|
-
* text (e.g. "kill the power to bypass security" for a required phrase
|
|
255
|
-
* of "kill the power"), so a player who reasonably quotes the clue back
|
|
256
|
-
* verbatim types more words than the exact answer. Strict equality
|
|
257
|
-
* rejected that. Normalizing punctuation/whitespace and accepting the
|
|
258
|
-
* required phrase as a substring of the input (not just an exact match)
|
|
259
|
-
* fixes it without loosening things enough for a wrong guess to pass.
|
|
260
|
-
*/
|
|
261
|
-
matchesRequiredPhrase(inputPhrase) {
|
|
262
|
-
if (!this.requiredPhrase)
|
|
263
|
-
return false;
|
|
264
|
-
// Punctuation is normalized BOTH ways, because the two readings
|
|
265
|
-
// disagree and players use both. Deleting it is right for a code
|
|
266
|
-
// ("44-71" is the same code as "4471"); treating it as a separator is
|
|
267
|
-
// right for words (a player typing the hyphenated "gate-7-alpha" for
|
|
268
|
-
// an answer of "gate 7 alpha" has the right answer and was being told
|
|
269
|
-
// otherwise -- which reads to them exactly like being handed a wrong
|
|
270
|
-
// code, this bug's own symptom arriving by a second road). Accepting
|
|
271
|
-
// a match under EITHER reading covers both without loosening
|
|
272
|
-
// anything: every variant still has to contain the whole answer.
|
|
273
|
-
const variants = (s) => {
|
|
274
|
-
const lower = s.toLowerCase();
|
|
275
|
-
const stripped = lower.replace(/[^\w\s]/g, '').replace(/\s+/g, ' ').trim();
|
|
276
|
-
const separated = lower.replace(/[^\w\s]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
277
|
-
return stripped === separated ? [stripped] : [stripped, separated];
|
|
278
|
-
};
|
|
279
|
-
const required = variants(this.requiredPhrase).filter(r => r.length > 0);
|
|
280
|
-
const input = variants(inputPhrase);
|
|
281
|
-
return required.some(r => input.some(i => i.includes(r)));
|
|
282
|
-
}
|
|
283
|
-
solve(providedAnswer, playerInventory) {
|
|
284
|
-
if (this.solved) {
|
|
285
|
-
this.logger.write('Puzzle: Attempted to solve an already solved puzzle.');
|
|
286
|
-
return {
|
|
287
|
-
success: false,
|
|
288
|
-
message: 'You have already solved this puzzle.',
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
if (this.requiresPuzzle && !this.requiresPuzzle.isSolved()) {
|
|
292
|
-
this.logger.write(`Puzzle: Attempted "${this.name}" before prerequisite "${this.requiresPuzzle.name}" was solved.`);
|
|
293
|
-
return {
|
|
294
|
-
success: false,
|
|
295
|
-
message: this.lockedMessage,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
if (this.hasRequiredItem(playerInventory) || this.matchesRequiredPhrase(providedAnswer)) {
|
|
299
|
-
this.solved = true;
|
|
300
|
-
this.logger.write('Puzzle: Correct solution provided.');
|
|
301
|
-
return {
|
|
302
|
-
success: true,
|
|
303
|
-
message: this.successMessage,
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
else {
|
|
307
|
-
this.logger.write('Puzzle: Necessary item or correct phrase not provided.');
|
|
308
|
-
return {
|
|
309
|
-
success: false,
|
|
310
|
-
message: this.failureMessage,
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* The risky alternate route never requires knowing requiredPhrase. Split
|
|
316
|
-
* into a gate check (run first, before any outcome is determined -- an
|
|
317
|
-
* already-solved, blocked, or type-mismatched puzzle should never make
|
|
318
|
-
* the player sit through an interactive minigame they were never going
|
|
319
|
-
* to be allowed to attempt) and applying an already-determined outcome.
|
|
320
|
-
* A failed attempt BURNS the route (see bypassBurned) -- the gate
|
|
321
|
-
* refuses retries with the burned flavor -- but never touches the safe
|
|
322
|
-
* solve() path: finding the actual answer remains deterministic. Further
|
|
323
|
-
* consequences (the alarm world event, spell backlash) belong to the
|
|
324
|
-
* calling command (see commands/bypass-command.ts).
|
|
325
|
-
*/
|
|
326
|
-
checkBypassGate(type) {
|
|
327
|
-
if (this.solved) {
|
|
328
|
-
this.logger.write('Puzzle: Attempted to bypass an already solved puzzle.');
|
|
329
|
-
return { allowed: false, reason: 'solved', message: 'You have already solved this puzzle.' };
|
|
330
|
-
}
|
|
331
|
-
if (this.requiresPuzzle && !this.requiresPuzzle.isSolved()) {
|
|
332
|
-
this.logger.write(`Puzzle: Attempted to bypass "${this.name}" before prerequisite "${this.requiresPuzzle.name}" was solved.`);
|
|
333
|
-
return { allowed: false, reason: 'locked', message: this.lockedMessage };
|
|
334
|
-
}
|
|
335
|
-
if (this.bypassType !== type) {
|
|
336
|
-
return { allowed: false, reason: 'mismatch', message: this.wrongRouteMessage() };
|
|
337
|
-
}
|
|
338
|
-
if (this.bypassBurned) {
|
|
339
|
-
this.logger.write(`Puzzle: Attempted a burned ${type} bypass on "${this.name}".`);
|
|
340
|
-
return { allowed: false, reason: 'burned', message: BYPASS_FLAVOR[type]?.burnedMessage ?? `That route is burned -- only the real answer works now.` };
|
|
341
|
-
}
|
|
342
|
-
return { allowed: true };
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* The wrong-verb answer, spoken in the barrier's OWN fiction. Keyed on
|
|
346
|
-
* this.bypassType (what the thing IS), never on the verb attempted --
|
|
347
|
-
* see the note on BYPASS_FLAVOR.resists. Always names a route that
|
|
348
|
-
* works, so a player never gets a dead end in front of a visible
|
|
349
|
-
* barrier; a barrier with no shortcut at all says so plainly instead
|
|
350
|
-
* of pretending not to exist, which is what a solve-only puzzle used
|
|
351
|
-
* to do (it was filtered out before this gate ever ran).
|
|
352
|
-
*/
|
|
353
|
-
wrongRouteMessage() {
|
|
354
|
-
const safeRoute = `(The answer itself always works, if you turn it up: "solve <the answer>".)`;
|
|
355
|
-
const flavor = this.bypassType ? BYPASS_FLAVOR[this.bypassType] : undefined;
|
|
356
|
-
if (!flavor) {
|
|
357
|
-
return `That finds no purchase -- this one has no shortcut in it. No mechanism to trip, no system to crack, nothing to unweave or talk round. Only the real answer opens it.\n${safeRoute}`;
|
|
358
|
-
}
|
|
359
|
-
return `That finds no purchase here. ${flavor.resists}\n${safeRoute}`;
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Applies an outcome already determined elsewhere (a coin flip, or a live
|
|
363
|
-
* minigame's win/loss) to this puzzle. Assumes checkBypassGate() already
|
|
364
|
-
* passed -- doesn't re-check it.
|
|
365
|
-
*/
|
|
366
|
-
resolveBypass(type, succeeded) {
|
|
367
|
-
if (succeeded) {
|
|
368
|
-
this.solved = true;
|
|
369
|
-
this.logger.write(`Puzzle: Successful ${type} bypass.`);
|
|
370
|
-
return { success: true, message: this.successMessage, alarmed: false };
|
|
371
|
-
}
|
|
372
|
-
// The trick is spent: mechanism seized, signature blacklisted, ward
|
|
373
|
-
// sealed, cover blown. The findable answer still works -- solve() never
|
|
374
|
-
// consults this flag.
|
|
375
|
-
this.bypassBurned = true;
|
|
376
|
-
this.logger.write(`Puzzle: Failed ${type} bypass -- alarmed, route burned.`);
|
|
377
|
-
return { success: false, message: BYPASS_FLAVOR[type]?.failureMessage ?? this.failureMessage, alarmed: true };
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* Convenience wrapper: gate check + a flat coin-flip outcome. Used for
|
|
381
|
-
* any bypass type without its own interactive minigame yet -- see
|
|
382
|
-
* BypassCommand.determineOutcome(), which lockpicking overrides to run a
|
|
383
|
-
* real player-skill challenge instead of this coin flip.
|
|
384
|
-
*/
|
|
385
|
-
attemptBypass(type) {
|
|
386
|
-
const gate = this.checkBypassGate(type);
|
|
387
|
-
if (!gate.allowed) {
|
|
388
|
-
return { success: false, message: gate.message ?? 'You can\'t do that here.', alarmed: false };
|
|
389
|
-
}
|
|
390
|
-
return this.resolveBypass(type, Math.random() < Puzzle.BYPASS_SUCCESS_CHANCE);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
//# sourceMappingURL=puzzle.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"puzzle.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/models/puzzle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAG7C,OAAO,EAAE,EAAE,EAAE,MAAM,kCAAkC,CAAC;AAGtD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiC9D;;;;;;;;;;GAUG;AACH,MAAM,aAAa,GAA8I;IAC/J,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QACzB,OAAO,EAAE,gLAAgL;QACzL,cAAc,EAAE,gFAAgF;QAChG,IAAI,EAAE,mOAAmO;QACzO,aAAa,EAAE,0GAA0G;KAC1H;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,iHAAiH;QAC1H,cAAc,EAAE,oGAAoG;QACpH,IAAI,EAAE,4JAA4J;QAClK,aAAa,EAAE,mHAAmH;KACnI;IACD,KAAK,EAAE;QACL,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QACzB,OAAO,EAAE,uJAAuJ;QAChK,cAAc,EAAE,qGAAqG;QACrH,IAAI,EAAE,8MAA8M;QACpN,aAAa,EAAE,kIAAkI;KAClJ;IACD,wEAAwE;IACxE,qEAAqE;IACrE,uEAAuE;IACvE,qEAAqE;IACrE,wEAAwE;IACxE,2CAA2C;IAC3C,GAAG,EAAE;QACH,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,CAAC,OAAO,CAAC;QAChB,OAAO,EAAE,+HAA+H;QACxI,cAAc,EAAE,2FAA2F;QAC3G,IAAI,EAAE,+JAA+J;QACrK,aAAa,EAAE,qGAAqG;KACrH;CACF,CAAC;AAEF,MAAM,OAAO,MAAO,SAAQ,cAAc;IAC9B,MAAM,GAAW,MAAM,CAAC,WAAW,EAAE,CAAC;IACtC,MAAM,GAAG,KAAK,CAAC;IACjB,WAAW,GAAG,KAAK,CAAC;IAErB,IAAI,CAAS;IACb,YAAY,CAAQ;IACpB,cAAc,CAAU;IACxB,MAAM,CAAU;IACvB,qEAAqE;IACrE,wEAAwE;IACxE,kCAAkC;IAC3B,UAAU,CAAQ;IACzB,uCAAuC;IAChC,MAAM,CAAU;IAChB,cAAc,CAAS;IACvB,cAAc,CAAS;IACvB,SAAS,CAAY;IAE5B,sEAAsE;IACtE,wEAAwE;IACxE,oEAAoE;IACpE,0DAA0D;IACnD,cAAc,CAAU;IACxB,aAAa,CAAS;IAE7B,uEAAuE;IACvE,oEAAoE;IACpE,yEAAyE;IACzE,wEAAwE;IACxE,kEAAkE;IAClE,oEAAoE;IACpE,+DAA+D;IAC/D,mBAAmB;IACZ,UAAU,CAAoB;IAC7B,MAAM,CAAU,qBAAqB,GAAG,GAAG,CAAC;IAEpD,mEAAmE;IACnE,oEAAoE;IACpE,qEAAqE;IACrE,sEAAsE;IACtE,eAAe;IACR,YAAY,GAAG,KAAK,CAAC;IAE5B,YAAY,MAAgC;QAC1C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACxC,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,wBAAwB,CAAC;QACxE,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,8EAA8E,CAAC;QAC9H,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,uCAAuC,CAAC;QAC7D,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH;;iDAE6C;IAC7C,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,CAAC;IAED;;;;;;;OAOG;IACH,cAAc;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAChC,OAAO,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IACrD,CAAC;IAED,aAAa;QACX,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,SAAS,CAAC;QACvC,qEAAqE;QACrE,qEAAqE;QACrE,mEAAmE;QACnE,mEAAmE;QACnE,uEAAuE;QACvE,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAC9B,kEAAkE;QAClE,4CAA4C;QAC5C,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;QACnC,CAAC;QACD,mEAAmE;QACnE,4DAA4D;QAC5D,mEAAmE;QACnE,qEAAqE;QACrE,kEAAkE;QAClE,kEAAkE;QAClE,wBAAwB;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,kHAAkH,CAAC,CAAC;QACpJ,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,YAAoB,EAAE,aAAsB;QAC5D,IAAI,CAAC,cAAc,GAAG,YAAY,CAAC;QACnC,IAAI,aAAa,EAAE,CAAC;YAClB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,KAAiD;QAC5D,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;IACzC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,cAAc,CAAC,YAAoB,EAAE,QAAiB,EAAE,OAA6B,QAAQ;QACxG,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAC7B,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE;YAAE,OAAO;QAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO;QAEjD,mEAAmE;QACnE,+DAA+D;QAC/D,iEAAiE;QACjE,+DAA+D;QAC/D,8DAA8D;QAC9D,kEAAkE;QAClE,wBAAwB;QACxB,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS;YAChC,CAAC,CAAC,saAAsa;YACxa,CAAC,CAAC;sEAC8D,CAAC;QAEnE,MAAM,MAAM,GAAG;EACjB,OAAO;;iBAEQ,YAAY;EAC3B,QAAQ,CAAC,CAAC,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE;EACtD,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,iCAAiC,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,gGAAgG,CAAC,CAAC,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC,EAAE;;mDAEzS,IAAI,CAAC,cAAc;gCACtC,IAAI,CAAC,MAAM;;;;;;;;;;;;GAYxC,IAAI,CAAC,cAAc,QAAQ,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1E,CAAC,CAAC,mGAAmG;YACrG,CAAC,CAAC,uUAAuU;;;;;kEAK3Q,CAAC;QAE/D,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,eAAe,CAAC,eAA0B;QACxC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;OAQG;IACH,qBAAqB,CAAC,WAAmB;QACvC,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC;QAEvC,gEAAgE;QAChE,iEAAiE;QACjE,sEAAsE;QACtE,qEAAqE;QACrE,sEAAsE;QACtE,qEAAqE;QACrE,qEAAqE;QACrE,6DAA6D;QAC7D,iEAAiE;QACjE,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3E,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7E,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACrE,CAAC,CAAC;QAEF,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QAEpC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,cAAsB,EAAE,eAA0B;QACtD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC1E,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,sCAAsC;aAChD,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,IAAI,CAAC,IAAI,0BAA0B,IAAI,CAAC,cAAc,CAAC,IAAI,eAAe,CAAC,CAAC;YACpH,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,IAAI,CAAC,aAAa;aAC5B,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,EAAE,CAAC;YACxF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI,CAAC,cAAc;aAC7B,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;YAC5E,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,IAAI,CAAC,cAAc;aAC7B,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,IAAsB;QACpC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAC3E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC;QAC/F,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,IAAI,CAAC,IAAI,0BAA0B,IAAI,CAAC,cAAc,CAAC,IAAI,eAAe,CAAC,CAAC;YAC9H,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3E,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;QACnF,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,IAAI,eAAe,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;YAClF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa,IAAI,yDAAyD,EAAE,CAAC;QACxJ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;OAQG;IACK,iBAAiB;QACvB,MAAM,SAAS,GAAG,4EAA4E,CAAC;QAC/F,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5E,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,yKAAyK,SAAS,EAAE,CAAC;QAC9L,CAAC;QACD,OAAO,gCAAgC,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;IACxE,CAAC;IAED;;;;OAIG;IACH,aAAa,CAAC,IAAsB,EAAE,SAAkB;QACtD,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,IAAI,UAAU,CAAC,CAAC;YACxD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACzE,CAAC;QAED,oEAAoE;QACpE,wEAAwE;QACxE,sBAAsB;QACtB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,IAAI,mCAAmC,CAAC,CAAC;QAC7E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,cAAc,IAAI,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAChH,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,IAAsB;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,0BAA0B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACjG,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAChF,CAAC"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export type PuzzleBypassType = 'lockpick' | 'hack' | 'spell' | 'con';
|
|
2
|
-
export interface IPuzzleSeedJson {
|
|
3
|
-
name: string;
|
|
4
|
-
room?: string;
|
|
5
|
-
riddle: string;
|
|
6
|
-
requiredPhrase?: string;
|
|
7
|
-
requiredItem?: string;
|
|
8
|
-
rewardItem?: string;
|
|
9
|
-
successMessage?: string;
|
|
10
|
-
failureMessage?: string;
|
|
11
|
-
hobbyTags?: string[];
|
|
12
|
-
/** Name of another puzzle in this same scene that must be solved first. */
|
|
13
|
-
requiresPuzzle?: string;
|
|
14
|
-
/** Shown when attempting to solve this puzzle before requiresPuzzle is met. */
|
|
15
|
-
lockedMessage?: string;
|
|
16
|
-
/**
|
|
17
|
-
* Optional risky alternate route to the same reward, matching this
|
|
18
|
-
* barrier's in-fiction nature (a lock -> "pick", a terminal -> "hack", a
|
|
19
|
-
* ward -> "cast") -- a coin-flip chance to bypass without ever knowing
|
|
20
|
-
* requiredPhrase, but a failed attempt is loud (see Puzzle.attemptBypass).
|
|
21
|
-
* Leave unset for a puzzle with no such physical/technical/magical route
|
|
22
|
-
* (e.g. a purely social one, solvable only by knowing the actual answer).
|
|
23
|
-
*/
|
|
24
|
-
bypassType?: PuzzleBypassType;
|
|
25
|
-
atSpot?: string;
|
|
26
|
-
guardsExit?: string;
|
|
27
|
-
footprint?: 'small' | 'medium' | 'large';
|
|
28
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"puzzle-seed.js","sourceRoot":"","sources":["../../../../../../../../src/commands/game/sideQuest/types/seed/puzzle-seed.ts"],"names":[],"mappings":""}
|