diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ae2644..211d73f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +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. - **[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. diff --git a/Modules/Options/GeneralTab/QuestieOptionsGeneral.lua b/Modules/Options/GeneralTab/QuestieOptionsGeneral.lua index a110e00..048bfe3 100644 --- a/Modules/Options/GeneralTab/QuestieOptionsGeneral.lua +++ b/Modules/Options/GeneralTab/QuestieOptionsGeneral.lua @@ -481,6 +481,59 @@ function QuestieOptions.tabs.general:Initialize() Questie.db.profile.enableTooltipsNextInChain = value end }, + learnerTooltipHeader = { + type = "header", + order = 8.55, + name = function() return l10n('Learner Tooltips'); end, + }, + learnerTooltips = { + type = "toggle", + order = 8.56, + name = function() return l10n('Enable learner tooltips'); end, + desc = function() return l10n('Show the learned spawn line and other learner-specific tooltip additions.'); end, + width = 1.5, + disabled = function() return not Questie.db.profile.enableTooltips; end, + get = function() return Questie.db.profile.learnerTooltips ~= false end, + set = function(_, value) + Questie.db.profile.learnerTooltips = value + end + }, + learnerTooltipShowSpawn = { + type = "toggle", + order = 8.57, + name = function() return l10n('Show learned spawn line'); end, + desc = function() return l10n('Show the learned spawn coordinates and kill count on unit 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.learnerTooltipShowSpawn ~= false end, + set = function(_, value) + Questie.db.profile.learnerTooltipShowSpawn = value + end + }, + learnerTooltipShowConfidence = { + type = "toggle", + order = 8.58, + name = function() return l10n('Show learner confidence lines'); end, + desc = function() return l10n('Show the learner confidence line attached to learned NPC and object 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.learnerTooltipShowConfidence ~= false end, + set = function(_, value) + Questie.db.profile.learnerTooltipShowConfidence = value + end + }, + learnerTooltipAutoResize = { + type = "toggle", + order = 8.59, + name = function() return l10n('Auto-resize learner tooltips'); end, + desc = function() return l10n('Grow tooltip width to fit learner-added lines cleanly.'); 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.learnerTooltipAutoResize ~= false end, + set = function(_, value) + Questie.db.profile.learnerTooltipAutoResize = value + end + }, partyOnlyToggle = { type = "toggle", order = 8.6, diff --git a/Modules/Options/QuestieOptionsDefaults.lua b/Modules/Options/QuestieOptionsDefaults.lua index 1e3a044..eae5556 100644 --- a/Modules/Options/QuestieOptionsDefaults.lua +++ b/Modules/Options/QuestieOptionsDefaults.lua @@ -89,6 +89,10 @@ function QuestieOptionsDefaults:Load() enableTooltipsQuestLevel = true, showQuestXpAtMaxLevel = true, enableTooltipsNextInChain = true, + learnerTooltips = true, + learnerTooltipShowSpawn = true, + learnerTooltipShowConfidence = true, + learnerTooltipAutoResize = true, learnerBroadcast = true, enableMapIcons = true, enableMiniMapIcons = true, diff --git a/Modules/QuestieLearner.lua b/Modules/QuestieLearner.lua index 39ec5aa..b67c919 100644 --- a/Modules/QuestieLearner.lua +++ b/Modules/QuestieLearner.lua @@ -4434,6 +4434,9 @@ local _tooltipHookRegistered = false ---@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 + return + end local guid = UnitGUID(unitToken) if not guid then return end @@ -4459,8 +4462,15 @@ local function _AddLearnedSpawnTooltipLine(unitToken) local formattedX = ("%.1f"):format(x) local formattedY = ("%.1f"):format(y) - GameTooltip:AddDoubleLine("Learned spawn", ("(%s, %s) from %d kill%s"):format( - formattedX, formattedY, kills, kills == 1 and "" or "s")) + 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) + local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips") + if QuestieTooltips and QuestieTooltips.ResizeTooltip then + QuestieTooltips:ResizeTooltip(GameTooltip) + end end --- Registers the GameTooltip OnTooltipSetUnit hook once. diff --git a/Modules/Tooltips/Tooltip.lua b/Modules/Tooltips/Tooltip.lua index f7bd5aa..6fb1423 100644 --- a/Modules/Tooltips/Tooltip.lua +++ b/Modules/Tooltips/Tooltip.lua @@ -43,6 +43,53 @@ local _tooltipLastText = "" local _InitObjectiveTexts +local function _LearnerTooltipsEnabled() + return not (Questie.db and Questie.db.profile) or Questie.db.profile.learnerTooltips ~= false +end + +local function _ResizeTooltipToFit(tooltip) + if not tooltip or not tooltip.GetName then + return + end + + local tooltipName = tooltip:GetName() + if not tooltipName then + return + end + + local maxWidth = 0 + for i = 1, tooltip:NumLines() do + local left = _G[tooltipName .. "TextLeft" .. i] + local right = _G[tooltipName .. "TextRight" .. i] + if left and left:GetText() then + maxWidth = math.max(maxWidth, left:GetStringWidth() or 0) + end + if right and right:GetText() then + maxWidth = math.max(maxWidth, right:GetStringWidth() or 0) + end + end + + if maxWidth <= 0 then + return + end + + maxWidth = maxWidth + 24 + local currentWidth = tooltip.GetWidth and tooltip:GetWidth() or 0 + if currentWidth < maxWidth then + if tooltip.SetMinimumWidth then + tooltip:SetMinimumWidth(maxWidth) + end + tooltip:SetWidth(maxWidth) + end +end + +function QuestieTooltips:ResizeTooltip(tooltip) + if Questie.db.profile.learnerTooltipAutoResize == false then + return + end + _ResizeTooltipToFit(tooltip) +end + local function _GetQuestObjectiveSummary(questId) if not QuestieDB or not QuestieDB.GetQuest then return nil @@ -307,7 +354,7 @@ if key:sub(1,2) == "m_" then end end end - if learnedNpc.mc then + if learnedNpc.mc and _LearnerTooltipsEnabled() and Questie.db.profile.learnerTooltipShowConfidence ~= false then tinsert(tooltipLines, "|cFF5EBAF3(Learned - Confidence: " .. tostring(learnedNpc.mc) .. ")|r") end end @@ -360,7 +407,7 @@ elseif key:sub(1,2) == "o_" then end end end - if learnedObj.mc then + if learnedObj.mc and _LearnerTooltipsEnabled() and Questie.db.profile.learnerTooltipShowConfidence ~= false then tinsert(tooltipLines, "|cFF5EBAF3(Learned - Confidence: " .. tostring(learnedObj.mc) .. ")|r") end end diff --git a/Modules/Tooltips/TooltipHandler.lua b/Modules/Tooltips/TooltipHandler.lua index 7c0634c..e10b123 100644 --- a/Modules/Tooltips/TooltipHandler.lua +++ b/Modules/Tooltips/TooltipHandler.lua @@ -329,6 +329,9 @@ function _QuestieTooltips:AddUnitDataToTooltip() _AddQuestStarterDropsToTooltip(npcNum) end + if QuestieTooltips.ResizeTooltip then + QuestieTooltips:ResizeTooltip(GameTooltip) + end QuestieTooltips.lastGametooltipCount = _QuestieTooltips:CountTooltip() end lastGuid = guid; @@ -371,6 +374,9 @@ function _QuestieTooltips:AddItemDataToTooltip() for _, v in next, tooltipData do self:AddLine(v) end + if QuestieTooltips.ResizeTooltip then + QuestieTooltips:ResizeTooltip(self) + end end QuestieTooltips.lastGametooltipCount = _QuestieTooltips:CountTooltip() end @@ -426,6 +432,9 @@ function _QuestieTooltips:AddObjectDataToTooltip(name) end end end + if QuestieTooltips.ResizeTooltip then + QuestieTooltips:ResizeTooltip(GameTooltip) + end GameTooltip:Show() end QuestieTooltips.lastGametooltipType = "object"; diff --git a/Tests/QuestieLearnerDataSourceMode_spec.lua b/Tests/QuestieLearnerDataSourceMode_spec.lua index b44e5ab..3bafc3a 100644 --- a/Tests/QuestieLearnerDataSourceMode_spec.lua +++ b/Tests/QuestieLearnerDataSourceMode_spec.lua @@ -44,6 +44,24 @@ describe("QuestieLearner data source mode", function() assert.is_true(has(tip, "mode ~= \"static\" and mode ~= \"none\"")) end) + it("exposes learner tooltip controls and tooltip resize support", function() + local general = read("Modules/Options/GeneralTab/QuestieOptionsGeneral.lua") + local defaults = read("Modules/Options/QuestieOptionsDefaults.lua") + local tip = read("Modules/Tooltips/Tooltip.lua") + local handler = read("Modules/Tooltips/TooltipHandler.lua") + local learner = read("Modules/QuestieLearner.lua") + 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, "learnerTooltipAutoResize = true")) + assert.is_true(has(general, "Learner Tooltips")) + assert.is_true(has(general, "Enable learner tooltips")) + 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")) + end) + it("allows learner mode to draw pins from a single learned spawn when needed", function() local priv = read("Modules/Quest/QuestieQuestPrivates.lua") assert.is_true(has(priv, "local staticHasSpawns = spawns and next(spawns) ~= nil")) diff --git a/docs/changelog.html b/docs/changelog.html index 069bf55..f2d95bc 100644 --- a/docs/changelog.html +++ b/docs/changelog.html @@ -180,6 +180,7 @@
QuestieDB.GetQuest() where quests that had requiredSourceItems but no objectives table would dereference objectives[3] while building SpecialObjectives. 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.