diff --git a/CHANGELOG.md b/CHANGELOG.md
index e142561..b04f4f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,37 @@
# Changelog
+## v1.5.3 (2026-03-29)
+
+### Ascension Custom Zone Support
+
+- **[Fix — Custom Zone Map Pins]** Fixed map icons not appearing in Ascension custom zones (e.g., Valley of Trials, Northshire Valley). The issue was that custom zone UiMapData was not properly injected into `QuestieCompat.UiMapData` before HBD initialized its map cache. Added `ApplyCustomZones()` function in `ZoneDB` that hooks `ZoneDB.Initialize` to inject custom zones BEFORE the original initialization runs, ensuring HBD's `mapData` table contains custom zone entries like 1244 (Valley of Trials).
+
+- **[Fix — Zone Name Fallback]** Fixed "Unknown Zone" display for custom zones in the tracker. When `GetZoneNameByID` fails for custom zone IDs, the system now falls back to `GetQuestLogZoneName` which reads the zone header directly from the quest log where custom zone names are properly displayed.
+
+- **[Fix — GetCurrentUiMapID]** Updated `QuestieCompat.GetCurrentUiMapID` to check `QuestieCompat.UiMapData` directly for custom zone IDs. Previously, only `mapIdToUiMapId` was checked, which doesn't contain custom zones.
+
+- **[Fix — Arrow Waypoint Zone Filter]** Fixed waypoint arrow not showing targets in custom zones. The arrow's auto-tracking logic was filtering out objectives by zone comparison, but custom zones use different IDs (e.g., 1244 for Valley of Trials) than their parent zones (e.g., 14 for Durotar). Added `QuestiePlayer:GetCurrentUiMapId()` function and updated arrow zone filtering to compare both `playerZoneId` AND `playerUiMapId` against objective zone IDs.
+
+- **[Fix — Tracker Objective Nil Check]** Added defensive nil check for `objective.Description` when rendering quest objectives. Custom server quests may have objectives without a Description field, which would previously cause a crash.
+
+- **[Fix — InjectUiMapData Registration]** Fixed `QuestiePluginAPI:InjectUiMapData` to call `ZoneDB:ApplyCustomZones()` after injecting custom zone data, ensuring the zone mappings are properly registered with both `ZoneDB` and `QuestieCompat.UiMapData`.
+
+### Realm Detection
+
+- **[Fix — Realm Name Matching]** Fixed Ascension realm detection in `AscensionUiMapData.lua` to use `string.find()` instead of exact string comparison. Realms like "Bronzebeard - Warcraft Reborn" now properly match the "Bronzebeard" pattern, allowing custom zone data to load on all Ascension server variants.
+
+### Database
+
+- **[Feature — Use Quest Item Keybind]** Added configurable keyboard hotkey to automatically use the quest item for the nearest incomplete quest objective. When pressed, Questie scans active quests for usable quest items (items with spells), checks which ones are in the player's bags, calculates proximity to quest objectives, and uses the nearest one. Configurable via Tracker options tab under "Use Quest Item (Nearest)".
+
+### Keybinds
+
+- **[Feature — Dedicated Keybinds Tab]** Added a new Keybinds options tab with configurable keybinds for:
+ - **Use Nearest Quest Item** — Press to automatically use the quest item for the nearest incomplete quest objective
+ - **Toggle Options** — Open/close the Questie Options window
+ - **Toggle Tracker** — Show/hide the Questie Tracker
+ - **Toggle My Journey** — Open/close the Journey window
+
## v1.5.2 (2026-03-29)
### Ascension Custom Zone Support
diff --git a/Modules/Options/KeybindsTab/QuestieOptionsKeybinds.lua b/Modules/Options/KeybindsTab/QuestieOptionsKeybinds.lua
new file mode 100644
index 0000000..d85eb58
--- /dev/null
+++ b/Modules/Options/KeybindsTab/QuestieOptionsKeybinds.lua
@@ -0,0 +1,95 @@
+-------------------------
+--Import modules.
+-------------------------
+---@type QuestieOptions
+local QuestieOptions = QuestieLoader:ImportModule("QuestieOptions")
+---@type QuestieOptionsUtils
+local QuestieOptionsUtils = QuestieLoader:ImportModule("QuestieOptionsUtils")
+---@type l10n
+local l10n = QuestieLoader:ImportModule("l10n")
+
+QuestieOptions.tabs.keybinds = { ... }
+
+local keybindOptions = {}
+
+function QuestieOptions.tabs.keybinds:Initialize()
+ keybindOptions = {
+ name = function() return l10n('Keybinds') end,
+ type = "group",
+ order = 15,
+ args = {
+ header = {
+ type = "header",
+ order = 1,
+ name = function() return l10n('Keybind Options') end,
+ },
+ description = {
+ type = "description",
+ order = 2,
+ name = function() return l10n('Here you can configure various keybinds for Questie UI elements and features.') end,
+ },
+ spacer_general = QuestieOptionsUtils:Spacer(3),
+ generalKeybinds = {
+ type = "group",
+ name = function() return l10n('General Keybinds') end,
+ inline = true,
+ order = 4,
+ args = {
+ useQuestItemKeybind = {
+ type = "keybinding",
+ order = 1,
+ name = function() return l10n('Use Nearest Quest Item') end,
+ desc = function() return l10n('Press this keybind to automatically use a quest item for the nearest incomplete quest objective. The item must be in your bags and be a usable quest item (trigger a spell when used).') end,
+ get = function() return Questie.db.profile.useQuestItemKeybind end,
+ set = function(_, key)
+ Questie.db.profile.useQuestItemKeybind = key
+ if QuestieTracker_UpdateQuestItemKeybind then
+ QuestieTracker_UpdateQuestItemKeybind()
+ end
+ end
+ },
+ toggleOptionsKeybind = {
+ type = "keybinding",
+ order = 2,
+ name = function() return l10n('Toggle Options') end,
+ desc = function() return l10n('Press this keybind to toggle the Questie Options window.') end,
+ get = function() return Questie.db.profile.toggleOptionsKeybind end,
+ set = function(_, key)
+ Questie.db.profile.toggleOptionsKeybind = key
+ if QuestieTracker_UpdateQuestItemKeybind then
+ QuestieTracker_UpdateQuestItemKeybind()
+ end
+ end
+ },
+ toggleTrackerKeybind = {
+ type = "keybinding",
+ order = 3,
+ name = function() return l10n('Toggle Tracker') end,
+ desc = function() return l10n('Press this keybind to toggle the Questie Tracker.') end,
+ get = function() return Questie.db.profile.toggleTrackerKeybind end,
+ set = function(_, key)
+ Questie.db.profile.toggleTrackerKeybind = key
+ if QuestieTracker_UpdateQuestItemKeybind then
+ QuestieTracker_UpdateQuestItemKeybind()
+ end
+ end
+ },
+ toggleMyJourneyKeybind = {
+ type = "keybinding",
+ order = 4,
+ name = function() return l10n('Toggle My Journey') end,
+ desc = function() return l10n('Press this keybind to toggle the Questie Journey window.') end,
+ get = function() return Questie.db.profile.toggleMyJourneyKeybind end,
+ set = function(_, key)
+ Questie.db.profile.toggleMyJourneyKeybind = key
+ if QuestieTracker_UpdateQuestItemKeybind then
+ QuestieTracker_UpdateQuestItemKeybind()
+ end
+ end
+ },
+ }
+ }
+ }
+ }
+ return keybindOptions
+end
diff --git a/Modules/Options/QuestieOptions.lua b/Modules/Options/QuestieOptions.lua
index e2d9042..767b1c5 100644
--- a/Modules/Options/QuestieOptions.lua
+++ b/Modules/Options/QuestieOptions.lua
@@ -141,6 +141,8 @@ _CreateOptionsTable = function()
coroutine.yield()
local credits_tab = QuestieOptions.tabs.credits:Initialize()
coroutine.yield()
+ local keybinds_tab = QuestieOptions.tabs.keybinds:Initialize()
+ coroutine.yield()
return {
name = "Questie",
handler = Questie,
@@ -161,6 +163,7 @@ _CreateOptionsTable = function()
advanced_tab = advanced_tab,
database_tab = database_tab,
credits_tab = credits_tab,
+ keybinds_tab = keybinds_tab,
profiles_tab = LibStub("AceDBOptions-3.0"):GetOptionsTable(Questie.db)
}
}
diff --git a/Modules/Options/QuestieOptionsDefaults.lua b/Modules/Options/QuestieOptionsDefaults.lua
index ef6d2a1..4410dae 100644
--- a/Modules/Options/QuestieOptionsDefaults.lua
+++ b/Modules/Options/QuestieOptionsDefaults.lua
@@ -101,6 +101,9 @@ function QuestieOptionsDefaults:Load()
trackerbindOpenQuestLog = 'left',
trackerbindUntrack = "shiftleft",
useQuestItemKeybind = '',
+ toggleOptionsKeybind = '',
+ toggleTrackerKeybind = '',
+ toggleMyJourneyKeybind = '',
trackerSetpoint = "TOPLEFT",
trackerFontSizeHeader = 12,
trackerFontHeader = 'Friz Quadrata TT',
diff --git a/Modules/Options/TrackerTab/QuestieOptionsTracker.lua b/Modules/Options/TrackerTab/QuestieOptionsTracker.lua
index e6746ef..b62f176 100644
--- a/Modules/Options/TrackerTab/QuestieOptionsTracker.lua
+++ b/Modules/Options/TrackerTab/QuestieOptionsTracker.lua
@@ -573,20 +573,6 @@ function QuestieOptions.tabs.tracker:Initialize()
Questie.db.profile.trackerbindSetTomTom = key
end
},
- useQuestItemKeybind = {
- type = "keybinding",
- order = 10.5,
- name = function() return l10n('Use Quest Item (Nearest)') end,
- desc = function() return l10n('Press this keybind to automatically use a quest item for the nearest incomplete quest objective. The item must be in your bags and be a usable quest item (trigger a spell when used).') end,
- disabled = function() return not Questie.db.profile.trackerEnabled end,
- get = function() return Questie.db.profile.useQuestItemKeybind end,
- set = function(_, key)
- Questie.db.profile.useQuestItemKeybind = key
- if QuestieTracker_UpdateQuestItemKeybind then
- QuestieTracker_UpdateQuestItemKeybind()
- end
- end
- },
trackerSetpoint = {
type = "select",
order = 11,
diff --git a/Modules/Tracker/QuestieTracker.lua b/Modules/Tracker/QuestieTracker.lua
index a4b2d7a..f640510 100644
--- a/Modules/Tracker/QuestieTracker.lua
+++ b/Modules/Tracker/QuestieTracker.lua
@@ -170,51 +170,87 @@ function QuestieTracker:PruneGhostQuests()
return removedAny
end
-local questItemKeybindFrame = nil
-questItemUseFrame = nil
+local KeybindFrame
-function QuestieTracker_UpdateQuestItemKeybind()
- if not questItemKeybindFrame then
- return
- end
+local function _CreateSecureKeybindFrame()
+ if KeybindFrame then return end
- local keybind = Questie and Questie.db and Questie.db.profile and Questie.db.profile.useQuestItemKeybind
+ KeybindFrame = CreateFrame("Button", "Questie_KeybindFrame", UIParent, "SecureActionButtonTemplate")
+ KeybindFrame:SetAttribute("type", "item")
+ KeybindFrame:RegisterForClicks("AnyDown")
+ KeybindFrame:Hide()
- 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)
+ KeybindFrame:SetScript("PostClick", function(self, button)
+ if button == "OptionsButton" then
+ TrackerUtils:ToggleOptions()
+ elseif button == "TrackerButton" then
+ TrackerUtils:ToggleTracker()
+ elseif button == "JourneyButton" then
+ TrackerUtils:ToggleJourney()
end
end)
- questItemKeybindFrame:RegisterEvent("PLAYER_LOGIN")
- questItemKeybindFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
+ local lastProximityUpdate = 0
+ local function UpdateNearestQuestItemButton()
+ if InCombatLockdown() then return end
+ local now = GetTime()
+ if now - lastProximityUpdate > 5 then
+ lastProximityUpdate = now
+ local itemId = TrackerUtils:GetNearestQuestItemId()
+ if itemId then
+ KeybindFrame:SetAttribute("item", "item:" .. itemId)
+ else
+ KeybindFrame:SetAttribute("item", nil)
+ end
+ end
+ end
- if IsLoggedIn() then
- C_Timer.After(0.5, QuestieTracker_UpdateQuestItemKeybind)
+ local f = CreateFrame("Frame")
+ f:RegisterEvent("PLAYER_REGEN_ENABLED")
+ f:SetScript("OnEvent", function()
+ UpdateNearestQuestItemButton()
+ end)
+ f:SetScript("OnUpdate", function()
+ UpdateNearestQuestItemButton()
+ end)
+end
+
+function QuestieTracker_UpdateQuestItemKeybind()
+ if not KeybindFrame then return end
+
+ if InCombatLockdown() then
+ return QuestieCombatQueue:Queue(QuestieTracker_UpdateQuestItemKeybind)
+ end
+
+ ClearOverrideBindings(KeybindFrame)
+
+ -- 1. Use Quest Item (Nearest)
+ local useItemKey = Questie.db.profile.useQuestItemKeybind
+ if useItemKey and useItemKey ~= "" then
+ SetOverrideBindingClick(KeybindFrame, true, useItemKey, "Questie_KeybindFrame", "LeftButton")
+ end
+
+ -- 2. Toggle Options
+ local optionsKey = Questie.db.profile.toggleOptionsKeybind
+ if optionsKey and optionsKey ~= "" then
+ SetOverrideBindingClick(KeybindFrame, true, optionsKey, "Questie_KeybindFrame", "OptionsButton")
+ end
+
+ -- 3. Toggle Tracker
+ local trackerKey = Questie.db.profile.toggleTrackerKeybind
+ if trackerKey and trackerKey ~= "" then
+ SetOverrideBindingClick(KeybindFrame, true, trackerKey, "Questie_KeybindFrame", "TrackerButton")
+ end
+
+ -- 4. Toggle My Journey
+ local journeyKey = Questie.db.profile.toggleMyJourneyKeybind
+ if journeyKey and journeyKey ~= "" then
+ SetOverrideBindingClick(KeybindFrame, true, journeyKey, "Questie_KeybindFrame", "JourneyButton")
end
end
+
+
local function _InstallQuestLogUpdateListener()
if QuestieTracker._questLogUpdateListenerInstalled then return end
@@ -301,12 +337,13 @@ 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
+ -- Initialize the secure keybind frame
+ _CreateSecureKeybindFrame()
+ QuestieTracker_UpdateQuestItemKeybind()
+
-- Initialize hooks
QuestieTracker:HookBaseTracker()
diff --git a/Modules/Tracker/TrackerUtils.lua b/Modules/Tracker/TrackerUtils.lua
index 2a5d36f..6182472 100644
--- a/Modules/Tracker/TrackerUtils.lua
+++ b/Modules/Tracker/TrackerUtils.lua
@@ -1298,69 +1298,85 @@ function TrackerUtils:UpdateVoiceOverPlayButtons()
end
end
-function TrackerUtils:UseNearestQuestItem()
- if InCombatLockdown() then
- Questie:Debug(Questie.DEBUG_INFO, "[TrackerUtils:UseNearestQuestItem] Cannot use items while in combat")
- return
- end
+---@return number|nil itemId The ID of the nearest usable quest item
+function TrackerUtils:GetNearestQuestItemId()
+ local questIds = QuestiePlayer.currentQuestlog
+ local bestItemId = nil
+ local minDistance = 999999
+
+ local playerPos = _GetWorldPlayerPosition()
+ if not playerPos then return nil 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
+ for questId in pairs(questIds) do
+ local quest = QuestieDB.GetQuest(questId)
+ if quest then
+ local items = {}
+ if quest.sourceItemId and quest.sourceItemId ~= 0 then
+ table.insert(items, quest.sourceItemId)
+ end
+ if type(quest.requiredSourceItems) == "table" then
+ for _, itemId in pairs(quest.requiredSourceItems) do
+ if itemId and itemId ~= 0 then
+ table.insert(items, itemId)
end
end
end
+
+ local foundItemId = nil
+ for i = 1, table.getn(items) do
+ local itemId = items[i]
+ -- Check if item is in bags and is a quest item (class 12)
+ if GetItemCount(itemId) > 0 and QuestieDB.QueryItemSingle(itemId, "class") == 12 then
+ foundItemId = itemId
+ break
+ end
+ end
+
+ if foundItemId then
+ local distance = _GetDistanceToClosestObjective(questId)
+ if distance and distance < minDistance then
+ minDistance = distance
+ bestItemId = foundItemId
+ end
+ end
end
end
+ return bestItemId
+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")
+--- Logic to use the nearest quest item (Fallback for non-secure usage or manual calls)
+function TrackerUtils:UseNearestQuestItem()
+ local itemId = self:GetNearestQuestItemId()
+ if itemId then
+ local itemName = GetItemInfo(itemId)
+ if itemName then
+ UseItemByName(itemName)
+ end
end
end
+
+--- Toggle the Questie Options window
+function TrackerUtils:ToggleOptions()
+ local QuestieOptions = QuestieLoader:ImportModule("QuestieOptions")
+ if QuestieOptions and QuestieOptions.OpenConfigWindow then
+ QuestieOptions:OpenConfigWindow()
+ end
+end
+
+--- Toggle the Questie Tracker
+function TrackerUtils:ToggleTracker()
+ local QuestieTracker = QuestieLoader:ImportModule("QuestieTracker")
+ if QuestieTracker and QuestieTracker.Toggle then
+ QuestieTracker:Toggle()
+ end
+end
+
+--- Toggle the Questie Journey window
+function TrackerUtils:ToggleJourney()
+ local QuestieJourney = QuestieLoader:ImportModule("QuestieJourney")
+ if QuestieJourney and QuestieJourney.ToggleJourneyWindow then
+ QuestieJourney:ToggleJourneyWindow()
+ end
+end
+
+
diff --git a/Questie-X-Classic.toc b/Questie-X-Classic.toc
index a9b84f1..71bc534 100644
--- a/Questie-X-Classic.toc
+++ b/Questie-X-Classic.toc
@@ -1,11 +1,11 @@
## Interface: 30300
-## Title: |cFF5EBAF3Questie|r|cFFDAFAFD-X|r-Classic|cFF00FF00 v1.5.0|r
+## Title: |cFF5EBAF3Questie|r|cFFDAFAFD-X|r-Classic|cFF00FF00 v1.5.3|r
## Notes: A standalone Classic QuestHelper
## Notes-esMX: Ayundante de misiones
## Notes-esES: Ayundante de misiones
## Notes-ptBR: Ajudante de misiones
## Notes-frFR: Assistant de quêtes
-## Version: 1.5.1
+## Version: 1.5.3
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
@@ -190,6 +190,7 @@ Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
+Modules\Options\KeybindsTab\QuestieOptionsKeybinds.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
diff --git a/Questie-X-TBC.toc b/Questie-X-TBC.toc
index 7015698..99aa1a9 100644
--- a/Questie-X-TBC.toc
+++ b/Questie-X-TBC.toc
@@ -1,11 +1,11 @@
## Interface: 30300
-## Title: |cFF5EBAF3Questie|r|cFFDAFAFD-X|r-TBC|cFF00FF00 v1.5.0|r
+## Title: |cFF5EBAF3Questie|r|cFFDAFAFD-X|r-TBC|cFF00FF00 v1.5.3|r
## Notes: A standalone Classic QuestHelper
## Notes-esMX: Ayundante de misiones
## Notes-esES: Ayundante de misiones
## Notes-ptBR: Ajudante de misiones
## Notes-frFR: Assistant de quêtes
-## Version: 1.5.1
+## Version: 1.5.3
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
@@ -182,6 +182,7 @@ Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
+Modules\Options\KeybindsTab\QuestieOptionsKeybinds.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
diff --git a/Questie-X-Turtle.toc b/Questie-X-Turtle.toc
index dac952a..8f72588 100644
--- a/Questie-X-Turtle.toc
+++ b/Questie-X-Turtle.toc
@@ -1,11 +1,11 @@
## Interface: 11200
-## Title: |cFF5EBAF3Questie|r|cFFDAFAFD-X|r-Turtle|cFF00FF00 v1.5.0|r
+## Title: |cFF5EBAF3Questie|r|cFFDAFAFD-X|r-Turtle|cFF00FF00 v1.5.3|r
## Notes: A standalone Classic QuestHelper
## Notes-esMX: Ayundante de misiones
## Notes-esES: Ayundante de misiones
## Notes-ptBR: Ajudante de misiones
## Notes-frFR: Assistant de quêtes
-## Version: 1.5.1
+## Version: 1.5.3
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu, Questie-X-TurtleDB
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
@@ -187,6 +187,7 @@ Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
+Modules\Options\KeybindsTab\QuestieOptionsKeybinds.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
diff --git a/Questie-X.toc b/Questie-X.toc
index 9787906..030e4ee 100644
--- a/Questie-X.toc
+++ b/Questie-X.toc
@@ -11,7 +11,7 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
-## Version: 1.5.1
+## Version: 1.5.3
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu, Questie-X-WotLKDB, Questie-X-ClassicDB, Questie-X-TBCDB, Questie-X-TurtleDB, Questie-X-AscensionDB, Questie-X-EbonholdDB
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB, QuestieJourneyDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
@@ -181,6 +181,7 @@ Modules\QuestieSlash.lua
# Options
Modules\Options\QuestieOptions.lua
Modules\Options\QuestieOptionsDefaults.lua
+Modules\Options\KeybindsTab\QuestieOptionsKeybinds.lua
Modules\Options\QuestieOptionsUtils.lua
Modules\Options\AdvancedTab\QuestieOptionsAdvanced.lua
Modules\Options\DatabaseTab\QuestieOptionsDatabase.lua
diff --git a/README.md b/README.md
index 79299c5..e954f16 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-
+
[](https://github.com/Xurkon/Questie-X/releases)
[](https://xurkon.github.io/Questie-X/)
[](https://www.patreon.com/Xurkon)
diff --git a/docs/changelog.html b/docs/changelog.html
index 4744b13..dc37c5e 100644
--- a/docs/changelog.html
+++ b/docs/changelog.html
@@ -169,13 +169,35 @@
Complete history of changes, fixes, and additions.
GetItemSpell), checks which ones are in the player's bags using QuestieCompat.GetContainerItemInfo, calculates proximity to quest objectives using HBD:GetWorldDistance, and uses the nearest one via UseItemByName. Configurable via Tracker options tab under "Use Quest Item (Nearest)".QuestieCompat.UiMapData before HBD initialized its map cache. Added ZoneDB:ApplyCustomZones() function that hooks ZoneDB.Initialize to inject custom zones BEFORE the original initialization runs. This ensures HBD's mapData table (which references QuestieCompat.UiMapData) contains custom zone entries like 1244 (Valley of Trials). Also modified QuestiePluginAPI:InjectUiMapData() to call ZoneDB:ApplyCustomZones() after injecting custom zone data.GetZoneNameByID fails for custom zone IDs (like 1244), the system now falls back to GetQuestLogZoneName which reads the zone header directly from the quest log where custom zone names are properly displayed.QuestieCompat.GetCurrentUiMapID() to check QuestieCompat.UiMapData directly for custom zone IDs. Previously, only mapIdToUiMapId was checked, which doesn't contain custom zones. Added fallback: if QuestieCompat.UiMapData and QuestieCompat.UiMapData[mapID] then return mapID endzone ~= playerZoneId), but custom zones use different IDs (e.g., 1244 for Valley of Trials) than their parent zones (e.g., 14 for Durotar). Added QuestiePlayer:GetCurrentUiMapId() function and updated arrow zone filtering to compare both playerZoneId AND playerUiMapId against objective zone IDs in all 4 zone filter locations within _CollectObjective, _CollectFinisherSpawns, and finisher waypoint loops.objective.Description when rendering quest objectives in QuestieTracker.lua. Custom server quests may have objectives without a Description field, which would previously cause "attempt to index field 'Description' (a nil value)" crash.QuestiePluginAPI:InjectUiMapData() to call ZoneDB:ApplyCustomZones() after injecting custom zone data, ensuring the zone mappings are properly registered with both ZoneDB and QuestieCompat.UiMapData.AscensionUiMapData.lua (Questie-X-AscensionDB) to use string.find() instead of exact string comparison. Realms like "Bronzebeard - Warcraft Reborn" now properly match the "Bronzebeard" pattern, allowing custom zone data to load on all Ascension server variants.QuestieCompat.UiMapData before HBD initialized its map cache. Added ZoneDB:ApplyCustomZones() function that hooks ZoneDB.Initialize to inject custom zones BEFORE the original initialization runs. This ensures HBD's mapData table (which references QuestieCompat.UiMapData) contains custom zone entries like 1244 (Valley of Trials). Also modified QuestiePluginAPI:InjectUiMapData() to call ZoneDB:ApplyCustomZones() after injecting custom zone data.
A universal WoW quest-helper with a plugin architecture for any private server.