namespace Outnumbered; // Per-player survival run state. RAM-only, never persisted; cleared on run end / disconnect (no mid-run reconnect-restore). // Implements IStatBonusSource so it IS the PlayerSnapshot.Cards source (no per-hit adapter allocation). Bonus resolves the // card def LIVE via the injected lookup, so !og_reload PerPick edits take effect immediately. (The wave state machine // [SurvivalDriver] + the plugin-side survival helpers live in Survival.cs.) public sealed class SurvivalRun(Func cardDef) : Domain.IStatBonusSource { private readonly Func _cardDef = cardDef; public double WaveXp { get; set; } // raw combat XP banked THIS wave (granted + reset at wave clear; forfeited on a wipe/leave mid-wave) public int RunPoints { get; set; } // unspent draft picks public Dictionary Cards { get; } = []; // card key -> times picked (get-only: the ref is fixed, the contents mutate) public List DrawnThisBreak { get; set; } = []; // the current offered draw (stable across reopen within a break) // Per-stat run bonus = picks x PerPick (live def). 0 for any key without picks. (Team cards are squad-wide and folded // into MDeal/MTake, NOT per-player here — they're keyed on the driver's shared counters, not run.Cards.) public double Bonus(string statKey) { if (!Cards.TryGetValue(statKey, out int picks) || picks <= 0) return 0.0; var def = _cardDef(statKey); return def is null ? 0.0 : picks * def.PerPick; } }