From 0f59db18e84d9eaeaaa6c84b2ca60685767de46b Mon Sep 17 00:00:00 2001 From: MarcelineVQ Date: Sat, 7 Mar 2026 10:42:01 -0800 Subject: [PATCH] Fix marker position snapping to terrain chunk grid UpdateWorldPosition (called during entity creation) snaps X/Y to the terrain chunk grid, causing markers to appear offset from the requested position. After creation, re-apply the exact position via SetUnitPositionAndOrientation (0x698e20) to override the grid snap. --- src/markers/markers.zig | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/markers/markers.zig b/src/markers/markers.zig index e01d1fd..a0174b3 100644 --- a/src/markers/markers.zig +++ b/src/markers/markers.zig @@ -457,6 +457,12 @@ fn spawnEntity(index: usize, pos: Vec3) bool { return false; }; + // UpdateWorldPosition (called by createEntityInstance with updateNow=1) snaps + // the position to the terrain chunk grid, modifying the position array in place. + // Re-apply the exact position via SetUnitPositionAndOrientation to override the snap. + position = [3]f32{ pos.x, pos.y, pos.z + MARKER_Z_OFFSET }; + setUnitPositionAndOrientation(obj, &position, 0.0); + marker_entities[index] = obj; marker_created_tick[index] = GetTickCount(); hold_queued[index] = false; @@ -467,6 +473,20 @@ fn spawnEntity(index: usize, pos: Vec3) bool { return true; } +/// SetUnitPositionAndOrientation - __fastcall(ECX=positionData, EDX=pos), 1 stack param. +fn setUnitPositionAndOrientation(entity: *anyopaque, pos: *[3]f32, facing: f32) void { + const facing_bits: u32 = @bitCast(facing); + asm volatile ( + \\ push %[facing] + \\ call *%[func] + : + : [_] "{ecx}" (@intFromPtr(entity)), + [_] "{edx}" (@intFromPtr(pos)), + [facing] "r" (facing_bits), + [func] "r" (@as(u32, 0x698e20)), + : .{ .eax = true, .ecx = true, .edx = true, .memory = true, .cc = true }); +} + /// Remove only the live entity for a marker slot (def untouched). /// Used internally before respawn/replacement. fn clearEntity(index: usize) void {