v1.5.3: Add dedicated Keybinds tab
This commit is contained in:
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,9 @@ function QuestieOptionsDefaults:Load()
|
||||
trackerbindOpenQuestLog = 'left',
|
||||
trackerbindUntrack = "shiftleft",
|
||||
useQuestItemKeybind = '',
|
||||
toggleOptionsKeybind = '',
|
||||
toggleTrackerKeybind = '',
|
||||
toggleMyJourneyKeybind = '',
|
||||
trackerSetpoint = "TOPLEFT",
|
||||
trackerFontSizeHeader = 12,
|
||||
trackerFontHeader = 'Friz Quadrata TT',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user