From e755416f8ae4c282a47e609a3e3c90de2b8bec5a Mon Sep 17 00:00:00 2001 From: Xurkon Date: Thu, 11 Jun 2026 06:49:51 -0500 Subject: [PATCH] fix(map): align minimap pins at non-1 UI scales --- CHANGELOG.md | 2 +- Compat/HBD.lua | 32 +++++++++++--------------------- docs/changelog.html | 14 +++++++------- docs/index.html | 2 +- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc6c1b2..e3a8c85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/Compat/HBD.lua b/Compat/HBD.lua index 99f554b..66116e9 100644 --- a/Compat/HBD.lua +++ b/Compat/HBD.lua @@ -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 diff --git a/docs/changelog.html b/docs/changelog.html index 89834e6..3705c24 100644 --- a/docs/changelog.html +++ b/docs/changelog.html @@ -232,21 +232,21 @@
  • [Fix — Arrow Runtime Texture Fallback] 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 arrowold.
  • [Fix — Arrow2 Orientation] Rotated Arrow2 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.
  • -
  • [Fix — Minimap Pin Drift: Live View-Radius API + Corrected Pixel Math] 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. +
  • [Fix — Minimap Pin Alignment At Non-1 UI Scales] 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.
  • [Fix — MapIconTooltip _GetLevelString Guard] Resolved attempt to concatenate local 'minLevel' (a nil value) crash in MapIconTooltip.lua:494 (_GetLevelString function). The creature name "Uneasy Citizen" existed in creatureLevels as an empty table {} rather than the expected [1]=minLevel, [2]=maxLevel, [3]=rank tuple. Added an early-return guard at the top of _GetLevelString: if creatureLevels[name] is falsy or not a table with a numeric level at index [1], return the name unmodified.
  • diff --git a/docs/index.html b/docs/index.html index af45971..aabf058 100644 --- a/docs/index.html +++ b/docs/index.html @@ -251,7 +251,7 @@

    Current Release Highlights

    -

    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.

    +

    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.