Fewer, smaller messages: mold percentages, markers for machine heat, short status lines
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+3
-3
@@ -3,7 +3,7 @@
|
||||
function removePieceAt(x, y) {
|
||||
droppedLast = 0;
|
||||
const msg = removePieceAt0(x, y);
|
||||
return msg && droppedLast ? msg.replace('taken back.', 'taken back. Your bag is full, so the rest dropped where it stood.') : msg;
|
||||
return msg && droppedLast ? msg.replace('taken back.', 'taken back; bag full, excess dropped here.') : msg;
|
||||
}
|
||||
function removePieceAt0(x, y) {
|
||||
if (x < 0 || y < 0 || x >= W || y >= H) return '';
|
||||
@@ -15,7 +15,7 @@ function removePieceAt0(x, y) {
|
||||
if (mach[i] && machines[mach[i]]) {
|
||||
const P = PIECE_BY_ID[machines[mach[i]].type];
|
||||
if (P.fixed) return '';
|
||||
if (siloFull(machines[mach[i]])) return `Empty the silo first: it holds ${machines[mach[i]].sn.toLocaleString('en-US')} ${MD[machines[mach[i]].sm].name.toLowerCase()}. Press F on it to open its gate.`;
|
||||
if (siloFull(machines[mach[i]])) return 'Empty the silo first; press F to open its gate.';
|
||||
removeMachine(mach[i], true, false); return `${P.name} taken back.`;
|
||||
}
|
||||
const mo = moldAt(x, y);
|
||||
@@ -80,7 +80,7 @@ function interactAt(x, y) {
|
||||
return blockP[pb] === BP_PUMP ? (blockV[pb] & 4 ? 'Pump off.' : 'Pump on.') : (blockV[pb] & 4 ? 'Outlet closed.' : 'Outlet open.');
|
||||
}
|
||||
const id = mach[y * W + x];
|
||||
if (id && machines[id] && machines[id].type === 'silo') { const mm = machines[id]; mm.open = !mm.open; return mm.open ? (mm.sn ? 'Silo gate open.' : 'Silo gate open. It is empty.') : 'Silo gate shut.'; }
|
||||
if (id && machines[id] && machines[id].type === 'silo') { const mm = machines[id]; mm.open = !mm.open; return mm.open ? (mm.sn ? 'Silo gate open.' : 'Silo gate open; it is empty.') : 'Silo gate shut.'; }
|
||||
if (id && machines[id] && machines[id].type === 'fan') { machines[id].on = !machines[id].on; powerDirty = true; return machines[id].on ? 'Fan on.' : 'Fan off.'; }
|
||||
return '';
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ function canPlaceBlock(bx, by) {
|
||||
if (blockP[by * BW + bx]) return 'Something is already built there';
|
||||
for (const i of blockCellList(bx, by)) {
|
||||
if (mach[i] || part[i]) return 'Something is already built there';
|
||||
if (PH[mat[i]] === PH_SOLID) return 'Needs open space. Clear the rock first.';
|
||||
if (PH[mat[i]] === PH_SOLID) return 'Needs open space; clear the rock first.';
|
||||
if (occ[i]) return 'A bar is in the way';
|
||||
}
|
||||
return '';
|
||||
|
||||
@@ -80,7 +80,7 @@ function footprintBlocker(bx, by, bw, bh) {
|
||||
for (let y = by * BS; y < (by + bh) * BS; y++) for (let x = bx * BS; x < (bx + bw) * BS; x++) {
|
||||
if (x < 0 || y < 0 || x >= W || y >= H) return 'Out of bounds';
|
||||
const i = y * W + x;
|
||||
if (PH[mat[i]] === PH_SOLID && (flags[i] & F_NAT)) return 'Needs open space. Clear the rock first.';
|
||||
if (PH[mat[i]] === PH_SOLID && (flags[i] & F_NAT)) return 'Needs open space; clear the rock first.';
|
||||
if (occ[i]) return 'A bar is in the way';
|
||||
if (mach[i] && machines[mach[i]] && PIECE_BY_ID[machines[mach[i]].type].fixed) return 'That cannot be replaced';
|
||||
if (mach[i] && siloFull(machines[mach[i]])) return 'Empty the silo first';
|
||||
|
||||
+2
-2
@@ -53,11 +53,11 @@ function toolPulse(ax, ay, width, tune) {
|
||||
if (HARD[m] > tier.hard) {
|
||||
const need = BIT_TIERS.find(b => b.hard >= HARD[m]);
|
||||
const nb = need ? need.name.toLowerCase() : 'better bit';
|
||||
status = HARD[m] > 6 ? `${MD[m].name} cannot be drilled.` : `${MD[m].name} is too hard for your ${tier.name.toLowerCase()}. Needs ${/^[aeiou]/.test(nb) ? 'an' : 'a'} ${nb}.`;
|
||||
status = HARD[m] > 6 ? `${MD[m].name} cannot be drilled.` : `${MD[m].name} is too hard; needs ${/^[aeiou]/.test(nb) ? 'an' : 'a'} ${nb}.`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!status && d > reach) status = `Out of reach. A ${Wd.name} pulse from your ${tier.name.toLowerCase()} reaches ${reach} grains from the bot.`;
|
||||
if (!status && d > reach) status = `Out of reach; a ${Wd.name} pulse reaches ${reach} grains.`;
|
||||
return { fired: true, status };
|
||||
}
|
||||
const THIN_BONUS = 0.75, CRUMBLE_MAX = 16;
|
||||
|
||||
+1
-1
@@ -131,4 +131,4 @@ function canAfford(cost, mult) { for (const [m, n] of cost) if ((m === CASH ? mo
|
||||
function payCost(cost, mult) { for (const [m, n] of cost) { if (m === CASH) money -= n * mult; else bagTake(m, n * mult); } }
|
||||
function fmtMoney(v) { return '$' + Math.round(v).toLocaleString('en-US'); }
|
||||
function costText(cost, mult) { return cost.map(([m, n]) => { const k = n * (mult || 1); return m === CASH ? fmtMoney(k) : `${k} ${MD[m].name.toLowerCase()}${PH[m] === PH_ITEM && k !== 1 ? 's' : ''}`; }).join(' + '); }
|
||||
function needText(cost, mult) { const c = cost.find(([m, n]) => (m === CASH ? money : bag[m]) < n * (mult || 1)); return c && c[0] === CASH ? `Costs ${fmtMoney(c[1] * (mult || 1))}; you have ${fmtMoney(money)}.` : 'Not enough ' + costText(cost, mult); }
|
||||
function needText(cost, mult) { const c = cost.find(([m, n]) => (m === CASH ? money : bag[m]) < n * (mult || 1)); return c && c[0] === CASH ? `Costs ${fmtMoney(c[1] * (mult || 1))}; you have ${fmtMoney(money)}.` : 'Not enough ' + costText(c ? [c] : cost, mult) + '.'; }
|
||||
|
||||
@@ -82,11 +82,11 @@ function machinesTick() {
|
||||
const sat = POWER_FREE ? 1 : net ? net.sat : 0;
|
||||
mm.angle += sat * 0.5 * (mm.on ? 1 : 0);
|
||||
if (mm.on && sat > 0.05) fanBlow(mm, sat);
|
||||
// a fan getting close to melting says so (once every few seconds)
|
||||
// Keep the measured heat for the marker and hover panel.
|
||||
if ((tick + mm.id) % 30 === 0) {
|
||||
let hotT = 0;
|
||||
for (let y = mm.y; y < mm.y + 4; y++) for (let x = mm.x; x < mm.x + 4; x++) { const tt = temp[y * W + x]; if (tt > hotT) hotT = tt; }
|
||||
if (hotT > 760 && (!mm.warnT || tick - mm.warnT > 600)) { mm.warnT = tick; emit({ t: 'toast', text: `A fan is at ${Math.round(hotT)}°C and melts at 1085°C. Move it out of the heat: outside the furnace wall, blowing in through a grate.` }); }
|
||||
mm.hot = Math.round(hotT);
|
||||
}
|
||||
}
|
||||
// belts and filters move what rests on them every other tick: half a grain per tick
|
||||
@@ -118,7 +118,7 @@ function machinesTick() {
|
||||
if (m === EMPTY || PH[m] !== PH_POWDER) { if (m === EMPTY || PH[m] !== PH_SOLID) tubeIntake(i, p, dx, dy); continue; }
|
||||
if (stamp[i] === tickStamp) continue;
|
||||
if (temp[i] > 1000 && rnd() < 0.02) {
|
||||
part[i] = 0; markPow(i, false); emit({ t: 'toast', text: 'A screw tube melted. Copper softens around 1000°C.' }); wakeIdx(i);
|
||||
part[i] = 0; markPow(i, false); emit({ t: 'warn', x: i % W, y: (i / W) | 0, text: 'melted' }); wakeIdx(i);
|
||||
continue;
|
||||
}
|
||||
const s = netSat(i);
|
||||
|
||||
+2
-2
@@ -112,7 +112,7 @@ function canPlaceMachine(type, bx, by) {
|
||||
for (const [cx, cy] of machineFootprint(type, bx * BS, by * BS)) {
|
||||
const i = cy * W + cx;
|
||||
if (mach[i] || part[i]) return 'Something is already built there';
|
||||
if (PH[mat[i]] === PH_SOLID) return (flags[i] & F_NAT) ? 'Needs open space. Clear the rock first.' : 'Something is already built there';
|
||||
if (PH[mat[i]] === PH_SOLID) return (flags[i] & F_NAT) ? 'Needs open space; clear the rock first.' : 'Something is already built there';
|
||||
if (occ[i]) return 'A bar is in the way';
|
||||
}
|
||||
for (let y = by; y < by + P.bh; y++) for (let x = bx; x < bx + P.bw; x++) if (blockP[y * BW + x]) return 'Something is already built there';
|
||||
@@ -150,5 +150,5 @@ function removeMachine(id, refund, scrap) {
|
||||
}
|
||||
machines[id] = null;
|
||||
if (refund) { refundAt(PIECE_BY_ID[mm.type].cost, 1, mm.x + mm.w / 2, mm.y + mm.h / 2); undoNote({ t: 'mach-', type: mm.type, bx: mm.x / BS, by: mm.y / BS, dir: mm.dir, on: mm.on }); }
|
||||
if (scrap) emit({ t: 'toast', text: `${PIECE_BY_ID[mm.type].name} was destroyed by heat.` });
|
||||
if (scrap) emit({ t: 'warn', x: mm.x + mm.w / 2, y: mm.y, text: `${PIECE_BY_ID[mm.type].name} destroyed` });
|
||||
}
|
||||
|
||||
+15
-24
@@ -11,13 +11,13 @@ function canPlaceMold(kind, bx, by) {
|
||||
if (bx < 0 || by < 0 || bx + md.bw > BW || by + md.bh > BH) return 'Out of bounds';
|
||||
for (let y = by; y < by + md.bh; y++) for (let x = bx; x < bx + md.bw; x++) if (blockP[y * BW + x]) return 'Something is already built there';
|
||||
const { walls, cavs } = moldCellsAt(kind, bx * BS, by * BS);
|
||||
for (const i of walls.concat(...cavs)) if (!cellBuildable(i)) return PH[mat[i]] === PH_SOLID && (flags[i] & F_NAT) ? 'Needs open space. Clear the rock first.' : 'Something is already built there';
|
||||
for (const i of walls.concat(...cavs)) if (!cellBuildable(i)) return PH[mat[i]] === PH_SOLID && (flags[i] & F_NAT) ? 'Needs open space; clear the rock first.' : 'Something is already built there';
|
||||
if (moldAt(bx * BS + 1, by * BS + 1)) return 'There is already a mold there';
|
||||
return null;
|
||||
}
|
||||
function newMoldRecord(kind, x, y, wall) {
|
||||
const md = MOLDS[kind];
|
||||
return { id: (molds.length ? molds[molds.length - 1].id : 0) + 1, kind, x, y, w: md.w, h: md.h, wall, cavs: moldCellsAt(kind, x, y).cavs, ready: [], state: 'empty', metal: 0, fill: 0, flaw: '' };
|
||||
return { id: (molds.length ? molds[molds.length - 1].id : 0) + 1, kind, x, y, w: md.w, h: md.h, wall, cavs: moldCellsAt(kind, x, y).cavs, ready: [], state: 'empty', metal: 0, fill: 0, flaw: '', blocked: false };
|
||||
}
|
||||
function addMold(kind, bx, by, wallLoose, free) {
|
||||
const md = MOLDS[kind];
|
||||
@@ -132,7 +132,7 @@ function rakeAbove(mo) {
|
||||
if (n) wakeXY(mo.x + (mo.w >> 1), mo.y - 8);
|
||||
return n;
|
||||
}
|
||||
// After a knock-out: if the furnace over the mold is badly loaded, say what to change
|
||||
// Hover advice when the furnace over the mold is badly loaded.
|
||||
function furnaceJunkHint(mo) {
|
||||
let ore = 0, fuel = 0, open = 0;
|
||||
for (let x = mo.x; x < mo.x + mo.w; x++) for (let y = mo.y - 1, k = 0; y >= 0 && k < 48; y--, k++) {
|
||||
@@ -161,6 +161,7 @@ function unplugMold(mo) {
|
||||
const grains = n => `${n} ${n === 1 ? 'grain' : 'grains'}`;
|
||||
const barWord = (m, n) => m === GLASS ? (n === 1 ? 'glass brick' : 'glass bricks') : n === 1 ? 'bar' : 'bars';
|
||||
function ejectIngot(mo) {
|
||||
mo.blocked = false;
|
||||
let r = troughState(mo), n = 0;
|
||||
const metal = r.metal, x = mo.x + (mo.w >> 1), y = mo.y + mo.h;
|
||||
if (r.st === 'ready') {
|
||||
@@ -173,6 +174,7 @@ function ejectIngot(mo) {
|
||||
free = true;
|
||||
if (spawnBar(BAR_OF[metal], sx, y, (rnd() - 0.5) * 0.15, 0.2, T)) n++;
|
||||
}
|
||||
mo.blocked = !n && !free;
|
||||
if (n) {
|
||||
// Take from the top so the short stub stays on the trough floor.
|
||||
let take = n * GRAINS_PER_BAR;
|
||||
@@ -203,7 +205,7 @@ function ejectIngot(mo) {
|
||||
setCell(dest, loose, temp[i], 0); slot++; placed = true; break;
|
||||
}
|
||||
}
|
||||
if (!placed) continue;
|
||||
if (!placed) { mo.blocked = true; continue; }
|
||||
}
|
||||
setCell(i, EMPTY, AMB[(i / W) | 0], 0); pushed++;
|
||||
}
|
||||
@@ -241,16 +243,6 @@ function moldAt(x, y) {
|
||||
for (const mo of molds) if (x >= mo.x && y >= mo.y && x < mo.x + mo.w && y < mo.y + mo.h) return mo;
|
||||
return null;
|
||||
}
|
||||
// What a knock-out sent where, as one short sentence after the main message
|
||||
function knockNote(scrap, other, chipped, raked) {
|
||||
let s = '';
|
||||
if (scrap) s += ` The leftover ${grains(scrap)} of scrap went into your bag${other ? ', with the grit that got in' : ''}.`;
|
||||
else if (other) s += ' The grit that got in went into your bag.';
|
||||
if (chipped && raked) s += ' The slag was chipped off and the grate raked clean.';
|
||||
else if (chipped) s += ' The slag was chipped off.';
|
||||
else if (raked) s += ' Slag and ash were raked off the grate.';
|
||||
return s;
|
||||
}
|
||||
function tally(got) {
|
||||
let scrap = 0, other = 0;
|
||||
for (const [k, c] of got) { if (PH[k] === PH_POWDER && MELTTO[k] && CASTMETAL[MELTTO[k]] && !SMELTP[k]) scrap += c; else other += c; }
|
||||
@@ -264,39 +256,38 @@ function collectMold(mo) {
|
||||
const scrap = g.scrap + u.metal;
|
||||
if (!scrap && !g.other && !g.dross && !u.chipped && !u.raked) return 'The mold is empty.';
|
||||
emit({ t: 'sfx', s: 'ui' });
|
||||
return 'Knocked the mold clean.' + knockNote(scrap, g.other, g.dross + u.chipped, u.raked);
|
||||
return 'Knocked the mold clean.';
|
||||
}
|
||||
let msg = '';
|
||||
if (mo.state === 'short' && !(mo.knockAsk != null && tick - mo.knockAsk >= 0 && tick - mo.knockAsk < 300)) {
|
||||
// an unfinished casting can still be topped up, so the first press only says so
|
||||
mo.knockAsk = tick;
|
||||
return (mo.flaw || 'The casting is not full yet.').replace(', or press F to knock it out as scrap.', '.') + ' Press F again to knock it out as scrap.';
|
||||
return 'Not full; press F again to knock it out as scrap.';
|
||||
}
|
||||
if (mo.state === 'flawed' || mo.state === 'short') {
|
||||
// a spoiled or unfinished casting is knocked out as scrap, so the mold is ready for another go
|
||||
const short = mo.state === 'short', g = tally(clearCavity(mo.cavs.flat())), u = unplugMold(mo);
|
||||
const short = mo.state === 'short'; clearCavity(mo.cavs.flat()); unplugMold(mo);
|
||||
mo.state = 'empty'; mo.ready = [];
|
||||
emit({ t: 'sfx', s: 'ui' });
|
||||
const what = mo.kind === 'bit' ? 'bit' : 'casting';
|
||||
return (short ? `The ${what} was not full, so it was knocked out as scrap.` : `The ${what} was spoiled, so it was knocked out as scrap.`)
|
||||
+ knockNote(g.scrap + u.metal, g.other, g.dross + u.chipped, u.raked) + furnaceJunkHint(mo);
|
||||
return (short ? `Unfinished ${what} knocked out as scrap.` : `Spoiled ${what} knocked out as scrap.`);
|
||||
}
|
||||
const tier = METAL_TIER[mo.metal];
|
||||
const cav = mo.cavs[0];
|
||||
if (tier <= 0) { msg = `${MD[mo.metal] ? MD[mo.metal].name : 'That metal'} is too ${mo.metal === GLASS ? 'brittle' : 'soft'} for a ${mo.kind === 'bit' ? 'drill bit' : 'tank'}. The casting broke into scrap, which went into your bag.`; }
|
||||
if (tier <= 0) { msg = `${MD[mo.metal] ? MD[mo.metal].name : 'That metal'} is too ${mo.metal === GLASS ? 'brittle' : 'soft'} for a ${mo.kind === 'bit' ? 'drill bit' : 'tank'}; returned as scrap.`; }
|
||||
else if (mo.kind === 'bit') {
|
||||
if (tier > player.bitTier) { player.bitTier = tier; msg = `New drill bit: ${BIT_TIERS[tier].name}.`; emit({ t: 'upgrade', kind: 'bit', tier }); }
|
||||
else { msg = `You already have a ${BIT_TIERS[player.bitTier].name.toLowerCase()}. The casting broke into scrap, which went into your bag.`; }
|
||||
else { msg = `You already have a ${BIT_TIERS[player.bitTier].name.toLowerCase()}; returned as scrap.`; }
|
||||
} else {
|
||||
if (tier > player.tankTier) { player.tankTier = tier; msg = `New bag: ${TANK_TIERS[tier].name}, holds ${TANK_TIERS[tier].cap.toLocaleString('en-US')}.`; emit({ t: 'upgrade', kind: 'tank', tier }); }
|
||||
else { msg = 'Your tank is already as good. The casting broke into scrap, which went into your bag.'; }
|
||||
else { msg = 'Your tank is already as good; returned as scrap.'; }
|
||||
}
|
||||
// a casting you could not use breaks into scrap, which goes to your bag
|
||||
if (msg.startsWith('New')) for (const i of cav) setCell(i, EMPTY, AMB[(i / W) | 0], 0);
|
||||
else clearCavity(cav);
|
||||
const u = unplugMold(mo);
|
||||
unplugMold(mo);
|
||||
mo.state = 'empty'; stats.cast++;
|
||||
return msg + knockNote(0, 0, u.chipped, u.raked) + furnaceJunkHint(mo);
|
||||
return msg;
|
||||
}
|
||||
function removeMold(mo) {
|
||||
undoNote({ t: 'mold-', kind: mo.kind, bx: mo.x / BS, by: mo.y / BS, wall: mo.wall });
|
||||
|
||||
+2
-2
@@ -42,11 +42,11 @@ function toolDig(cx, cy, r) {
|
||||
stats.dug += dug;
|
||||
let status = '';
|
||||
void 0;
|
||||
if (far && !dug && !tooHard) status = `Out of reach. Your ${tier.name.toLowerCase()} reaches ${drillReach()} grains from the bot.`;
|
||||
if (far && !dug && !tooHard) status = `Out of reach; your bit reaches ${drillReach()} grains.`;
|
||||
if (tooHard && !dug) {
|
||||
const need = BIT_TIERS.find(b => b.hard >= HARD[tooHard]);
|
||||
const nb = need ? need.name.toLowerCase() : 'better bit';
|
||||
status = HARD[tooHard] > 6 ? `${MD[tooHard].name} cannot be drilled.` : `${MD[tooHard].name} is too hard for your ${tier.name.toLowerCase()}. Needs ${/^[aeiou]/.test(nb) ? 'an' : 'a'} ${nb}.`;
|
||||
status = HARD[tooHard] > 6 ? `${MD[tooHard].name} cannot be drilled.` : `${MD[tooHard].name} is too hard; needs ${/^[aeiou]/.test(nb) ? 'an' : 'a'} ${nb}.`;
|
||||
}
|
||||
return { dug, status, tooHard };
|
||||
}
|
||||
|
||||
+3
-3
@@ -17,8 +17,8 @@ function undoLast() {
|
||||
const rec = undoStack.pop();
|
||||
if (!rec) return 'Nothing to undo.';
|
||||
const prev = undoRec; undoRec = null;
|
||||
let fails = 0, why = '';
|
||||
const fail = (r) => { fails++; if (r && !why) why = r; };
|
||||
let fails = 0;
|
||||
const fail = () => { fails++; };
|
||||
for (let k = rec.ops.length - 1; k >= 0; k--) {
|
||||
const o = rec.ops[k];
|
||||
if (o.t === 'block+') { if (blockP[o.by * BW + o.bx] === o.code) removeBlock(o.bx, o.by); }
|
||||
@@ -38,7 +38,7 @@ function undoLast() {
|
||||
undoRec = prev;
|
||||
powerDirty = true;
|
||||
const n = rec.ops.length;
|
||||
return fails ? `Undid ${rec.label}, but ${fails === n ? 'none' : fails} of it could not be put back${why ? ': ' + why.replace(/\.$/, '').toLowerCase() : ''}.` : `Undid ${rec.label}.`;
|
||||
return fails ? `Undo incomplete: ${fails} of ${n} changes could not be put back.` : `Undid ${rec.label}.`;
|
||||
}
|
||||
function clearAllGhosts() { ghostBlocks.clear(); ghostMachines = []; ghostMolds = []; ghostBlocked.clear(); }
|
||||
let ghostMissing = 0, ghostIter = null;
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@ function toolVacuum(cx, cy, r, pick) {
|
||||
if (got & 1) emit({ t: 'suck', x, y, m });
|
||||
if (--budget <= 0) return false;
|
||||
});
|
||||
return { got, full, status: full ? 'Bag full. Blow something out or cast a Tank mold.' : '' };
|
||||
return { got, full, status: full ? 'Bag full; blow material out or cast a bigger tank.' : '' };
|
||||
}
|
||||
// Blow: grains leave the bot's nozzle and fly to the cursor, where they drop.
|
||||
// Liquids need the Flask. Bars are thrown, one at a time.
|
||||
@@ -45,11 +45,11 @@ function toolBlow(cx, cy, r, m, mix) {
|
||||
let pickM = null;
|
||||
if (mix && mix.length) {
|
||||
const avail = mix.filter(k => bag[k] > 0 && PH[k] !== PH_ITEM && (PH[k] !== PH_LIQUID || player.flask));
|
||||
if (!avail.length) return { placed: 0, status: 'Nothing ticked left to mix. Tick materials in your bag.' };
|
||||
if (!avail.length) return { placed: 0, status: 'Tick materials in your bag to mix.' };
|
||||
pickM = () => { for (let k = 0; k < avail.length; k++) { const c = avail[(blowRR++) % avail.length]; if (bag[c] > 0) return c; } return 0; };
|
||||
m = avail[0];
|
||||
}
|
||||
if (!m) return { placed: 0, status: 'Pick something to blow out. Q and E cycle, or click it in your bag.' };
|
||||
if (!m) return { placed: 0, status: 'Pick what to blow out: Q/E, or click it in your bag.' };
|
||||
if (bag[m] <= 0) return { placed: 0, status: `No ${MD[m].name.toLowerCase()} left.` };
|
||||
const ph = PH[m];
|
||||
if (ph === PH_LIQUID && !player.flask) return { placed: 0, status: 'You need the Flask to carry liquids.' };
|
||||
|
||||
Reference in New Issue
Block a user