feat: expand learner tooltip controls

This commit is contained in:
Xurkon
2026-06-06 14:30:07 -05:00
parent 1f3de0e02e
commit 1ca426ee9f
7 changed files with 148 additions and 19 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
### Performance
- **[Questie Debug - Message Throttle]** Added a live debug-message throttle so non-fatal debug output cannot spam chat faster than it can be read. The throttle is configurable in the Advanced tab and keeps fatal output separate.
- **[Questie Learner - Tooltip Controls]** Added learner-specific tooltip controls so players can toggle the learned spawn line, learner confidence lines, and automatic tooltip resizing from the Tooltip options. The learner tooltip paths now respect those toggles before adding extra lines.
- **[Questie Learner - Tooltip Controls]** Added learner-specific tooltip controls so players can toggle the learned spawn line, total learned spawn count, learner confidence lines, automatic tooltip resizing, and a secondary learner tooltip from the Tooltip options. The learner tooltip paths now respect those toggles before adding extra lines.
- **[QuestieLearner - Kill/Pin Refresh Throttling]** Debounced learner-triggered map-pin refreshes so heavy kill streaks do not redraw pins on every event. Added a maximum wait cap so batched updates still flush predictably instead of being pushed out forever by constant activity.
- **[QuestieLearner - Bystander Kill Suppression]** Changed visible nearby `UNIT_DIED` handling so kills from other players can update short-lived correlation evidence without immediately running full learner injection or pin refresh work.
- **[QuestieLearner - PARTY_KILL Event-Order Fix]** Fixed an edge case where a `UNIT_DIED` debounce entry could suppress a later authoritative `PARTY_KILL` for the same GUID. The debounce now tracks event type and allows the player's/group's kill event through while still suppressing true duplicates.
@@ -522,6 +522,18 @@ function QuestieOptions.tabs.general:Initialize()
Questie.db.profile.learnerTooltipShowConfidence = value
end
},
learnerTooltipShowTotalSpawns = {
type = "toggle",
order = 8.585,
name = function() return l10n('Show total spawns learned'); end,
desc = function() return l10n('Show the total number of learned spawn points for NPC tooltips.'); end,
width = 1.5,
disabled = function() return not (Questie.db.profile.enableTooltips and (Questie.db.profile.learnerTooltips ~= false)); end,
get = function() return Questie.db.profile.learnerTooltipShowTotalSpawns ~= false end,
set = function(_, value)
Questie.db.profile.learnerTooltipShowTotalSpawns = value
end
},
learnerTooltipAutoResize = {
type = "toggle",
order = 8.59,
@@ -534,9 +546,21 @@ function QuestieOptions.tabs.general:Initialize()
Questie.db.profile.learnerTooltipAutoResize = value
end
},
partyOnlyToggle = {
learnerTooltipUseSecondary = {
type = "toggle",
order = 8.6,
name = function() return l10n('Use secondary learner tooltip'); end,
desc = function() return l10n('Show learner-specific spawn details in a separate tooltip instead of adding them to the existing one.'); end,
width = 1.5,
disabled = function() return not (Questie.db.profile.enableTooltips and (Questie.db.profile.learnerTooltips ~= false)); end,
get = function() return Questie.db.profile.learnerTooltipUseSecondary == true end,
set = function(_, value)
Questie.db.profile.learnerTooltipUseSecondary = value
end
},
partyOnlyToggle = {
type = "toggle",
order = 8.61,
name = function() return l10n('Only show party members'); end,
desc = function() return l10n('When this is enabled, shared quest info will only show players in your party.'); end,
width = 1.5,
@@ -92,7 +92,9 @@ function QuestieOptionsDefaults:Load()
learnerTooltips = true,
learnerTooltipShowSpawn = true,
learnerTooltipShowConfidence = true,
learnerTooltipShowTotalSpawns = true,
learnerTooltipAutoResize = true,
learnerTooltipUseSecondary = false,
learnerBroadcast = true,
enableMapIcons = true,
enableMiniMapIcons = true,
+106 -9
View File
@@ -4427,33 +4427,103 @@ end
------------------------------------------------------------------------
local _tooltipHookRegistered = false
local _learnerTooltipFrame = nil
local function _CountLearnedNpcSpawns(entry)
if not entry or not entry[7] then
return 0
end
local total = 0
for _, zoneSpawns in next, entry[7] do
if type(zoneSpawns) == "table" then
total = total + table.getn(zoneSpawns)
end
end
return total
end
local function _GetLearnerTooltipFrame()
if _learnerTooltipFrame then
return _learnerTooltipFrame
end
local frame = CreateFrame("GameTooltip", "QuestieLearnerTooltip", UIParent, "GameTooltipTemplate")
frame:SetFrameStrata("TOOLTIP")
frame:SetClampedToScreen(true)
frame:SetOwner(UIParent, "ANCHOR_NONE")
_learnerTooltipFrame = frame
return _learnerTooltipFrame
end
local function _HideLearnerTooltipFrame()
if _learnerTooltipFrame then
_learnerTooltipFrame:Hide()
end
end
local function _ShowLearnerTooltipFrame(sourceTooltip, lines)
local tooltip = _GetLearnerTooltipFrame()
tooltip:ClearLines()
tooltip:SetOwner(sourceTooltip or GameTooltip, "ANCHOR_RIGHT")
for _, line in next, lines do
tooltip:AddLine(line)
end
local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips")
if QuestieTooltips and QuestieTooltips.ResizeTooltip then
QuestieTooltips:ResizeTooltip(tooltip)
end
tooltip:Show()
end
--- Adds a "Learned spawn: (x, y) from N kills" line to the tooltip
--- for the NPC represented by the given unit token.
--- Called by the GameTooltip OnTooltipSetUnit hook.
---@param unitToken string WoW unit token (e.g. "mouseover")
local function _AddLearnedSpawnTooltipLine(unitToken)
if not Questie or not Questie.dbLearner then return end
if not Questie.db.profile or Questie.db.profile.learnerTooltips == false or Questie.db.profile.learnerTooltipShowSpawn == false then
if not Questie or not Questie.dbLearner then
_HideLearnerTooltipFrame()
return
end
if not Questie.db.profile or Questie.db.profile.learnerTooltips == false then
_HideLearnerTooltipFrame()
return
end
local guid = UnitGUID(unitToken)
if not guid then return end
if not guid then
_HideLearnerTooltipFrame()
return
end
local npcId, guidType = GetIdAndTypeFromGUID(guid)
if guidType ~= "Creature" and guidType ~= "Vehicle" then return end
if not npcId then return end
if guidType ~= "Creature" and guidType ~= "Vehicle" then
_HideLearnerTooltipFrame()
return
end
if not npcId then
_HideLearnerTooltipFrame()
return
end
local entry = Questie.dbLearner.global.npcs[npcId]
if not entry or not entry[7] then return end
if not entry or not entry[7] then
_HideLearnerTooltipFrame()
return
end
-- Find the first zone with spawn data
local spawnsByZone = entry[7]
local zoneId = next(spawnsByZone)
if not zoneId then return end
if not zoneId then
_HideLearnerTooltipFrame()
return
end
local zoneSpawns = spawnsByZone[zoneId]
if not zoneSpawns or #zoneSpawns == 0 then return end
if not zoneSpawns or #zoneSpawns == 0 then
_HideLearnerTooltipFrame()
return
end
-- Use the first recorded coordinate
local x = zoneSpawns[1][1]
@@ -4462,15 +4532,39 @@ local function _AddLearnedSpawnTooltipLine(unitToken)
local formattedX = ("%.1f"):format(x)
local formattedY = ("%.1f"):format(y)
local lines = {}
if Questie.db.profile.learnerTooltipShowSpawn ~= false then
local text = ("(%s, %s)"):format(formattedX, formattedY)
if Questie.db.profile.learnerTooltipShowConfidence ~= false then
text = text .. (" from %d kill%s"):format(kills, kills == 1 and "" or "s")
end
GameTooltip:AddDoubleLine("Learned spawn", text)
lines[#lines + 1] = {"Learned spawn", text}
end
if Questie.db.profile.learnerTooltipShowTotalSpawns ~= false then
lines[#lines + 1] = {"Total spawns learned", tostring(_CountLearnedNpcSpawns(entry))}
end
if #lines == 0 then
_HideLearnerTooltipFrame()
return
end
if Questie.db.profile.learnerTooltipUseSecondary == true then
local rendered = {}
for _, pair in ipairs(lines) do
rendered[#rendered + 1] = pair[1] .. ": " .. pair[2]
end
_ShowLearnerTooltipFrame(GameTooltip, rendered)
else
for _, pair in ipairs(lines) do
GameTooltip:AddDoubleLine(pair[1], pair[2])
end
local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips")
if QuestieTooltips and QuestieTooltips.ResizeTooltip then
QuestieTooltips:ResizeTooltip(GameTooltip)
end
end
end
--- Registers the GameTooltip OnTooltipSetUnit hook once.
@@ -4485,6 +4579,9 @@ local function _RegisterLearnedSpawnTooltipHook()
_AddLearnedSpawnTooltipLine(unitToken)
end
end)
GameTooltip:HookScript("OnHide", function()
_HideLearnerTooltipFrame()
end)
end
------------------------------------------------------------------------
+1 -1
View File
@@ -84,7 +84,7 @@ local function _ResizeTooltipToFit(tooltip)
end
function QuestieTooltips:ResizeTooltip(tooltip)
if Questie.db.profile.learnerTooltipAutoResize == false then
if not (Questie.db and Questie.db.profile) or Questie.db.profile.learnerTooltipAutoResize == false then
return
end
_ResizeTooltipToFit(tooltip)
@@ -53,13 +53,19 @@ describe("QuestieLearner data source mode", function()
assert.is_true(has(defaults, "learnerTooltips = true"))
assert.is_true(has(defaults, "learnerTooltipShowSpawn = true"))
assert.is_true(has(defaults, "learnerTooltipShowConfidence = true"))
assert.is_true(has(defaults, "learnerTooltipShowTotalSpawns = true"))
assert.is_true(has(defaults, "learnerTooltipAutoResize = true"))
assert.is_true(has(defaults, "learnerTooltipUseSecondary = false"))
assert.is_true(has(general, "Learner Tooltips"))
assert.is_true(has(general, "Enable learner tooltips"))
assert.is_true(has(general, "Show total spawns learned"))
assert.is_true(has(general, "Use secondary learner tooltip"))
assert.is_true(has(tip, "function QuestieTooltips:ResizeTooltip(tooltip)"))
assert.is_true(has(handler, "QuestieTooltips:ResizeTooltip(GameTooltip)"))
assert.is_true(has(handler, "QuestieTooltips:ResizeTooltip(self)"))
assert.is_true(has(learner, "learnerTooltipShowSpawn"))
assert.is_true(has(learner, "_CountLearnedNpcSpawns(entry)"))
assert.is_true(has(learner, "_ShowLearnerTooltipFrame(GameTooltip, rendered)"))
end)
it("allows learner mode to draw pins from a single learned spawn when needed", function()
+1 -1
View File
@@ -180,7 +180,7 @@
<ul>
<li><strong>[QuestieDB &mdash; Required Source Item Guard]</strong> Fixed a fresh-load crash in <code>QuestieDB.GetQuest()</code> where quests that had <code>requiredSourceItems</code> but no <code>objectives</code> table would dereference <code>objectives[3]</code> while building <code>SpecialObjectives</code>. This was a code-side nil guard bug on our end, not a saved-variable problem, and it is now covered by a regression test.</li>
<li><strong>[Questie Debug &mdash; Message Throttle]</strong> Added a live debug-message throttle so non-fatal debug output cannot spam chat faster than it can be read. The throttle is configurable in the Advanced tab and keeps fatal output separate.</li>
<li><strong>[Questie Learner &mdash; Tooltip Controls]</strong> Added learner-specific tooltip controls so players can toggle the learned spawn line, learner confidence lines, and automatic tooltip resizing from the Tooltip options. The learner tooltip paths now respect those toggles before adding extra lines.</li>
<li><strong>[Questie Learner &mdash; Tooltip Controls]</strong> Added learner-specific tooltip controls so players can toggle the learned spawn line, total learned spawn count, learner confidence lines, automatic tooltip resizing, and a secondary learner tooltip from the Tooltip options. The learner tooltip paths now respect those toggles before adding extra lines.</li>
<li><strong>[QuestieLearner &mdash; Learner Sunstrider Clustering]</strong> Relaxed the Sunstrider Isle clustering override in learner mode so the clustering/deduplication knobs can still consolidate newly learned pins there. Static/auto keeps the original Sunstrider visibility behavior, but learner mode now preserves clustering so nearby learner spawns do not render as an unbounded fan-out of separate icons.</li>
<li><strong>[QuestieLearner &mdash; Turn-In Arrow Spawn Promotion]</strong> Allowed quest-related NPC and object spawns to keep their live learner coordinates even when the static database marks those spawn fields as protected. Learner mode now merges the learner's live override tables back into the getter path too, so quest giver and turn-in locations can point from learner-discovered hand-in targets without relaxing protection for unrelated world spawns.</li>
<li><strong>[QuestieLearner &mdash; Quest-Only Item Learning]</strong> Hardened item learning so plain junk loot no longer gets recorded as learner state. Only quest-relevant items are accepted now, including items that already have quest references in learned quest data. Quest-item drops still learn and still build source pins, but non-quest loot like generic trade goods and junk no longer pollutes the item learner or source cache.</li>