Multi-instancing migration (Step 4): convert Cute.Certification.ViewerId — the per-battle "who is the local seat" identity — to resolve through BattleAmbient.Current when a scope is active, falling back to the legacy SavedataManager-backed static when not. The old `viewer_id` backing field is renamed to `_viewerIdFallback` so unwrapped callers (real client, in-process unit tests without a BattleAmbient scope) keep the original lazy-load-from-savedata + write- through-savedata behavior bit-for-bit; scoped callers get a per-AsyncLocal id without writing to savedata (design 2026-06-07-engine-multi-instancing, Task 4). Inside a scope the setter is a NO-OP: ViewerId is an init-time identity (it's set at scope entry via `new BattleAmbientContext { ViewerId = ... }`'s init-only property), and swallowing the write avoids any in-battle setter from mutating sibling-battle perspective. The fallback setter preserves the original sequence exactly: SetInt + Save + assign backing field. In-file references (3 total) handled as follows: - line 19 declaration → renamed to `_viewerIdFallback` - line 41 ViewerId property → ambient-first getter; setter swallows when scoped - line 147 InitializeFileds → resets the renamed `_viewerIdFallback` External reflection follow-up (NOT in this patch — separate edit, same commit): SVSim.BattleNode/Sessions/Engine/EngineGlobalInit.cs (~line 154) reads the private field by name to seed the headless "who am I" perspective. Renamed there from "viewer_id" to "_viewerIdFallback" to match. --- Engine/Cute/Certification.cs (~line 19) - private static int viewer_id; + private static int _viewerIdFallback; --- Engine/Cute/Certification.cs (~lines 41-57) public static int ViewerId { get { - if (viewer_id == 0) + var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current; + if (c != null) return c.ViewerId; + if (_viewerIdFallback == 0) { - viewer_id = Toolbox.SavedataManager.GetInt("VIEWER_ID"); + _viewerIdFallback = Toolbox.SavedataManager.GetInt("VIEWER_ID"); } - return viewer_id; + return _viewerIdFallback; } set { + var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current; + if (c != null) + { + // Inside a scope, ViewerId is fixed at scope entry — swallow the write. + return; + } Toolbox.SavedataManager.SetInt("VIEWER_ID", value); Toolbox.SavedataManager.Save(); - viewer_id = value; + _viewerIdFallback = value; } } --- Engine/Cute/Certification.cs (~line 147, InitializeFileds) - viewer_id = 0; + _viewerIdFallback = 0;