feat: add Use Quest Item keybind + fix custom zone names + nil check

This commit is contained in:
Xurkon
2026-03-28 22:33:54 -05:00
parent 69c0f8045c
commit e6c27ddf77
5 changed files with 187 additions and 38 deletions
+49 -1
View File
@@ -170,6 +170,51 @@ function QuestieTracker:PruneGhostQuests()
return removedAny
end
local questItemKeybindFrame = nil
questItemUseFrame = nil
function QuestieTracker_UpdateQuestItemKeybind()
if not questItemKeybindFrame then
return
end
local keybind = Questie and Questie.db and Questie.db.profile and Questie.db.profile.useQuestItemKeybind
ClearOverrideBindings(questItemKeybindFrame)
if keybind and keybind ~= "" then
local upperKeybind = string.upper(keybind)
SetOverrideBinding(questItemKeybindFrame, true, upperKeybind, "CLICK Questie_QuestItemUseBtn:LeftButton")
end
end
local function _InstallQuestItemKeybindHandler()
if questItemKeybindFrame then
return
end
questItemKeybindFrame = CreateFrame("Frame", "Questie_QuestItemKeybindFrame")
questItemUseFrame = CreateFrame("Button", "Questie_QuestItemUseBtn", questItemKeybindFrame, "SecureActionButtonTemplate")
questItemUseFrame:SetAttribute("type", "item")
questItemUseFrame:Hide()
questItemKeybindFrame:SetScript("OnEvent", function(self, event)
if event == "PLAYER_LOGIN" then
C_Timer.After(0.5, QuestieTracker_UpdateQuestItemKeybind)
elseif event == "PLAYER_REGEN_ENABLED" then
ClearOverrideBindings(questItemKeybindFrame)
end
end)
questItemKeybindFrame:RegisterEvent("PLAYER_LOGIN")
questItemKeybindFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
if IsLoggedIn() then
C_Timer.After(0.5, QuestieTracker_UpdateQuestItemKeybind)
end
end
local function _InstallQuestLogUpdateListener()
if QuestieTracker._questLogUpdateListenerInstalled then return end
@@ -256,6 +301,9 @@ function QuestieTracker.Initialize()
-- Note: _InstallMissingQuestLogWarningFilter was removed (fix #1).
-- Ghost quest warnings are now prevented upstream in PruneGhostQuests.
-- Initialize keyboard handler for Use Quest Item keybind
_InstallQuestItemKeybindHandler()
TrackerFadeTicker.Initialize(trackerBaseFrame, trackerHeaderFrame)
QuestieTracker.started = true
@@ -1230,7 +1278,7 @@ function QuestieTracker:Update()
-- Add incomplete Quest Objectives
if complete == 0 and quest.isComplete ~= true then
for _, objective in pairs(quest.Objectives) do
if objective and (not Questie.db.profile.hideCompletedQuestObjectives or (Questie.db.profile.hideCompletedQuestObjectives and objective.Needed ~= objective.Collected)) then
if objective and objective.Description and (not Questie.db.profile.hideCompletedQuestObjectives or (Questie.db.profile.hideCompletedQuestObjectives and objective.Needed ~= objective.Collected)) then
-- Get next line in linePool
line = TrackerLinePool.GetNextLine()
+122 -37
View File
@@ -656,41 +656,7 @@ local function _GetContinent(uiMapId)
end
end
local function _GetZoneName(zoneOrSort, questId)
if not zoneOrSort then return "Unknown Zone" end
local zoneName
local sortObj = Questie.db.profile.trackerSortObjectives
if sortObj == "byZone" or sortObj == "byZonePlayerProximity" or sortObj == "byZonePlayerProximityReversed" then
if (zoneOrSort) > 0 then
-- Valid ZoneID
zoneName = TrackerUtils:GetZoneNameByID(zoneOrSort)
elseif (zoneOrSort) < 0 then
-- Valid CategoryID
zoneName = TrackerUtils:GetCategoryNameByID(zoneOrSort)
else
-- The quest has no explicit zone or category. Fallback to "Unknown Zone"
zoneName = "Unknown Zone"
Questie:Debug(Questie.DEBUG_CRITICAL, "[TrackerUtils:_GetZoneName] zoneOrSort", zoneOrSort, "of quest",
questId, "is not in the Database!")
end
else
-- Let's create custom Zones based on Sorting type.
if sortObj == "byComplete" then
zoneName = "Quests (By %% Complete)"
elseif sortObj == "byCompleteReversed" then
zoneName = "Quests (By %% Complete Reversed)"
elseif sortObj == "byLevel" then
zoneName = "Quests (By Level)"
elseif sortObj == "byLevelReversed" then
zoneName = "Quests (By Level Reversed)"
elseif sortObj == "byProximity" then
zoneName = "Quests (By Proximity)"
elseif sortObj == "byProximityReversed" then
zoneName = "Quests (By Proximity Reversed)"
end
end
return zoneName
end
---@return table sortedQuestIds Table with sorted Quest ID's by Sort Type
---@return table questDetails Table with raw quest table from QuestiePlayer.currentQuestLog, percentage completed value per quest, and a "translated" zoneName
@@ -727,6 +693,47 @@ local function GetQuestLogZoneName(questId)
return nil
end
local function _GetZoneName(zoneOrSort, questId, zoneNameOverride)
if zoneNameOverride and zoneNameOverride ~= "" then
return zoneNameOverride
end
if not zoneOrSort then return "Unknown Zone" end
local zoneName
local sortObj = Questie.db.profile.trackerSortObjectives
if sortObj == "byZone" or sortObj == "byZonePlayerProximity" or sortObj == "byZonePlayerProximityReversed" then
if (zoneOrSort) > 0 then
zoneName = TrackerUtils:GetZoneNameByID(zoneOrSort)
if not zoneName or zoneName == "Unknown Zone" then
local logZone = GetQuestLogZoneName(questId)
if logZone then
zoneName = logZone
end
end
elseif (zoneOrSort) < 0 then
zoneName = TrackerUtils:GetCategoryNameByID(zoneOrSort)
else
zoneName = "Unknown Zone"
Questie:Debug(Questie.DEBUG_CRITICAL, "[TrackerUtils:_GetZoneName] zoneOrSort", zoneOrSort, "of quest",
questId, "is not in the Database!")
end
else
if sortObj == "byComplete" then
zoneName = "Quests (By %% Complete)"
elseif sortObj == "byCompleteReversed" then
zoneName = "Quests (By %% Complete Reversed)"
elseif sortObj == "byLevel" then
zoneName = "Quests (By Level)"
elseif sortObj == "byLevelReversed" then
zoneName = "Quests (By Level Reversed)"
elseif sortObj == "byProximity" then
zoneName = "Quests (By Proximity)"
elseif sortObj == "byProximityReversed" then
zoneName = "Quests (By Proximity Reversed)"
end
end
return zoneName
end
-- Returns nil if the quest is not currently in the quest log.
function TrackerUtils:BuildFallbackQuest(questId)
for i = 1, GetNumQuestLogEntries() do
@@ -763,6 +770,10 @@ function TrackerUtils:BuildFallbackQuest(questId)
end
end
local zoneId = (zoneText and GetAreaIdByZoneName(zoneText)) or 0
local zoneNameOverride = nil
if zoneText and (not zoneId or zoneId == 0) then
zoneNameOverride = zoneText
end
local quest = {
Id = questId,
@@ -770,6 +781,7 @@ function TrackerUtils:BuildFallbackQuest(questId)
level = level or 0,
zoneOrSort = zoneId,
zoneName = zoneText,
zoneNameOverride = zoneNameOverride,
Objectives = objectives,
SpecialObjectives = {},
isFallback = true,
@@ -829,7 +841,13 @@ function TrackerUtils:GetSortedQuestIds()
local logZone = GetQuestLogZoneName(capturedId)
if logZone then
quest.zoneName = logZone
quest.zoneOrSort = GetAreaIdByZoneName(logZone) or 0
local areaId = GetAreaIdByZoneName(logZone)
if areaId and areaId > 0 then
quest.zoneOrSort = areaId
else
quest.zoneOrSort = 0
quest.zoneNameOverride = logZone
end
end
end
QuestiePlayer.currentQuestlog[qid] = quest
@@ -860,7 +878,7 @@ function TrackerUtils:GetSortedQuestIds()
-- Create questDetails table keys and insert values
questDetails[qid] = {}
questDetails[qid].quest = quest
questDetails[qid].zoneName = quest.zoneName or _GetZoneName(quest.zoneOrSort, qid)
questDetails[qid].zoneName = _GetZoneName(quest.zoneOrSort, qid, quest.zoneNameOverride)
if quest:IsComplete() == 1 or (not next(quest.Objectives)) then
questDetails[qid].questCompletePercent = 1
@@ -1279,3 +1297,70 @@ function TrackerUtils:UpdateVoiceOverPlayButtons()
end
end
end
function TrackerUtils:UseNearestQuestItem()
if InCombatLockdown() then
Questie:Debug(Questie.DEBUG_INFO, "[TrackerUtils:UseNearestQuestItem] Cannot use items while in combat")
return
end
local playerPosition = _GetWorldPlayerPosition()
if not playerPosition then
Questie:Debug(Questie.DEBUG_INFO, "[TrackerUtils:UseNearestQuestItem] Could not get player position")
return
end
local bestDistance = math.huge
local bestQuestIndex = nil
local bestItemName = nil
local numEntries, numQuests = GetNumQuestLogEntries()
for i = 1, numEntries do
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, questId = GetQuestLogTitle(i)
if not isHeader and questId then
local itemInfo = GetQuestLogSpecialItemInfo(i)
if itemInfo then
local itemName
if type(itemInfo) == "string" then
itemName = itemInfo
else
itemName = tostring(itemInfo)
end
local quest = QuestieDB.GetQuest(questId)
if quest and quest:IsComplete() ~= 1 then
local spawn, zone = QuestieMap:GetNearestQuestSpawn(quest)
if spawn and zone then
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone)
if uiMapId then
local _, worldPosition = C_Map.GetWorldPosFromMapPos(uiMapId, {
x = spawn[1] / 100,
y = spawn[2] / 100
})
if worldPosition then
local distance = _GetDistance(playerPosition.x, playerPosition.y, worldPosition.x, worldPosition.y)
if distance < bestDistance then
bestDistance = distance
bestQuestIndex = i
bestItemName = itemName
end
end
end
end
end
end
end
end
if bestQuestIndex and bestItemName then
Questie:Debug(Questie.DEBUG_INFO, "[TrackerUtils:UseNearestQuestItem] Using item:", bestItemName, "for quest index:", bestQuestIndex, "distance:", bestDistance)
UseItemByName(bestItemName)
else
Questie:Debug(Questie.DEBUG_INFO, "[TrackerUtils:UseNearestQuestItem] No usable quest item found")
end
end