Fires: everyone keeps their own pile
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a02a81dffd
commit
b4ecacf96c
4 changed files with 91 additions and 54 deletions
|
|
@ -571,8 +571,9 @@ function skillGear(skill) {
|
|||
}
|
||||
|
||||
// --- fires ----------------------------------------------------------------
|
||||
// The guild's shared fires. Between polls the client burns them down itself, hottest
|
||||
// fuel first, the same way the server does.
|
||||
// The guild's shared fires. Between polls the client burns them down itself, the same
|
||||
// way the server does: the burn shared evenly between everyone's piles, each pile's
|
||||
// hottest fuel first.
|
||||
|
||||
const ROMAN = ["I", "II", "III", "IV", "V", "VI"];
|
||||
// Core to edge of each flame colour, for the animated fires.
|
||||
|
|
@ -590,16 +591,20 @@ const tendLevel = (tier) => C.actions.find((a) => a.id === `tend_forge_${C.firew
|
|||
|
||||
function fireNow(id) {
|
||||
const f = S.city.fires[id], fuel = f.fuel.map((c) => ({ ...c }));
|
||||
const hottest = (by) => fuel.filter((c) => c.by === by).reduce((best, c) => (c.tier > best.tier ? c : best));
|
||||
let burn = Math.max(0, serverNow() - f.at) * f.speed;
|
||||
while (burn > 0 && fuel.length) {
|
||||
const top = fuel.reduce((best, c) => (c.tier > best.tier ? c : best));
|
||||
const used = Math.min(burn, top.left);
|
||||
top.left -= used;
|
||||
burn -= used;
|
||||
if (top.left <= 1e-6) fuel.splice(fuel.indexOf(top), 1);
|
||||
while (burn > 1e-9 && fuel.length) {
|
||||
const heads = [...new Set(fuel.map((c) => c.by))].map(hottest);
|
||||
const step = Math.min(burn, Math.min(...heads.map((c) => c.left)) * heads.length);
|
||||
for (const c of heads) {
|
||||
c.left -= step / heads.length;
|
||||
if (c.left <= 1e-6) fuel.splice(fuel.indexOf(c), 1);
|
||||
}
|
||||
burn -= step;
|
||||
}
|
||||
const heat = fuel.reduce((h, c) => Math.max(h, c.tier), -1), left = fuel.reduce((sum, c) => sum + c.left, 0);
|
||||
return { fuel, heat, left, low: heat >= 0 && left < C.fire_low, speed: f.speed };
|
||||
const mine = fuel.filter((c) => c.by === S.uid);
|
||||
return { fuel, mine, heat, left, low: heat >= 0 && left < C.fire_low, speed: f.speed };
|
||||
}
|
||||
|
||||
function pickFirewood() {
|
||||
|
|
@ -628,6 +633,8 @@ function fireCard(id, pick) {
|
|||
const start = `tend_${id}_${C.firewood[pick]}`, why = mine ? "" : me.blocked[start];
|
||||
const crafting = f.users.filter((u) => !u.action.startsWith("tend_"));
|
||||
const doing = (u) => C.actions.find((a) => a.id === u.action);
|
||||
const piles = [...new Set(f.fuel.map((c) => c.by))];
|
||||
const keepers = piles.length ? `<span title="${esc(piles.map(playerName).join("\n"))}">🔥 ${piles.length}</span>` : "";
|
||||
const who = crafting.length
|
||||
? `<span title="${esc(crafting.map((u) => `${u.name}: ${doing(u).name}`).join("\n"))}">👤 ${crafting.length} ${crafting.map((u) => doing(u).icon).join("")}</span>`
|
||||
: `<span class="muted">👤 0</span>`;
|
||||
|
|
@ -635,9 +642,10 @@ function fireCard(id, pick) {
|
|||
<div class="fire-stage"><canvas data-flame="${id}"></canvas><span class="fire-state" data-fire-state="${id}"></span></div>
|
||||
<div class="fire-body">
|
||||
<div class="fire-head">${glyph(spec.glyph, "#e7e9f0")}<b>${esc(spec.name)}</b><span class="muted small">${skill.icon} ${esc(skill.name)}</span></div>
|
||||
<div class="fuel" data-fuel="${id}"></div>
|
||||
<div class="fire-line"><span data-fire-left="${id}"></span><span data-fire-covers="${id}"></span></div>
|
||||
<div class="fire-line small">${who}<span title="Logs this fire has paid for">🪵 ${fmt(f.saved || 0)}</span></div>
|
||||
<div class="fire-line"><span data-fire-left="${id}" title="Until it's out"></span><span data-fire-covers="${id}"></span></div>
|
||||
<div class="fuel" data-fuel="${id}" title="Your pile"></div>
|
||||
<div class="fire-line small"><span data-fire-mine="${id}" title="Your pile / the most you can bank"></span><span title="Logs this fire has paid for">🪵 ${fmt(f.saved || 0)}</span></div>
|
||||
<div class="fire-line small">${who}${keepers}</div>
|
||||
${mine ? `<div class="bar thick"><span data-progress></span></div>` : ""}
|
||||
<div class="foot"><span class="why">${esc(why || "")}</span>${mine
|
||||
? `<button class="btn danger" data-stop>Stop</button>`
|
||||
|
|
@ -670,10 +678,11 @@ function animateFires() {
|
|||
if (canvas) drawFlame(canvas, id, n);
|
||||
if (!text) continue;
|
||||
const set = (sel, html) => { for (const el of document.querySelectorAll(sel)) if (el.dataset.v !== html) { el.innerHTML = html; el.dataset.v = html; } };
|
||||
const bank = Math.max(S.me.firekeeping.bank * 60, n.left);
|
||||
const tiers = C.flames.map((_, t) => n.fuel.filter((c) => c.tier === t).reduce((sum, c) => sum + c.left, 0));
|
||||
set(`[data-fuel="${id}"]`, tiers.map((left, t) => left ? `<i style="--c:${flameTint(t)};width:${(left / bank * 100).toFixed(2)}%"></i>` : "").join(""));
|
||||
set(`[data-fire-left="${id}"]`, `<b>${dur(n.left / n.speed)}</b> / ${dur(S.me.firekeeping.bank * 60 / n.speed)}`);
|
||||
const bank = S.me.firekeeping.bank * 60, mine = n.mine.reduce((sum, c) => sum + c.left, 0);
|
||||
const tiers = C.flames.map((_, t) => n.mine.filter((c) => c.tier === t).reduce((sum, c) => sum + c.left, 0));
|
||||
set(`[data-fuel="${id}"]`, tiers.map((left, t) => left ? `<i style="--c:${flameTint(t)};width:${(left / Math.max(bank, mine) * 100).toFixed(2)}%"></i>` : "").join(""));
|
||||
set(`[data-fire-left="${id}"]`, n.heat >= 0 ? `🔥 <b>${dur(n.left / n.speed)}</b>` : "");
|
||||
set(`[data-fire-mine="${id}"]`, `You ${dur(mine / n.speed)} / ${dur(bank / n.speed)}`);
|
||||
set(`[data-fire-time="${id}"]`, dur(n.left / n.speed));
|
||||
set(`[data-fire-covers="${id}"]`, n.heat >= 0 ? `<span class="tag flame" style="--c:${flameTint(n.heat)}" title="Pays the log for tier ${ROMAN[n.heat]} and below">🪵 ≤ ${ROMAN[n.heat]}</span>` : "");
|
||||
set(`[data-fire-state="${id}"]`, n.heat < 0 ? "Out" : n.low ? "Low" : C.flames[n.heat][0]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue