@maka/maka-cli 5.147.0 → 5.149.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/attack.js +13 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js +25 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/install.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +3 -2
- package/bundle/typescript/src/commands/game/sideQuest/utilities/web-character-generator.js +12 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maka/maka-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.149.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
|
|
6
6
|
"description": "A command line tool for scaffolding Meteor 3.x applications using React.",
|
|
@@ -6,7 +6,7 @@ import { fuzzyPickName } from '../utilities/fuzzy-match.js';
|
|
|
6
6
|
import { describeFledTarget } from '../utilities/pursuit.js';
|
|
7
7
|
import { shellsInRoom, resolveBodyAttack, crossPlaneRefusal } from '../utilities/planes.js';
|
|
8
8
|
import { heldBy, holding } from '../utilities/grapple.js';
|
|
9
|
-
import { spotOf, ensureAtSpot, ensureAtExit, canReach, spotDistanceMeters } from '../utilities/spots.js';
|
|
9
|
+
import { spotOf, ensureAtSpot, ensureAtExit, canReach, spotDistanceMeters, OPEN_FLOOR } from '../utilities/spots.js';
|
|
10
10
|
import { resolveBarrierStrike } from '../utilities/barrier-combat.js';
|
|
11
11
|
import { billAction, notYourPhase, phaseHint } from '../utilities/action-cost.js';
|
|
12
12
|
import { spendMovementMeters } from '../utilities/movement-cost.js';
|
|
@@ -369,6 +369,18 @@ export class AttackCommand extends Command {
|
|
|
369
369
|
// MELEE REACH: ground costs (p.161-162).
|
|
370
370
|
if (isMelee) {
|
|
371
371
|
const targetSpot = spotOf(target);
|
|
372
|
+
// An attacker with no spot of their own reads to canReach as
|
|
373
|
+
// "reaches everything" (the same compat rule that lets an unbound
|
|
374
|
+
// exit be worked from anywhere) -- fine for a location query, but
|
|
375
|
+
// for the ATTACKER in a reach check it skips ground-closing
|
|
376
|
+
// billing entirely: a hostile spawned mid-room, never having
|
|
377
|
+
// moved, could swing on a target the player had just paced away
|
|
378
|
+
// from in a fully gridded room (MotczCjebFNdHAWq7). Resolving
|
|
379
|
+
// an unset spot to the open floor first -- move.ts's own default
|
|
380
|
+
// -- gives canReach and spotDistanceMeters a real position to
|
|
381
|
+
// measure the reach/cost from instead of "unknown = anywhere".
|
|
382
|
+
if (spotOf(actor) === undefined)
|
|
383
|
+
actor.atSpot = OPEN_FLOOR;
|
|
372
384
|
const mine = spotOf(actor);
|
|
373
385
|
if (targetSpot !== undefined && !canReach(actor, targetSpot)) {
|
|
374
386
|
const meters = mine !== undefined && room.ensureGrid() ? spotDistanceMeters(room, mine, targetSpot) : 0;
|
|
@@ -38,10 +38,11 @@ export class BacklogCommand extends Command {
|
|
|
38
38
|
static verb = "backlog";
|
|
39
39
|
// Writes to the player OWN board over their auth token -- never an NPC.
|
|
40
40
|
static humanOnly = true;
|
|
41
|
-
static description = 'File a play-tester item that somebody acts on -- it goes to maka-cli.com, keeps a link to this session, and comes back checked against the rulebooks. "backlog <what you noticed>" files one; "backlog list [status]" reads the board. For private scribbles, use "note".';
|
|
41
|
+
static description = 'File a play-tester item that somebody acts on -- it goes to maka-cli.com, keeps a link to this session, and comes back checked against the rulebooks. "backlog <what you noticed>" files one; "backlog list [status]" reads the board; "backlog web" opens the live board in your browser. For private scribbles, use "note".';
|
|
42
42
|
static subcommands = [
|
|
43
43
|
{ usage: 'backlog <text>', short: 'File an item against this session.' },
|
|
44
44
|
{ usage: 'backlog list', short: 'The whole board, what needs you last.' },
|
|
45
|
+
{ usage: 'backlog web', short: 'Open the live backlog board in your browser.' },
|
|
45
46
|
{ usage: 'backlog <n>', short: 'Read board item n in full.' },
|
|
46
47
|
{ usage: 'backlog repro <n>', short: 'Play the repro bench for board item n.' },
|
|
47
48
|
{ usage: 'backlog close <n> [why]', short: 'Close item n outright -- filed in error, duplicate, no longer real.' },
|
|
@@ -71,6 +72,12 @@ export class BacklogCommand extends Command {
|
|
|
71
72
|
if (args.length === 0 || sub === 'list') {
|
|
72
73
|
return this.list(args[1]);
|
|
73
74
|
}
|
|
75
|
+
// Claimed here, same reason "accept"/"reject"/"repro"/"close" are:
|
|
76
|
+
// every unclaimed word past this point is report text, and "backlog
|
|
77
|
+
// web" must open the board, not file an item whose text is "web".
|
|
78
|
+
if (sub === 'web') {
|
|
79
|
+
return this.webBoard();
|
|
80
|
+
}
|
|
74
81
|
// A BARE NUMBER READS THAT ROW OF THE BOARD, and it has to be caught
|
|
75
82
|
// here for the same reason `list` and `review` are: everything that
|
|
76
83
|
// reaches the bottom of this method FILES AN ITEM. Without this,
|
|
@@ -118,6 +125,23 @@ export class BacklogCommand extends Command {
|
|
|
118
125
|
}
|
|
119
126
|
return this.file(args.join(' '));
|
|
120
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* "backlog web" (user request, 2026-09-10): the same /cli-login
|
|
130
|
+
* handoff as "sheet web" (sheet.ts), landing on the shared board --
|
|
131
|
+
* /backlog, already on the NEXT_ALLOWLIST. The token is guaranteed
|
|
132
|
+
* present here: execute() already refused above if authToken() was
|
|
133
|
+
* empty, before any subcommand (this one included) could be reached.
|
|
134
|
+
*/
|
|
135
|
+
async webBoard() {
|
|
136
|
+
const { buildBacklogBoardUrl } = await import('../utilities/web-character-generator.js');
|
|
137
|
+
const url = buildBacklogBoardUrl(authToken());
|
|
138
|
+
const { openBrowser } = await import('../../../../tools/browser/open-browser.js');
|
|
139
|
+
openBrowser(url);
|
|
140
|
+
return [
|
|
141
|
+
`Your backlog board is opening in the browser -- the game keeps running right here.`,
|
|
142
|
+
` ${url}`,
|
|
143
|
+
].join('\n');
|
|
144
|
+
}
|
|
121
145
|
async file(text) {
|
|
122
146
|
const game = this.game;
|
|
123
147
|
// LAZY, and not for speed: shared-run.ts pulls in tools/version/
|
|
@@ -57,7 +57,10 @@ export class DocwagonCommand extends Command {
|
|
|
57
57
|
const surcharge = Math.ceil(def.price * check.surchargePct);
|
|
58
58
|
const total = def.price + surcharge;
|
|
59
59
|
if (this.actor.currency < total) {
|
|
60
|
-
return
|
|
60
|
+
return [
|
|
61
|
+
...(check.lines[0] ? [check.lines[0]] : []),
|
|
62
|
+
`${reachable.name} taps the rate card: ${total} nuyen a year for ${tier}${surcharge > 0 ? ` (papers with a smell run extra)` : ''}. You're carrying ${this.actor.currency}.`,
|
|
63
|
+
].join('\n');
|
|
61
64
|
}
|
|
62
65
|
const renewal = this.game.docwagon?.tier === tier;
|
|
63
66
|
this.actor.adjustCurrency(-total);
|
|
@@ -161,7 +161,10 @@ export class InstallCommand extends Command {
|
|
|
161
161
|
paymentLine = `You put the ${part.name} on the tray. The doc turns it over once, nods. "Part's good. Installation's on the house story-rate."`;
|
|
162
162
|
}
|
|
163
163
|
else if (actor.currency < aug.cost) {
|
|
164
|
-
return
|
|
164
|
+
return [
|
|
165
|
+
...(identityLine ? [identityLine] : []),
|
|
166
|
+
`${aug.name} runs ${aug.cost} nuyen -- you're carrying ${actor.currency}. The doc doesn't do tabs on surgery.`,
|
|
167
|
+
].join('\n');
|
|
165
168
|
}
|
|
166
169
|
else {
|
|
167
170
|
actor.adjustCurrency(-aug.cost);
|
|
@@ -1840,8 +1840,9 @@ ${worldEventsSummary}
|
|
|
1840
1840
|
${wares.map(i => `- "${i.name}" (${priceOf(i)} nuyen)`).join('\n')}
|
|
1841
1841
|
When a customer orders or agrees to buy, SERVE it in the same response: [COMMAND] give <item name> to <customer name>
|
|
1842
1842
|
Serve EXACTLY the stock item whose name best matches what the customer asked for (they say "noodles", you have a "Noodle Bowl" -- that's the one). Substitute a different dish ONLY if the match is out of stock, and say so out loud when you do. The stock list above is the truth about what you have -- never claim a listed item is gone.
|
|
1843
|
-
The till settles automatically on handoff (they're charged street price, or what they can cover). Quote the price when they order. Never serve someone who hasn't asked
|
|
1844
|
-
|
|
1843
|
+
The till settles automatically on handoff (they're charged street price, or what they can cover). Quote the price when they order. Never serve someone who hasn't asked.
|
|
1844
|
+
NEVER claim a sale is complete from dialogue alone -- no "here you go," no till chirping, no describing them pocketing anything, unless this SAME response also issues the [COMMAND] give line above. A sale without that command simply never happened, and the customer is left owning nothing while believing they bought something.`
|
|
1845
|
+
: `YOUR SHOP STOCK: you have NOTHING owner-tagged to you on the shelf/counter right now -- the list above is empty. If a customer asks to buy something, you do not have it to sell: say so honestly (out of stock, don't carry it, check back later), or point them at where they might actually find it. NEVER narrate handing over an item, taking payment, or a till settling for anything that isn't real stock -- there is nothing here to [COMMAND] give, so nothing changes hands no matter how the conversation reads.`;
|
|
1845
1846
|
// SWAG OVER THE LINE (source.ts; the shop-stock lesson's remote
|
|
1846
1847
|
// twin): a contact with a TRADE can order anything in their domain
|
|
1847
1848
|
// through the network -- but only the order system closes a deal.
|
|
@@ -82,6 +82,18 @@ export function buildCharacterSheetUrl(resumeToken, slug) {
|
|
|
82
82
|
const next = `${CHARACTERS_PAGE}/${encodeURIComponent(slug)}`;
|
|
83
83
|
return `${cliLoginUrl()}?t=${Date.now()}#token=${encodeURIComponent(resumeToken)}&next=${next}`;
|
|
84
84
|
}
|
|
85
|
+
const BACKLOG_PAGE = '/backlog';
|
|
86
|
+
/**
|
|
87
|
+
* "backlog web" (user request, 2026-09-10): the same /cli-login handoff
|
|
88
|
+
* as the live sheet, landing on the shared backlog board -- /backlog,
|
|
89
|
+
* already on cli-login-next.ts's NEXT_ALLOWLIST as a bare path. Unlike
|
|
90
|
+
* buildCharacterSheetUrl/buildDossierUrl there is no per-item deep link
|
|
91
|
+
* to validate here: the board itself is the destination, not a row on
|
|
92
|
+
* it.
|
|
93
|
+
*/
|
|
94
|
+
export function buildBacklogBoardUrl(resumeToken) {
|
|
95
|
+
return `${cliLoginUrl()}?t=${Date.now()}#token=${encodeURIComponent(resumeToken)}&next=${BACKLOG_PAGE}`;
|
|
96
|
+
}
|
|
85
97
|
/**
|
|
86
98
|
* WHAT THE CLI SAYS ON ITS WAY OUT of the chargen handoff. Extracted
|
|
87
99
|
* from the command handler so the two things that matter about it are
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maka/maka-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.149.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
|
|
6
6
|
"description": "A command line tool for scaffolding Meteor 3.x applications using React.",
|