Fittings: Construction-made building upgrades from planks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-19 11:15:19 +01:00
parent fb4b8bf7c8
commit cdb109e554
7 changed files with 218 additions and 14 deletions

View file

@ -462,6 +462,10 @@ function itemStats(id) {
if (it.tool) parts.push(`${Math.round(it.speed * 100)}% faster ${skillOf(it.tool).name.toLowerCase()}`);
if (it.req && it.req[1] > 1) parts.push(`needs ${skillOf(it.req[0]).name.toLowerCase()} ${it.req[1]}`);
if (it.potion) parts.push(`${it.potion.text}, ${C.potion_charges} uses`);
if (it.fitting) {
const f = C.fittings.find((x) => x.id === id), done = S.city.buildings[f.building].fittings.includes(id);
parts.push(`${C.buildings[f.building].icon} For the ${C.buildings[f.building].name.toLowerCase()} (Lv ${f.level}): ${f.effect}${done ? " · already fitted" : ""}`);
}
return parts.join(", ");
}
@ -738,6 +742,7 @@ function buildingCard(key, b) {
</span></div>`;
}).join("")}</div>`;
}
body += fittingRows(key, b);
const levelText = b.cap < spec.max ? `Lv ${b.level} · max ${b.cap} for a ${city.tier_name.toLowerCase()}` : `Lv ${b.level} / ${spec.max}`;
return `<div class="action building ${b.damaged ? "damaged" : ""}">
<div class="top"><div class="ico">${spec.icon}</div><div>
@ -746,6 +751,29 @@ function buildingCard(key, b) {
</div></div>${body}</div>`;
}
// Fittings Construction makes for this building: fitted, ready to fit, or waiting on a level.
function fittingRows(key, b) {
const rows = C.fittings.filter((f) => f.building === key).map((f) => {
const it = item(f.id), recipe = C.actions.find((a) => a.id === `make_${f.id}`);
let state;
if (b.fittings.includes(f.id)) {
state = b.damaged ? `<span class="tag bad">Paused</span>` : `<span class="tag good">Fitted</span>`;
} else if (b.level < f.level) {
state = `<span class="tag">Needs Lv ${f.level}</span>`;
} else {
const mine = S.me.bank[f.id] || 0, stores = S.city.stockpile[f.id] || 0;
state = mine || stores
? `${mine ? `<button class="btn sm gold" data-install="${f.id}" data-source="bank" title="From your bank, earns favour">Fit</button>` : ""}
${stores ? `<button class="btn sm" data-install="${f.id}" data-source="city" title="From the city's stockpile">Fit from stockpile</button>` : ""}`
: `<span class="muted small">Construction ${recipe.level}</span>`;
}
return `<div class="fitting-row"><span class="fit-ico">${it.icon}</span>
<span class="fitting-text"><b>${esc(f.name)}</b> <span class="muted small">${esc(f.effect)}</span></span>
<span class="btns">${state}</span></div>`;
});
return rows.length ? `<div class="fittings">${rows.join("")}</div>` : "";
}
// --- council --------------------------------------------------------------
function pips(level) {
@ -1018,6 +1046,7 @@ document.addEventListener("click", (e) => {
if (d.equip) return act("/api/equip", { item: d.equip });
if (d.unequip) return act("/api/equip", { slot: d.unequip });
if (d.fund) return act("/api/fund", { building: d.fund, item: d.item, source: d.source, qty: "all" });
if (d.install) return act("/api/install", { fitting: d.install, source: d.source });
if (d.garrison) return act("/api/garrison", { join: d.garrison === "1" });
if (d.perk) return act("/api/perk", { perk: d.perk });
if (d.favour) return act("/api/favour", { kind: d.favour });