Dungeons: run on while anyone watches

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-27 21:49:49 +00:00
parent 13371ec269
commit 25ecb885f5
2 changed files with 29 additions and 12 deletions

20
game.py
View file

@ -1008,7 +1008,7 @@ COMBAT_ACTIONS = [
# cast what has to be interrupted, hit what has to be braced for, call in help, and lose patience.
DUNGEON_SIZE = 4 # the most in a run
DUNGEON_WIPES = 3 # on one pull, and the run is over
DUNGEON_AWAY = 90 # real seconds without looking before a run waits for you
DUNGEON_AWAY = 90 # real seconds without looking before you count as away (a run waits if everyone is)
TRASH = (1.5, 1.5) # a pull's HP (and XP) and hits against the open world's
MINI_BOSS = 5.0 # a mini-boss's HP (and XP, and loot odds) against its race's elite
FINAL_BOSS = (2.5, 1.3) # the area boss's (and its adds') HP and hits against the open-world one
@ -3476,9 +3476,9 @@ def process_party(world: dict, pid: str, now: float, rng: random.Random) -> None
break
members = [world["players"][uid] for uid in party["members"]]
if action.get("dungeon"):
# A run waits for its leader to start it, then for anyone who's looked away: it's played together.
away = [p for p in members if p["last_active"] < party["start"] - DUNGEON_AWAY]
if "run" not in party or away:
# A run waits for its leader to start it, then for someone to be watching. Whoever's
# looked away fights on auto.
if "run" not in party or run_away(world, party):
party["start"] = max(party["start"], now)
for player in members:
player["action"]["start"] = party["start"]
@ -3593,6 +3593,12 @@ def _clear_bonus(world: dict, player: dict, spec: dict, now: float, rng: random.
summary["items"][item] = summary["items"].get(item, 0) + kept
def run_away(world: dict, party: dict) -> list:
"""Everyone in the run, if no one's been looking: it waits for one of them to come back."""
members = [world["players"][uid] for uid in party["members"]]
return members if all(p["last_active"] < party["start"] - DUNGEON_AWAY for p in members) else []
def run_of(world: dict, player: dict) -> dict | None:
"""Where your group's dungeon run stands, if you're in one."""
party = party_of(world, player)
@ -3600,10 +3606,9 @@ def run_of(world: dict, player: dict) -> dict | None:
return None
spec = DUNGEONS[ACTION_BY_ID[party["action"]]["dungeon"]]
run = party.get("run", {"pull": 0, "wipes": 0})
away = [world["players"][uid]["name"] for uid in party["members"]
if world["players"][uid]["last_active"] < party["start"] - DUNGEON_AWAY]
return {"dungeon": spec["name"], "pull": run["pull"] + 1, "of": len(spec["pulls"]), "wipes": run["wipes"],
"next": spec["pulls"][min(run["pull"], len(spec["pulls"]) - 1)][0], "away": away,
"next": spec["pulls"][min(run["pull"], len(spec["pulls"]) - 1)][0],
"away": [p["name"] for p in run_away(world, party)],
"leader": party["members"][0], "size": len(party["members"]), "started": "run" in party}
@ -6275,6 +6280,7 @@ ORDER_RECIPES, ORDER_RAW = _order_sources()
# line here (new / balance / fix), and a new release a new entry on top.
PATCH_NOTES = [
{"date": "2026-10-27", "title": "Prayer", "notes": [
("new", "Dungeons: runs go on while anyone is watching. Members who look away fight on auto."),
("new", "Group stays in lobby after finishing dungeon"),
("new", "Added \"Drink all\" option to potions in the bank."),
("new", "Firekeeping: Tend all fires. Each log goes on the lowest fire with room in your pile."),