Construction: buildings rise by labour; planks and hammers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4093245b8e
commit
a4e4bd4385
6 changed files with 180 additions and 47 deletions
|
|
@ -323,6 +323,8 @@ function skillPage(id) {
|
|||
</div></div>`;
|
||||
if (id === "combat") html += combatPanel();
|
||||
if (id === "prayer") html += prayerPanel();
|
||||
if (id === "construction") html += S.city.construction ? siteBanner()
|
||||
: `<div class="panel muted">Nothing is being built right now. Fund a building on the Town square and its site opens here.</div>`;
|
||||
html += potionPanel(id);
|
||||
if (`tool_${id}` in me.equip) html += toolPanel(id);
|
||||
if (id === "reconnaissance") html += `<div class="panel small muted">Every ${8} reconnaissance points on an upcoming event raises its intel by one level, on top of what the spymaster's guild provides. The council & threats page shows the progress.</div>`;
|
||||
|
|
@ -467,6 +469,7 @@ function actionCard(a) {
|
|||
}
|
||||
if (a.special === "recon") extra = `<div class="small muted">+${a.recon} recon on the next event</div>`;
|
||||
const temple = S.city.buildings.temple?.level || 0;
|
||||
if (a.special === "labour") extra = `<div class="small makes">🏗️ +${me.labour_per_action} labour per action</div>`;
|
||||
if (a.special === "bury") extra = `<div class="small makes">🙏 +${a.pp + temple} prayer points</div>`;
|
||||
if (a.special === "offer") extra = `<div class="small makes">⛪ +${+(a.devotion * (1 + 0.25 * temple)).toFixed(1)} devotion for the city's ward</div>`;
|
||||
const made = Object.keys(a.outputs).map(itemStats).filter(Boolean);
|
||||
|
|
@ -597,16 +600,7 @@ function town() {
|
|||
</div>`;
|
||||
if (city.starving) html += `<div class="banner bad">🍞<div class="grow"><b>The granary is empty.</b> People are leaving and the city defends worse. Donate bread, cooked meat or stew.</div></div>`;
|
||||
if (city.merchant_until > serverNow()) html += `<div class="banner">🐪<div class="grow"><b>A merchant caravan is in town.</b> Everything sells for 50% more for another ${countdown(city.merchant_until)}.</div></div>`;
|
||||
const work = city.construction;
|
||||
if (work) {
|
||||
const spec = C.buildings[work.building];
|
||||
const queued = city.queue.map((key) => esc(C.buildings[key].name)).join(", ");
|
||||
const hire = S.favours.builders;
|
||||
html += `<div class="banner">🏗️<div class="grow"><b>${work.repair ? "Repairing" : "Building"} ${esc(spec.name)}</b> · done in ${countdown(work.done_at)}
|
||||
${hire.why ? "" : `<button class="btn sm gold" data-favour="builders" ${S.me.favour < hire.cost ? "disabled" : ""} title="Halve the time left">Hire builders ✨ ${fmt(hire.cost)}</button>`}
|
||||
<div class="bar gold" style="margin-top:6px"><span data-span="${work.start},${work.done_at}"></span></div>
|
||||
${queued ? `<div class="small muted" style="margin-top:6px">Next: ${queued}</div>` : ""}</div></div>`;
|
||||
}
|
||||
if (city.construction) html += siteBanner();
|
||||
html += `<div class="section-title">Buildings</div>
|
||||
<p class="small muted">Each building collects its own fund. Materials in a fund are safe from raiders, and building starts on its own once the fund is complete.</p>
|
||||
<div class="grid wide">${Object.entries(city.buildings).map(([key, b]) => buildingCard(key, b)).join("")}</div>`;
|
||||
|
|
@ -617,6 +611,26 @@ function town() {
|
|||
return html;
|
||||
}
|
||||
|
||||
// The building site: labour so far, who is helping, and ways to speed it up.
|
||||
function siteBanner() {
|
||||
const city = S.city, work = city.construction, me = S.me;
|
||||
const spec = C.buildings[work.building];
|
||||
const queued = city.queue.map((key) => esc(C.buildings[key].name)).join(", ");
|
||||
const hire = S.favours.builders;
|
||||
const working = me.action?.id === "labour";
|
||||
const builders = S.players.filter((p) => p.skill === "construction" && p.doing === "Work on the building site").map((p) => esc(p.name));
|
||||
return `<div class="banner">🏗️<div class="grow">
|
||||
<div class="site-head"><b>${work.repair ? "Repairing" : "Building"} ${esc(spec.name)}</b>
|
||||
<span class="muted small">${fmt(work.labour)} / ${fmt(work.needed)} labour</span>
|
||||
<span class="btns">
|
||||
${working ? `<span class="tag good">You're working on it</span>` : `<button class="btn sm primary" data-start="labour">Work on it</button>`}
|
||||
${hire.why ? "" : `<button class="btn sm gold" data-favour="builders" ${me.favour < hire.cost ? "disabled" : ""} title="Adds half the labour that's left">Hire builders ✨ ${fmt(hire.cost)}</button>`}
|
||||
</span></div>
|
||||
<div class="bar gold" style="margin-top:6px"><span style="width:${Math.min(100, work.labour / work.needed * 100)}%"></span></div>
|
||||
<div class="small muted" style="margin-top:6px">${builders.length ? `On site: ${builders.join(", ")}. ` : ""}The townsfolk add about ${fmt(city.townsfolk_labour)} labour an hour.${queued ? ` Next: ${queued}.` : ""}</div>
|
||||
</div></div>`;
|
||||
}
|
||||
|
||||
function buildingCard(key, b) {
|
||||
const spec = C.buildings[key], city = S.city, me = S.me;
|
||||
const tags = {
|
||||
|
|
@ -705,7 +719,7 @@ function favourSpends() {
|
|||
</div>`;
|
||||
};
|
||||
return `<div class="panel"><h2>Spend favour on the city · you have ✨ ${fmt(me.favour)}</h2>
|
||||
${option("builders", "🏗️", "Hire extra builders", f.builders.why ? esc(f.builders.why) + "." : `Halves the time left on the current building (saves about ${dur(Math.round(f.builders.saves * 60) * 60)}).`)}
|
||||
${option("builders", "🏗️", "Hire extra builders", f.builders.why ? esc(f.builders.why) + "." : `Adds ${fmt(f.builders.labour)} labour to the current building, half of what's left.`)}
|
||||
${option("informant", "🕵️", "Pay an informant", f.informant.why ? esc(f.informant.why) + "." : "One more level of intel on what's coming.")}
|
||||
${option("militia", "📯", "Rally the militia", f.militia.why ? esc(f.militia.why) + "." : `+10 defence for the coming raid${f.militia.rallied ? ` (+${f.militia.rallied} so far)` : ""}. Costs more each time.`)}
|
||||
</div>`;
|
||||
|
|
|
|||
|
|
@ -386,3 +386,5 @@ button.sheet-skill:hover { background: var(--panel-2); }
|
|||
.prayer.on { border-color: var(--favour); box-shadow: 0 0 0 1px var(--favour) inset; background: rgba(185, 140, 232, .12); }
|
||||
.prayer.locked { opacity: .45; cursor: not-allowed; }
|
||||
.prayer-points { font-size: 15px; }
|
||||
.site-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
||||
.site-head .btns { margin-left: auto; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue