From faf186f1027a9ab4b8af5b8b1198a79ef444ce09 Mon Sep 17 00:00:00 2001 From: rope Date: Wed, 28 Oct 2026 15:36:38 +0000 Subject: [PATCH] Mood bar: gradient, growing / falling Co-Authored-By: Claude Opus 5.5 --- game.py | 1 - static/app.js | 11 ++++++----- static/styles.css | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/game.py b/game.py index 066fabd..edef4d5 100644 --- a/game.py +++ b/game.py @@ -4585,7 +4585,6 @@ def happiness(world: dict, now: float) -> dict: band = mood(world) return { "score": round(city["happiness"], 3), "target": round(target, 3), "name": band["name"], "icon": band["icon"], - "heading": next(b["name"] for b in MOODS if target < b["below"]), "effects": {key: band[key] for key in ("growth", "militia", "work", "leave")}, "needs": {key: {**needs[key], "score": round(needs[key]["score"], 3), "weight": NEEDS[key]} for key in active}, "locked": [key for key in NEEDS if key not in active], diff --git a/static/app.js b/static/app.js index 880b986..fe09c47 100644 --- a/static/app.js +++ b/static/app.js @@ -2054,11 +2054,12 @@ const NEED_NAMES = { food: ["๐Ÿฒ", "Food"], warmth: ["๐Ÿ”ฅ", "Firewood"], cloth const NEED_TIERS = { warmth: "Village", clothes: "Town" }; const pct = (x) => `${Math.round(x * 100)}%`; +const moodTrend = (h) => Math.abs(h.target - h.score) < .005 ? "Steady" : h.target > h.score ? "โ†— Growing" : "โ†˜ Falling"; + function moodStat() { const h = S.city.happiness; - const trend = Math.abs(h.target - h.score) < .005 ? "Steady" : `${h.target > h.score ? "โ†—" : "โ†˜"} ${h.heading}`; - return `
Mood ${h.icon}
-
${h.name}
${trend}
`; + return `
Mood ${h.icon}
+
${h.name}
${moodTrend(h)}
`; } function moodPanel() { @@ -2070,8 +2071,8 @@ function moodPanel() { const mods = h.mods.map((m) => `${esc(m.name)} ${m.value > 0 ? "+" : "โˆ’"}${pct(Math.abs(m.value))}`).join(""); const effects = [`๐ŸŒฑ Growth ${pct(e.growth)}`, `๐Ÿ›ก๏ธ Guards ${pct(e.militia)}`, `๐Ÿ”จ Labour ${pct(e.work)}`, `${COIN} Taxes ${pct(e.work)}`, ...(e.leave ? [`๐Ÿšถ ${pct(e.leave)} leave a day`] : [])]; - return `

${h.icon} Townsfolk ยท ${h.name}

-
+ return `

${h.icon} Townsfolk ยท ${h.name} ยท ${moodTrend(h)}

+
${effects.join(" ยท ")}
${needs}
${mods || locked ? `
${mods}${locked}
` : ""}
`; diff --git a/static/styles.css b/static/styles.css index 4d07b5d..1dbae87 100644 --- a/static/styles.css +++ b/static/styles.css @@ -879,10 +879,10 @@ button.swatch { width: 36px; height: 36px; } .qp-then .x { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 11px; padding: 0 2px; } /* Townsfolk mood */ -.mood-bar { position: relative; height: 12px; border-radius: 99px; margin: 4px 0 8px; - background: linear-gradient(90deg, #e2645c33, #e3a04333 40%, #5cbf6a33); } -.mood-bar > span { display: block; height: 100%; border-radius: 99px; background: var(--c); } -.mood-bar > i { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--text); border-radius: 2px; } +/* The whole bar is the red โ†’ yellow โ†’ green scale; the part above the mood is covered by the track. */ +.mood-bar { position: relative; height: 12px; border-radius: 99px; margin: 4px 0 8px; overflow: hidden; + background: linear-gradient(90deg, var(--bad), #e3c34a 50%, var(--good)); } +.mood-bar > span { position: absolute; top: 0; right: 0; bottom: 0; background: var(--bg); } .mood-effects { color: var(--muted); margin-bottom: 12px; } .needs { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); } .need-head { display: flex; justify-content: space-between; margin-bottom: 8px; }