Raid replay plays like a fight; fight-once can be joined
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4f2d113abd
commit
387f4c201b
4 changed files with 513 additions and 112 deletions
50
game.py
50
game.py
|
|
@ -3090,16 +3090,9 @@ def process_player(world: dict, player: dict, now: float, rng: random.Random | N
|
|||
current["turn"] = 1 - current.get("turn", 0)
|
||||
if player["action"] is current and "left" in current:
|
||||
current["left"] -= 1
|
||||
if current["left"] <= 0:
|
||||
back = current.get("resume")
|
||||
if back:
|
||||
plot2 = current.get("resume_plot2")
|
||||
player["action"] = current = {"id": back, "start": current["start"]}
|
||||
if plot2:
|
||||
current.update(plot2=plot2, turn=0)
|
||||
summary["resumed"] = back
|
||||
else:
|
||||
stop(player)
|
||||
if current["left"] <= 0 and finish_once(player, current["start"]):
|
||||
current = player["action"]
|
||||
summary["resumed"] = current["id"]
|
||||
if player["action"] is current and "enemy" not in action and not current.get("plot2"):
|
||||
# Out of materials: stop now, not once the next bar has filled.
|
||||
reason = can_start(world, player, growing(player))
|
||||
|
|
@ -3117,6 +3110,19 @@ def stop(player: dict, reason: str | None = None) -> None:
|
|||
player["stopped"] = reason
|
||||
|
||||
|
||||
def finish_once(player: dict, at: float, reason: str | None = None) -> bool:
|
||||
"""A one-off is done: back to what you were doing before (True), or stop."""
|
||||
current = player["action"]
|
||||
back = current.get("resume")
|
||||
if not back:
|
||||
stop(player, reason)
|
||||
return False
|
||||
player["action"] = {"id": back, "start": at}
|
||||
if current.get("resume_plot2"):
|
||||
player["action"].update(plot2=current["resume_plot2"], turn=0)
|
||||
return True
|
||||
|
||||
|
||||
def drop_out(world: dict, player: dict, now: float, reason: str | None = None) -> None:
|
||||
"""Stop, stepping out of a shared fight if you're in one."""
|
||||
current = player["action"]
|
||||
|
|
@ -3180,7 +3186,7 @@ def offline_limit(world: dict, player: dict) -> float:
|
|||
def joinable(world: dict, player: dict) -> bool:
|
||||
"""Whether someone's fight is one others can tag into."""
|
||||
current = player["action"]
|
||||
if not current or "left" in current or "order" in current:
|
||||
if not current or "order" in current:
|
||||
return False
|
||||
action = ACTION_BY_ID[current["id"]]
|
||||
if action.get("dungeon"):
|
||||
|
|
@ -3309,9 +3315,9 @@ def process_party(world: dict, pid: str, now: float, rng: random.Random) -> None
|
|||
if world["parties"].get(pid) is not party:
|
||||
break # the last of them carries on alone, and picks up when they're back
|
||||
at = max(party["start"], offline_limit(world, player))
|
||||
wind = {"wind_used": True} if player["action"].get("wind_used") else {}
|
||||
keep = {k: v for k, v in player["action"].items() if k in ("wind_used", "left", "resume", "resume_plot2")}
|
||||
leave_party(world, player, pid, at)
|
||||
player["action"] = {"id": action["id"], "start": at, **wind}
|
||||
player["action"] = {"id": action["id"], "start": at, **keep}
|
||||
continue
|
||||
if end > now:
|
||||
break
|
||||
|
|
@ -3336,6 +3342,15 @@ def process_party(world: dict, pid: str, now: float, rng: random.Random) -> None
|
|||
for other in members:
|
||||
if other is not player:
|
||||
together[other["name"]] = together.get(other["name"], 0) + 1
|
||||
current = player["action"]
|
||||
if not action.get("dungeon") and "left" in current:
|
||||
# Fought once: step out, and back to what you were doing. The rest carry on.
|
||||
current["left"] -= 1
|
||||
if current["left"] <= 0:
|
||||
if world["parties"].get(current.get("party")) is party:
|
||||
leave_party(world, player, pid, end)
|
||||
if finish_once(player, end):
|
||||
summary["resumed"] = player["action"]["id"]
|
||||
if action.get("dungeon") and world["parties"].get(pid) is party:
|
||||
_advance_run(world, party, action, fight, members, end, rng)
|
||||
|
||||
|
|
@ -3382,8 +3397,11 @@ def _advance_run(world: dict, party: dict, action: dict, fight: dict, members: l
|
|||
log(world, now, "party", f"{names}: {reason.lower()} in {spec['name']}")
|
||||
del world["parties"][party["id"]]
|
||||
for player in members:
|
||||
stop(player, reason)
|
||||
player.setdefault("away", empty_summary())["stopped"] = reason
|
||||
summary = player.setdefault("away", empty_summary())
|
||||
if finish_once(player, now, reason):
|
||||
summary["resumed"] = player["action"]["id"]
|
||||
else:
|
||||
summary["stopped"] = reason
|
||||
|
||||
|
||||
def _clear_bonus(world: dict, player: dict, spec: dict, now: float, rng: random.Random) -> None:
|
||||
|
|
@ -6074,6 +6092,8 @@ PATCH_NOTES = [
|
|||
("fix", "Resting in a group: everyone heals at their own pace, so good food tops you up first. The pull still "
|
||||
"waits for the slowest, and Pull now sends each in as healed as they really are."),
|
||||
("new", "DPS meter under the combat log: damage per second and total for each fighter, live. Shows the last fight while resting."),
|
||||
("new", "Improved raid UI"),
|
||||
("fix", "Bugfix: Combats started using \"Fight once\" can now be joined."),
|
||||
]},
|
||||
{"date": "2026-10-24", "title": "Dungeon loot", "notes": [
|
||||
("new", "Masterwork patterns: every dungeon boss can drop one of 7 (15% from a mini-boss, 35% from the last boss, "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue