From 6c500f7cdb00395bc4d5546fa2e91b5af34108dc Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 8 Apr 2026 16:17:16 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20add=20180=C2=B0=20heading=20offset=20for?= =?UTF-8?q?=20dungeons=20(from=20UB=20line=201013)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UB applies HeadingToQuaternion(heading - 180) for dungeon rendering. The layer has Y increasing downward, and the 180° offset flips N/S. Reverted coordinates to Version 1 (X mirror, Y direct) which had correct tile connections, and added the 180° heading offset that UB uses to fix N/S orientation. Co-Authored-By: Claude Opus 4.6 (1M context) --- static/script.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/static/script.js b/static/script.js index 218dcef8..f405585d 100644 --- a/static/script.js +++ b/static/script.js @@ -3853,7 +3853,9 @@ function updateRadarWindow(msg) { const dmap = dungeonMapCache[landblock]; const playerRoundedZ = Math.floor((playerRawZ + 3) / 6) * 6; ctx.translate(cx, cy); - ctx.rotate(-playerHeading * Math.PI / 180); // heading-up rotation + // UB applies (heading - 180) rotation for dungeons (line 1013 DungeonMaps.cs) + // The layer has Y increasing downward; the 180° offset flips N/S + ctx.rotate(-(playerHeading - 180) * Math.PI / 180); const cellSize = 10 * scale; // each cell is 10 game units const hasTiles = dungeonTileCanvases && Object.keys(dungeonTileCanvases).length > 0; @@ -3877,9 +3879,9 @@ function updateRadarWindow(msg) { ctx.globalAlpha = isCurrentFloor ? 0.85 : 0.12; (level.cells || []).forEach(cell => { - // X mirrored (matches UB's layer rendering), Y negated for north-up + // X mirrored (matches UB's layer rendering), Y direct const dx = -(cell.x - playerX) * scale; - const dy = -(cell.y - playerY) * scale; + const dy = (cell.y - playerY) * scale; const tileCanvas = hasTiles ? dungeonTileCanvases[String(cell.env_id)] : null; if (tileCanvas) { @@ -3967,7 +3969,8 @@ function updateRadarWindow(msg) { ctx.stroke(); // Rotate world by heading so player facing = up on canvas - const rotAngle = headingRad; + // In dungeons, add 180° to match UB's (heading - 180) rotation + const rotAngle = isDungeon ? headingRad + Math.PI : headingRad; // Draw objects and cache positions for click hit-testing const cosA = Math.cos(rotAngle); @@ -3977,7 +3980,7 @@ function updateRadarWindow(msg) { let dX, dY; if (isDungeon && obj.raw_x !== undefined) { dX = -(obj.raw_x - playerX); // X mirrored to match tile space - dY = -(obj.raw_y - playerY); // Y negated for north-up + dY = (obj.raw_y - playerY); // Y direct (180° heading offset handles N/S) } else { dX = obj.ew - playerEW; dY = obj.ns - playerNS; @@ -4040,7 +4043,7 @@ function updateRadarWindow(msg) { let distMeters, dX, dY; if (isDungeon && obj.raw_x !== undefined) { dX = -(obj.raw_x - playerX); // X mirrored - dY = -(obj.raw_y - playerY); // Y negated + dY = (obj.raw_y - playerY); // Y direct distMeters = Math.sqrt(dX * dX + dY * dY); // raw coords are ~meters } else { dX = obj.ew - playerEW;