fix(map): align minimap pins at non-1 UI scales
This commit is contained in:
+1
-1
@@ -42,7 +42,7 @@
|
||||
|
||||
- **[Map - Quest-Type Filters Now Truly Apply To The Minimap]** (#11) Filtered quest types (e.g. dungeon quests) could still show on the minimap while correctly hidden on the world map. The previous fix made the minimap `FadeLogic` re-check `ShouldBeHidden` only when deciding whether to *re-show* an already-hidden icon — so an icon that was already visible (or that HBD's pin renderer showed on coming into range) was never hidden. `FadeLogic` now proactively calls `ShouldBeHidden` for every in-range minimap icon and `FakeHide`s it when filtered, in both minimap fade paths (quest icons and townsfolk/manual icons). The same path also picked up the #17 minimap-radius cutoff gating it was missing.
|
||||
- **[Learner - Kills Never Recorded Spawn Coordinates]** The combat-log kill handler computed the player's spawn position inside `if credited then ... end`, but `credited` was read **before** it was assigned (the `local credited = ...` came several lines later), so it was always `nil` — the position-capture block never ran. Every killed NPC was saved with `spawnSource="fallback"` and no `[7]` spawns regardless of kill count, so in learner-only mode their pins never appeared (and re-killing didn't help). Moved the `credited` computation above the position capture, and guard against a `0,0` position being stored. The learner's `GetPlayerCoords` (used by quest-giver/object learning) also now uses the robust `QuestieCompat.GetCurrentPlayerPosition()` (handles `SetMapToCurrentZone` and the Sunstrider parent/child coordinate correction) instead of the raw `GetPlayerMapPosition`, returning `nil` when no valid position exists so no `0,0` pins are recorded. Newly killed mobs now record real coordinates and their learner pins persist.
|
||||
- **[Map - Minimap Icon Pixel Snapping At Fractional Scales]** (#6) Minimap quest icons are now snapped to the physical pixel grid when positioned. At fractional UI scales (e.g. a 0.71 game scale combined with Windows display scaling) the raw fractional offset placed icons between physical pixels, making them render blurry and visibly offset from the engine-drawn native quest blips. Rounding the pin offset to a whole physical pixel (via the minimap's effective scale) keeps Questie's icons on the same grid as the native markers, improving alignment at non-integer scales.
|
||||
- **[Map - Minimap Icon Alignment At Non-1 UI Scales]** (#6) Reverted the attempted physical-pixel snapping fix and corrected the underlying minimap coordinate math instead. HBD pins already use `SetPoint` offsets in the minimap frame's coordinate space, so multiplying the minimap half-width by `GetScale()` made Questie `?`/`!` pins drift away from the native minimap quest blips whenever UI/minimap scale was not 1.0. Minimap pins now combine the live minimap view radius with unscaled `GetWidth()/2` and `GetHeight()/2`, which keeps placement resolution-independent across fractional UI scales.
|
||||
- **[Map - Hide Callboard Quests: Robust Board Detection]** (#10) The "hide repeatable quests below level 60" option only hid quests flagged repeatable in the DB, but Ascension's Call Board / Contract Board bounties (e.g. NPC 24 "Outlaw's Contract Board") aren't reliably flagged repeatable, so their `!` markers still showed. Added `QuestieDB.IsBoardQuest(questId)` which detects these by their starter NPC/object name containing "board" (cached per quest), and the hide-below-60 option now hides a quest when it is repeatable **or** a board quest — closing the gap in both the available-quest draw path and the icon visibility check.
|
||||
- **[Tooltip - ElvUI Style No Longer On By Default]** (#16) The "ElvUI tooltip style" option shipped enabled by default, so Questie restyled every default WoW tooltip — stripping the border — for users who never asked for it and don't run ElvUI. It is now opt-in (default off), and a one-time migration resets it off for existing installs so their default tooltips return. Users who want the flat style can re-enable it in the General tab.
|
||||
- **[Quest - Turned-In Quests Misclassified As Abandoned]** (#9) On Ascension some turn-ins (notably crafting/auto-complete quests) fire `QUEST_REMOVED` without a preceding `QUEST_TURNED_IN`, so Questie's 1-second abandon timer ran `MarkQuestAsAbandoned`. By then `QuestLogCache.RemoveQuest` had already cleared the quest, so the `IsComplete` check returned 0 and the *turned-in* quest was treated as abandoned — leaving its objective pins and turn-in `?` lingering on the map and minimap. The completion state is now snapshotted at `QUEST_REMOVED` time (while the quest is still in the cache) and used by the abandon timer, so a quest that was complete at removal is correctly completed (pins/`?` cleared) rather than abandoned.
|
||||
|
||||
+11
-21
@@ -490,19 +490,7 @@ local function drawMinimapPin(pin, data)
|
||||
if dist <= 1 or (data.floatOnEdge and ((pin.texture and pin.texture.a and pin.texture.a ~= 0) or pin.texture == nil)) then
|
||||
pin:Show()
|
||||
pin:ClearAllPoints()
|
||||
-- Snap the icon offset to the physical pixel grid. At fractional UI scales (e.g. a
|
||||
-- 0.71 game scale combined with Windows display scaling) a raw fractional offset lands
|
||||
-- the icon between physical pixels, so it renders blurry and visibly misaligned with the
|
||||
-- engine-drawn native quest blips that ARE pixel-aligned (#6). Rounding the offset to a
|
||||
-- whole physical pixel keeps Questie's pins on the same grid as the native markers.
|
||||
local ox = diffX * minimapWidth
|
||||
local oy = -diffY * minimapHeight
|
||||
local eScale = pins.Minimap:GetEffectiveScale()
|
||||
if eScale and eScale > 0 then
|
||||
ox = math.floor(ox * eScale + 0.5) / eScale
|
||||
oy = math.floor(oy * eScale + 0.5) / eScale
|
||||
end
|
||||
pin:SetPoint("CENTER", pins.Minimap, "CENTER", ox, oy)
|
||||
pin:SetPoint("CENTER", pins.Minimap, "CENTER", diffX * minimapWidth, -diffY * minimapHeight)
|
||||
data.onEdge = (dist > 1)
|
||||
else
|
||||
pin:Hide()
|
||||
@@ -568,11 +556,11 @@ local function UpdateMinimapPins(force)
|
||||
or sizeTable[2] or sizeTable[1] or sizeTable[0]
|
||||
mapRadius = size / 2
|
||||
end
|
||||
-- minimapWidth = actual half-width of the visible minimap frame in screen pixels.
|
||||
-- diffX (yards) / mapRadius (yards in viewport) * minimapWidth (pixels) = correct screen offset.
|
||||
-- No additional scaling needed when mapRadius comes from the live API.
|
||||
minimapWidth = pins.Minimap:GetWidth() * pins.Minimap:GetScale() / 2
|
||||
minimapHeight = pins.Minimap:GetHeight() * pins.Minimap:GetScale() / 2
|
||||
-- SetPoint offsets are in the minimap parent's coordinate space, not
|
||||
-- physical pixels. Keep width/height unscaled so non-1 UI/minimap scales
|
||||
-- do not push pins away from the native minimap blips (#6).
|
||||
minimapWidth = pins.Minimap:GetWidth() / 2
|
||||
minimapHeight = pins.Minimap:GetHeight() / 2
|
||||
|
||||
--[[ DEBUG: One-shot per (zoom, indoors, diffZoom) — shows pixel math state
|
||||
if not _G.QuestieDebugPinMath then _G.QuestieDebugPinMath = {} end
|
||||
@@ -691,9 +679,11 @@ local function UpdateMinimapIconPosition()
|
||||
|
||||
mapRadius = size / 2
|
||||
end
|
||||
-- minimapWidth = actual half-width of the visible minimap frame in screen pixels.
|
||||
minimapWidth = pins.Minimap:GetWidth() * pins.Minimap:GetScale() / 2
|
||||
minimapHeight = pins.Minimap:GetHeight() * pins.Minimap:GetScale() / 2
|
||||
-- SetPoint offsets are in the minimap parent's coordinate space, not
|
||||
-- physical pixels. Keep width/height unscaled so non-1 UI/minimap scales
|
||||
-- do not push pins away from the native minimap blips (#6).
|
||||
minimapWidth = pins.Minimap:GetWidth() / 2
|
||||
minimapHeight = pins.Minimap:GetHeight() / 2
|
||||
|
||||
--[[ DEBUG: One-shot per (zoom, indoors) per-pin — shows ratio stability across zooms
|
||||
if not _G.QuestieDebugPinMath.pinMath then _G.QuestieDebugPinMath.pinMath = {} end
|
||||
|
||||
+7
-7
@@ -232,21 +232,21 @@
|
||||
</li>
|
||||
<li><strong>[Fix — Arrow Runtime Texture Fallback]</strong> Bundled image arrows now use the generated runtime TGA as the live render source, while the preview TGA stays dedicated to the dropdown swatch. This keeps image arrows stable even when the client behaves oddly with a specific source file, while the sheet arrow stays isolated to <code>arrowold</code>.</li>
|
||||
<li><strong>[Fix — Arrow2 Orientation]</strong> Rotated <code>Arrow2</code> 180 degrees so the pointed tip is the top-facing tip of the asset instead of the base. The runtime TGA and its preview stay in sync so the dropdown thumbnail and in-game arrow match exactly.</li>
|
||||
<li><strong>[Fix — Minimap Pin Drift: Live View-Radius API + Corrected Pixel Math]</strong> Resolved the long-running minimap pin drift bug where quest pins appeared to "follow" the player or jump on every frame. Pins now stay anchored to their world positions across all minimap zoom levels (0-5+) and across both Stock UI and ElvUI.
|
||||
<li><strong>[Fix — Minimap Pin Alignment At Non-1 UI Scales]</strong> Reverted the attempted pixel-snapping fix and corrected the minimap coordinate math instead. Quest pins now stay anchored to their world positions across all minimap zoom levels (0-5+) and across both Stock UI and ElvUI.
|
||||
<ul>
|
||||
<li><strong>Time-to-fix note</strong>: This took roughly three weeks of iteration. The first three attempts either crashed, partially fixed only some zoom levels, or regressed zoom 0. The final patch was the first one that held across the full zoom range without the pin math drifting again.</li>
|
||||
<li><strong>Iteration 1 — mapRadius reuse (broken)</strong>: The first attempt reused <code>mapRadius</code> for both the radius and the pixel multiplier, which crashed on 3.3.5a because the live API fallback was not wired in yet.</li>
|
||||
<li><strong>Iteration 2 — direct half-width (partial)</strong>: The second attempt used <code>GetWidth() * GetScale() / 2</code> directly and fixed low zoom levels, but higher zooms still drifted because the map radius source was still wrong.</li>
|
||||
<li><strong>Iteration 2 — direct half-width (partial)</strong>: The second attempt used the unscaled minimap half-width directly and fixed low zoom levels, but higher zooms still drifted because the map radius source was still wrong.</li>
|
||||
<li><strong>Iteration 3 — scaleFactor normalization (regressed)</strong>: The third attempt added a normalization factor based on a reference radius and inverted the ratio, which made zoom 0 worse and had to be backed out.</li>
|
||||
<li><strong>Iteration 4 — final fix</strong>: The final patch combined the native 3.3.5a <code>Minimap:GetViewRadius()</code> API with the correct pixel half-width formula, which aligned the world-yard math with the on-screen pixel math.</li>
|
||||
<li><strong>Iteration 4 — final fix</strong>: The final patch combined the native 3.3.5a <code>Minimap:GetViewRadius()</code> API with the unscaled minimap half-width formula, which kept the world-yard math aligned with the minimap frame coordinate space.</li>
|
||||
<li><strong>Root Cause 1 — Hardcoded lookup table used on 3.3.5a</strong>: <code>Compat/HBD.lua</code> was reading <code>mapRadius</code> from a hardcoded <code>minimap_size</code> lookup table calibrated for stock WoW zoom levels. The API check <code>C_Minimap and C_Minimap.GetViewRadius</code> evaluated to <code>nil</code> on 3.3.5a (and Ascension), so the broken lookup table was always used. The lookup value <code>minimap_size.outdoor[5] = 250</code> produced <code>mapRadius = 125</code>, but the actual live minimap view radius at zoom 5 is <code>116.67</code> yards (from <code>Minimap:GetViewRadius()</code>). This 6.7% error compounded across all pin offsets.</li>
|
||||
<li><strong>Root Cause 2 — Factor-of-2 in pixel math</strong>: <code>minimapWidth</code> was computed as <code>(GetWidth() * mapRadius / 155.52) / 2</code>, mixing pixel-half-width with a yards-based scale factor. The <code>/ 155.52</code> constant was a hardcoded normalization that did not match the live API value. The math was self-inconsistent: ratio <code>minimapWidth / mapRadius</code> was <code>0.56</code> (off by ~7% from the correct <code>0.6</code>).</li>
|
||||
<li><strong>Root Cause 3 — Scale not applied to pixel dimensions</strong>: <code>minimapWidth</code> was based on <code>GetWidth()</code> alone, ignoring <code>GetScale()</code>. When UI scale changed, the pixel dimensions reported by <code>GetWidth()</code> would diverge from the actual on-screen size, while <code>mapRadius</code> (in yards) stayed fixed. This caused drift to worsen at higher zoom levels where the ratio was most sensitive.</li>
|
||||
<li><strong>Root Cause 3 — Scale applied to the wrong layer</strong>: <code>SetPoint</code> offsets are expressed in the minimap parent frame's coordinate space, not physical pixels. Multiplying the offset by <code>GetScale()</code> pushed Questie pins away from that coordinate space and made them diverge from the native minimap quest blips whenever UI/minimap scale was not 1.0.</li>
|
||||
<li><strong>Fix — <code>Compat/HBD.lua</code> lines 337-339</strong>: Changed the radius API detection to use the 3.3.5a-native <code>Minimap:GetViewRadius()</code> (instance method), with <code>C_Minimap.GetViewRadius</code> as secondary fallback. The new line:<pre><code>local MinimapRadiusAPI = (C_Minimap and C_Minimap.GetViewRadius) or Minimap.GetViewRadius</code></pre></li>
|
||||
<li><strong>Fix — <code>Compat/HBD.lua</code> line 528 and line 639</strong>: Replaced <code>C_Minimap.GetViewRadius()</code> with <code>MinimapRadiusAPI(Minimap)</code> in both call sites, so the live API is invoked through the resolved function reference.</li>
|
||||
<li><strong>Fix — <code>Compat/HBD.lua</code> lines 536-540 and lines 653-656</strong>: Replaced the <code>minimapWidth = (GetWidth() / 2) * (mapRadius / 155.52)</code> formula with <code>minimapWidth = GetWidth() * GetScale() / 2</code>. The new formula yields the actual half-width of the visible minimap in screen pixels, which is the correct multiplier for <code>diffX * minimapWidth</code> when <code>diffX</code> is normalized by <code>mapRadius</code> (yards in viewport).</li>
|
||||
<li><strong>Fix (debug code preserved as comments)</strong>: All <code>QDMATH</code> / <code>UPDATE entering</code> / <code>ICON</code> debug prints and <code>_G.QuestieDebugPinMath</code> global state in <code>Compat/HBD.lua</code> are now wrapped in <code>--[[ DEBUG: ... --]]</code> block comments. The drift bug is fixed; debug output is silent in production. The commented-out blocks are preserved for future regression investigation — to re-enable, remove the <code>--[[</code> and <code>--]]</code> markers and reload.</li>
|
||||
<li><strong>Verification</strong>: Live <code>Minimap:GetViewRadius()</code> returns <code>116.67</code> at zoom 5. <code>minimapWidth = 70</code> (from <code>GetWidth()=140 * GetScale()=1.0 / 2</code>). <code>diffX * minimapWidth / mapRadius</code> = <code>diffX * 0.6</code>, matching the expected 0.6 pixels-per-yard scaling. Pins now stay anchored to their world positions as the player moves; the per-frame <code>diffX</code> of ~0.35 yards during walking translates to ~0.21 pixels of pin movement per frame (correct for 1 yard of world movement).</li>
|
||||
<li><strong>Fix — <code>Compat/HBD.lua</code> lines 536-540 and lines 653-656</strong>: Replaced the <code>minimapWidth = (GetWidth() / 2) * (mapRadius / 155.52)</code> formula with <code>minimapWidth = GetWidth() / 2</code>. The offset math now stays in the minimap frame's own coordinate space, which is the correct unit for <code>SetPoint</code>.</li>
|
||||
<li><strong>Fix (debug code preserved as comments)</strong>: The temporary debug prints and <code>_G.QuestieDebugPinMath</code> global state in <code>Compat/HBD.lua</code> remain wrapped as comments so production chat stays clean. The commented-out blocks are preserved for future regression investigation — to re-enable, remove the comment markers and reload.</li>
|
||||
<li><strong>Verification</strong>: Live <code>Minimap:GetViewRadius()</code> still returns the correct world-space radius at zoom 5. The pin offsets now use the same unscaled coordinate space as the minimap frame, so quest pins stay aligned with the native markers across fractional UI scales and window scaling combinations.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>[Fix — MapIconTooltip _GetLevelString Guard]</strong> Resolved <code>attempt to concatenate local 'minLevel' (a nil value)</code> crash in <code>MapIconTooltip.lua:494</code> (<code>_GetLevelString</code> function). The creature name "Uneasy Citizen" existed in <code>creatureLevels</code> as an empty table <code>{}</code> rather than the expected <code>[1]=minLevel, [2]=maxLevel, [3]=rank</code> tuple. Added an early-return guard at the top of <code>_GetLevelString</code>: if <code>creatureLevels[name]</code> is falsy or not a table with a numeric level at index <code>[1]</code>, return the name unmodified.</li>
|
||||
|
||||
+1
-1
@@ -251,7 +251,7 @@
|
||||
|
||||
<section id="release-highlights">
|
||||
<h2>Current Release Highlights</h2>
|
||||
<p>The v1.6.3 release includes the arrow redesign, the minimap pin drift fix, and the Sunstrider map and tooltip corrections. These notes summarize the shipped behavior in the live release.</p>
|
||||
<p>The v1.6.3 release includes the arrow redesign, the minimap pin alignment fix for non-1 UI scales, and the Sunstrider map and tooltip corrections. These notes summarize the shipped behavior in the live release.</p>
|
||||
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
|
||||
Reference in New Issue
Block a user