namespace AcDream.Core.Physics.Motion; /// /// Campaign P P5 (#167 / register TS-35) — retail /// CPhysicsObj::GetStartConstraintDistance (0x0050ebc0) and /// GetMaxConstraintDistance (0x0050ec10): the leash's start/max band, /// keyed by whether the object's OWN current cell is outdoor or indoor. /// /// Byte-decoded, not guessed — BN elided both getters' return /// value as a bare this->m_position; expression (the classic x87 /// FPU-return decompile artifact). The actual values were recovered by /// disassembling the matching binary's raw machine code (see /// docs/research/2026-07-30-constraint-leash-constants.md §1): /// outdoor start = 10.0, indoor start = 5.0; outdoor max = /// 50.0, indoor max = 20.0. Indoor is decided by the object's /// full cell id's low 16 bits: >= 0x0100 = EnvCell (indoor). /// /// The retail player-vs-remote branch is INTENTIONALLY OMITTED. /// The disassembly shows both getters branch on this == player_object /// AND load byte-identical constants either way — the branch is vestigial /// (both sides return the same four numbers). Porting that dead branch would /// only add a phantom "is this the player" parameter with zero behavioral /// effect, so this class keys purely on the object's own cell id. /// /// ACE-inversion pin. ACE's PhysicsObj.GetStartConstraintDistance /// (PhysicsObj.cs:620) maps outdoor → 5, indoor → 10 — the OPPOSITE of /// the binary. ACE's max mapping (outdoor 50 / indoor 20) matches. Do not /// "fix" this class to match ACE's start mapping; the disassembly is the /// oracle here (feedback_acme_oracle: binary wins over ACE on disagreement). /// /// public static class ConstraintDistance { private const float OutdoorStart = 10.0f; private const float IndoorStart = 5.0f; private const float OutdoorMax = 50.0f; private const float IndoorMax = 20.0f; /// Retail cmp eax, 0x100; jae indoor on the object's own /// m_position.objcell_id & 0xFFFF — low 16 bits ≥ 0x0100 is an /// EnvCell (indoor); below that is an outdoor landblock cell index. public static bool IsIndoorCell(uint objCellId) => (objCellId & 0xFFFFu) >= 0x0100u; /// Retail CPhysicsObj::GetStartConstraintDistance /// (0x0050ebc0) — the near edge of the leash's brake band, keyed by the /// object's own current cell. public static float GetStartConstraintDistance(uint objCellId) => IsIndoorCell(objCellId) ? IndoorStart : OutdoorStart; /// Retail CPhysicsObj::GetMaxConstraintDistance /// (0x0050ec10) — the far edge (full clamp), keyed by the object's own /// current cell. public static float GetMaxConstraintDistance(uint objCellId) => IsIndoorCell(objCellId) ? IndoorMax : OutdoorMax; }