# R6 complete root Frame cutover — retail pseudocode Date: 2026-07-19 Scope: the translation and orientation emitted by `CSequence` and consumed by `CPhysicsObj::UpdatePositionInternal`. This note replaces the former acdream split between animation root translation and command-derived/manual rotation. ## Named retail oracle - `Frame::combine` `0x005122E0` (`acclient_2013_pseudo_c.txt:280355`) - `Frame::set_rotate` `0x00535080` - `Frame::IsValid` `0x00534ED0` - `Position::subtract2` (complete relative Position/Frame) - `CPhysicsObj::UpdatePositionInternal` `0x00512C30` (`:280817`) - `CPhysicsObj::UpdateObjectInternal` `0x005156B0` - `CPhysicsObj::SetPositionInternal(CTransition const*)` `0x00515330` - `CPhysicsObj::change_cell` `0x00513390` - `CPhysicsObj::remove_shadows_from_cells` `0x00511230` - `CPhysicsObj::add_shadows_to_cells` `0x00514AE0` - `CPhysicsObj::update_object` `0x00515D10` - `CPhysicsObj::prepare_to_enter_world` `0x00511FA0` - `CPhysicsObj::set_active` `0x0050FC40` - `CPhysicsObj::animate_static_object` `0x00513DF0` - `CPhysics::UseTime` `0x00509950` (separate static-object loop) - `CPartArray::Update` `0x00517DB0` (`:285883`) - `add_motion` `0x005224B0` (`:298437`) - `CSequence::apply_physics` `0x00524AB0` (`:300955`) - `InterpolationManager::InterpolateTo` `0x00555B20` - `InterpolationManager::adjust_offset` `0x00555D30` The installed retail portal DAT is a second executable fixture. Motion table `0x09000001` (Humanoid), global `TurnRight` modifier `0x0000000D`, has `HasOmega` and literal omega `(0, 0, -1.5)` radians/second. It is not `-pi/2`, and it is not absent. The fixture is pinned by `HumanoidMotionTableRootMotionTests`. ACE cross-reference: `docs/research/2026-07-02-r2-motiontable/r2-ace-motiontable.md` records the ACE `MotionTable`/`Sequence` implementation: modifier lookup tries the styled key then the unstyled key, and `add_motion` writes `MotionData.Velocity * speed` plus `MotionData.Omega * speed`. ACE agrees with the named client here. Retail remains the ordering and transform oracle. ## Pseudocode ```text add_motion(sequence, motionData, speed): if motionData is null: return sequence.velocity = motionData.velocity * speed sequence.omega = motionData.omega * speed for animation in motionData.animations: sequence.append_animation(animation * speed) apply_physics(sequence, frame, magnitudeQuantum, signSource): signedQuantum = abs(magnitudeQuantum) if signSource < 0: signedQuantum = -signedQuantum frame.origin += sequence.velocity * signedQuantum frame.rotate(sequence.omega * signedQuantum) CPartArray.Update(dt, localFrame): sequence.update(dt, localFrame) CPhysicsObj.prepare_to_enter_world(now): update_time = now remove object and children from lost/destroy queues if not Static: transient_state.Active = true CPhysicsObj.update_object(now): if parent exists or cell is null or Frozen: transient_state.Active = false return without consuming update_time if player_object exists: player_vector = offset(player.position, object.position) player_distance = length(player_vector) if player_distance <= 96 world units or partArray is null: set_active(true) else: transient_state.Active = false // With no player_object, retain the prior Active state. elapsed = now - update_time if elapsed <= F_EPSILON or elapsed > HugeQuantum: update_time = now return while elapsed > MaxQuantum: UpdateObjectInternal(MaxQuantum) update_time += MaxQuantum elapsed -= MaxQuantum if elapsed > MinQuantum: UpdateObjectInternal(elapsed) update_time = now // A remainder at or below MinQuantum stays pending. CPartArray.InitDefaults(setup): if setup.DefaultAnimation != 0: sequence.clear_animations() sequence.append_animation( animation = setup.DefaultAnimation, low = 0, high = -1, framerate = 30) owner.InitDefaults(setup) CPhysicsObj.InitDefaults(setup): if setup.DefaultScript != 0: play_script_internal(setup.DefaultScript) install setup default motion/sound/physics-script tables if state has Static: if setup.DefaultAnimation != 0: state |= HasDefaultAnim if setup.DefaultScript != 0: state |= HasDefaultScript if state has HasDefaultAnim or HasDefaultScript: CPhysics.AddStaticAnimatingObject(this) CPhysicsObj.animate_static_object(now): if cell is null: return elapsed = now - update_time if elapsed <= F_EPSILON or elapsed > 2 seconds: update_time = now return if partArray exists: if state has HasDefaultAnim: partArray.Update(elapsed, null) // Retail passes the stored vector directly; no elapsed multiply. position.frame.grotate(angularVelocity) UpdatePartsInternal() UpdateChildrenInternal() if state has HasDefaultScript and scriptManager exists: scriptManager.UpdateScripts() if particleManager exists: particleManager.UpdateParticles() process_hooks() update_time = now CPhysics.UseTime(now): for object in ordinary object table: object.update_object(now) for object in static_animating_objects: object.animate_static_object(now) // These are separate ownership/workset paths. InitDefaults registers any // physics-Static object carrying Setup DefaultAnimation/DefaultScript, // including a server-created live object. CPhysicsObj.UpdatePositionInternal(dt, outputWorldFrame): localFrame = identity if not Hidden: if partArray exists: partArray.Update(dt, localFrame) if OnWalkable: localFrame.origin *= objectScale else: localFrame.origin *= 0 // Orientation is never cleared or scaled by this gate. if positionManager exists: positionManager.adjust_offset(localFrame, dt) outputWorldFrame = combine(position.frame, localFrame) if not Hidden: UpdatePhysicsInternal(dt, outputWorldFrame) process_hooks() Frame.combine(output, current, delta): output.origin = current.origin + rotate(current.orientation, delta.origin) output.set_rotate(current.orientation * delta.orientation) Frame.set_rotate(candidate): previous = orientation orientation = normalize(candidate) if not Frame.IsValid(): orientation = previous InterpolationManager.adjust_offset(delta, dt): if no Position node or body is not in Contact: return without mutating delta relative = Position.subtract2(target, current) relative.origin = clamp_to_catchup_distance(relative.origin, dt) if manager.keep_heading: relative.frame.set_heading(0) delta = relative.frame // replaces both origin and orientation CPhysicsObj.SetPositionInternal(transition): if transition.current_cell is null: prepare_to_leave_visibility() store_position(transition.current_position) object_maintenance.goto_lost_cell() clear Active return if current cell differs: change_cell(transition.current_cell) else: commit the new full objcell id to the object, PartArray, and children set_frame(transition.current_position.frame) commit contact plane, OnWalkable, sliding normal, and collision callbacks if transition has a non-empty crossed-cell array: remove_shadows_from_cells() add_shadows_to_cells(transition.cell_array) ``` The ordering consequence is important: a delta translates through the old orientation and only then applies its relative rotation. A large elapsed frame must run multiple complete object quanta in time order. A render fragment below the strict minimum does not advance CSequence at all; it stays in the object clock until a later admitted quantum. ## Port mapping - `MotionDeltaFrame.Combine` implements the retail composition and scales only the incoming origin. - One incarnation-stable `RetailObjectQuantumClock` is shared by local, remote, Hidden, and projectile components of each live object. It admits complete object quanta; the local animation callback writes one reusable `MotionDeltaFrame` only after admission. `prepare_to_enter_world` clears the retained fragment and immediately restores Active only for non-Static objects, so their next elapsed frame can run; Static objects retain the inactive state established by initialization/leave-visibility. It does not invent a second reactivation frame. - `CPartArray::InitDefaults` installs Setup DefaultAnimation for every setup-backed PartArray, independent of Static. Static controls only the additional `static_animating_objects -> animate_static_object` workset. Both DAT-hydrated statics and server-created objects whose final physics state is Static enter that workset when their Setup carries a DefaultAnimation. Default animation bypasses the MotionTable and installs the Setup animation directly over `0..last` at 30 frames/second. A short cell-less interval remains on the owner's clock and catches up after re-entry; an interval above two seconds is rebased and discarded. Script-only static owners still use acdream's shared PhysicsScriptRunner and are covered by TS-51 rather than entering an empty animation scan. A live static workset entry binds the exact PartArray and PhysicsBody already owned by its `LiveEntityRecord`; it never constructs a second sequencer or body. The raw angular-velocity vector is applied without multiplying by elapsed time, exactly as the named function does. A changed root commits the entity, effect pose, and multipart collision shadow together. Zero omega does not trigger a collision reflood, and a Hidden/nonresident object cannot have its suspended shadow restored by this animation path. - Animation hooks are captured after `UpdatePhysicsInternal` and before the transition/manager tail. Semantic `AnimationDone` executes there, matching `CPhysicsObj::process_hooks`. Other pose-dependent router sinks remain deferred until final root/part/equipped-child pose publication; that known residual is registered as TS-50 rather than claimed as exact ordering. Static owners retain their semantic hook tail until final root, part, and attached-child publication, matching `animate_static_object`'s later `process_hooks` call. A residency change invalidates both the prepared pose and that pending tail. - Retail session dispatch and `CPhysics::UseTime` are single-threaded FIFO operations. App therefore wraps complete packet and object-frame operations in `RetailInboundEventDispatcher`: a callback-triggered packet queues behind the current operation instead of recursively interleaving with its tail. Position, State, Vector, and Movement keep separate authority versions; Position/Vector/Movement additionally share only a velocity-write version. Never replace these with one global body-mutation token: that incorrectly discards independent accepted channels (for example State during Position). The direct packet/frame path carries state into a cached static callback and allocates nothing; only genuinely nested work receives a retained FIFO node. - Projectile `BeginQuantum` is candidate-only. It restores the canonical begin frame/dynamics before returning; `CompleteQuantum` may commit only while the exact live record, projectile runtime, entity, spatial owner, and prediction version remain current. Any accepted Position, Vector, or State invalidates the candidate without rolling back the authoritative mutation. - Animation-hook batches capture the pose owner's monotonic lifetime before running semantic AnimationDone. Capture rechecks it before every completion, and drain rechecks that lifetime and root pose before every routed hook, because either AnimationDone or an earlier sink can delete the owner and reuse the same local ID synchronously. - Remote animation advances into one reusable DAT `Frame`; both components are passed to `RemotePhysicsUpdater` and applied through the same `PositionManager` frame. - A body-backed animated object without a MovementManager now commits its complete Frame through `LiveEntityOrdinaryPhysicsUpdater`: root translation is admitted only while OnWalkable, orientation remains live, the resulting candidate runs through Transition/SetPositionInternal, and the same record is rebucketed without recreating resources. Callback deletion/replacement is revalidated before every commit. - The resolved body and `WorldEntity` root/full-cell frame are committed before the canonical rebucket callback, matching SetPositionInternal's frame/contact commit before its final shadow replacement. A loaded-to-pending rebucket (or same-GUID replacement during its visibility callback) invalidates the caller before shadow or manager-tail publication. Non-projectile shadow residency is symmetric in `LiveEntityPresentationController`, including the pending-first case whose initial false edge precedes collision registration; projectiles retain their dedicated residency owner. - Local projection and both authoritative remote UpdatePosition tails use the same post-rebucket exact-owner gate. Remote collision refresh is forced by a cell change or by a changed complete pose (translation or sign-invariant quaternion), so offset/multipart Setup shapes rotate in place and a same-pose cell crossing cannot retain an old flood seed. - A retained projectile remains the same CPhysicsObj when Missile clears. With no MovementManager it continues through the ordinary one-sphere transition owner; with a MovementManager the owner transfers exactly once to remote motion. Projection re-entry restores its retained collision shadow on the visibility edge, before any later simulation quantum. - Active interpolation preserves the target's complete quaternion and replaces the PartArray Frame. The already-close `InterpolateTo` branch applies only the target heading, matching `CPhysicsObj::set_heading`. `keep_heading` is manager-wide, not a per-node flag; each near enqueue replaces it. - `FrameOps.SetRotate` rejects zero, non-finite, and otherwise invalid quaternion candidates by restoring the prior orientation. - Spawn, teleport, correction, and outbound movement/position serialization read the authoritative body quaternion directly; none round-trips through the horizontal `Yaw` projection. - `MotionTableDispatchSink` only dispatches motion-table commands. It no longer reports turn callbacks. - `RemoteMotion.ObservedOmega`, the player/NPC multiplication-order fork, and `AnimationSequencer.SetCycle`'s synthetic `pi/2` turn omega are deleted. - A controller deliberately constructed without a `PartArray` retains a Humanoid-only fallback at the DAT-pinned `1.5` radians/second. A normal GUI client does not enter that path. ## Conformance gates - `MotionDeltaFrameTests`: exact `FrameOps.Combine` equivalence, scale affects origin only, and temporal turn-then-move composition. - `RetailObjectQuantumClockTests`: strict bounds, retained remainder, MaxQuantum subdivision, HugeQuantum discard, `set_active` rebasing, and Static-aware `prepare_to_enter_world` reset. - `RetailObjectActivityGateTests` and `LiveEntityRuntimeTests`: the 96-unit PartArray gate, parent/cell/Frozen suspension, loaded rebucket retention, pending re-entry rebasing, body/clock Active synchronization, and GUID-reuse clock isolation. - `LiveEntityAnimationSchedulerTests`: the canonical live-object workset also advances objects without a render animation, consumes their queued near UpdatePosition correction, applies complete generic root Frames, transfers a retained missile body exactly once when classification clears, and stops catch-up immediately when a callback deletes, withdraws, or replaces an incarnation. - `RetailStaticAnimatingObjectSchedulerTests` and `AnimationSequencerTests`: unconditional Setup DefaultAnimation installation, DAT/live physics-Static workset membership, direct 30-fps playback, short-residency-gap catch-up, canonical PartArray/body reuse, raw (not elapsed-scaled) omega, synchronized multipart shadow rotation, zero-omega no-op commits, callback-safe removal, and the retail greater-than-two-second discard. `StaticLiveRootCommitter` coverage proves Hidden omega cannot resurrect a suspended shadow. - `RemoteInboundMotionDispatcherTests`: one animation-optional owner preserves retail packet-head/style/type-0/sticky ordering with a null PartArray sink; unknown movement types execute the head and never enter the case-0 funnel; supersession during interrupt prevents every later packet side effect. - `LiveEntityOrdinaryPhysicsUpdaterTests`: complete root Frames cross cells and landblocks through Transition, while hook-side deletion prevents stale body, shadow, pose, or spatial commits. - `ProjectileControllerTests`: pending-cell hydration restores the same body's Active/InWorld/shadow residency immediately and does not replay logical creation; the destination cell is canonical before suspension and after hydration, and authoritative Position/Vector/State between prediction halves discards only the stale candidate. - `RetailInboundEventDispatcherTests`, `LiveEntityPresentationControllerTests`, `RemoteTeleportControllerTests`, and `EntityEffectPoseRegistryTests`: nested packet arrival drains after the complete older tail, independent State and Position both survive resolver callbacks, newer Position supersedes older placement, Hidden-to-Visible recursion remains FIFO, and hook batches cannot cross deletion/local-ID reuse during capture or drain. The FIFO's nonnested state path is pinned at zero allocations after warmup. - `PlayerMovementControllerTests`: full-frame local composition, large-frame equivalence, hidden/airborne gates, hook cadence, and proof that animation-backed turns are not integrated twice. - `InterpolationManagerTests`: complete relative target orientation, keep-heading, and already-close heading-only behavior. - `RemotePhysicsUpdaterTests` and `LiveEntityPresentationControllerTests`: translation uses the pre-turn orientation and the same frame then rotates the body; cross-cell loaded-to-pending commits the destination root before the callback boundary, suspends rather than re-adds collision, restores on hydration, and isolates old shadows across callback GUID reuse. Direct authoritative rebuckets and initial-pending materialization cover the same symmetric collision-residency contract; same-position rotation and cell-only changes refresh collision while unchanged/sign-flipped quaternion poses do not reflood. - `LiveEntityRuntimeTests`: update iteration and render-ID classification copy only concrete spatial animation owners through reusable storage with zero steady-state allocations. - `MotionTableDispatchSinkTests`: Branch-4 turn preserves the locomotion cycle, contributes literal DAT omega, and unwinds on stop. - `RemoteChaseEndToEndHarnessTests`: turn, chase, re-arm, action completion, and sticky following run through the complete Frame plus retail manager tail. - `HumanoidMotionTableRootMotionTests`: installed retail walk displacement and exact Humanoid `TurnRight` omega `-1.5` radians/second. - `MovementManagerTests` and `PlayerMovementControllerTests`: `PerformMovement` invokes `set_active(1)` before request validation, while a Static physics object preserves retail's no-op activation behavior. ## Registered residual The ordinary/static object worksets and their root/animation clocks are now retail-shaped, but acdream's shared particle and PhysicsScript managers still advance once per render frame after every owner has run. Retail advances those tails inside each admitted object update (and inside `animate_static_object`). This timing difference is deliberately registered as TS-51; it is not part of the R6 conformance claim. Final automated gate (2026-07-20): three independent retail-conformance, architecture/integration, and adversarial re-reviews reported no actionable finding after correction; Release build completed with zero warnings; the full solution passed 6,446 tests with 5 intentional skips.