Multi-instancing migration (Step 8 — forcing function): delete the static per-battle fallbacks the earlier ambient-* patches added as a coexistence shim. With the fallbacks gone, any unwrapped engine call into IsForecast/IsRandomDraw fails fast (BattleAmbient.Require() throws InvalidOperationException); GetIns soft-returns null when no scope is active so engine code that patterns `GetIns()?.Foo ?? default` keeps composing (per design — strict for setters / load-bearing reads, soft for the GetIns null-tolerant chain). Supersedes the intermediate .ambient-isforecast-israndomdraw + .ambient-main-getins patches (kept for the audit trail). Semantics chosen per accessor: - IsForecast : get/set both BattleAmbient.Require() — strict (must be in a scope) - IsRandomDraw : get/set both BattleAmbient.Require() — strict - GetIns() : Current?.Mgr — soft (null when no scope; preserves engine `?.` patterns) - ctor : `_mainFallback = this` line deleted entirely - DisposeManager: `_mainFallback = null` line deleted entirely In-file edits: - line ~413 declaration `private static BattleManagerBase _mainFallback;` DELETED - lines ~415-432 the four fallback statics + their if-else fallback branches DELETED, replaced with strict get/set via BattleAmbient.Require() - line ~727 GetIns() body -> Current?.Mgr (no fallback) - line ~732 ctor `_mainFallback = this` DELETED (no longer needed; ambient.Mgr is published explicitly from SessionBattleEngine.SetupInternal after construction) - line ~1491 dispose `_mainFallback = null` DELETED (the matching scope drop replaces it) --- Engine/BattleManagerBase.cs (~lines 413-433) - private static BattleManagerBase _mainFallback; - - private static bool _isRandomDrawFallback = false; - public static bool IsRandomDraw { - get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.IsRandomDraw ?? _isRandomDrawFallback; - set { - var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current; - if (c != null) c.IsRandomDraw = value; - else _isRandomDrawFallback = value; - } - } - - private static bool _isForecastFallback = false; - public static bool IsForecast { - get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.IsForecast ?? _isForecastFallback; - set { - var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current; - if (c != null) c.IsForecast = value; - else _isForecastFallback = value; - } - } + public static bool IsRandomDraw { + get => SVSim.BattleEngine.Ambient.BattleAmbient.Require().IsRandomDraw; + set => SVSim.BattleEngine.Ambient.BattleAmbient.Require().IsRandomDraw = value; + } + + public static bool IsForecast { + get => SVSim.BattleEngine.Ambient.BattleAmbient.Require().IsForecast; + set => SVSim.BattleEngine.Ambient.BattleAmbient.Require().IsForecast = value; + } --- Engine/BattleManagerBase.cs (~line 727) public static BattleManagerBase GetIns() { - return SVSim.BattleEngine.Ambient.BattleAmbient.Current?.Mgr ?? _mainFallback; + // Soft read: returns null when no scope is active, preserving engine call sites that + // pattern `GetIns()?.Foo ?? default`. Inside a scope, returns the scope's Mgr (which may + // itself be null mid-Setup — see SessionBattleEngine.SetupInternal, which publishes Mgr + // before WireMulliganPhase). + return SVSim.BattleEngine.Ambient.BattleAmbient.Current?.Mgr; } --- Engine/BattleManagerBase.cs (~line 732) protected BattleManagerBase(IBattleMgrContentsCreator contentsCreator) { - _mainFallback = this; BattleLifeTimeSharedObject = new BattleLifeTimeSharedObject(); --- Engine/BattleManagerBase.cs (~line 1491) GameMgr.GetIns().GetPrefabMgr().AllUnLoad(); - _mainFallback = null; }