Gear stats grid on recipes and in the bank: damage and power, 1H/2H, swing time, requirement, bonus

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-20 14:36:05 +01:00
parent ea1bae9b53
commit 9804c0bf85
4 changed files with 54 additions and 4 deletions

View file

@ -664,6 +664,39 @@ function gearStats(it) {
return stats.filter(Boolean).join(", ") + (it.weight ? ` (${C.weights[it.weight].name.toLowerCase()})` : "");
}
const GEAR_SLOTS = ["weapon", "shield", "helmet", "body", "legs"];
// A weapon's or armour piece's stats in a small grid. Weapons: damage type and power | 1H or 2H | swing
// time; armour: armour | weight | ward. Below: what it needs to wear, and any bonus for you.
function gearChips(it) {
const cell = (icon, text, tip, cls = "") => `<span class="gstat ${cls}" title="${esc(tip)}">${icon}${text === "" ? "" : `<span>${text}</span>`}</span>`;
const hands = (two) => `<span class="hands">${two ? "2H" : "1H"}</span>`;
let row = ["", "", ""];
if (it.style) {
const st = C.styles[it.style], dt = C.damage_types[st.damage];
row = [cell(glyph(dt.glyph, dt.tint), it.power, `${dt.name} damage, +${it.power} power`),
cell(hands(it.two_handed), "", it.two_handed ? "Two-handed: no shield" : "One-handed: room for a shield"),
cell(glyph("stopwatch", "#9fb3c8"), `${st.interval}s`, `A swing every ${st.interval}s`)];
} else if (it.slot === "shield") {
row = [cell(glyph("checked-shield", "#d4dae2"), it.armour, `+${it.armour} armour, +${it.power} power`),
cell(hands(false), "", "Held in one hand"),
cell(glyph("checked-shield", "#e0b04a"), `${Math.round(C.block_chance * 100)}%`, "Blocks this share of hits")];
} else if (it.weight) {
row = [cell(glyph("checked-shield", "#d4dae2"), it.armour, `+${it.armour} armour: less damage from blows`),
cell("", C.weights[it.weight].name, `${C.weights[it.weight].name} armour`, "muted"),
cell(glyph("magic-shield", "#a77be8"), it.ward, `+${it.ward} ward: less damage from magic`)];
}
let req = "", bonus = "";
if (it.req) {
const [skill, level] = it.req;
req = cell(skillOf(skill).icon, level, `Needs ${skillOf(skill).name.toLowerCase()} ${level}`, S.me.levels[skill] < level ? "short" : "");
}
if (it.style && C.class_style[S.me.cls] === it.style) {
bonus = cell(C.classes[S.me.cls].icon, "+15%", "Your trade's weapon: +15% damage", "trade");
}
return `<div class="stat-grid">${row.join("")}${req}<span></span>${bonus || "<span></span>"}</div>`;
}
// What an item does once made: healing, defence, tool speed, and who can use it.
function itemStats(id) {
const it = item(id);
@ -733,7 +766,9 @@ function actionCard(a) {
}
if (a.special === "bury") extra = `<div class="small makes">${skillOf("prayer").icon} +${a.pp + temple} prayer points</div>`;
if (a.special === "offer") extra = `<div class="small makes">${C.buildings.temple.icon} +${+(a.devotion * (1 + 0.25 * temple)).toFixed(1)} devotion</div>`;
const made = Object.keys(a.outputs).map(itemStats).filter(Boolean);
const gear = Object.keys(a.outputs).filter((id) => GEAR_SLOTS.includes(item(id).slot));
const made = Object.keys(a.outputs).filter((id) => !gear.includes(id)).map(itemStats).filter(Boolean);
extra += gear.map((id) => gearChips(item(id))).join("");
if (made.length) extra += `<div class="small makes">${made.join(" · ")}</div>`;
return `
<div class="action ${active || second ? "active" : ""} ${locked ? "locked" : ""}">
@ -803,6 +838,7 @@ function itemPanel(id) {
<div class="ico">${it.icon}</div>
<h3>${esc(it.name)}</h3>
<div class="muted small">You have ${fmt(have)} · worth ${price % 1 ? price.toFixed(1) : price} gold each${merchant ? " (merchant in town!)" : ""}</div>
${GEAR_SLOTS.includes(it.slot) ? gearChips(it) : ""}
${it.slot ? equipRow(id, it) : ""}
${it.potion ? `<div class="row"><div class="small">${esc(it.potion.text)} for ${C.potion_charges} ${it.potion.skill === "combat" ? "fights" : "actions"}.</div>
<button class="btn gold" data-potion="${id}">Drink</button>
@ -833,8 +869,7 @@ function equipRow(id, it) {
function equipLabel(it) {
if (it.tool) return `Use as ${skillOf(it.tool).name.toLowerCase()} tool (${Math.round(it.speed * 100)}% faster)`;
const stats = gearStats(it);
return `Equip ${it.slot === "body" ? "body armour" : it.slot === "legs" ? "leg armour" : it.slot} (${stats})`;
return "Equip";
}
function goldPanel() {