815 lignes
25 Kio
Lua
815 lignes
25 Kio
Lua
|
QuestHelper_File["tracker.lua"] = "1.4.0"
|
||
|
QuestHelper_Loadtime["tracker.lua"] = GetTime()
|
||
|
|
||
|
local debug_output = false
|
||
|
if QuestHelper_File["tracker.lua"] == "Development Version" then debug_output = true end
|
||
|
|
||
|
--[[ NOTES TO SELF
|
||
|
|
||
|
So here's what we want to do.
|
||
|
|
||
|
We want a "refresh notification" where we send it the current route.
|
||
|
|
||
|
If things aren't in the route, we don't care about them . . . unless they're pinned.
|
||
|
|
||
|
So we have "refresh notification" and "pin toggles". In both cases, the objective and only the objective is passed in. Right now there's no concept of priority within the pins.
|
||
|
|
||
|
We're also not bothering with the whole metaobjective tree, we're just going one step up.
|
||
|
|
||
|
So, our algorithm:
|
||
|
|
||
|
Note that "add" means "add iff it hasn't already been added."
|
||
|
|
||
|
Iff we haven't loaded yet, add a loaded message and a gap.
|
||
|
|
||
|
For each pinned objective, add the metaobjective and all objectives in its internal order. Iff we added things, add a gap.
|
||
|
|
||
|
For each route objective, add the metaobjective and all objectives in route order.
|
||
|
|
||
|
Later on we'll add an option for "splitting" metaobjectives, or possibly following the metaobjective tree all the way up.
|
||
|
|
||
|
|
||
|
|
||
|
So, "add" is complicated, due to the two requirements. We have to both add everything, and not add everything *yet*. I think the goal here is to make an Add function for adding a metaobjective that takes a list of objectives to be children, then doublecheck inside the function that we have all objectives.
|
||
|
|
||
|
We don't actually want "all objectives" long-term, note, we want only unfinished objectives. I sort of don't like the idea of keeping "finished objectives" around, however. Maybe we should only toss objectives in if they're in the routing system? Then how do I handle unknown objectives? (Simple - you pin them, and point out that we don't know how to do them.)
|
||
|
|
||
|
Also, to handle the "moving things around", we need to be a little clever. One line might be either a metaobjective or an objective, but in either case, we need a counter for which case it is. If everything shuffles, and we had two copies of metaobjective, MO1 moves to MO1 and MO2 moves to MO2. Easy.
|
||
|
]]
|
||
|
|
||
|
local tracker = CreateFrame("Frame", "QuestHelperQuestWatchFrame", UIParent)
|
||
|
local minbutton = CreateFrame("Button", "QuestHelperQuestWatchFrameMinimizeButton", UIParent)
|
||
|
|
||
|
QuestHelper.tracker = tracker
|
||
|
|
||
|
local resizing = false
|
||
|
tracker:SetWidth(200)
|
||
|
tracker:SetHeight(100)
|
||
|
tracker:SetFrameStrata("BACKGROUND")
|
||
|
tracker.dw, tracker.dh = 200, 100
|
||
|
|
||
|
local in_tracker = 0
|
||
|
|
||
|
minbutton:SetFrameStrata("LOW")
|
||
|
minbutton:Hide()
|
||
|
minbutton:SetPoint("TOPRIGHT", WatchFrame) -- We default to a different location to make it more likely to display the right item.
|
||
|
minbutton:SetMovable(true)
|
||
|
minbutton:SetUserPlaced(true)
|
||
|
minbutton:SetWidth(24 / 1.6)
|
||
|
minbutton:SetHeight(24)
|
||
|
minbutton:SetFrameLevel(3)
|
||
|
local minbutton_tex = minbutton:CreateTexture()
|
||
|
minbutton_tex:SetAllPoints()
|
||
|
minbutton_tex:SetTexture(.6, .6, .6)
|
||
|
minbutton_tex:SetParent(minbutton)
|
||
|
|
||
|
local sigargh = CreateFrame("Frame", minbutton)
|
||
|
sigargh:SetFrameStrata("LOW")
|
||
|
sigargh:SetFrameLevel(4)
|
||
|
|
||
|
local sigil = sigargh:CreateTexture("BACKGROUND")
|
||
|
sigil:SetHeight(24)
|
||
|
sigil:SetWidth(24)
|
||
|
--sigil:SetPoint("CENTER", 0, 0)
|
||
|
sigil:SetTexture("Interface\\AddOns\\QuestHelper\\sigil")
|
||
|
sigil:SetPoint("CENTER", minbutton_tex, "CENTER")
|
||
|
|
||
|
|
||
|
tracker:SetPoint("CENTER", minbutton)
|
||
|
|
||
|
function minbutton:moved()
|
||
|
local x, y = self:GetCenter()
|
||
|
local w, h = UIParent:GetWidth(), UIParent:GetHeight()
|
||
|
local anchor = (y < h*.45 and "BOTTOM" or y > h*.55 and "TOP" or "")..(x < w*.45 and "LEFT" or x > w*.55 and "RIGHT" or "")
|
||
|
|
||
|
tracker:ClearAllPoints()
|
||
|
tracker:SetPoint("CENTER", self)
|
||
|
|
||
|
if anchor ~= "" then
|
||
|
tracker:SetPoint(anchor, self)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QuestHelper:ResetTrackerPosition(cmd)
|
||
|
minbutton:ClearAllPoints()
|
||
|
if cmd and string.find(cmd, "center") then
|
||
|
minbutton:SetPoint("CENTER", nil, "CENTER", 100, 100)
|
||
|
else
|
||
|
minbutton:SetPoint("RIGHT", nil, "RIGHT", -20, 230)
|
||
|
end
|
||
|
minbutton:moved()
|
||
|
QuestHelper_Pref.track_minimized = false
|
||
|
tracker:Show()
|
||
|
self:TextOut("Quest tracker postion reset.")
|
||
|
end
|
||
|
|
||
|
QH_Event({"DISPLAY_SIZE_CHANGED", "PLAYER_ENTERING_WORLD"}, function () minbutton:moved() end)
|
||
|
|
||
|
QH_Hook(minbutton, "OnClick", function ()
|
||
|
QuestHelper_Pref.track_minimized = not QuestHelper_Pref.track_minimized
|
||
|
if QuestHelper_Pref.track_minimized then
|
||
|
tracker:Hide()
|
||
|
else
|
||
|
tracker:Show()
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
minbutton:RegisterForDrag("LeftButton")
|
||
|
|
||
|
QH_Hook(minbutton, "OnDragStart", function(self)
|
||
|
if self:IsVisible() then
|
||
|
self:StartMoving()
|
||
|
QH_Hook(self, "OnUpdate", self.moved)
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
QH_Hook(minbutton, "OnDragStop", function(self)
|
||
|
QH_Hook(self, "OnUpdate", nil)
|
||
|
self:StopMovingOrSizing()
|
||
|
self:moved()
|
||
|
end)
|
||
|
|
||
|
local entered_main = false
|
||
|
local entered_tracker = false
|
||
|
local function RefreshColor()
|
||
|
if entered_main then
|
||
|
minbutton:SetAlpha(1)
|
||
|
sigargh:SetAlpha(1)
|
||
|
elseif entered_tracker then
|
||
|
minbutton:SetAlpha(.3)
|
||
|
sigargh:SetAlpha(.3)
|
||
|
elseif QuestHelper_Pref.track_minimized then
|
||
|
minbutton:SetAlpha(.3)
|
||
|
sigargh:SetAlpha(.3)
|
||
|
else
|
||
|
minbutton:SetAlpha(0)
|
||
|
sigargh:SetAlpha(0)
|
||
|
end
|
||
|
end
|
||
|
local function SetEnteredMain(x)
|
||
|
entered_main = x
|
||
|
RefreshColor()
|
||
|
end
|
||
|
local function SetEnteredTracker(x)
|
||
|
entered_tracker = x
|
||
|
RefreshColor()
|
||
|
end
|
||
|
|
||
|
QH_Hook(minbutton, "OnEnter", function (self)
|
||
|
SetEnteredMain(true)
|
||
|
end)
|
||
|
|
||
|
QH_Hook(minbutton, "OnLeave", function (self)
|
||
|
SetEnteredMain(false)
|
||
|
end)
|
||
|
|
||
|
-- used_items[objective][index]
|
||
|
-- used_count[objective] is incremented as the last valid index
|
||
|
-- so, therefore, used_items[objective][used_count[objective]] is not nil
|
||
|
local used_items = {}
|
||
|
local used_count = {}
|
||
|
|
||
|
-- it's possible for an item to be in neither used_items nor recycled_items, if it's in the process of fading out
|
||
|
local recycled_items = {}
|
||
|
|
||
|
-- These two functions are basically identical. Combine them.
|
||
|
local function itemupdate(item, delta)
|
||
|
local done = true
|
||
|
|
||
|
local a = item:GetAlpha()
|
||
|
a = a + delta
|
||
|
|
||
|
if a < 1 then
|
||
|
item:SetAlpha(a)
|
||
|
done = false
|
||
|
else
|
||
|
item:SetAlpha(1)
|
||
|
end
|
||
|
|
||
|
local t = item.t + delta
|
||
|
|
||
|
if t < 1 then
|
||
|
item.t = t
|
||
|
local it = 1-t
|
||
|
local sp = math.sqrt(t-t*t)
|
||
|
item.x, item.y = item.sx*it+item.ex*t+(item.sy-item.ey)*sp, item.sy*it+item.ey*t+(item.ex-item.sx)*sp
|
||
|
done = false
|
||
|
else
|
||
|
item.t = 1
|
||
|
item.x, item.y = item.ex, item.ey
|
||
|
end
|
||
|
|
||
|
item:ClearAllPoints()
|
||
|
item:SetPoint("TOPLEFT", tracker, "TOPLEFT", item.x, -item.y)
|
||
|
|
||
|
if done then
|
||
|
QH_Hook(item, "OnUpdate", nil)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function itemfadeout(item, delta)
|
||
|
local a = item:GetAlpha()
|
||
|
a = a - delta
|
||
|
|
||
|
if a > 0 then
|
||
|
item:SetAlpha(a)
|
||
|
else
|
||
|
item:SetAlpha(1)
|
||
|
item:Hide()
|
||
|
QH_Hook(item, "OnUpdate", nil)
|
||
|
table.insert(recycled_items, item)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local t = item.t + delta
|
||
|
|
||
|
if t < 1 then
|
||
|
item.t = t
|
||
|
local it = 1-t
|
||
|
local sp = math.sqrt(t-t*t)
|
||
|
item.x, item.y = item.sx*it+item.ex*t+(item.sy-item.ey)*sp, item.sy*it+item.ey*t+(item.ex-item.sx)*sp
|
||
|
else
|
||
|
item.t = 1
|
||
|
item.x, item.y = item.ex, item.ey
|
||
|
end
|
||
|
|
||
|
item:ClearAllPoints()
|
||
|
item:SetPoint("TOPLEFT", tracker, "TOPLEFT", item.x, -item.y)
|
||
|
end
|
||
|
|
||
|
--[[function QH_ToggleQuestLog() -- This seems to be gone in 3.0, so I'm adding it here.
|
||
|
if (QuestLogFrame:IsShown()) then
|
||
|
HideUIPanel(QuestLogFrame);
|
||
|
else
|
||
|
ShowUIPanel(QuestLogFrame);
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Grim stuff with uberquest, I need a better way to handle this
|
||
|
local function itemclick(item, button)
|
||
|
if button == "RightButton" then
|
||
|
local quest = item.quest
|
||
|
local index = 1
|
||
|
while true do
|
||
|
local title = GetQuestLogTitle(index)
|
||
|
if not title then break end
|
||
|
|
||
|
if title == quest then
|
||
|
if UberQuest then
|
||
|
-- UberQuest needs a little extra effort to work properly.
|
||
|
|
||
|
if UberQuest_List:IsShown() and GetQuestLogSelection() == index then
|
||
|
QH_ToggleQuestLog()
|
||
|
else
|
||
|
QuestLog_SetSelection(index)
|
||
|
|
||
|
-- By hiding the list, the replaced ToggleQuestLog function should try to reshow it
|
||
|
-- and in the process update the frames to reflect the selected quest.
|
||
|
UberQuest_List:Hide()
|
||
|
UberQuest_Details:Show()
|
||
|
QH_ToggleQuestLog()
|
||
|
end
|
||
|
else
|
||
|
-- This code seems to work properly with the builtin questlog, as well as bEQL and DoubleWide.
|
||
|
|
||
|
if QuestLogFrame:IsShown() and GetQuestLogSelection() == index then
|
||
|
-- If the selected quest is already being shown, hide it.
|
||
|
QH_ToggleQuestLog()
|
||
|
else
|
||
|
-- Otherwise, select it and show it.
|
||
|
QuestLog_SetSelection(index)
|
||
|
|
||
|
if not QuestLogFrame:IsShown() then
|
||
|
QH_ToggleQuestLog()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
index = index + 1
|
||
|
end
|
||
|
end
|
||
|
end]]
|
||
|
|
||
|
local function allocateItem()
|
||
|
local item
|
||
|
|
||
|
item = table.remove(recycled_items)
|
||
|
if item then return item end
|
||
|
|
||
|
item = CreateFrame("Frame", nil, tracker)
|
||
|
item.text = item:CreateFontString()
|
||
|
item.text:SetShadowColor(0, 0, 0, .8)
|
||
|
item.text:SetShadowOffset(1, -1)
|
||
|
item.text:SetPoint("TOPLEFT", item)
|
||
|
return item
|
||
|
end
|
||
|
|
||
|
local specitem_max = 1
|
||
|
local specitem_unused = {}
|
||
|
|
||
|
-- This is adding a *single item*. This won't be called by the main parsing loop, but it does need some serious hackery. Let's see now
|
||
|
local function addItem(objective, y, meta)
|
||
|
-- THIS IS WHERE WE START IN THE MORNING!
|
||
|
local obj_key = objective
|
||
|
if obj_key.cluster then obj_key = obj_key.cluster end
|
||
|
used_count[obj_key] = (used_count[obj_key] or 0) + 1
|
||
|
if not used_items[obj_key] then used_items[obj_key] = QuestHelper:CreateTable("additem used_items") end
|
||
|
local item = used_items[obj_key][used_count[obj_key]]
|
||
|
|
||
|
local x = meta and 4 or 20
|
||
|
|
||
|
if not item then
|
||
|
used_items[obj_key][used_count[obj_key]] = allocateItem()
|
||
|
item = used_items[obj_key][used_count[obj_key]]
|
||
|
|
||
|
if meta then
|
||
|
item.text:SetFont(QuestHelper.font.serif, 12)
|
||
|
item.text:SetTextColor(.82, .65, 0)
|
||
|
else
|
||
|
item.text:SetFont(QuestHelper.font.sans, 12)
|
||
|
item.text:SetTextColor(.82, .82, .82)
|
||
|
end
|
||
|
|
||
|
item.obj = objective
|
||
|
|
||
|
item.sx, item.sy, item.x, item.y, item.ex, item.ey, item.t = x+30, y, x, y, x, y, 0
|
||
|
QH_Hook(item, "OnUpdate", itemupdate)
|
||
|
item:SetAlpha(0)
|
||
|
item:Show()
|
||
|
end
|
||
|
|
||
|
item.text:SetText(item.obj.tracker_desc or "(no description)")
|
||
|
|
||
|
local w, h = item.text:GetWidth(), item.text:GetHeight()
|
||
|
item:SetWidth(w)
|
||
|
item:SetHeight(h)
|
||
|
|
||
|
if objective.tracker_clicked then
|
||
|
QH_Hook(item, "OnMouseDown", function (self, button) if button == "RightButton" then objective.tracker_clicked() end end)
|
||
|
item:EnableMouse(true)
|
||
|
end
|
||
|
|
||
|
if item.ex ~= x or item.ey ~= y then
|
||
|
item.sx, item.sy, item.ex, item.ey = item.x, item.y, x, y
|
||
|
item.t = 0
|
||
|
QH_Hook(item, "OnUpdate", itemupdate)
|
||
|
end
|
||
|
|
||
|
-- we're just going to recycle this each time
|
||
|
if item.specitem then
|
||
|
item.specitem:Hide()
|
||
|
table.insert(specitem_unused, item.specitem)
|
||
|
item.specitem = nil
|
||
|
end
|
||
|
|
||
|
local spacer = 0
|
||
|
-- hacky - progress only shows up if we're not on a metaobjective. wheee
|
||
|
if objective.type_quest and objective.type_quest.index and not objective.progress and GetQuestLogSpecialItemInfo(objective.type_quest.index) then
|
||
|
item.specitem = table.remove(specitem_unused)
|
||
|
if not item.specitem then
|
||
|
item.specitem = CreateFrame("BUTTON", "QH_SpecItem_" .. tostring(specitem_max), item, "WatchFrameItemButtonTemplate")
|
||
|
QuestHelper: Assert(item.specitem)
|
||
|
|
||
|
local rangey = _G["QH_SpecItem_" .. tostring(specitem_max) .. "HotKey"]
|
||
|
QuestHelper: Assert(rangey)
|
||
|
local fn, fh, ff = rangey:GetFont()
|
||
|
rangey:SetFont("Fonts\\ARIALN.TTF", fh, ff)
|
||
|
rangey:SetText(RANGE_INDICATOR)
|
||
|
rangey:ClearAllPoints()
|
||
|
rangey:SetPoint("BOTTOMRIGHT", item.specitem, "BOTTOMRIGHT", 0, 2)
|
||
|
|
||
|
specitem_max = specitem_max + 1
|
||
|
end
|
||
|
|
||
|
item.specitem:SetScale(0.9)
|
||
|
item.specitem:ClearAllPoints()
|
||
|
item.specitem:SetParent(item)
|
||
|
item.specitem:SetPoint("TOPRIGHT", item, "TOPLEFT", 0, 0)
|
||
|
|
||
|
local _, tex, charges = GetQuestLogSpecialItemInfo(objective.type_quest.index)
|
||
|
item.specitem:SetID(objective.type_quest.index)
|
||
|
SetItemButtonTexture(item.specitem, tex)
|
||
|
item.specitem.rangeTimer = -1 -- This makes the little dot go away. Why does it do that?
|
||
|
item.specitem.charges = charges
|
||
|
|
||
|
item.specitem:Show()
|
||
|
|
||
|
spacer = h
|
||
|
end
|
||
|
|
||
|
return w+x+4, y+h, y+h+spacer
|
||
|
end
|
||
|
|
||
|
local function addMetaObjective(metaobj, items, y, depth)
|
||
|
local seen_texts = QuestHelper:CreateTable("amo_seen_texts")
|
||
|
|
||
|
local x, spacer
|
||
|
x, y, spacer = addItem(metaobj, y, true)
|
||
|
for _, v in ipairs(items) do
|
||
|
if not v.tracker_hide_dupes or not seen_texts[v.tracker_desc] then
|
||
|
x, y = addItem(v, y, false)
|
||
|
seen_texts[v.tracker_desc] = true
|
||
|
end
|
||
|
end
|
||
|
return math.max(y, spacer), depth + #items + 1
|
||
|
end
|
||
|
|
||
|
local function removeUnusedItem(item)
|
||
|
item.t = 0
|
||
|
item.sx, item.sy, item.dx, item.dy = item.x, item.y, item.x+30, item.y
|
||
|
QH_Hook(item, "OnMouseDown", nil)
|
||
|
item:EnableMouse(false)
|
||
|
QH_Hook(item, "OnUpdate", itemfadeout)
|
||
|
|
||
|
if item.specitem then
|
||
|
item.specitem:Hide()
|
||
|
table.insert(specitem_unused, item.specitem)
|
||
|
item.specitem = nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
local loading_vquest = {tracker_desc = QHFormat("QH_LOADING", "0")}
|
||
|
local flightpath_vquest = {tracker_desc = QHFormat("QH_FLIGHTPATH", "0")}
|
||
|
local recalculating_vquest = {tracker_desc = QHFormat("QH_RECALCULATING", "0")}
|
||
|
|
||
|
local recalculating_start = nil
|
||
|
|
||
|
|
||
|
local hidden_vquest1 = { tracker_desc = QHText("QUESTS_HIDDEN_1"), tracker_clicked = QH_Hidden_Menu }
|
||
|
local hidden_vquest2 = { tracker_desc = " " .. QHText("QUESTS_HIDDEN_2"), tracker_clicked = QH_Hidden_Menu }
|
||
|
|
||
|
local route = {}
|
||
|
local pinned = {}
|
||
|
|
||
|
-- This is actually called surprisingly often.
|
||
|
function QH_Tracker_Rescan()
|
||
|
used_count = QuestHelper:CreateTable("tracker rescan used_count")
|
||
|
|
||
|
local mo_done = QuestHelper:CreateTable("tracker rescan mo_done")
|
||
|
local obj_done = QuestHelper:CreateTable("tracker rescan obj_done")
|
||
|
|
||
|
local y, depth = 0, 0
|
||
|
|
||
|
do
|
||
|
local had_pinned = false
|
||
|
|
||
|
local objs = QuestHelper:CreateTable("tracker objs")
|
||
|
for k, v in pairs(pinned) do
|
||
|
if not objs[k.why] then objs[k.why] = QuestHelper:CreateTable("tracker objs sub") end
|
||
|
if not k.ignore and not k.tracker_hidden then table.insert(objs[k.why], k) end
|
||
|
obj_done[k.cluster] = true
|
||
|
end
|
||
|
|
||
|
local sort_objs = QuestHelper:CreateTable("tracker sobjs")
|
||
|
for k, v in pairs(objs) do
|
||
|
v.cluster = k
|
||
|
v.trackkey = k
|
||
|
table.insert(sort_objs, v)
|
||
|
end
|
||
|
|
||
|
table.sort(sort_objs, function (a, b) return tostring(a.trackkey) < tostring(b.trackkey) end)
|
||
|
|
||
|
for _, v in ipairs(sort_objs) do
|
||
|
y, depth = addMetaObjective(v.cluster, v, y, depth)
|
||
|
had_pinned = true
|
||
|
QuestHelper:ReleaseTable(v)
|
||
|
end
|
||
|
QuestHelper:ReleaseTable(sort_objs)
|
||
|
QuestHelper:ReleaseTable(objs)
|
||
|
|
||
|
if had_pinned then y = y + 10 end
|
||
|
end
|
||
|
|
||
|
if QuestHelper.loading_main then
|
||
|
loading_vquest.tracker_desc = QHFormat("QH_LOADING", string.format("%d", QuestHelper.loading_main:GetPercentage() * 100))
|
||
|
local x, ty = addItem(loading_vquest, y)
|
||
|
y = ty + 10
|
||
|
end
|
||
|
if QuestHelper.flightpathing then
|
||
|
flightpath_vquest.tracker_desc = QHFormat("QH_FLIGHTPATH", string.format("%d", QuestHelper.flightpathing:GetPercentage() * 100))
|
||
|
local x, ty = addItem(flightpath_vquest, y)
|
||
|
y = ty + 10
|
||
|
end
|
||
|
if not QuestHelper.loading_main and not QuestHelper.flightpathing and QuestHelper.route_change_progress then
|
||
|
if recalculating_start then
|
||
|
if recalculating_start + 5 < GetTime() then
|
||
|
recalculating_vquest.tracker_desc = QHFormat("QH_RECALCULATING", string.format("%d", QuestHelper.route_change_progress:GetPercentage() * 100))
|
||
|
local x, ty = addItem(recalculating_vquest, y)
|
||
|
y = ty + 10
|
||
|
end
|
||
|
else
|
||
|
recalculating_start = GetTime()
|
||
|
end
|
||
|
else
|
||
|
recalculating_start = nil
|
||
|
end
|
||
|
|
||
|
local metalookup = QuestHelper:CreateTable("tracker rescan metalookup")
|
||
|
for k, v in ipairs(route) do
|
||
|
if not v.ignore then
|
||
|
if not metalookup[v.why] then metalookup[v.why] = QuestHelper:CreateTable("tracker rescan metalookup item") end
|
||
|
if not v.tracker_hidden then table.insert(metalookup[v.why], v) end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
do
|
||
|
local current_mo
|
||
|
local current_mo_cluster
|
||
|
for k, v in ipairs(route) do
|
||
|
if depth > QuestHelper_Pref.track_size and not debug_output then break end
|
||
|
if not v.ignore and not v.why.tracker_hidden and not obj_done[v.cluster] then
|
||
|
if current_mo and v.why ~= current_mo and (v.why.tracker_split or not mo_done[v.why]) then
|
||
|
y, depth = addMetaObjective(current_mo, current_mo_cluster, y, depth)
|
||
|
QuestHelper:ReleaseTable(current_mo_cluster)
|
||
|
current_mo, current_mo_cluster = nil, nil
|
||
|
end
|
||
|
|
||
|
if not v.why.tracker_split then
|
||
|
if not mo_done[v.why] then
|
||
|
y, depth = addMetaObjective(v.why, metalookup[v.why], y, depth)
|
||
|
mo_done[v.why] = true
|
||
|
end
|
||
|
else
|
||
|
if not current_mo then
|
||
|
current_mo = v.why
|
||
|
current_mo_cluster = QuestHelper:CreateTable("tracker current cluster")
|
||
|
end
|
||
|
if not v.tracker_hidden then table.insert(current_mo_cluster, v) end
|
||
|
end
|
||
|
|
||
|
obj_done[v] = true
|
||
|
end
|
||
|
end
|
||
|
if current_mo and not (depth > QuestHelper_Pref.track_size and not debug_output) then
|
||
|
y, depth = addMetaObjective(current_mo, current_mo_cluster, y, depth)
|
||
|
end
|
||
|
if current_mo_cluster then
|
||
|
QuestHelper:ReleaseTable(current_mo_cluster)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- now we check to see if we need a hidden display
|
||
|
if (debug_output or depth < QuestHelper_Pref.track_size) and not QuestHelper.loading_main and not QuestHelper_Pref.filter_done and not QuestHelper_Pref.filter_zone and not QuestHelper_Pref.filter_watched then
|
||
|
local show = false
|
||
|
|
||
|
QH_Route_TraverseClusters(
|
||
|
function (clust)
|
||
|
if not show then
|
||
|
QH_Route_IgnoredReasons_Cluster(clust, function (reason)
|
||
|
show = true
|
||
|
end)
|
||
|
|
||
|
for _, v in ipairs(clust) do
|
||
|
QH_Route_IgnoredReasons_Node(v, function (reason)
|
||
|
show = true
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
)
|
||
|
|
||
|
if show then
|
||
|
y = y + 10
|
||
|
_, y = addItem(hidden_vquest1, y)
|
||
|
_, y = addItem(hidden_vquest2, y)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
-- any manipulations of the tracker should be done by now, everything after this is bookkeeping
|
||
|
|
||
|
for k, v in pairs(used_items) do
|
||
|
if not used_count[k] or used_count[k] < #v then
|
||
|
local ttp = QuestHelper:CreateTable("used_items ttp")
|
||
|
for m = 1, (used_count[k] or 0) do
|
||
|
table.insert(ttp, v[m])
|
||
|
end
|
||
|
for m = (used_count[k] or 0) + 1, #v do
|
||
|
removeUnusedItem(v[m])
|
||
|
end
|
||
|
|
||
|
if used_items[k] then
|
||
|
QuestHelper:ReleaseTable(used_items[k])
|
||
|
end
|
||
|
|
||
|
if #ttp > 0 then
|
||
|
used_items[k] = ttp
|
||
|
else
|
||
|
used_items[k] = nil
|
||
|
QuestHelper:ReleaseTable(ttp)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
QuestHelper:ReleaseTable(mo_done)
|
||
|
QuestHelper:ReleaseTable(obj_done)
|
||
|
for k, v in pairs(metalookup) do
|
||
|
QuestHelper:ReleaseTable(v)
|
||
|
end
|
||
|
QuestHelper:ReleaseTable(metalookup)
|
||
|
|
||
|
QuestHelper:ReleaseTable(used_count)
|
||
|
used_count = nil
|
||
|
|
||
|
if y ~= tracker.dh then
|
||
|
tracker.t = 0
|
||
|
tracker.sh = tracker:GetHeight()
|
||
|
tracker.dh = y
|
||
|
tracker.sw = tracker.dw
|
||
|
resizing = true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QH_Tracker_UpdateRoute(new_route)
|
||
|
route = new_route
|
||
|
QH_Tracker_Rescan()
|
||
|
end
|
||
|
|
||
|
function QH_Tracker_Pin(metaobjective, suppress)
|
||
|
if not pinned[metaobjective] then
|
||
|
pinned[metaobjective] = true
|
||
|
|
||
|
if not suppress then
|
||
|
QH_Tracker_Rescan()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QH_Tracker_Unpin(metaobjective, suppress)
|
||
|
if pinned[metaobjective] then
|
||
|
pinned[metaobjective] = nil -- nil, not false, so it'll be garbage-collected appropriately
|
||
|
|
||
|
if not suppress then
|
||
|
QH_Tracker_Rescan()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QH_Tracker_SetPin(metaobjective, flag, suppress)
|
||
|
if flag then
|
||
|
QH_Tracker_Pin(metaobjective, suppress)
|
||
|
else
|
||
|
QH_Tracker_Unpin(metaobjective, suppress)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
local check_delay = 4
|
||
|
|
||
|
-- This function does the grunt work of cursor positioning and rescaling. It does not actually reorganize items.
|
||
|
function tracker:update(delta)
|
||
|
if not delta then
|
||
|
-- This is called without a value when the questlog is updated.
|
||
|
-- We'll make sure we update the display on the next update.
|
||
|
check_delay = 1e99
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if resizing then
|
||
|
local t = self.t+delta
|
||
|
|
||
|
if t > 1 then
|
||
|
self:SetWidth(self.dw)
|
||
|
self:SetHeight(self.dh)
|
||
|
resizing = false
|
||
|
else
|
||
|
self.t = t
|
||
|
local it = 1-t
|
||
|
self:SetWidth(self.sw*it+self.dw*t)
|
||
|
self:SetHeight(self.sh*it+self.dh*t)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Manually checking if the mouse is in the frame, because if I used on OnEnter, i'd have to enable mouse input,
|
||
|
-- and if I did that, it would prevent the player from using the mouse to change the view if they clicked inside
|
||
|
-- the tracker.
|
||
|
local x, y = GetCursorPosition()
|
||
|
local s = 1/self:GetEffectiveScale()
|
||
|
x, y = x*s, y*s
|
||
|
|
||
|
QuestHelper: Assert(x)
|
||
|
QuestHelper: Assert(y)
|
||
|
--[[ QuestHelper: Assert(self:GetLeft())
|
||
|
QuestHelper: Assert(self:GetBottom())
|
||
|
QuestHelper: Assert(self:GetRight())
|
||
|
QuestHelper: Assert(self:GetTop())]]
|
||
|
|
||
|
-- Sometimes it just doesn't know its own coordinates. Not sure why. Maybe this will fix it.
|
||
|
local inside = (self:GetLeft() and (x >= self:GetLeft() and y >= self:GetBottom() and x < self:GetRight() and y < self:GetTop()))
|
||
|
if inside ~= was_inside then
|
||
|
was_inside = inside
|
||
|
if inside then
|
||
|
SetEnteredTracker(true)
|
||
|
else
|
||
|
SetEnteredTracker(false)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
check_delay = check_delay + delta
|
||
|
if check_delay > 1 then
|
||
|
check_delay = 0
|
||
|
|
||
|
QH_Tracker_Rescan()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
QH_Hook(tracker, "OnUpdate", tracker.update)
|
||
|
|
||
|
-- Some hooks to update the tracker when quests are added or removed. These should be moved into the quest director.
|
||
|
--[[
|
||
|
local orig_AddQuestWatch, orig_RemoveQuestWatch = AddQuestWatch, RemoveQuestWatch
|
||
|
|
||
|
function AddQuestWatch(...)
|
||
|
tracker:update()
|
||
|
return orig_AddQuestWatch(...)
|
||
|
end
|
||
|
|
||
|
function RemoveQuestWatch(...)
|
||
|
tracker:update()
|
||
|
return orig_RemoveQuestWatch(...)
|
||
|
end]]
|
||
|
|
||
|
-------------------------------------------------------------------------------------------------
|
||
|
-- This batch of stuff is to make sure the original tracker (and any modifications) stay hidden
|
||
|
|
||
|
local orig_TrackerBackdropOnShow -- bEQL (and perhaps other mods) add a backdrop to the tracker
|
||
|
local TrackerBackdropFound = false
|
||
|
|
||
|
local function TrackerBackdropOnShow(self, ...)
|
||
|
if QuestHelper_Pref.track and not QuestHelper_Pref.hide then
|
||
|
TrackerBackdropFound:Hide()
|
||
|
end
|
||
|
|
||
|
if orig_TrackerBackdropOnShow then
|
||
|
return orig_TrackerBackdropOnShow(self, ...)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function tracker:HideDefaultTracker()
|
||
|
-- The easy part: hide the original tracker
|
||
|
WatchFrame_RemoveObjectiveHandler(WatchFrame_DisplayTrackedQuests)
|
||
|
WatchFrame_ClearDisplay()
|
||
|
WatchFrame_Update()
|
||
|
|
||
|
-- The harder part: hide all those little buttons
|
||
|
do
|
||
|
local index = 1
|
||
|
while true do
|
||
|
local orig = _G["WatchFrameItem" .. tostring(index)]
|
||
|
if orig then orig:Hide() else break end
|
||
|
index = index + 1
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- The harder part: check if a known backdrop is present (but we don't already know about it).
|
||
|
-- If it is, make sure it's hidden, and hook its OnShow to make sure it stays that way.
|
||
|
-- Unfortunately, I can't figure out a good time to check for this once, so we'll just have
|
||
|
-- to keep checking. Hopefully, this won't happen too often.
|
||
|
if not TrackerBackdropFound then
|
||
|
if QuestWatchFrameBackdrop then
|
||
|
-- Found bEQL's QuestWatchFrameBackdrop...
|
||
|
TrackerBackdropFound = QuestWatchFrameBackdrop
|
||
|
end
|
||
|
|
||
|
if TrackerBackdropFound then
|
||
|
-- OK, we found something - so hide it, and make sure it doesn't rear its ugly head again
|
||
|
TrackerBackdropFound:Hide()
|
||
|
|
||
|
orig_TrackerBackdropOnShow = TrackerBackdropFound:GetScript("OnShow")
|
||
|
QH_Hook(TrackerBackdropFound, "OnShow", TrackerBackdropOnShow)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function tracker:ShowDefaultTracker()
|
||
|
-- I like how there's code explicitly to allow us to do this without checking if it's already added
|
||
|
WatchFrame_AddObjectiveHandler(WatchFrame_DisplayTrackedQuests)
|
||
|
-- Make sure the default tracker is up to date on what what's being watched and what isn't.
|
||
|
WatchFrame_Update()
|
||
|
|
||
|
if TrackerBackdropFound then
|
||
|
TrackerBackdropFound:Show()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QuestHelper:ShowTracker()
|
||
|
tracker:HideDefaultTracker()
|
||
|
minbutton:Show()
|
||
|
|
||
|
RefreshColor()
|
||
|
if not QuestHelper_Pref.track_minimized then
|
||
|
tracker:Show()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QuestHelper:HideTracker()
|
||
|
tracker:ShowDefaultTracker()
|
||
|
tracker:Hide()
|
||
|
minbutton:Hide()
|
||
|
end
|