fix(tooltip): robust NPC/object ID resolution via learner GUID parsers

Expose QuestieLearner:GetIdAndTypeFromGUID / GetObjectIdFromGUID /
GetNpcIdFromGUID (they handle modern dash GUIDs AND legacy 0x hex /
GameObject GUIDs). Tooltips now fall back to these when strsplit('-',guid)
can't parse the GUID, so NPC IDs no longer silently fail to write on
hex-GUID units; the Object ID line resolves from the object's GUID when
its name isn't in the lookup. IDs deduped per tooltip.
This commit is contained in:
Xurkon
2026-06-11 17:53:36 -05:00
parent 5abeff2768
commit 150c59fa77
3 changed files with 36 additions and 3 deletions
+1
View File
@@ -41,6 +41,7 @@
### Bug Fixes
- **[Tooltip - Robust ID Resolution For Hex/Object GUIDs]** Tooltip NPC IDs are now resolved with the learner's robust GUID parser (`QuestieLearner:GetIdAndTypeFromGUID`, now public) as a fallback when the naive `strsplit("-", guid)` can't parse the GUID — e.g. legacy `0x` hex GUIDs — which previously left the NPC ID line silently unwritten. The Object ID line gained a matching fallback: when a hovered object's name isn't in the lookup, it resolves the ID from the object's GUID via the new `QuestieLearner:GetObjectIdFromGUID`. Both ID lines are also deduped per tooltip.
- **[Tooltip - ID Lines No Longer Vanish On Re-Hover]** The "Item ID" / "NPC ID" lines were only added when the hovered item/unit *changed* (`lastItemId`/`lastGuid` gate). But WoW clears and re-fires `OnTooltipSetItem`/`OnTooltipSetUnit` for the *same* item/unit, rebuilding the tooltip — and the gate skipped re-adding the line on the rebuilt tooltip, so the ID disappeared (e.g. hovering the same quest item twice). The ID lines are now (re)added on every render and deduplicated per tooltip (via `_TooltipHasLeftLine`), so they're always present exactly once.
- **[Learner - Exclude Critters & Fix Sunstrider Object Mis-Key]** Critters (Rabbit, Deer, Sheep, Cow, Cat, …) are never quest-relevant but were being recorded by the learner when killed, polluting the DB. The learner now refuses to record critters (a static list of common classic critters plus runtime detection via `UnitCreatureType` for Ascension's custom critters, flagged the moment a unit token is available on mouseover/target), purges any already-recorded critters on `InjectLearnedData` and on sight, and skips them in every learn path. Also fixed object spawns mis-stored under the Eversong parent areaID `3430` (e.g. object 180516 "Shrine of Dath'Remar", which is on Sunstrider): the migration now moves any `3430`-keyed spawn — and the matching home-zone field — to Sunstrider's uiMapID `1241`, since legitimate Eversong data is always keyed by `1941`.
- **[Learner - InjectLearnedData Was Corrupting Saved Spawns]** The real cause of learner pins collapsing to one (and the data appearing to "not persist"): `InjectLearnedData` ran on every login/redraw and **rewrote the saved learner spawns**. Its zone-key migration was inverted — it called `GetAreaIdByUiMapId(1241)`, which returns the Eversong **parent areaId 3430**, and *moved* Sunstrider's coordinates there (rendering them on the wrong map) while `InsertIfNewBucket` silently deduped distinct coords away. On top of that, `Sanitize` re-deduplicated coordinates with the flat `COORD_GRID` (2.0) instead of the per-zone grid, collapsing Sunstrider's tightly-packed spawns (its grid is 0.5). Together these turned seven saved Arcane Wraith coordinates into one pin and persisted the damage back to SavedVariables. Fixed: the migration now converts only legacy areaId keys **forward** to the canonical uiMapId (never the reverse) and leaves uiMapId keys untouched; the `[9]`/`[5]` home-zone fields are normalized the same direction; and `Sanitize` now de-dups with the correct per-zone grid. A regression test (`Tests/QuestieLearnerMultiSpawn_spec.lua`) drives `InjectLearnedData` + `GetNPC` and asserts all distinct learner spawns survive.
+8
View File
@@ -3402,6 +3402,14 @@ local GetObjectIdFromGUID = function(guid)
return nil
end
-- Public wrappers so other modules (e.g. tooltips) can reuse the learner's robust GUID
-- parsing. These handle modern dash GUIDs AND legacy 0x hex GUIDs (and GameObject GUIDs),
-- unlike a naive strsplit("-", guid) which returns nothing for hex/object GUIDs — the cause
-- of NPC/Object IDs failing to show on some tooltips.
function QuestieLearner:GetIdAndTypeFromGUID(guid) return GetIdAndTypeFromGUID(guid) end
function QuestieLearner:GetObjectIdFromGUID(guid) return GetObjectIdFromGUID(guid) end
function QuestieLearner:GetNpcIdFromGUID(guid) return GetNpcIdFromGUID(guid) end
local function TraceLearnerEntity(source, guid, unitType, entityId, name)
if not Questie or not Questie.Debug then return end
local prefix = "n/a"
+27 -3
View File
@@ -368,9 +368,23 @@ function _QuestieTooltips:AddUnitDataToTooltip()
local guidType, _, _, _, _, npcId, _ = strsplit("-", guid or "");
-- Robust fallback for GUIDs strsplit("-") can't parse — legacy 0x hex GUIDs (and any
-- malformed/short modern GUID). The learner's GetIdAndTypeFromGUID handles both formats,
-- so reuse it; without this the NPC ID line silently failed to write on those units.
if (not tonumber(npcId)) and guid then
local QuestieLearner = QuestieLoader:ImportModule("QuestieLearner")
if QuestieLearner and QuestieLearner.GetIdAndTypeFromGUID then
local fallbackId, fallbackType = QuestieLearner:GetIdAndTypeFromGUID(guid)
if fallbackId then
npcId = tostring(fallbackId)
if (not guidType) or guidType == "" then guidType = fallbackType end
end
end
end
-- NPC ID is (re)added on EVERY render so it survives WoW's tooltip rebuilds, not only the
-- first hover of a new unit. Deduped per tooltip so it never doubles up.
if name and (guidType == "Creature" or guidType == "Vehicle") and npcId
if name and (guidType == "Creature" or guidType == "Vehicle") and npcId and tonumber(npcId)
and Questie.db.profile.enableTooltipsNPCID == true
and not _TooltipHasLeftLine(self, "NPC ID") then
GameTooltip:AddDoubleLine("NPC ID", "|cFFFFFFFF" .. npcId .. "|r")
@@ -504,11 +518,21 @@ function _QuestieTooltips:AddObjectDataToTooltip(name)
local lookup = l10n.objectNameLookup[name] or {}
local count = table.getn(lookup)
if Questie.db.profile.enableTooltipsObjectID == true and count ~= 0 then
if Questie.db.profile.enableTooltipsObjectID == true and not _TooltipHasLeftLine(GameTooltip, "Object ID") then
if count == 1 then
GameTooltip:AddDoubleLine("Object ID", "|cFFFFFFFF" .. lookup[1] .. "|r")
else
elseif count > 1 then
GameTooltip:AddDoubleLine("Object ID", "|cFFFFFFFF" .. lookup[1] .. " (" .. count .. ")|r")
else
-- Name not in the object lookup ("problematic"). Fall back to the object's
-- GUID via the learner's robust GameObject-GUID parser, so the ID still shows.
local QuestieLearner = QuestieLoader:ImportModule("QuestieLearner")
local objGuid = UnitGUID and UnitGUID("mouseover")
local objId = objGuid and QuestieLearner and QuestieLearner.GetObjectIdFromGUID
and QuestieLearner:GetObjectIdFromGUID(objGuid)
if objId then
GameTooltip:AddDoubleLine("Object ID", "|cFFFFFFFF" .. objId .. "|r")
end
end
end