class_name StatusCatalog ## Static factory registry for named statuses. ## ## Mirrors ThoughtCatalog: each factory returns a fresh Status with all fields ## set correctly. Callers must not mutate the returned object before passing ## it to Pawn.add_status() — add_status() handles severity stack-merging. ## ## Phase 9 ships: bleeding(), downed(). ## Phase 12 will add: wet(), cold(). ## Phase 17 will add: sick(), infected(). ## ## Usage pattern: ## pawn.add_status(StatusCatalog.bleeding(2)) ## ## docs/design.md "Health & status effects"; docs/design.md "Downed & death". ## Sim ticks before an untreated bleed-out causes death. ## design.md "Downed & death": 6 in-game hours. ## At 20 Hz × 60 s/min × 60 min/hr × 6 hr = 432 000 ticks at 1×. ## At Fast (5×) that compresses to ~86 400 real-Hz-ticks — but game time is ## what the player sees, so this constant is in game-time-equivalent ticks ## (the same 20-Hz tick stream; speed multiplier compresses the real clock, ## not the tick count that this timer counts against). ## Phase 20 may retune; keeping the name locked from day one per design.md. const BLEED_OUT_TICKS: int = 432000 # 6 in-game hours at 20 Hz ## HP lost per sim tick per severity level. ## Severity 1: 0.05 / tick. Severity 3: 0.15 / tick. ## At severity 3, 100 HP → 0 in 100 / 0.15 = ~667 ticks ≈ 33 sim-seconds at 1×. ## At Fast (5×) real time: ~7 s. Tune Phase 20. const BLEED_HP_PER_TICK: float = 0.05 ## Returns a Bleeding status at the given severity (1–3). ## Severity is clamped to [1, 3]. Lifetime is PERSISTENT — cleared by doctor ## treatment, not by time expiry. static func bleeding(severity: int = 1) -> Status: var s := Status.new() s.id = &"bleeding" s.kind = Status.Kind.BLEEDING s.label = "Bleeding" s.severity = clampi(severity, 1, 3) s.max_severity = 3 s.lifetime = Status.Lifetime.PERSISTENT return s ## Returns a Downed status. ## Downed has severity 1 (single-instance — you're either down or you're not). ## Cleared externally by Pawn._check_revive() when HP rises to HP_REVIVE_THRESHOLD. static func downed() -> Status: var s := Status.new() s.id = &"downed" s.kind = Status.Kind.DOWNED s.label = "Downed" s.severity = 1 s.max_severity = 1 s.lifetime = Status.Lifetime.PERSISTENT return s