From c42945a1f83ef46e11b9b918f99c85192945f895 Mon Sep 17 00:00:00 2001 From: Xurkon <36556990+Xurkon@users.noreply.github.com> Date: Sat, 21 Feb 2026 22:52:51 -0600 Subject: [PATCH] Release v9.7.10 --- CHANGELOG.md | 10 ++ Database/QuestieDB.lua | 7 -- Modules/Arrow/QuestieArrow.lua | 183 +++++++++++++-------------------- Modules/Quest/QuestieQuest.lua | 2 +- Modules/QuestiePlayer.lua | 1 + Questie-335.toc | 2 +- README.md | 2 +- 7 files changed, 83 insertions(+), 124 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0192bc2..e59195d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## v9.7.10 + +### Fixes +- **[Arrow]** Refactored Arrow logic to drastically improve target distance calculations and prioritize targets correctly based on the player's current zone. +- **[Arrow]** Fixed a bug where the Arrow would mistakenly point to previously completed objective locations instead of the Quest Finisher's exact location. +- **[Tracker]** Fixed `QuestieDB.IsComplete` edge case returning incomplete incorrectly; now verifies `numFulfilled == numRequired` to immediately acknowledge completed quests while awaiting the server flag. +- **[Tracker]** Resolved false-positive "broken quest log" errors spamming chat on WotLK servers by correctly handling API responses for trackable objectives. +- **[Tracker]** Demoted harmless WotLK objective cache count mismatches from Error to Debug visibility level to eliminate chat spam on login. +- **[Quest]** Fixed quest arrow pointing to the key-drop NPC after using all consumable quest keys (e.g. Cold Iron Key for "They Took Our Men!" quest 12843). When a quest uses a key item that is consumed on interaction, it leaves the bag and `CheckQuestSourceItem` returns false, incorrectly triggering a quest reset that re-drew the key source NPC on the map. Now checks if all tracked objectives are already `Completed=true` before applying the reset, preventing the spurious icon. + ## v9.7.9 ### Fixes diff --git a/Database/QuestieDB.lua b/Database/QuestieDB.lua index 2602368..70ee71f 100644 --- a/Database/QuestieDB.lua +++ b/Database/QuestieDB.lua @@ -1100,18 +1100,11 @@ function QuestieDB.IsComplete(questId) local allDone = true for _, obj in ipairs(objectives) do if obj.numRequired and obj.numRequired > 0 and obj.numFulfilled ~= obj.numRequired then - if questLogEntry.questId == 12843 or questLogEntry.questId == 12844 then - print("QuestieDB " .. tostring(questLogEntry.title) .. " incomplete because obj " .. tostring(obj.text) .. " has " .. tostring(obj.numFulfilled) .. "/" .. tostring(obj.numRequired)) - end allDone = false break end end - if (questLogEntry.questId == 12843 or questLogEntry.questId == 12844) and allDone then - print("QuestieDB " .. tostring(questLogEntry.title) .. " thinks it is all done.") - end - return allDone and 1 or 0 end diff --git a/Modules/Arrow/QuestieArrow.lua b/Modules/Arrow/QuestieArrow.lua index 1e82437..543d3b2 100644 --- a/Modules/Arrow/QuestieArrow.lua +++ b/Modules/Arrow/QuestieArrow.lua @@ -436,33 +436,32 @@ function QuestieArrow:UpdateNearestTargets() end end - if quest.Id == 12843 or quest.Id == 12844 then - print("QuestieArrow: Evaluating " .. tostring(quest.name) .. ". quest.isComplete is " .. tostring(quest.isComplete) .. ", QuestieDB.IsComplete is " .. tostring(QuestieDB.IsComplete(quest.Id))) + local isComplete = quest.isComplete or (QuestieDB.IsComplete(quest.Id) == 1) + if isComplete then + quest.isComplete = true end - -- If the quest is complete, track the finisher/turn-in location - if quest.isComplete or QuestieDB.IsComplete(quest.Id) == 1 then - quest.isComplete = true - local function _GetCompleteIconType() - local iconType = Questie.ICON_TYPE_COMPLETE - if QuestieDB and QuestieDB.IsActiveEventQuest and QuestieDB.IsActiveEventQuest(quest.Id) then - iconType = Questie.ICON_TYPE_EVENTQUEST_COMPLETE - elseif QuestieDB and QuestieDB.IsPvPQuest and QuestieDB.IsPvPQuest(quest.Id) then - iconType = Questie.ICON_TYPE_PVPQUEST_COMPLETE - elseif quest.IsRepeatable then - iconType = Questie.ICON_TYPE_REPEATABLE_COMPLETE - end - return iconType + local function _GetCompleteIconType() + local iconType = Questie.ICON_TYPE_COMPLETE + if QuestieDB and QuestieDB.IsActiveEventQuest and QuestieDB.IsActiveEventQuest(quest.Id) then + iconType = Questie.ICON_TYPE_EVENTQUEST_COMPLETE + elseif QuestieDB and QuestieDB.IsPvPQuest and QuestieDB.IsPvPQuest(quest.Id) then + iconType = Questie.ICON_TYPE_PVPQUEST_COMPLETE + elseif quest.IsRepeatable then + iconType = Questie.ICON_TYPE_REPEATABLE_COMPLETE + end + return iconType + end + + local function _CollectFinisherSpawns(finisher) + if not finisher then + return end - local function _CollectFinisherSpawns(finisher) - if not finisher then - return - end + local iconPath = ResolveIconTexture(_GetCompleteIconType()) - local iconPath = ResolveIconTexture(_GetCompleteIconType()) - - for finisherZone, spawns in pairs(finisher.spawns or {}) do + if finisher.spawns then + for finisherZone, spawns in pairs(finisher.spawns) do if finisherZone and spawns then for _, coords in ipairs(spawns) do if coords and coords[1] and coords[2] then @@ -474,31 +473,18 @@ function QuestieArrow:UpdateNearestTargets() local x = value[2] local y = value[3] -- Auto Logic: Hide distant quests (different zone) - if usingAutoLogic and zone ~= playerZoneId then - -- continue - else + if not (usingAutoLogic and zone ~= playerZoneId) then local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone) if uiMapId and x and y then - local targetX, targetY, targetInstance = HBD - :GetWorldCoordinatesFromZone( - x / 100.0, y / 100.0, uiMapId) + local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId) if targetX and targetY and targetInstance then - local dist = HBD:GetWorldDistance(targetInstance, playerX, - playerY, - targetX, targetY) + local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY) if dist then if targetInstance ~= playerInstance then dist = 500000 + dist * 100 end - table.insert(sortedTargets, { - x = x, - y = y, - uiMapId = uiMapId, - title = quest.name, - questLevel = quest.level, - iconPath = iconPath, - distance = dist, + x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist, }) end end @@ -508,32 +494,20 @@ function QuestieArrow:UpdateNearestTargets() end else -- Auto Logic: Hide distant quests (different zone) - if usingAutoLogic and finisherZone ~= playerZoneId then - -- continue - else + if not (usingAutoLogic and finisherZone ~= playerZoneId) then local x = coords[1] local y = coords[2] local uiMapId = ZoneDB:GetUiMapIdByAreaId(finisherZone) if uiMapId then - local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone( - x / 100.0, y / 100.0, uiMapId) + local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId) if targetX and targetY and targetInstance then - local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, - targetX, - targetY) + local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY) if dist then if targetInstance ~= playerInstance then dist = 500000 + dist * 100 end - table.insert(sortedTargets, { - x = x, - y = y, - uiMapId = uiMapId, - title = quest.name, - questLevel = quest.level, - iconPath = iconPath, - distance = dist, + x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist, }) end end @@ -543,56 +517,34 @@ function QuestieArrow:UpdateNearestTargets() end end end + end + end - - if finisher.waypoints then - for zone, waypoints in pairs(finisher.waypoints) do - -- Auto Logic: Hide distant quests (different zone) - if usingAutoLogic and zone ~= playerZoneId then - -- continue - elseif waypoints and waypoints[1] and waypoints[1][1] and waypoints[1][1][1] then - local x = waypoints[1][1][1] - local y = waypoints[1][1][2] - local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone) - if uiMapId and x and y then - local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, - y / 100.0, uiMapId) - if targetX and targetY and targetInstance then - local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, - targetY) - if dist then - if targetInstance ~= playerInstance then - dist = 500000 + dist * 100 - end - - table.insert(sortedTargets, { - x = x, - y = y, - uiMapId = uiMapId, - title = quest.name, - questLevel = quest.level, - iconPath = iconPath, - distance = dist, - }) + if finisher.waypoints then + for zone, waypoints in pairs(finisher.waypoints) do + -- Auto Logic: Hide distant quests (different zone) + if not (usingAutoLogic and zone ~= playerZoneId) then + if waypoints and waypoints[1] and waypoints[1][1] and waypoints[1][1][1] then + local x = waypoints[1][1][1] + local y = waypoints[1][1][2] + local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone) + if uiMapId and x and y then + local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId) + if targetX and targetY and targetInstance then + local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY) + if dist then + if targetInstance ~= playerInstance then + dist = 500000 + dist * 100 end + table.insert(sortedTargets, { + x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist, + }) end end end end end end - - if quest.Finisher and quest.Finisher.Id and quest.Finisher.Type then - local finisher - if quest.Finisher.Type == "monster" and QuestieDB and QuestieDB.GetNPC then - finisher = QuestieDB:GetNPC(quest.Finisher.Id) - elseif quest.Finisher.Type == "object" and QuestieDB and QuestieDB.GetObject then - finisher = QuestieDB:GetObject(quest.Finisher.Id) - end - _CollectFinisherSpawns(finisher) - end - - return end end @@ -616,31 +568,20 @@ function QuestieArrow:UpdateNearestTargets() if spawnData and spawnData.Spawns then for zone, spawns in pairs(spawnData.Spawns) do -- Auto Logic: Hide distant quests (different zone) - if usingAutoLogic and zone ~= playerZoneId then - -- continue - else + if not (usingAutoLogic and zone ~= playerZoneId) then for _, spawn in pairs(spawns) do local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone) if uiMapId then - local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone( - spawn[1] / 100.0, spawn[2] / 100.0, uiMapId) + local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(spawn[1] / 100.0, spawn[2] / 100.0, uiMapId) if targetX and targetY and targetInstance then - local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, - targetY) + local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY) if dist then if targetInstance ~= playerInstance then dist = 500000 + dist * 100 end - table.insert(sortedTargets, { - x = spawn[1], - y = spawn[2], - uiMapId = uiMapId, - title = quest.name, - questLevel = quest.level, - iconPath = ResolveIconTexture(objective.Icon) or - ResolveIconTexture(spawnData and spawnData.Icon), - distance = dist, + x = spawn[1], y = spawn[2], uiMapId = uiMapId, title = quest.name, questLevel = quest.level, + iconPath = ResolveIconTexture(objective.Icon) or ResolveIconTexture(spawnData and spawnData.Icon), distance = dist, }) end end @@ -652,7 +593,21 @@ function QuestieArrow:UpdateNearestTargets() end end - + -- Main Logic Route for this quest target + if isComplete then + if quest.Finisher and quest.Finisher.Id and quest.Finisher.Type then + local finisher + if quest.Finisher.Type == "monster" and QuestieDB and QuestieDB.GetNPC then + finisher = QuestieDB:GetNPC(quest.Finisher.Id) + elseif quest.Finisher.Type == "object" and QuestieDB and QuestieDB.GetObject then + finisher = QuestieDB:GetObject(quest.Finisher.Id) + end + + _CollectFinisherSpawns(finisher) + end + -- If the quest is complete, do not add normal objectives to the arrow! + return + end if quest.Objectives then for _, objective in pairs(quest.Objectives) do diff --git a/Modules/Quest/QuestieQuest.lua b/Modules/Quest/QuestieQuest.lua index a2be8ff..ae95025 100644 --- a/Modules/Quest/QuestieQuest.lua +++ b/Modules/Quest/QuestieQuest.lua @@ -1239,7 +1239,7 @@ function QuestieQuest:PopulateObjective(quest, objectiveIndex, objective, blockI -- For completed and uncompleted objectives _RegisterObjectiveTooltips(objective, quest.Id, blockItemTooltips) - if completed then + if completed or quest.isComplete then _UnloadAlreadySpawnedIcons(objective) return end diff --git a/Modules/QuestiePlayer.lua b/Modules/QuestiePlayer.lua index 39dc577..cd23d24 100644 --- a/Modules/QuestiePlayer.lua +++ b/Modules/QuestiePlayer.lua @@ -33,6 +33,7 @@ local playerClassFlagX2 = 1 -- dummy default value to always return class not ma local math_max = math.max; QuestiePlayer.numberOfGroupMembers = 0 +QuestiePlayer.pendingCompleteQuestIds = {} function QuestiePlayer:Initialize() _QuestiePlayer.playerLevel = UnitLevel("player") diff --git a/Questie-335.toc b/Questie-335.toc index 9ce8443..ad78690 100644 --- a/Questie-335.toc +++ b/Questie-335.toc @@ -6,7 +6,7 @@ ## Notes-esES: Ayundante de misión ## Notes-ptBR: Ajudante de missão ## Notes-frFR: Assistant de quête -## Version: 9.7.9 +## Version: 9.7.10 ## RequiredDeps: ## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu ## SavedVariables: QuestieConfig diff --git a/README.md b/README.md index b8a4174..1a0ae09 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Questie (3.3.5a) -![Version](https://img.shields.io/badge/version-v9.7.5-blue.svg?style=for-the-badge) +![Version](https://img.shields.io/badge/version-v9.7.10-blue.svg?style=for-the-badge) ![Downloads](https://img.shields.io/github/downloads/Xurkon/PE-Questie/total?style=for-the-badge&color=e67e22) [![Documentation](https://img.shields.io/badge/Documentation-View%20Docs-58a6ff?style=for-the-badge)](https://xurkon.github.io/PE-Questie/) [![Patreon](https://img.shields.io/badge/Patreon-F96854?style=for-the-badge&logo=patreon&logoColor=white)](https://www.patreon.com/Xurkon)