Release v9.7.10

This commit is contained in:
Xurkon
2026-02-21 22:52:51 -06:00
parent 52c13b98aa
commit c42945a1f8
7 changed files with 83 additions and 124 deletions
+10
View File
@@ -1,5 +1,15 @@
# Changelog # 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 ## v9.7.9
### Fixes ### Fixes
-7
View File
@@ -1100,18 +1100,11 @@ function QuestieDB.IsComplete(questId)
local allDone = true local allDone = true
for _, obj in ipairs(objectives) do for _, obj in ipairs(objectives) do
if obj.numRequired and obj.numRequired > 0 and obj.numFulfilled ~= obj.numRequired then 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 allDone = false
break break
end end
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 return allDone and 1 or 0
end end
+69 -114
View File
@@ -436,33 +436,32 @@ function QuestieArrow:UpdateNearestTargets()
end end
end end
if quest.Id == 12843 or quest.Id == 12844 then local isComplete = quest.isComplete or (QuestieDB.IsComplete(quest.Id) == 1)
print("QuestieArrow: Evaluating " .. tostring(quest.name) .. ". quest.isComplete is " .. tostring(quest.isComplete) .. ", QuestieDB.IsComplete is " .. tostring(QuestieDB.IsComplete(quest.Id))) if isComplete then
quest.isComplete = true
end end
-- If the quest is complete, track the finisher/turn-in location local function _GetCompleteIconType()
if quest.isComplete or QuestieDB.IsComplete(quest.Id) == 1 then local iconType = Questie.ICON_TYPE_COMPLETE
quest.isComplete = true if QuestieDB and QuestieDB.IsActiveEventQuest and QuestieDB.IsActiveEventQuest(quest.Id) then
local function _GetCompleteIconType() iconType = Questie.ICON_TYPE_EVENTQUEST_COMPLETE
local iconType = Questie.ICON_TYPE_COMPLETE elseif QuestieDB and QuestieDB.IsPvPQuest and QuestieDB.IsPvPQuest(quest.Id) then
if QuestieDB and QuestieDB.IsActiveEventQuest and QuestieDB.IsActiveEventQuest(quest.Id) then iconType = Questie.ICON_TYPE_PVPQUEST_COMPLETE
iconType = Questie.ICON_TYPE_EVENTQUEST_COMPLETE elseif quest.IsRepeatable then
elseif QuestieDB and QuestieDB.IsPvPQuest and QuestieDB.IsPvPQuest(quest.Id) then iconType = Questie.ICON_TYPE_REPEATABLE_COMPLETE
iconType = Questie.ICON_TYPE_PVPQUEST_COMPLETE end
elseif quest.IsRepeatable then return iconType
iconType = Questie.ICON_TYPE_REPEATABLE_COMPLETE end
end
return iconType local function _CollectFinisherSpawns(finisher)
if not finisher then
return
end end
local function _CollectFinisherSpawns(finisher) local iconPath = ResolveIconTexture(_GetCompleteIconType())
if not finisher then
return
end
local iconPath = ResolveIconTexture(_GetCompleteIconType()) if finisher.spawns then
for finisherZone, spawns in pairs(finisher.spawns) do
for finisherZone, spawns in pairs(finisher.spawns or {}) do
if finisherZone and spawns then if finisherZone and spawns then
for _, coords in ipairs(spawns) do for _, coords in ipairs(spawns) do
if coords and coords[1] and coords[2] then if coords and coords[1] and coords[2] then
@@ -474,31 +473,18 @@ function QuestieArrow:UpdateNearestTargets()
local x = value[2] local x = value[2]
local y = value[3] local y = value[3]
-- Auto Logic: Hide distant quests (different zone) -- Auto Logic: Hide distant quests (different zone)
if usingAutoLogic and zone ~= playerZoneId then if not (usingAutoLogic and zone ~= playerZoneId) then
-- continue
else
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone) local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone)
if uiMapId and x and y then if uiMapId and x and y then
local targetX, targetY, targetInstance = HBD local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId)
:GetWorldCoordinatesFromZone(
x / 100.0, y / 100.0, uiMapId)
if targetX and targetY and targetInstance then if targetX and targetY and targetInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
playerY,
targetX, targetY)
if dist then if dist then
if targetInstance ~= playerInstance then if targetInstance ~= playerInstance then
dist = 500000 + dist * 100 dist = 500000 + dist * 100
end end
table.insert(sortedTargets, { table.insert(sortedTargets, {
x = x, x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist,
y = y,
uiMapId = uiMapId,
title = quest.name,
questLevel = quest.level,
iconPath = iconPath,
distance = dist,
}) })
end end
end end
@@ -508,32 +494,20 @@ function QuestieArrow:UpdateNearestTargets()
end end
else else
-- Auto Logic: Hide distant quests (different zone) -- Auto Logic: Hide distant quests (different zone)
if usingAutoLogic and finisherZone ~= playerZoneId then if not (usingAutoLogic and finisherZone ~= playerZoneId) then
-- continue
else
local x = coords[1] local x = coords[1]
local y = coords[2] local y = coords[2]
local uiMapId = ZoneDB:GetUiMapIdByAreaId(finisherZone) local uiMapId = ZoneDB:GetUiMapIdByAreaId(finisherZone)
if uiMapId then if uiMapId then
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone( local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId)
x / 100.0, y / 100.0, uiMapId)
if targetX and targetY and targetInstance then if targetX and targetY and targetInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
targetX,
targetY)
if dist then if dist then
if targetInstance ~= playerInstance then if targetInstance ~= playerInstance then
dist = 500000 + dist * 100 dist = 500000 + dist * 100
end end
table.insert(sortedTargets, { table.insert(sortedTargets, {
x = x, x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist,
y = y,
uiMapId = uiMapId,
title = quest.name,
questLevel = quest.level,
iconPath = iconPath,
distance = dist,
}) })
end end
end end
@@ -543,56 +517,34 @@ function QuestieArrow:UpdateNearestTargets()
end end
end end
end end
end
end
if finisher.waypoints then
if finisher.waypoints then for zone, waypoints in pairs(finisher.waypoints) do
for zone, waypoints in pairs(finisher.waypoints) do -- Auto Logic: Hide distant quests (different zone)
-- Auto Logic: Hide distant quests (different zone) if not (usingAutoLogic and zone ~= playerZoneId) then
if usingAutoLogic and zone ~= playerZoneId then if waypoints and waypoints[1] and waypoints[1][1] and waypoints[1][1][1] then
-- continue local x = waypoints[1][1][1]
elseif waypoints and waypoints[1] and waypoints[1][1] and waypoints[1][1][1] then local y = waypoints[1][1][2]
local x = waypoints[1][1][1] local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone)
local y = waypoints[1][1][2] if uiMapId and x and y then
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone) local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId)
if uiMapId and x and y then if targetX and targetY and targetInstance then
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
y / 100.0, uiMapId) if dist then
if targetX and targetY and targetInstance then if targetInstance ~= playerInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, dist = 500000 + dist * 100
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
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
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
end end
@@ -616,31 +568,20 @@ function QuestieArrow:UpdateNearestTargets()
if spawnData and spawnData.Spawns then if spawnData and spawnData.Spawns then
for zone, spawns in pairs(spawnData.Spawns) do for zone, spawns in pairs(spawnData.Spawns) do
-- Auto Logic: Hide distant quests (different zone) -- Auto Logic: Hide distant quests (different zone)
if usingAutoLogic and zone ~= playerZoneId then if not (usingAutoLogic and zone ~= playerZoneId) then
-- continue
else
for _, spawn in pairs(spawns) do for _, spawn in pairs(spawns) do
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone) local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone)
if uiMapId then if uiMapId then
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone( local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(spawn[1] / 100.0, spawn[2] / 100.0, uiMapId)
spawn[1] / 100.0, spawn[2] / 100.0, uiMapId)
if targetX and targetY and targetInstance then if targetX and targetY and targetInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
targetY)
if dist then if dist then
if targetInstance ~= playerInstance then if targetInstance ~= playerInstance then
dist = 500000 + dist * 100 dist = 500000 + dist * 100
end end
table.insert(sortedTargets, { table.insert(sortedTargets, {
x = spawn[1], x = spawn[1], y = spawn[2], uiMapId = uiMapId, title = quest.name, questLevel = quest.level,
y = spawn[2], iconPath = ResolveIconTexture(objective.Icon) or ResolveIconTexture(spawnData and spawnData.Icon), distance = dist,
uiMapId = uiMapId,
title = quest.name,
questLevel = quest.level,
iconPath = ResolveIconTexture(objective.Icon) or
ResolveIconTexture(spawnData and spawnData.Icon),
distance = dist,
}) })
end end
end end
@@ -652,7 +593,21 @@ function QuestieArrow:UpdateNearestTargets()
end end
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 if quest.Objectives then
for _, objective in pairs(quest.Objectives) do for _, objective in pairs(quest.Objectives) do
+1 -1
View File
@@ -1239,7 +1239,7 @@ function QuestieQuest:PopulateObjective(quest, objectiveIndex, objective, blockI
-- For completed and uncompleted objectives -- For completed and uncompleted objectives
_RegisterObjectiveTooltips(objective, quest.Id, blockItemTooltips) _RegisterObjectiveTooltips(objective, quest.Id, blockItemTooltips)
if completed then if completed or quest.isComplete then
_UnloadAlreadySpawnedIcons(objective) _UnloadAlreadySpawnedIcons(objective)
return return
end end
+1
View File
@@ -33,6 +33,7 @@ local playerClassFlagX2 = 1 -- dummy default value to always return class not ma
local math_max = math.max; local math_max = math.max;
QuestiePlayer.numberOfGroupMembers = 0 QuestiePlayer.numberOfGroupMembers = 0
QuestiePlayer.pendingCompleteQuestIds = {}
function QuestiePlayer:Initialize() function QuestiePlayer:Initialize()
_QuestiePlayer.playerLevel = UnitLevel("player") _QuestiePlayer.playerLevel = UnitLevel("player")
+1 -1
View File
@@ -6,7 +6,7 @@
## Notes-esES: Ayundante de misión ## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão ## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête ## Notes-frFR: Assistant de quête
## Version: 9.7.9 ## Version: 9.7.10
## RequiredDeps: ## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu ## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig ## SavedVariables: QuestieConfig
+1 -1
View File
@@ -2,7 +2,7 @@
# Questie (3.3.5a) # 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) ![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/) [![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) [![Patreon](https://img.shields.io/badge/Patreon-F96854?style=for-the-badge&logo=patreon&logoColor=white)](https://www.patreon.com/Xurkon)