mirror of
https://github.com/Blaststar/Questie-Octo-Vanilla.git
synced 2026-10-19 20:00:49 +00:00
Added routes and submenu
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
-- Right-click quest menu, rendered with the native Vanilla UIDropDownMenu so it
|
||||
-- matches Blizzard/Titan context menus (submenu arrows, checks, highlight).
|
||||
QuestieOcto.QuestMenu = QuestieOcto.QuestMenu or {}
|
||||
local QM = QuestieOcto.QuestMenu
|
||||
|
||||
local function DB()
|
||||
QuestieOctoDB=QuestieOctoDB or {}
|
||||
QuestieOctoDB.questMenu=QuestieOctoDB.questMenu or {}
|
||||
local d=QuestieOctoDB.questMenu
|
||||
d.hiddenObjectives=d.hiddenObjectives or {}
|
||||
d.hiddenQuests=d.hiddenQuests or {}
|
||||
return d
|
||||
end
|
||||
|
||||
local function ObjectiveKey(questID,objIndex)
|
||||
return tostring(questID).." "..tostring(objIndex)
|
||||
end
|
||||
|
||||
local function IsObjectiveRole(role)
|
||||
return role=="objectiveCreature" or role=="objectiveObject" or role=="objectiveItemSource"
|
||||
end
|
||||
|
||||
-- State queries -------------------------------------------------------------
|
||||
|
||||
function QM:IsQuestHidden(questID)
|
||||
return DB().hiddenQuests[tonumber(questID)] and true or false
|
||||
end
|
||||
|
||||
function QM:IsObjectiveHidden(questID,objIndex)
|
||||
return DB().hiddenObjectives[ObjectiveKey(questID,objIndex)] and true or false
|
||||
end
|
||||
|
||||
function QM:GetFocus()
|
||||
local f=DB().focus
|
||||
if type(f)~="string" then return nil,nil end
|
||||
local _,_,qid,oi=string.find(f,"^(%d+) (%d+)$")
|
||||
return tonumber(qid),tonumber(oi)
|
||||
end
|
||||
|
||||
function QM:IsFocused(questID,objIndex)
|
||||
local fq,fo=self:GetFocus()
|
||||
return fq==tonumber(questID) and fo==tonumber(objIndex)
|
||||
end
|
||||
|
||||
-- A node is hidden when its whole quest is hidden (objective nodes only) or when
|
||||
-- its specific objective is hidden.
|
||||
function QM:IsNodeHidden(node)
|
||||
if not node then return false end
|
||||
local qid=tonumber(node.questID)
|
||||
if not qid or qid<=0 then return false end
|
||||
if IsObjectiveRole(node.role) then
|
||||
if self:IsQuestHidden(qid) then return true end
|
||||
local oi=tonumber(node.objectiveIndex)
|
||||
if oi and self:IsObjectiveHidden(qid,oi) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Toggles -------------------------------------------------------------------
|
||||
|
||||
function QM:RefreshMaps()
|
||||
if QuestieOcto.Minimap and QuestieOcto.Minimap.RefreshVisualSettings then
|
||||
QuestieOcto.Minimap:RefreshVisualSettings()
|
||||
end
|
||||
if QuestieOcto.Map and QuestieOcto.Map.RequestSync then
|
||||
QuestieOcto.Map:RequestSync(true)
|
||||
end
|
||||
end
|
||||
|
||||
function QM:ToggleFocus(questID,objIndex)
|
||||
local d=DB()
|
||||
if self:IsFocused(questID,objIndex) then
|
||||
d.focus=nil
|
||||
else
|
||||
d.focus=ObjectiveKey(questID,objIndex)
|
||||
end
|
||||
end
|
||||
|
||||
function QM:ToggleObjectiveHidden(questID,objIndex)
|
||||
local d=DB()
|
||||
local key=ObjectiveKey(questID,objIndex)
|
||||
d.hiddenObjectives[key]=(not d.hiddenObjectives[key]) or nil
|
||||
self:RefreshMaps()
|
||||
end
|
||||
|
||||
function QM:ToggleQuestHidden(questID)
|
||||
local d=DB()
|
||||
questID=tonumber(questID)
|
||||
d.hiddenQuests[questID]=(not d.hiddenQuests[questID]) or nil
|
||||
self:RefreshMaps()
|
||||
end
|
||||
|
||||
-- Menu data -----------------------------------------------------------------
|
||||
|
||||
local function ObjectiveName(q,row)
|
||||
local defs=q and q.objectiveData or nil
|
||||
local def=defs and row.dataIndex and defs[tonumber(row.dataIndex)] or nil
|
||||
if def and def.id then
|
||||
if def.kind=="creature" then return QuestieOcto.DatabaseAPI:GetCreatureName(def.id) end
|
||||
if def.kind=="gameObject" then return QuestieOcto.DatabaseAPI:GetObjectName(def.id) end
|
||||
if def.kind=="item" then return QuestieOcto.DatabaseAPI:GetItemName(def.id) end
|
||||
end
|
||||
local text=row.rawText or row.text or ""
|
||||
local stripped=string.gsub(text,"%s*:?%s*%d+%s*/%s*%d+%s*$","")
|
||||
-- Drop a trailing objective verb (e.g. "... slain") so only the name remains.
|
||||
local nameOnly=string.gsub(stripped,"%s+%l+$","")
|
||||
if nameOnly~="" then return nameOnly end
|
||||
if stripped~="" then return stripped end
|
||||
return text
|
||||
end
|
||||
|
||||
local function ActiveState(questID)
|
||||
return QuestieOcto.QuestLog and QuestieOcto.QuestLog.active and QuestieOcto.QuestLog.active[tonumber(questID)] or nil
|
||||
end
|
||||
|
||||
local function HasIncompleteObjectives(state)
|
||||
local objectives=state and state.objectives or {}
|
||||
local i=1
|
||||
while i<=table.getn(objectives) do
|
||||
if not objectives[i].complete then return true end
|
||||
i=i+1
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Native UIDropDownMenu rendering -------------------------------------------
|
||||
|
||||
local function AddTitle(text)
|
||||
local info={}
|
||||
info.text=text
|
||||
info.isTitle=1
|
||||
info.notClickable=1
|
||||
info.notCheckable=1
|
||||
UIDropDownMenu_AddButton(info,UIDROPDOWNMENU_MENU_LEVEL)
|
||||
end
|
||||
|
||||
local function AddArrow(text,value)
|
||||
local info={}
|
||||
info.text=text
|
||||
info.value=value
|
||||
info.hasArrow=1
|
||||
info.notCheckable=1
|
||||
UIDropDownMenu_AddButton(info,UIDROPDOWNMENU_MENU_LEVEL)
|
||||
end
|
||||
|
||||
local function AddToggle(text,isChecked,onToggle)
|
||||
local info={}
|
||||
info.text=text
|
||||
info.checked=isChecked and 1 or nil
|
||||
info.keepShownOnClick=1
|
||||
info.func=onToggle
|
||||
UIDropDownMenu_AddButton(info,UIDROPDOWNMENU_MENU_LEVEL)
|
||||
end
|
||||
|
||||
local function Initialize()
|
||||
local questID=QM.currentQuestID
|
||||
if not questID then return end
|
||||
local state=ActiveState(questID)
|
||||
local q=QuestieOcto.QuestModel and QuestieOcto.QuestModel:Get(questID) or nil
|
||||
local level=UIDROPDOWNMENU_MENU_LEVEL or 1
|
||||
|
||||
if level==1 then
|
||||
local title=(q and q.title) or (state and state.title) or ("Quest "..tostring(questID))
|
||||
local qlevel=q and tonumber(q.level)
|
||||
if qlevel and qlevel>0 then title="["..tostring(qlevel).."] "..title end
|
||||
AddTitle(title)
|
||||
if HasIncompleteObjectives(state) then
|
||||
AddArrow("Objectives","objectives")
|
||||
end
|
||||
AddToggle("Hide icons",QM:IsQuestHidden(questID),function()
|
||||
QM:ToggleQuestHidden(questID)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
if level==2 and UIDROPDOWNMENU_MENU_VALUE=="objectives" then
|
||||
local objectives=state and state.objectives or {}
|
||||
local oi=1
|
||||
while oi<=table.getn(objectives) do
|
||||
local row=objectives[oi]
|
||||
local objIndex=tonumber(row.index)
|
||||
if objIndex and not row.complete then
|
||||
AddArrow(ObjectiveName(q,row),"obj:"..objIndex)
|
||||
end
|
||||
oi=oi+1
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if level==3 then
|
||||
local _,_,idx=string.find(tostring(UIDROPDOWNMENU_MENU_VALUE),"^obj:(%d+)$")
|
||||
local objIndex=tonumber(idx)
|
||||
if objIndex then
|
||||
AddToggle("Focus Objective",QM:IsFocused(questID,objIndex),function()
|
||||
QM:ToggleFocus(questID,objIndex)
|
||||
end)
|
||||
AddToggle("Hide icons",QM:IsObjectiveHidden(questID,objIndex),function()
|
||||
QM:ToggleObjectiveHidden(questID,objIndex)
|
||||
end)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function QM:Open(questID,row)
|
||||
questID=tonumber(questID)
|
||||
-- No menu for a quest that is already complete/ready to turn in.
|
||||
local state=ActiveState(questID)
|
||||
if state and state.complete then return end
|
||||
|
||||
if not self.dropdown then
|
||||
self.dropdown=CreateFrame("Frame","QuestieOctoQuestMenuDropDown",UIParent,"UIDropDownMenuTemplate")
|
||||
end
|
||||
self.currentQuestID=questID
|
||||
UIDropDownMenu_Initialize(self.dropdown,Initialize,"MENU")
|
||||
ToggleDropDownMenu(1,nil,self.dropdown,"cursor",0,0)
|
||||
end
|
||||
Reference in New Issue
Block a user