@maka/maka-cli 5.3.17 → 5.5.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/archetypes.d.ts +62 -0
- package/bundle/typescript/src/commands/game/sideQuest/archetypes.js +196 -0
- package/bundle/typescript/src/commands/game/sideQuest/archetypes.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/advance.d.ts +16 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/advance.js +65 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/advance.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/assense.d.ts +16 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/assense.js +122 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/assense.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/attack.d.ts +42 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js +243 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.d.ts +16 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js +39 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/brandish.d.ts +21 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/brandish.js +82 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/brandish.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.d.ts +28 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js +101 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.d.ts +19 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js +219 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.d.ts +58 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js +397 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/command-registry.d.ts +11 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/command-registry.js +8 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/command-registry.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/command.d.ts +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/command.js +4 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/command.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/drone.d.ts +15 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/drone.js +72 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/drone.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/drop.js +3 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/drop.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/edge.d.ts +13 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/edge.js +31 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/edge.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/end-call.d.ts +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/end-call.js +27 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/end-call.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/equip.d.ts +4 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/equip.js +59 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/equip.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.d.ts +13 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js +50 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/give.js +7 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/give.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.d.ts +13 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +147 -4
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.d.ts +25 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +199 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/haggle.d.ts +15 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/haggle.js +75 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/haggle.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/inv.d.ts +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js +43 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/jack.d.ts +17 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js +64 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/kill.d.ts +10 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/kill.js +11 -33
- package/bundle/typescript/src/commands/game/sideQuest/commands/kill.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +47 -4
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.d.ts +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +46 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/pan.d.ts +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js +55 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/persuade.d.ts +18 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/persuade.js +100 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/persuade.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.d.ts +10 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js +33 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/project.d.ts +19 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/project.js +54 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/project.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/read.js +6 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/read.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.d.ts +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.js +52 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/reboot.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/reload.d.ts +14 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/reload.js +40 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/reload.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/rest.d.ts +15 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js +59 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +31 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +71 -7
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.d.ts +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +58 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.d.ts +13 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js +50 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/sneak.d.ts +15 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/sneak.js +35 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/sneak.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js +32 -11
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/spells.d.ts +14 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js +86 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/stance.d.ts +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js +41 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/subdue.d.ts +21 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/subdue.js +43 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/subdue.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/surrender.d.ts +20 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/surrender.js +45 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/surrender.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/take.d.ts +8 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/take.js +138 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/take.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/talk.js +8 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/talk.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/unequip.js +6 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/unequip.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.d.ts +24 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.js +102 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/item-factory.js +2 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/item-factory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/npc-factory.js +7 -2
- package/bundle/typescript/src/commands/game/sideQuest/factories/npc-factory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js +2 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/room-factory.js +3 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/room-factory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.d.ts +175 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +673 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.d.ts +8 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js +139 -21
- 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 +174 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js +647 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +138 -9
- package/bundle/typescript/src/commands/game/sideQuest/game.js +757 -197
- package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/minigames/hack-minigame.d.ts +16 -0
- package/bundle/typescript/src/commands/game/sideQuest/minigames/hack-minigame.js +101 -0
- package/bundle/typescript/src/commands/game/sideQuest/minigames/hack-minigame.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/minigames/lockpick-minigame.d.ts +15 -0
- package/bundle/typescript/src/commands/game/sideQuest/minigames/lockpick-minigame.js +95 -0
- package/bundle/typescript/src/commands/game/sideQuest/minigames/lockpick-minigame.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/door.d.ts +10 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/door.js +15 -2
- package/bundle/typescript/src/commands/game/sideQuest/models/door.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/inventory.d.ts +10 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/inventory.js +54 -4
- package/bundle/typescript/src/commands/game/sideQuest/models/inventory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/item.d.ts +41 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/item.js +106 -3
- package/bundle/typescript/src/commands/game/sideQuest/models/item.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.d.ts +27 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +312 -50
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +278 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js +661 -9
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.d.ts +75 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js +199 -6
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/room.d.ts +24 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js +53 -18
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.d.ts +73 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +208 -3
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/scenes/scene1.json +319 -70
- package/bundle/typescript/src/commands/game/sideQuest/scenes/scene2.json +661 -227
- package/bundle/typescript/src/commands/game/sideQuest/types/player-equipment.d.ts +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/exit-seed.d.ts +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/item-seed.d.ts +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/npc-seed.d.ts +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/player-seed.d.ts +42 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.d.ts +15 -1
- 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 +8 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/win-condition-seed.d.ts +15 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/win-condition-seed.js +2 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/win-condition-seed.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.d.ts +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js +5 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.d.ts +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.js +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/ui.d.ts +3 -0
- package/bundle/typescript/src/commands/game/sideQuest/ui.js +95 -6
- package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.d.ts +60 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.js +138 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/auto-fight.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.d.ts +145 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js +354 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/comm-style.d.ts +2 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/comm-style.js +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/comm-style.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.d.ts +22 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.js +34 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/dice.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.d.ts +36 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js +92 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.d.ts +77 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +265 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/pursuit.d.ts +16 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/pursuit.js +36 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/pursuit.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +78 -7
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
- package/bundle/typescript/src/commands/set/global.sub.cmd.js +59 -5
- package/bundle/typescript/src/commands/set/global.sub.cmd.js.map +1 -1
- package/bundle/typescript/src/tools/ai/ai.class.d.ts +42 -0
- package/bundle/typescript/src/tools/ai/ai.class.js +117 -0
- package/bundle/typescript/src/tools/ai/ai.class.js.map +1 -0
- package/bundle/typescript/src/tools/fsi/fsi.interfaces.d.ts +1 -0
- package/bundle/typescript/src/tools/fsi/fsi.interfaces.js.map +1 -1
- package/bundle/typescript/src/tools/https/https.class.d.ts +3 -2
- package/bundle/typescript/src/tools/https/https.class.js +51 -2
- package/bundle/typescript/src/tools/https/https.class.js.map +1 -1
- package/bundle/typescript/src/tools/https/https.interface.d.ts +10 -0
- package/package.json +1 -1
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { Command } from './command.js';
|
|
2
|
+
import { CombatExchange } from '../utilities/combat-exchange.js';
|
|
3
|
+
import { fuzzyPickName } from '../utilities/fuzzy-match.js';
|
|
4
|
+
import { describeFledTarget } from '../utilities/pursuit.js';
|
|
5
|
+
import { shellsInRoom, resolveBodyAttack, crossPlaneRefusal } from '../utilities/planes.js';
|
|
6
|
+
/**
|
|
7
|
+
* Shadowrun-style dice-pool combat, one full exchange per command:
|
|
8
|
+
*
|
|
9
|
+
* 1. Attacker rolls Agility + combat skill + weapon bonus, opposed by the
|
|
10
|
+
* defender's Reaction. Net hits land the blow.
|
|
11
|
+
* 2. Damage = weapon DV + net hits, soaked by Body + armor (each soak hit
|
|
12
|
+
* cancels one box).
|
|
13
|
+
* 3. Whatever gets through fills the defender's condition monitor; a full
|
|
14
|
+
* track is death.
|
|
15
|
+
* 4. If the defender survives, they immediately strike back with the same
|
|
16
|
+
* math reversed -- starting a fight means eating one, so a fight is a
|
|
17
|
+
* real decision, not a free action.
|
|
18
|
+
*
|
|
19
|
+
* Wound modifiers (-1 die per 3 boxes taken) apply to every pool on both
|
|
20
|
+
* sides, so a fight tilts as it goes. Pools/derivations live on Player
|
|
21
|
+
* (getAttackPool() etc.); narration pacing, strike resolution, and death
|
|
22
|
+
* handling live in CombatExchange (shared with spell combat -- see
|
|
23
|
+
* cast.ts). This command only orchestrates the weapon exchange.
|
|
24
|
+
*/
|
|
25
|
+
export class AttackCommand extends Command {
|
|
26
|
+
static verb = 'attack';
|
|
27
|
+
static description = 'Attack someone in the room -- dice-pool combat with your equipped weapon. They WILL hit back.';
|
|
28
|
+
async execute(args = []) {
|
|
29
|
+
if (!args || args.length === 0) {
|
|
30
|
+
return 'Who do you want to attack? Try: `attack <name>`';
|
|
31
|
+
}
|
|
32
|
+
// The dead (and the unconscious) don't fight. Covers a downed player
|
|
33
|
+
// (who stays in the scene -- endGame only freezes input) and a downed
|
|
34
|
+
// NPC whose in-flight AI loop is still issuing commands after removal
|
|
35
|
+
// from the scene.
|
|
36
|
+
if (this.actor.isIncapacitated()) {
|
|
37
|
+
return `You're down. The fight is over.`;
|
|
38
|
+
}
|
|
39
|
+
// Violence is loud -- sneak mode ends the moment you swing.
|
|
40
|
+
this.actor.sneaking = false;
|
|
41
|
+
const room = this.actor.currentLocation;
|
|
42
|
+
if (!room) {
|
|
43
|
+
return 'You are not in a valid location to fight anyone.';
|
|
44
|
+
}
|
|
45
|
+
// Same fuzzy matching "take" uses (see utilities/fuzzy-match.ts) --
|
|
46
|
+
// punctuation, case, typos, and partial names all resolve, but an
|
|
47
|
+
// ambiguous guess deliberately misses rather than shooting someone
|
|
48
|
+
// at random. You can only fight what shares your plane: meat can't
|
|
49
|
+
// touch a Matrix persona or an astral form, and vice versa.
|
|
50
|
+
const targetName = args.join(' ');
|
|
51
|
+
const candidates = this.scene.getActorsInRoom(room).filter(a => a !== this.actor && a.plane === this.actor.plane);
|
|
52
|
+
const pickedName = fuzzyPickName(targetName, candidates.map(a => a.name));
|
|
53
|
+
const target = pickedName ? candidates.find(a => a.name === pickedName) : undefined;
|
|
54
|
+
if (!target) {
|
|
55
|
+
// An empty body IS attackable from the meat plane -- one unanswered
|
|
56
|
+
// strike, and its owner gets slammed back into it (see planes.ts).
|
|
57
|
+
if (this.actor.plane === 'meat') {
|
|
58
|
+
const shells = shellsInRoom(this.scene, room);
|
|
59
|
+
const shellPick = fuzzyPickName(targetName, shells.map(s => s.name));
|
|
60
|
+
const shell = shellPick ? shells.find(s => s.name === shellPick) : undefined;
|
|
61
|
+
if (shell) {
|
|
62
|
+
// Even a defenseless body gets shot, not slapped -- draw first.
|
|
63
|
+
const drawn = this.actor.drawWeapon();
|
|
64
|
+
const lines = resolveBodyAttack(this.scene, this.actor, shell);
|
|
65
|
+
if (drawn)
|
|
66
|
+
lines.unshift(`${this.actor.name} draws ${drawn.name}.`);
|
|
67
|
+
const exchange = new CombatExchange(this.scene, this.logger, this.actor);
|
|
68
|
+
await exchange.announce(lines);
|
|
69
|
+
if (shell.isDown()) {
|
|
70
|
+
const death = await exchange.resolveDeath(shell, this.actor, {
|
|
71
|
+
fallLine: `${shell.name}'s body never wakes -- whatever came rushing back arrived too late. Their gear scatters across ${room.name}.`,
|
|
72
|
+
});
|
|
73
|
+
lines.push(...death);
|
|
74
|
+
}
|
|
75
|
+
return this.actor === this.scene.getPlayer() ? '' : lines.join('\n');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Visible on another plane beats "no one": a projecting mage's look
|
|
79
|
+
// lists the meat world's auras, so a miss here must name the actual
|
|
80
|
+
// rule, not deny the person exists (see planes.crossPlaneRefusal).
|
|
81
|
+
const cross = crossPlaneRefusal(this.scene, this.actor, room, targetName, 'strike');
|
|
82
|
+
if (cross)
|
|
83
|
+
return cross;
|
|
84
|
+
// If they exist but fled the room, say WHERE and how to chase --
|
|
85
|
+
// this result is what lands in a pursuing NPC's AI history, and
|
|
86
|
+
// without the explicit direction a hostile NPC just spams failed
|
|
87
|
+
// attacks at the empty room instead of following (real session:
|
|
88
|
+
// dozens of them while the player ping-ponged between two rooms).
|
|
89
|
+
const fled = describeFledTarget(this.scene, room, targetName);
|
|
90
|
+
if (fled)
|
|
91
|
+
return fled;
|
|
92
|
+
const present = candidates.map(a => a.name).join(', ') || 'no one';
|
|
93
|
+
return `You don't see anyone named "${targetName}" here to attack. Present: ${present}.`;
|
|
94
|
+
}
|
|
95
|
+
// The dead can't be fought either. A downed NPC is removed from the
|
|
96
|
+
// scene, so a still-present downed target can only be the dead player
|
|
97
|
+
// -- found via a real session where the killer's AI loop, with nothing
|
|
98
|
+
// gating this, beat the player's corpse for a full minute, re-running
|
|
99
|
+
// the whole death sequence every swing. The plain-text result below is
|
|
100
|
+
// what actually lands in the attacker's AI history and tells it the
|
|
101
|
+
// fight is over.
|
|
102
|
+
if (target.isIncapacitated()) {
|
|
103
|
+
return `${target.name} is already down. The fight is over -- there's nothing left to attack.`;
|
|
104
|
+
}
|
|
105
|
+
// One exchange at a time per combatant: overlapping AI loops firing
|
|
106
|
+
// parallel exchanges once double-killed a target (two death events,
|
|
107
|
+
// two narrations). The player is refused cleanly (they can just retype
|
|
108
|
+
// in the lull); an NPC's attack instead WAITS for the lull and re-runs
|
|
109
|
+
// -- discarding it meant NPCs never got a single action off, because
|
|
110
|
+
// their AI always reacts while the player's exchange is still beating
|
|
111
|
+
// out (see CombatExchange.waitForLull).
|
|
112
|
+
if (this.actor.inExchange || target.inExchange) {
|
|
113
|
+
if (this.actor === this.scene.getPlayer()) {
|
|
114
|
+
return this.actor.inExchange
|
|
115
|
+
? `You're already mid-exchange -- let it resolve.`
|
|
116
|
+
: `${target.name} is already trading fire -- wait for that exchange to resolve.`;
|
|
117
|
+
}
|
|
118
|
+
if (this.actor.waitingForLull) {
|
|
119
|
+
return `You're already waiting for an opening -- one move at a time.`;
|
|
120
|
+
}
|
|
121
|
+
this.actor.waitingForLull = true;
|
|
122
|
+
try {
|
|
123
|
+
const settled = await CombatExchange.waitForLull([this.actor, target]);
|
|
124
|
+
if (!settled) {
|
|
125
|
+
return `You're already mid-exchange -- let it resolve.`;
|
|
126
|
+
}
|
|
127
|
+
this.logger.write(`${this.actor.name}'s attack waited out an exchange and now retries.`);
|
|
128
|
+
return await this.execute(args);
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
this.actor.waitingForLull = false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// A deliberately INITIATED attack with a dry gun is blocked with a
|
|
135
|
+
// reload prompt -- the involuntary strikes (retaliation) auto-fall-back
|
|
136
|
+
// to fists instead (see CombatExchange.weaponProfile).
|
|
137
|
+
const weaponItem = this.actor.equipment.rightHand?.weapon ?? this.actor.equipment.leftHand?.weapon;
|
|
138
|
+
if (this.usesEquippedWeapon() && weaponItem?.isFirearm() && weaponItem.jammed) {
|
|
139
|
+
return `The ${weaponItem.name}'s smartlink is LOCKED -- someone cracked your PAN. "reboot" to clear it, or go in swinging.`;
|
|
140
|
+
}
|
|
141
|
+
if (this.usesEquippedWeapon() && weaponItem?.isFirearm() && weaponItem.ammo <= 0) {
|
|
142
|
+
return `Click -- the ${weaponItem.name} is dry. "reload" (needs ammunition), or go in swinging with something else.`;
|
|
143
|
+
}
|
|
144
|
+
const exchange = new CombatExchange(this.scene, this.logger, this.actor);
|
|
145
|
+
const report = [];
|
|
146
|
+
// Movement locks for the duration of the exchange when the player is a
|
|
147
|
+
// combatant (see go.ts) -- the try/finally is exception safety so a
|
|
148
|
+
// crash mid-exchange can never leave the player permanently rooted.
|
|
149
|
+
// beginExchange auto-draws holstered weapons for whoever's weapon is
|
|
150
|
+
// about to speak -- the aggressor only when this attack actually uses
|
|
151
|
+
// it (subdue's hold doesn't; the defender's counter always does).
|
|
152
|
+
const drawLines = exchange.beginExchange(target, { aggressorDraws: this.usesEquippedWeapon() });
|
|
153
|
+
try {
|
|
154
|
+
this.actor.performAction(this.actionVerb(), target.name);
|
|
155
|
+
this.scene.addWorldEvent(`${this.actor.name} ${this.actionVerb()} ${target.name} in ${room.name}.`);
|
|
156
|
+
if (drawLines.length > 0) {
|
|
157
|
+
report.push(...drawLines);
|
|
158
|
+
await exchange.announce(drawLines);
|
|
159
|
+
}
|
|
160
|
+
// ---- Initiative decides who acts first (see rollInitiative) ----
|
|
161
|
+
const init = exchange.rollInitiative(this.actor, target);
|
|
162
|
+
report.push(...init.lines);
|
|
163
|
+
await exchange.announce(init.lines);
|
|
164
|
+
// ---- The two strikes, in initiative order. The aggressor's strike
|
|
165
|
+
// uses this command's profile (weapon, or subdue's stun hold); the
|
|
166
|
+
// defender's answer is always their own lethal weapon. Being
|
|
167
|
+
// preempted and dropped means your swing never happens. ----
|
|
168
|
+
for (const striker of [init.first, init.second]) {
|
|
169
|
+
if (striker.isIncapacitated())
|
|
170
|
+
continue;
|
|
171
|
+
const defender = striker === this.actor ? target : this.actor;
|
|
172
|
+
if (defender.isIncapacitated())
|
|
173
|
+
break;
|
|
174
|
+
// A mid-exchange forced dump (cold-sim persona crash) yanks a
|
|
175
|
+
// combatant off this plane -- the fight is over, not continued
|
|
176
|
+
// across realities.
|
|
177
|
+
if (striker.plane !== defender.plane)
|
|
178
|
+
break;
|
|
179
|
+
const profile = striker === this.actor ? this.strikeProfile(exchange, target) : undefined;
|
|
180
|
+
const prefix = striker === init.second ? [`${striker.name} retaliates!`] : [];
|
|
181
|
+
const strike = [...prefix, ...exchange.resolveStrike(striker, defender, profile)];
|
|
182
|
+
report.push('', ...strike);
|
|
183
|
+
await exchange.announce(strike);
|
|
184
|
+
const takedown = await this.resolveTakedown(exchange, defender, striker);
|
|
185
|
+
if (takedown) {
|
|
186
|
+
report.push(...takedown);
|
|
187
|
+
return await exchange.finishExchange(report);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// ---- The initiative pass: a decisive winner presses the advantage
|
|
191
|
+
// with one extra strike. ----
|
|
192
|
+
if (init.extraStriker && !init.extraStriker.isIncapacitated()) {
|
|
193
|
+
const defender = init.extraStriker === this.actor ? target : this.actor;
|
|
194
|
+
if (!defender.isIncapacitated() && init.extraStriker.plane === defender.plane) {
|
|
195
|
+
const profile = init.extraStriker === this.actor ? this.strikeProfile(exchange, target) : undefined;
|
|
196
|
+
const strike = [`${init.extraStriker.name} presses the advantage!`, ...exchange.resolveStrike(init.extraStriker, defender, profile)];
|
|
197
|
+
report.push('', ...strike);
|
|
198
|
+
await exchange.announce(strike);
|
|
199
|
+
const takedown = await this.resolveTakedown(exchange, defender, init.extraStriker);
|
|
200
|
+
if (takedown)
|
|
201
|
+
report.push(...takedown);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return await exchange.finishExchange(report);
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
this.scene.endPlayerExchange();
|
|
208
|
+
exchange.releaseExchange();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/** subdue.ts overrides to false: its strike ignores the equipped gun entirely. */
|
|
212
|
+
usesEquippedWeapon() {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
/** Overridden by subdue.ts to swap in a stun-dealing strike. undefined = weapon default. */
|
|
216
|
+
strikeProfile(_exchange, _target) {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
/** The verb observers see ("attacks" / "moves to subdue"). */
|
|
220
|
+
actionVerb() {
|
|
221
|
+
return 'attacks';
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Post-strike incapacitation, both flavors: a full physical track is a
|
|
225
|
+
* death; a full stun track (only reachable via a stun-dealing strike,
|
|
226
|
+
* or its overflow) is a live capture. Returns the narration, or null if
|
|
227
|
+
* the fallen still stands. Either combatant can be the one who falls --
|
|
228
|
+
* initiative order means the aggressor eats preemptive strikes too.
|
|
229
|
+
*/
|
|
230
|
+
async resolveTakedown(exchange, fallen, killer) {
|
|
231
|
+
if (fallen.isDown()) {
|
|
232
|
+
return exchange.resolveDeath(fallen, killer);
|
|
233
|
+
}
|
|
234
|
+
if (fallen.isUnconscious()) {
|
|
235
|
+
return exchange.resolveDeath(fallen, killer, {
|
|
236
|
+
fatal: false,
|
|
237
|
+
fallLine: `${fallen.name} sags and drops -- out cold, breathing. Their gear scatters across ${fallen.currentLocation.name}.`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=attack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attack.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/attack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAkB,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAI5F;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,aAAc,SAAQ,OAAO;IAC9B,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;IACvB,MAAM,CAAC,WAAW,GAAG,+FAA+F,CAAC;IAE/H,KAAK,CAAC,OAAO,CAAC,OAAiB,EAAE;QAC/B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,iDAAiD,CAAC;QAC3D,CAAC;QAED,qEAAqE;QACrE,sEAAsE;QACtE,sEAAsE;QACtE,kBAAkB;QAClB,IAAI,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,CAAC;YACjC,OAAO,iCAAiC,CAAC;QAC3C,CAAC;QAED,4DAA4D;QAC5D,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;QAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,kDAAkD,CAAC;QAC5D,CAAC;QAED,oEAAoE;QACpE,kEAAkE;QAClE,mEAAmE;QACnE,mEAAmE;QACnE,4DAA4D;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClH,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEpF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,oEAAoE;YACpE,mEAAmE;YACnE,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC9C,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBACrE,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7E,IAAI,KAAK,EAAE,CAAC;oBACV,gEAAgE;oBAChE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;oBACtC,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;oBAC/D,IAAI,KAAK;wBAAE,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,UAAU,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;oBACpE,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzE,MAAM,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;oBAC/B,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;wBACnB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;4BAC3D,QAAQ,EAAE,GAAG,KAAK,CAAC,IAAI,kGAAkG,IAAI,CAAC,IAAI,GAAG;yBACtI,CAAC,CAAC;wBACH,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;oBACvB,CAAC;oBACD,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;YAED,oEAAoE;YACpE,oEAAoE;YACpE,mEAAmE;YACnE,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YACpF,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;YAExB,iEAAiE;YACjE,gEAAgE;YAChE,iEAAiE;YACjE,gEAAgE;YAChE,kEAAkE;YAClE,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;YAC9D,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAC;YAEtB,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;YACnE,OAAO,+BAA+B,UAAU,8BAA8B,OAAO,GAAG,CAAC;QAC3F,CAAC;QAED,oEAAoE;QACpE,sEAAsE;QACtE,uEAAuE;QACvE,sEAAsE;QACtE,uEAAuE;QACvE,oEAAoE;QACpE,iBAAiB;QACjB,IAAI,MAAM,CAAC,eAAe,EAAE,EAAE,CAAC;YAC7B,OAAO,GAAG,MAAM,CAAC,IAAI,wEAAwE,CAAC;QAChG,CAAC;QAED,oEAAoE;QACpE,oEAAoE;QACpE,uEAAuE;QACvE,uEAAuE;QACvE,qEAAqE;QACrE,sEAAsE;QACtE,wCAAwC;QACxC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YAC/C,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU;oBAC1B,CAAC,CAAC,gDAAgD;oBAClD,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,gEAAgE,CAAC;YACrF,CAAC;YACD,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;gBAC9B,OAAO,8DAA8D,CAAC;YACxE,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;gBACvE,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,gDAAgD,CAAC;gBAC1D,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,mDAAmD,CAAC,CAAC;gBACzF,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;YACpC,CAAC;QACH,CAAC;QAED,mEAAmE;QACnE,wEAAwE;QACxE,uDAAuD;QACvD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;QACnG,IAAI,IAAI,CAAC,kBAAkB,EAAE,IAAI,UAAU,EAAE,SAAS,EAAE,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;YAC9E,OAAO,OAAO,UAAU,CAAC,IAAI,8FAA8F,CAAC;QAC9H,CAAC;QACD,IAAI,IAAI,CAAC,kBAAkB,EAAE,IAAI,UAAU,EAAE,SAAS,EAAE,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;YACjF,OAAO,gBAAgB,UAAU,CAAC,IAAI,8EAA8E,CAAC;QACvH,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACzE,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,uEAAuE;QACvE,oEAAoE;QACpE,oEAAoE;QACpE,qEAAqE;QACrE,sEAAsE;QACtE,kEAAkE;QAClE,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAChG,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;YAEpG,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;gBAC1B,MAAM,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACrC,CAAC;YAED,mEAAmE;YACnE,MAAM,IAAI,GAAG,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEpC,oEAAoE;YACpE,mEAAmE;YACnE,6DAA6D;YAC7D,6DAA6D;YAC7D,KAAK,MAAM,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAChD,IAAI,OAAO,CAAC,eAAe,EAAE;oBAAE,SAAS;gBACxC,MAAM,QAAQ,GAAG,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;gBAC9D,IAAI,QAAQ,CAAC,eAAe,EAAE;oBAAE,MAAM;gBACtC,8DAA8D;gBAC9D,+DAA+D;gBAC/D,oBAAoB;gBACpB,IAAI,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK;oBAAE,MAAM;gBAE5C,MAAM,OAAO,GAAG,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC1F,MAAM,MAAM,GAAG,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9E,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;gBAClF,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC;gBAC3B,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAEhC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACzE,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;oBACzB,OAAO,MAAM,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC;YAED,oEAAoE;YACpE,8BAA8B;YAC9B,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,CAAC;gBAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;gBACxE,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;oBAC9E,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBACpG,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,yBAAyB,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;oBACrI,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC;oBAC3B,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBAEhC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;oBACnF,IAAI,QAAQ;wBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;YAED,OAAO,MAAM,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC/B,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,kFAAkF;IACxE,kBAAkB;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4FAA4F;IAClF,aAAa,CAAC,SAAyB,EAAE,OAAqB;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,8DAA8D;IACpD,UAAU;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACO,KAAK,CAAC,eAAe,CAAC,QAAwB,EAAE,MAAoB,EAAE,MAAoB;QAClG,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACpB,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC;YAC3B,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE;gBAC3C,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,GAAG,MAAM,CAAC,IAAI,sEAAsE,MAAM,CAAC,eAAe,CAAC,IAAI,GAAG;aAC7H,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BypassCommand } from './bypass-command.js';
|
|
2
|
+
import { PuzzleBypassType } from '../types/seed/puzzle-seed.js';
|
|
3
|
+
/**
|
|
4
|
+
* The CON skill's barrier verb: fast-talk past a social gate -- a doorman,
|
|
5
|
+
* an intercom challenge, a receptionist with a list (bypassType "con").
|
|
6
|
+
* Same fatal stakes as pick/hack/cast: a blown story means whoever you
|
|
7
|
+
* were working knows exactly what you are. Rolled on Charisma + con.
|
|
8
|
+
*/
|
|
9
|
+
export declare class BluffCommand extends BypassCommand {
|
|
10
|
+
protected static verb: string;
|
|
11
|
+
protected static description: string;
|
|
12
|
+
protected bypassType: PuzzleBypassType;
|
|
13
|
+
protected noPuzzleMessage: string;
|
|
14
|
+
execute(args: string[]): Promise<string>;
|
|
15
|
+
protected determineOutcome(): Promise<boolean>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { BypassCommand } from './bypass-command.js';
|
|
2
|
+
import { rollPool, formatRoll } from '../utilities/dice.js';
|
|
3
|
+
/**
|
|
4
|
+
* The CON skill's barrier verb: fast-talk past a social gate -- a doorman,
|
|
5
|
+
* an intercom challenge, a receptionist with a list (bypassType "con").
|
|
6
|
+
* Same fatal stakes as pick/hack/cast: a blown story means whoever you
|
|
7
|
+
* were working knows exactly what you are. Rolled on Charisma + con.
|
|
8
|
+
*/
|
|
9
|
+
export class BluffCommand extends BypassCommand {
|
|
10
|
+
static verb = 'bluff';
|
|
11
|
+
static description = 'Talk your way past a social barrier (a doorman, a voice-gate) without the passphrase -- Charisma + con, but a blown bluff is fatal: no second chances.';
|
|
12
|
+
bypassType = 'con';
|
|
13
|
+
noPuzzleMessage = `There's nobody here to bluff past.`;
|
|
14
|
+
async execute(args) {
|
|
15
|
+
// Fast-talk needs a face and a voice on the scene -- your meat ones.
|
|
16
|
+
if (this.actor.plane === 'matrix') {
|
|
17
|
+
return `Your silver tongue is meat-side, slumped with the rest of you. "jack out" to run your game in person.`;
|
|
18
|
+
}
|
|
19
|
+
if (this.actor.plane === 'astral') {
|
|
20
|
+
return `Nobody physical can hear a word you say from out here. "return" to your body first.`;
|
|
21
|
+
}
|
|
22
|
+
// Working a mark out loud is the opposite of sneaking (see sneak.ts).
|
|
23
|
+
this.actor.sneaking = false;
|
|
24
|
+
return super.execute(args);
|
|
25
|
+
}
|
|
26
|
+
async determineOutcome() {
|
|
27
|
+
// A CON test (Charisma + con, 2 hits; unskilled Charisma - 1) -- the
|
|
28
|
+
// Face's answer to the decker's terminal and the ops specialist's
|
|
29
|
+
// maglock.
|
|
30
|
+
const skill = this.actor.skillRating('con');
|
|
31
|
+
const pool = Math.max(1, this.actor.charisma + (skill > 0 ? skill : -1) + this.actor.woundModifier - this.actor.sustainingPenalty);
|
|
32
|
+
const roll = rollPool(pool);
|
|
33
|
+
if (this.actor === this.scene.getPlayer()) {
|
|
34
|
+
this.logger.log(`Con: ${formatRoll(roll)} (2+ to sell it)`);
|
|
35
|
+
}
|
|
36
|
+
return roll.hits >= 2;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=bluff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bluff.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/bluff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,OAAO,YAAa,SAAQ,aAAa;IACnC,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IACtB,MAAM,CAAC,WAAW,GAAG,wJAAwJ,CAAC;IAC9K,UAAU,GAAqB,KAAK,CAAC;IACrC,eAAe,GAAG,oCAAoC,CAAC;IAEjE,KAAK,CAAC,OAAO,CAAC,IAAc;QAC1B,qEAAqE;QACrE,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,uGAAuG,CAAC;QACjH,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,qFAAqF,CAAC;QAC/F,CAAC;QACD,sEAAsE;QACtE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAES,KAAK,CAAC,gBAAgB;QAC9B,qEAAqE;QACrE,kEAAkE;QAClE,WAAW;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACnI,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IACxB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Command, ICommand } from './command.js';
|
|
2
|
+
/**
|
|
3
|
+
* The two halves of the holster mechanic (see Player.weaponDrawn): an
|
|
4
|
+
* equipped weapon rides holstered until "brandish" puts it in hand, and
|
|
5
|
+
* "holster" stows it again. Combat never requires either -- an exchange
|
|
6
|
+
* auto-draws (CombatExchange.beginExchange) -- so what these verbs really
|
|
7
|
+
* are is body language: both fire performAction, so every NPC in the room
|
|
8
|
+
* watches the steel come out (a threat display) or go away (a de-escalation
|
|
9
|
+
* that pairs with "surrender"). Registered as brandish/draw and
|
|
10
|
+
* holster/stow.
|
|
11
|
+
*/
|
|
12
|
+
export declare class BrandishCommand extends Command implements ICommand {
|
|
13
|
+
protected static verb: string;
|
|
14
|
+
protected static description: string;
|
|
15
|
+
execute(_args?: string[]): Promise<string>;
|
|
16
|
+
}
|
|
17
|
+
export declare class HolsterCommand extends Command implements ICommand {
|
|
18
|
+
protected static verb: string;
|
|
19
|
+
protected static description: string;
|
|
20
|
+
execute(_args?: string[]): Promise<string>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Command } from './command.js';
|
|
2
|
+
import { Category } from '../types/shared/item-enum.js';
|
|
3
|
+
import { rollPool, formatRoll } from '../utilities/dice.js';
|
|
4
|
+
/**
|
|
5
|
+
* The two halves of the holster mechanic (see Player.weaponDrawn): an
|
|
6
|
+
* equipped weapon rides holstered until "brandish" puts it in hand, and
|
|
7
|
+
* "holster" stows it again. Combat never requires either -- an exchange
|
|
8
|
+
* auto-draws (CombatExchange.beginExchange) -- so what these verbs really
|
|
9
|
+
* are is body language: both fire performAction, so every NPC in the room
|
|
10
|
+
* watches the steel come out (a threat display) or go away (a de-escalation
|
|
11
|
+
* that pairs with "surrender"). Registered as brandish/draw and
|
|
12
|
+
* holster/stow.
|
|
13
|
+
*/
|
|
14
|
+
export class BrandishCommand extends Command {
|
|
15
|
+
static verb = 'brandish';
|
|
16
|
+
static description = 'Draw your holstered weapon -- everyone present sees it happen. "holster" stows it.';
|
|
17
|
+
async execute(_args = []) {
|
|
18
|
+
const actor = this.actor;
|
|
19
|
+
// Your gun is meat -- it stayed behind with the rest of you.
|
|
20
|
+
if (actor.plane === 'matrix') {
|
|
21
|
+
return `Your weapon is hanging off a body you're not currently in. The Matrix runs on attack programs, not iron.`;
|
|
22
|
+
}
|
|
23
|
+
if (actor.plane === 'astral') {
|
|
24
|
+
return `Your weapon stayed with your body -- on the astral, your will IS the weapon.`;
|
|
25
|
+
}
|
|
26
|
+
const carried = actor.getCarriedWeapon();
|
|
27
|
+
if (!carried) {
|
|
28
|
+
// Point at the fix if there's a weapon one "equip" away.
|
|
29
|
+
const weaponCategories = [Category.Weapon, Category.MeleeWeapon, Category.RangedWeapon];
|
|
30
|
+
const inBag = actor.inventory.getAllItems().find(i => weaponCategories.includes(i.category));
|
|
31
|
+
return inBag
|
|
32
|
+
? `Nothing holstered. The ${inBag.name} is still loose in your bag -- "equip ${inBag.name}" first.`
|
|
33
|
+
: `Nothing to draw -- you're not carrying a weapon.`;
|
|
34
|
+
}
|
|
35
|
+
if (actor.weaponDrawn) {
|
|
36
|
+
return `The ${carried.name} is already in your hand.`;
|
|
37
|
+
}
|
|
38
|
+
actor.drawWeapon();
|
|
39
|
+
// A threat display is the OPPOSITE of sneaking.
|
|
40
|
+
actor.sneaking = false;
|
|
41
|
+
// The INTIMIDATION skill gives the display its teeth: the menace roll
|
|
42
|
+
// rides into the witnessed action itself, so every NPC's AI hears HOW
|
|
43
|
+
// convincing the steel looked -- and reacts to that, not just the act.
|
|
44
|
+
const skill = actor.skillRating('intimidation');
|
|
45
|
+
const menaceRoll = rollPool(Math.max(1, actor.charisma + (skill > 0 ? skill : -1) + actor.woundModifier - actor.sustainingPenalty));
|
|
46
|
+
const menace = menaceRoll.hits >= 3
|
|
47
|
+
? 'radiating flat, lethal intent'
|
|
48
|
+
: menaceRoll.hits >= 1
|
|
49
|
+
? 'with hard, steady eyes'
|
|
50
|
+
: 'though the hand wavers, just a little';
|
|
51
|
+
actor.performAction('draws', `${carried.name} -- ${menace}`);
|
|
52
|
+
this.logger.write(`${actor.name} brandishes ${carried.name} (${menaceRoll.hits} menace hits).`);
|
|
53
|
+
this.scene.updateStatus();
|
|
54
|
+
const ammoNote = carried.isFirearm()
|
|
55
|
+
? (carried.ammo === 0 ? ' The magazine is DRY -- "reload".' : ` ${carried.ammo} rounds ready.`)
|
|
56
|
+
: '';
|
|
57
|
+
return `You draw the ${carried.name}.${ammoNote} Menace: ${formatRoll(menaceRoll)} -- everyone here just watched you do it.`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export class HolsterCommand extends Command {
|
|
61
|
+
static verb = 'holster';
|
|
62
|
+
static description = 'Stow your drawn weapon -- a visible stand-down. "brandish" draws it again.';
|
|
63
|
+
async execute(_args = []) {
|
|
64
|
+
const actor = this.actor;
|
|
65
|
+
if (actor.inExchange) {
|
|
66
|
+
return `Mid-exchange is no time to put your weapon away -- let it resolve.`;
|
|
67
|
+
}
|
|
68
|
+
const carried = actor.getCarriedWeapon();
|
|
69
|
+
if (!carried) {
|
|
70
|
+
return `Nothing to holster -- you're not carrying a weapon.`;
|
|
71
|
+
}
|
|
72
|
+
if (!actor.weaponDrawn) {
|
|
73
|
+
return `The ${carried.name} is already holstered.`;
|
|
74
|
+
}
|
|
75
|
+
actor.stowWeapon();
|
|
76
|
+
actor.performAction('holsters', carried.name);
|
|
77
|
+
this.logger.write(`${actor.name} holsters ${carried.name}.`);
|
|
78
|
+
this.scene.updateStatus();
|
|
79
|
+
return `You holster the ${carried.name}. Hands empty, posture easy -- everyone here saw you stand down.`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=brandish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brandish.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/brandish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;GASG;AACH,MAAM,OAAO,eAAgB,SAAQ,OAAO;IAChC,MAAM,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,MAAM,CAAC,WAAW,GAAG,oFAAoF,CAAC;IAEpH,KAAK,CAAC,OAAO,CAAC,QAAkB,EAAE;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAEzB,6DAA6D;QAC7D,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,0GAA0G,CAAC;QACpH,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,8EAA8E,CAAC;QACxF,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,yDAAyD;YACzD,MAAM,gBAAgB,GAAa,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;YAClG,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC7F,OAAO,KAAK;gBACV,CAAC,CAAC,0BAA0B,KAAK,CAAC,IAAI,yCAAyC,KAAK,CAAC,IAAI,UAAU;gBACnG,CAAC,CAAC,kDAAkD,CAAC;QACzD,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,OAAO,OAAO,CAAC,IAAI,2BAA2B,CAAC;QACxD,CAAC;QAED,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,gDAAgD;QAChD,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;QAEvB,sEAAsE;QACtE,sEAAsE;QACtE,uEAAuE;QACvE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACpI,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,IAAI,CAAC;YACjC,CAAC,CAAC,+BAA+B;YACjC,CAAC,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;gBACpB,CAAC,CAAC,wBAAwB;gBAC1B,CAAC,CAAC,uCAAuC,CAAC;QAC9C,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,OAAO,MAAM,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,eAAe,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,gBAAgB,CAAC,CAAC;QAChG,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;QAE1B,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE;YAClC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,gBAAgB,CAAC;YAC/F,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,gBAAgB,OAAO,CAAC,IAAI,IAAI,QAAQ,YAAY,UAAU,CAAC,UAAU,CAAC,2CAA2C,CAAC;IAC/H,CAAC;;AAGH,MAAM,OAAO,cAAe,SAAQ,OAAO;IAC/B,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC;IACxB,MAAM,CAAC,WAAW,GAAG,4EAA4E,CAAC;IAE5G,KAAK,CAAC,OAAO,CAAC,QAAkB,EAAE;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAEzB,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,oEAAoE,CAAC;QAC9E,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,qDAAqD,CAAC;QAC/D,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACvB,OAAO,OAAO,OAAO,CAAC,IAAI,wBAAwB,CAAC;QACrD,CAAC;QAED,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,KAAK,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,aAAa,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;QAE1B,OAAO,mBAAmB,OAAO,CAAC,IAAI,kEAAkE,CAAC;IAC3G,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Command, ICommand } from './command.js';
|
|
2
|
+
import { PuzzleBypassType } from '../types/seed/puzzle-seed.js';
|
|
3
|
+
/**
|
|
4
|
+
* Shared implementation for pick/hack/cast. The gate check (already
|
|
5
|
+
* solved? prerequisite met? does this puzzle even have this bypassType?)
|
|
6
|
+
* always runs first and synchronously, so a doomed attempt never makes the
|
|
7
|
+
* player sit through an interactive challenge they were never going to be
|
|
8
|
+
* allowed to attempt. Each concrete command differs in its verb,
|
|
9
|
+
* description, bypass type, the "nothing to do that to" message, and
|
|
10
|
+
* optionally how the outcome itself gets determined (see
|
|
11
|
+
* determineOutcome() -- defaults to a coin flip; lockpicking overrides it
|
|
12
|
+
* with a real minigame).
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class BypassCommand extends Command implements ICommand {
|
|
15
|
+
protected abstract bypassType: PuzzleBypassType;
|
|
16
|
+
protected abstract noPuzzleMessage: string;
|
|
17
|
+
/** Default: a flat coin flip. Override for a type with its own minigame. */
|
|
18
|
+
protected determineOutcome(): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* There's no typed answer here to disambiguate with (unlike solve.ts),
|
|
21
|
+
* so with more than one barrier in the room the player has to name which
|
|
22
|
+
* one: a direction ("pick north", for a locked door) or a word from the
|
|
23
|
+
* barrier's own name ("pick maglock"). With only one candidate, a bare
|
|
24
|
+
* "pick" still works exactly as before.
|
|
25
|
+
*/
|
|
26
|
+
private resolveTarget;
|
|
27
|
+
execute(args: string[]): Promise<string>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Command } from './command.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shared implementation for pick/hack/cast. The gate check (already
|
|
4
|
+
* solved? prerequisite met? does this puzzle even have this bypassType?)
|
|
5
|
+
* always runs first and synchronously, so a doomed attempt never makes the
|
|
6
|
+
* player sit through an interactive challenge they were never going to be
|
|
7
|
+
* allowed to attempt. Each concrete command differs in its verb,
|
|
8
|
+
* description, bypass type, the "nothing to do that to" message, and
|
|
9
|
+
* optionally how the outcome itself gets determined (see
|
|
10
|
+
* determineOutcome() -- defaults to a coin flip; lockpicking overrides it
|
|
11
|
+
* with a real minigame).
|
|
12
|
+
*/
|
|
13
|
+
export class BypassCommand extends Command {
|
|
14
|
+
/** Default: a flat coin flip. Override for a type with its own minigame. */
|
|
15
|
+
async determineOutcome() {
|
|
16
|
+
return Math.random() < 0.5;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* There's no typed answer here to disambiguate with (unlike solve.ts),
|
|
20
|
+
* so with more than one barrier in the room the player has to name which
|
|
21
|
+
* one: a direction ("pick north", for a locked door) or a word from the
|
|
22
|
+
* barrier's own name ("pick maglock"). With only one candidate, a bare
|
|
23
|
+
* "pick" still works exactly as before.
|
|
24
|
+
*/
|
|
25
|
+
resolveTarget(args, targets) {
|
|
26
|
+
const raw = args.join(' ').trim().toLowerCase();
|
|
27
|
+
if (!raw) {
|
|
28
|
+
if (targets.length === 1)
|
|
29
|
+
return { target: targets[0] };
|
|
30
|
+
const options = targets.map(t => t.direction ?? t.label).join(', ');
|
|
31
|
+
return { error: `There's more than one thing to ${this.bypassType === 'lockpick' ? 'pick' : this.bypassType === 'hack' ? 'hack' : this.bypassType === 'con' ? 'bluff' : 'cast'} at here -- say which: ${options}.` };
|
|
32
|
+
}
|
|
33
|
+
if (this.isValidDirection(raw)) {
|
|
34
|
+
const match = targets.find(t => t.direction === raw);
|
|
35
|
+
return match ? { target: match } : { error: `There's nothing to bypass in that direction.` };
|
|
36
|
+
}
|
|
37
|
+
const matches = targets.filter(t => t.label.toLowerCase().includes(raw));
|
|
38
|
+
if (matches.length === 1)
|
|
39
|
+
return { target: matches[0] };
|
|
40
|
+
if (matches.length > 1)
|
|
41
|
+
return { error: `That could mean more than one thing here -- be more specific.` };
|
|
42
|
+
return { error: `There's nothing here called "${raw}".` };
|
|
43
|
+
}
|
|
44
|
+
async execute(args) {
|
|
45
|
+
const room = this.actor.currentLocation;
|
|
46
|
+
const targets = (room?.getPuzzleTargets() ?? []).filter(t => t.puzzle.bypassType === this.bypassType);
|
|
47
|
+
if (targets.length === 0) {
|
|
48
|
+
return this.noPuzzleMessage;
|
|
49
|
+
}
|
|
50
|
+
const { target, error } = this.resolveTarget(args, targets);
|
|
51
|
+
if (!target) {
|
|
52
|
+
return error ?? this.noPuzzleMessage;
|
|
53
|
+
}
|
|
54
|
+
const gate = target.puzzle.checkBypassGate(this.bypassType);
|
|
55
|
+
if (!gate.allowed) {
|
|
56
|
+
return gate.message ?? `You can't do that here.`;
|
|
57
|
+
}
|
|
58
|
+
const succeeded = await this.determineOutcome();
|
|
59
|
+
const result = target.puzzle.resolveBypass(this.bypassType, succeeded);
|
|
60
|
+
if (result.success) {
|
|
61
|
+
if (target.door) {
|
|
62
|
+
target.door.isLocked = false;
|
|
63
|
+
this.scene.updateExits(room);
|
|
64
|
+
this.scene.addWorldEvent(`${this.actor.name} bypassed (${this.bypassType}) the way ${target.direction} in ${room.name}.`);
|
|
65
|
+
}
|
|
66
|
+
else if (target.puzzle.rewardItem) {
|
|
67
|
+
this.actor.inventory.addItem(target.puzzle.rewardItem);
|
|
68
|
+
this.scene.addWorldEvent(`${this.actor.name} bypassed "${target.puzzle.name}" (${this.bypassType}) in ${room.name}.`);
|
|
69
|
+
this.scene.updateInventory(this.scene.getPlayer().inventory);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (result.alarmed) {
|
|
73
|
+
// The consequence for a failed bypass: NPCs already listen for world
|
|
74
|
+
// events (see scene.ts's getWorldEventsSummary()), so this alone lets
|
|
75
|
+
// them react organically without a dedicated alarm/alert subsystem.
|
|
76
|
+
this.scene.addWorldEvent(`${this.actor.name}'s ${this.bypassType} attempt on "${target.puzzle.name}" in ${room.name} went loud.`);
|
|
77
|
+
}
|
|
78
|
+
this.logger.write(`${this.actor.name} attempted to ${this.bypassType} "${target.puzzle.name}": ${result.success ? 'success' : 'failure'}${result.alarmed ? ' (alarmed)' : ''}`);
|
|
79
|
+
this.actor.performAction(this.bypassType, result.message);
|
|
80
|
+
// A failed bypass is instant, unrecoverable death -- there's no partial
|
|
81
|
+
// credit for tripping an alarm or a ward's backlash mid-run. Reuses the
|
|
82
|
+
// same endGame() a player-kill already uses (see kill.ts): freezes
|
|
83
|
+
// input and self-announces directly to the screen, so the fatal reason
|
|
84
|
+
// stays on screen instead of vanishing the instant blessed's alternate
|
|
85
|
+
// buffer tears down. That announcement happens synchronously before
|
|
86
|
+
// this returns, so it renders BEFORE this command's own return value --
|
|
87
|
+
// found via a real session where an immediate process.exit() killed the
|
|
88
|
+
// alternate screen before the player had any chance to read why. Only
|
|
89
|
+
// ends the actual player's session: an NPC has no `game` in its context
|
|
90
|
+
// (see command.ts), so this is a no-op for an NPC's own failed attempt.
|
|
91
|
+
if (result.alarmed && this.game) {
|
|
92
|
+
await this.scene.endGame();
|
|
93
|
+
this.logger.logWithColor(result.message, 'red');
|
|
94
|
+
this.logger.logWithColor(`💀 GAME OVER -- your run ends here.`, 'red');
|
|
95
|
+
this.logger.logWithColor(`Press ctrl-c to quit.`, 'red');
|
|
96
|
+
return '';
|
|
97
|
+
}
|
|
98
|
+
return result.message;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=bypass-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bypass-command.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/commands/bypass-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,cAAc,CAAC;AAIjD;;;;;;;;;;GAUG;AACH,MAAM,OAAgB,aAAc,SAAQ,OAAO;IAIjD,4EAA4E;IAClE,KAAK,CAAC,gBAAgB;QAC9B,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC;IAC7B,CAAC;IAED;;;;;;OAMG;IACK,aAAa,CAAC,IAAc,EAAE,OAAuB;QAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAEhD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpE,OAAO,EAAE,KAAK,EAAE,kCAAkC,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,0BAA0B,OAAO,GAAG,EAAE,CAAC;QACvN,CAAC;QAED,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,CAAC;YACrD,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,8CAA8C,EAAE,CAAC;QAC/F,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACzE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,+DAA+D,EAAE,CAAC;QAC1G,OAAO,EAAE,KAAK,EAAE,gCAAgC,GAAG,IAAI,EAAE,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAc;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC;QACxC,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC;QAEtG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,eAAe,CAAC;QAC9B,CAAC;QAED,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC;QACvC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,OAAO,IAAI,yBAAyB,CAAC;QACnD,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAEvE,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;gBAC7B,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBAC7B,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,IAAI,CAAC,UAAU,aAAa,MAAM,CAAC,SAAS,OAAO,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;YAC5H,CAAC;iBAAM,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBACvD,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,UAAU,QAAQ,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;gBACtH,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,qEAAqE;YACrE,sEAAsE;YACtE,oEAAoE;YACpE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,IAAI,CAAC,UAAU,gBAAgB,MAAM,CAAC,MAAM,CAAC,IAAI,QAAQ,IAAI,CAAC,IAAI,aAAa,CAAC,CAAC;QACpI,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,iBAAiB,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChL,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAE1D,wEAAwE;QACxE,wEAAwE;QACxE,mEAAmE;QACnE,uEAAuE;QACvE,uEAAuE;QACvE,oEAAoE;QACpE,wEAAwE;QACxE,wEAAwE;QACxE,sEAAsE;QACtE,wEAAwE;QACxE,wEAAwE;QACxE,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAChC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YACvE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;YACzD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Command, ICommand } from './command.js';
|
|
2
|
+
export declare class CallCommand extends Command implements ICommand {
|
|
3
|
+
protected static verb: string;
|
|
4
|
+
protected static description: string;
|
|
5
|
+
execute(args: string[]): Promise<string>;
|
|
6
|
+
private hasEquippedCommlink;
|
|
7
|
+
private hasCommlink;
|
|
8
|
+
/**
|
|
9
|
+
* Multi-word names ("Mr. Johnson") shouldn't require the player to quote
|
|
10
|
+
* them just to call someone, and partial names shouldn't fail -- found
|
|
11
|
+
* via real sessions where "call Mr. Johnson" (period parsing), then
|
|
12
|
+
* "call mr" and "call Mr. J" (partials) all bounced. Tries progressively
|
|
13
|
+
* shorter word-prefixes of the input (longest first), resolving each
|
|
14
|
+
* through the same fuzzy matcher "take"/"attack"/"cast" use (punctuation
|
|
15
|
+
* and typo tolerant; an ambiguous fragment deliberately misses).
|
|
16
|
+
* Whatever's left over after the matched name becomes the message.
|
|
17
|
+
*/
|
|
18
|
+
private resolveTargetAndMessage;
|
|
19
|
+
}
|