Work orders: names on phones

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-24 18:13:44 +01:00
parent 049e2c771a
commit 2bcda564b8
3 changed files with 26 additions and 6 deletions

View file

@ -5984,6 +5984,8 @@ PATCH_NOTES = [
("new", "An interrupted cast stays on the enemy's bar for a moment, struck through: ✋ interrupted."),
("balance", "Volley no longer takes arrows: abilities never cost anything. Wyrmscale quiver: Volley 40% harder "
"and Aimed Shot 25% faster."),
("fix", "Work orders on phones: the item picker and reagent slots show names, and picking an item scrolls to "
"the amount, price and Post."),
]},
{"date": "2026-10-24", "title": "A dungeon in every area", "notes": [
("new", "Six more dungeons for 2–4, seven pulls each with two mini-bosses and a final boss: Goblin Warren "

View file

@ -1838,21 +1838,21 @@ function orderSlots(o) {
const name = item(id).name, pool = o.provided[id] || 0, have = S.me.bank[id] || 0;
if (o.status !== "open") {
return `<div class="ro-slot open"><span class="doll-slot empty-req" title="${esc(name)}">${item(id).icon}</span>
<span class="ro-have muted">×${fmt(per * all)}</span></div>`;
<span class="ro-have muted">×${fmt(per * all)}</span><span class="ro-name">${esc(name)}</span></div>`;
}
const need = per * left;
const who = Object.entries(o.gave || {}).filter(([, items]) => items[id]).map(([uid, items]) => `${playerName(uid)} ${fmt(items[id])}`);
const tip = [`${name}: ${fmt(pool)} / ${fmt(need)}`, ...who].join(" · ");
if (pool >= need) {
return `<div class="ro-slot filled" title="${esc(tip)}"><span class="doll-slot">${item(id).icon}
<span class="swap-qty">${fmt(need)}</span><span class="tick">✓</span></span></div>`;
<span class="swap-qty">${fmt(need)}</span><span class="tick">✓</span></span><span class="ro-name">${esc(name)}</span></div>`;
}
const give = Math.min(have, need - pool);
// What putting them in pays you once they're crafted: your value's slice of the reagents' share.
const share = o.by === S.uid ? 0 : Math.round(o.reward / o.qty * out * C.input_share * item(id).value / worth * give);
const fill = give ? `${tip} · +${fmt(give)}${share ? ` → ${fmt(share)} gold` : ""}` : `${tip} · 🎒 0`;
return `<div class="ro-slot open"><button class="doll-slot empty-req" data-order-fill="${o.id}" data-item="${id}" ${give ? "" : "disabled"} title="${esc(fill)}">${item(id).icon}</button>
<span class="ro-have ${pool + have < need ? "bad" : "good"}">${fmt(pool)} / ${fmt(need)}</span></div>`;
<span class="ro-have ${pool + have < need ? "bad" : "good"}">${fmt(pool)} / ${fmt(need)}</span><span class="ro-name">${esc(name)}</span></div>`;
}).join("");
}
@ -1911,7 +1911,7 @@ function orderPicker(list) {
const makers = others.filter((p) => p.levels[a.skill] >= a.level).length;
const tip = `${item(id).name} · ${skillOf(a.skill).name} ${a.level}${d.kind === "craft" ? ` · 👥 ${makers}` : ""}`;
return `<button class="doll-slot swap pick ${d.item === id ? "on" : ""} ${d.kind === "craft" && !makers ? "nobody" : ""}" data-draft-item="${id}" title="${esc(tip)}">
${item(id).icon}<span class="pick-lvl">${a.level}</span></button>`;
${item(id).icon}<span class="pick-name">${esc(item(id).name)}${d.kind === "craft" ? ` <span class="muted">👥 ${makers}</span>` : ""}</span><span class="pick-lvl">${a.level}</span></button>`;
}).join("");
return `<div class="picker">
<div class="pick-skills">${skills.map((k) => `<button class="pick-skill ${!q && k === d.skill ? "on" : ""}" data-draft-skill="${k}" title="${esc(skillOf(k).name)}">${skillOf(k).icon}</button>`).join("")}
@ -1934,7 +1934,7 @@ function orderComposer() {
return `<div class="ro-slot ${on ? "filled" : "open"}"><button class="doll-slot ${on ? "on" : "empty-req"}" data-provide="${id}"
${!on && have < need ? `disabled title="${esc(`${item(id).name}: ${fmt(have)} / ${fmt(need)}`)}"` : `title="${esc(item(id).name)}"`}>
${item(id).icon}${on ? `<span class="tick">✓</span>` : ""}</button>
<span class="ro-have ${have < need ? "bad" : "good"}">${fmt(have)} / ${fmt(need)}</span></div>`;
<span class="ro-have ${have < need ? "bad" : "good"}">${fmt(have)} / ${fmt(need)}</span><span class="ro-name">${esc(item(id).name)}</span></div>`;
}).join("");
}
}
@ -2350,7 +2350,13 @@ document.addEventListener("click", (e) => {
if (d.draftKind) { draft = { kind: d.draftKind, item: "", qty: 1, provide: [], reward: 0 }; clearSearch(); return render(); }
if (d.draftSkill) { draft.skill = d.draftSkill; draft.search = ""; clearSearch(); return render(); }
if (d.draftGroup) { draft.group = d.draftGroup; return render(); }
if (d.draftItem) { pickOrderItem(d.draftItem); return render(); }
if (d.draftItem) {
pickOrderItem(d.draftItem);
render();
// On a phone the named list is long: bring the amount, price and Post into view.
if (draft.item && matchMedia("(max-width: 900px)").matches) $(".compose-grid")?.scrollIntoView({ behavior: "smooth", block: "start" });
return;
}
if (d.provide) {
draft.provide = draft.provide.includes(d.provide) ? draft.provide.filter((x) => x !== d.provide) : [...draft.provide, d.provide];
return render();

View file

@ -690,6 +690,18 @@ button.sheet-skill:hover { background: var(--panel-2); }
.pick-lvl { position: absolute; bottom: -5px; right: -5px; font-size: 10px; font-weight: 700; line-height: 1; padding: 2px 4px; border-radius: 6px; background: var(--panel); border: 1px solid var(--line); color: var(--muted); }
.doll-slot.pick.on .pick-lvl { border-color: var(--gold); }
.doll-slot.pick.on .pick-lvl { color: var(--gold); }
.pick-name, .ro-name { display: none; }
/* No hover, no tooltips: name every pickable item and reagent. */
@media (hover: none) {
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px; }
.doll-slot.pick { width: auto; height: auto; min-height: 44px; display: flex; align-items: center; gap: 8px; padding: 5px 8px; text-align: left; }
.doll-slot.pick > .gi { flex: none; }
.pick-name { display: block; flex: 1; min-width: 0; font-size: 13px; line-height: 1.25; }
.pick-name .muted { display: block; font-size: 11px; }
.doll-slot.pick .pick-lvl { left: 26px; right: auto; bottom: 3px; }
.doll-slot.pick.nobody .pick-name { opacity: .55; }
.ro-name { display: block; max-width: 72px; font-size: 10.5px; line-height: 1.2; text-align: center; color: var(--muted); }
}
/* --- fires ------------------------------------------------------------ */