Lane B R34: ⚖ LIST in the crate · AT AUCTION section · the morning paper rides the toasts

hud.js: every crate find row gains ⚖ (mail-in consignment — very 1996); AT AUCTION section
(non-empty only) shows what hammers tomorrow; the rebuild watcher now folds listings in.
index.html: the wake toast and the travel-arrival toast carry the drained auction news —
'🌅 day 2 · ⚖ SOLD "Cane Toad Blues" — hammer $22, $19 after fees' is the come-back-tomorrow
hook paying off at dawn.
This commit is contained in:
type-two 2026-07-20 19:32:06 +10:00
parent b048f51640
commit e528c92fed
2 changed files with 40 additions and 5 deletions

View File

@ -264,7 +264,9 @@ const game = GAME_ON ? createGame({
onDay: (day) => { onDay: (day) => {
if (gigState) gigState.setWeekNight(weekNightOf(day)); // (day 1) % 7 — see the seam note below if (gigState) gigState.setWeekNight(weekNightOf(day)); // (day 1) % 7 — see the seam note below
lighting.setSegment(0); lighting.setSegment(0);
hud.showToast(`🌅 day ${day}`); // [R34] the morning paper: GODBAY resolved before this hook fired — fold the results in
const news = game ? game.takeAuctionNews() : [];
hud.showToast(`🌅 day ${day}` + (news.length ? ' · ' + news.join(' · ') : ''), news.length ? 6 : 2.6);
}, },
}) : null; }) : null;
const wallet = game ? game.wallet : baseWallet; const wallet = game ? game.wallet : baseWallet;
@ -283,7 +285,13 @@ const weekNightOf = (day) => (Math.max(1, day) - 1) % 7;
if (game && gigState) gigState.setWeekNight(weekNightOf(game.day)); if (game && gigState) gigState.setWeekNight(weekNightOf(game.day));
// [R33 — TRAVEL COSTS A DAY] this boot adopted a save from another town: the ride ate a day (save.js // [R33 — TRAVEL COSTS A DAY] this boot adopted a save from another town: the ride ate a day (save.js
// adopt() did the increment + pull-pruning; weekNight above already read the incremented day). Tell John. // adopt() did the increment + pull-pruning; weekNight above already read the incremented day). Tell John.
if (game && game.traveled) hud.showToast(`🚌 ${plan.name || 'a new town'} — the ride cost a day. Day ${game.day}`, 4); // [R34] the ride also resolved any GODBAY listings the day moved past — the arrival toast carries the news.
if (game) {
const bootNews = game.takeAuctionNews();
if (game.traveled) hud.showToast(`🚌 ${plan.name || 'a new town'} — the ride cost a day. Day ${game.day}`
+ (bootNews.length ? ' · ' + bootNews.join(' · ') : ''), bootNews.length ? 7 : 4);
else if (bootNews.length) hud.showToast(bootNews.join(' · '), 6);
}
// [Lane F R9] occupancyOf closure defers to `citizens` (declared just below); only invoked at enter() // [Lane F R9] occupancyOf closure defers to `citizens` (declared just below); only invoked at enter()
// time (door click), long after citizens is initialized — so the forward reference is safe. // time (door click), long after citizens is initialized — so the forward reference is safe.
const interiorMode = createInteriorMode({ THREE, renderer, camera, plan, fleet, useGLB: !NOASSETS, const interiorMode = createInteriorMode({ THREE, renderer, camera, plan, fleet, useGLB: !NOASSETS,

View File

@ -200,7 +200,34 @@ export function createHUD({ camera, renderer, plan, getDoorMeshes, onEnterShop }
const meta = document.createElement('div'); meta.className = 'pc-crate-meta'; const meta = document.createElement('div'); meta.className = 'pc-crate-meta';
meta.textContent = `paid $${e.pricePaid} · ${foundAt(e, game)} · day ${e.dayFound}`; meta.textContent = `paid $${e.pricePaid} · ${foundAt(e, game)} · day ${e.dayFound}`;
main.append(t, a, meta); main.append(t, a, meta);
row.append(th, main); panel.appendChild(row); row.append(th, main);
// [R34 GODBAY] ⚖ LIST — mail-in consignment; the entry leaves the crate, hammers tomorrow.
if (typeof game.listFind === 'function') {
const lb = document.createElement('div');
lb.textContent = '⚖'; lb.title = 'LIST at GodBay — the auction resolves tomorrow';
lb.style.cssText = 'cursor:pointer;opacity:.65;padding:0 4px;flex:none;font-size:15px';
lb.onclick = () => { if (game.listFind(e)) rebuildList(); };
row.appendChild(lb);
}
panel.appendChild(row);
}
// [R34] AT AUCTION — consigned finds, hammering overnight. Non-empty only (no header over nothing).
const listings = game.listings || [];
if (listings.length) {
const lh = document.createElement('h3');
lh.style.marginTop = '10px';
lh.textContent = `AT AUCTION — ${listings.length} consigned · hammers tomorrow`;
panel.appendChild(lh);
for (const l of listings) {
const row = document.createElement('div'); row.className = 'pc-crate-row';
const main = document.createElement('div'); main.className = 'pc-crate-main';
const t = document.createElement('div'); t.className = 'pc-crate-title';
t.textContent = l.title || l.sku || l.slotId || 'item';
const meta = document.createElement('div'); meta.className = 'pc-crate-meta';
meta.textContent = `paid $${l.pricePaid} · listed day ${l.listDay}`;
main.append(t, meta);
row.append(main); panel.appendChild(row);
}
} }
// [R33] THE WANTLIST — what you're hunting (☆ on a pull card adds; ✕ here removes; buying one // [R33] THE WANTLIST — what you're hunting (☆ on a pull card adds; ✕ here removes; buying one
// clears it automatically). Section exists only when non-empty — no stray header over nothing. // clears it automatically). Section exists only when non-empty — no stray header over nothing.
@ -245,8 +272,8 @@ export function createHUD({ camera, renderer, plan, getDoorMeshes, onEnterShop }
shownCount = col.length; btnCrate.textContent = `CRATE ${shownCount}`; shownCount = col.length; btnCrate.textContent = `CRATE ${shownCount}`;
if (open) rebuildList(); if (open) rebuildList();
} }
const nw = (game.wants || []).length; // [R33] want add/clear refreshes an open panel too const nw = (game.wants || []).length + (game.listings || []).length * 100; // [R33/R34] wants OR
if (nw !== shownWants) { shownWants = nw; if (open) rebuildList(); } if (nw !== shownWants) { shownWants = nw; if (open) rebuildList(); } // listings change → rebuild
// [R32] the surface yields to the map and to the dig/sell cards (they own the screen), and shows // [R32] the surface yields to the map and to the dig/sell cards (they own the screen), and shows
// everywhere else — street AND interior. Cheap: a style write only when the answer changes. // everywhere else — street AND interior. Cheap: a style write only when the answer changes.
const P = window.PROCITY, im = P && P.interiorMode; const P = window.PROCITY, im = P && P.interiorMode;