diff --git a/app.py b/app.py index 78a7011..5f4b7de 100644 --- a/app.py +++ b/app.py @@ -330,6 +330,14 @@ class Handler(BaseHTTPRequestHandler): return "There's no raid to stand guard for" player["garrison"] = bool(body.get("join")) return None + if path == "/api/board/delete": + message = next((m for m in world["board"] if m.get("id") == body.get("id")), None) + if not message: + return "That message is gone" + if message["who"] != player["id"]: + return "You can only delete your own messages" + world["board"].remove(message) + return None if path == "/api/aid": return game.aid_problem(world, player, str(body.get("kind")), str(body.get("item")), str(body.get("source")), now) if path == "/api/hire": @@ -358,7 +366,8 @@ class Handler(BaseHTTPRequestHandler): text = str(body.get("text", "")).strip()[:500] if not text: return "Say something" - world["board"].append({"at": now, "who": player["id"], "text": text}) + world["next_message_id"] = world.get("next_message_id", 1) + 1 + world["board"].append({"id": world["next_message_id"] - 1, "at": now, "who": player["id"], "text": text}) del world["board"][:-game.MAX_LOG] return None return "Not found" diff --git a/game.py b/game.py index 7751b97..b797899 100644 --- a/game.py +++ b/game.py @@ -496,7 +496,7 @@ RAID_TRAITS = ["lightly armoured, heavy on archers", "mounted and fast, few bows # --- world --------------------------------------------------------------- -WORLD_VERSION = 8 +WORLD_VERSION = 9 def new_world(now: float, speed: float = 1.0) -> dict: @@ -528,6 +528,7 @@ def new_world(now: float, speed: float = 1.0) -> dict: "next_event_id": 1, "ledger": [], "board": [], + "next_message_id": 1, } @@ -592,6 +593,12 @@ def migrate(world: dict, now: float | None = None) -> dict: world.setdefault("next_hardship_at", now + 24 * HOUR / speed(world)) world.setdefault("next_fortune_at", now + 8 * HOUR / speed(world)) world["version"] = 8 + if world["version"] < 9: + # Board messages get ids so their authors can delete them. + for number, message in enumerate(world["board"], 1): + message["id"] = number + world["next_message_id"] = len(world["board"]) + 1 + world["version"] = 9 return world diff --git a/static/app.js b/static/app.js index c4ecd07..2183bda 100644 --- a/static/app.js +++ b/static/app.js @@ -471,7 +471,7 @@ function actionCard(a) { if (a.skill === "combat") { const chance = Math.min(0.97, Math.max(0.15, 0.5 + (me.power - a.difficulty) * 0.04)); extra = `
Win chance ${Math.round(chance * 100)}% · about ${me.fight_damage[a.id]} damage a fight${a.gold ? ` · ${a.gold} gold` : ""}
`; - if (a.drops) io += a.drops.map(([id, q, odds]) => `${item(id).icon} ${q} ${Math.round(odds * 100)}%`).join(""); + if (a.drops) io += a.drops.map(([id, q, odds]) => `${item(id).icon} ${q} ${Math.round(odds * 100)}%`).join(""); if (a.special === "sabotage") extra += `
Each win weakens the coming raid by 3%, up to 30%.
`; } if (a.special === "recon") extra = `
+${a.recon} recon on the next event
`; @@ -818,7 +818,9 @@ function raidPrep(ev) { // --- board & roster ------------------------------------------------------- function board() { - const msgs = S.board.map((m) => `
${esc(playerName(m.who))}${ago(m.at)}
${esc(m.text)}
`).join(""); + const msgs = S.board.map((m) => `
${esc(playerName(m.who))}${ago(m.at)} + ${m.who === S.uid && m.id ? `` : ""} +
${esc(m.text)}
`).join(""); const ledger = [...S.ledger].reverse().map((l) => `
  • ${esc(l.text)}${ago(l.at)}
  • `).join(""); return `

    Town board

    @@ -1000,6 +1002,10 @@ document.addEventListener("click", (e) => { if (d.favour) return act("/api/favour", { kind: d.favour }); if (d.food) return act("/api/food", { item: d.food }); if (d.potion) return act("/api/potion", { item: d.potion }); + if (d.unpost) { + if (!confirm("Delete this message?")) return; + return act("/api/board/delete", { id: Number(d.unpost) }); + } if (d.aid) return act("/api/aid", { kind: d.aid, item: d.item, source: d.source }); if ("hire" in d) return act("/api/hire", {}); if (d.devHappen) return act("/api/dev/happen", { track: d.devHappen }); diff --git a/static/styles.css b/static/styles.css index 5f50fa1..83e0111 100644 --- a/static/styles.css +++ b/static/styles.css @@ -395,3 +395,5 @@ button.sheet-skill:hover { background: var(--panel-2); } .happening .grow { display: flex; flex-direction: column; gap: 4px; } .happening > .btn, .happening > .small { align-self: center; } .skill-happenings { flex-direction: column; align-items: flex-start; gap: 4px; } +.msg-delete { background: none; border: 0; color: var(--muted); padding: 0 4px; margin-left: 4px; font-size: 12px; } +.msg-delete:hover { color: var(--bad); }