1 QuestHelper_File
["tracker.lua"] = "Development Version"
2 QuestHelper_Loadtime
["tracker.lua"] = GetTime()
4 local debug_output
= false
5 if QuestHelper_File
["tracker.lua"] == "Development Version" then debug_output
= true end
9 So here's what we want to do.
11 We want a "refresh notification" where we send it the current route.
13 If things aren't in the route, we don't care about them . . . unless they're pinned.
15 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.
17 We're also not bothering with the whole metaobjective tree, we're just going one step up.
21 Note that "add" means "add iff it hasn't already been added."
23 Iff we haven't loaded yet, add a loaded message and a gap.
25 For each pinned objective, add the metaobjective and all objectives in its internal order. Iff we added things, add a gap.
27 For each route objective, add the metaobjective and all objectives in route order.
29 Later on we'll add an option for "splitting" metaobjectives, or possibly following the metaobjective tree all the way up.
33 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.
35 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.)
37 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.
40 local tracker
= CreateFrame("Frame", "QuestHelperQuestWatchFrame", UIParent
)
41 local minbutton
= CreateFrame("Button", "QuestHelperQuestWatchFrameMinimizeButton", UIParent
)
43 QuestHelper
.tracker
= tracker
45 local resizing
= false
47 tracker
:SetHeight(100)
48 tracker
:SetFrameStrata("BACKGROUND")
49 tracker
.dw
, tracker
.dh
= 200, 100
53 minbutton
:SetFrameStrata("LOW")
55 minbutton
:SetPoint("TOPRIGHT", WatchFrame
) -- We default to a different location to make it more likely to display the right item.
56 minbutton
:SetMovable(true)
57 minbutton
:SetUserPlaced(true)
58 minbutton
:SetWidth(32 / 1.6)
59 minbutton
:SetHeight(32)
60 minbutton
:SetFrameLevel(3)
61 local minbutton_tex
= minbutton
:CreateTexture()
62 minbutton_tex
:SetAllPoints()
63 minbutton_tex
:SetTexture(.6, .6, .6)
64 minbutton_tex
:SetParent(minbutton
)
66 local sigargh
= CreateFrame("Frame", minbutton
)
67 sigargh
:SetFrameStrata("LOW")
68 sigargh
:SetFrameLevel(4)
70 local sigil
= sigargh
:CreateTexture("BACKGROUND")
73 --sigil:SetPoint("CENTER", 0, 0)
74 sigil
:SetTexture("Interface\\AddOns\\QuestHelper\\sigil")
75 sigil
:SetPoint("CENTER", minbutton_tex
, "CENTER")
78 tracker
:SetPoint("CENTER", minbutton
)
80 function minbutton
:moved()
81 local x
, y
= self
:GetCenter()
82 local w
, h
= UIParent
:GetWidth(), UIParent
:GetHeight()
83 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 "")
85 tracker
:ClearAllPoints()
86 tracker
:SetPoint("CENTER", self
)
89 tracker
:SetPoint(anchor
, self
)
93 function QuestHelper
:ResetTrackerPosition(cmd
)
94 minbutton
:ClearAllPoints()
95 if cmd
and string.find(cmd
, "center") then
96 minbutton
:SetPoint("CENTER", nil, "CENTER", 100, 100)
98 minbutton
:SetPoint("RIGHT", nil, "RIGHT", -20, 230)
101 QuestHelper_Pref
.track_minimized
= false
103 self
:TextOut("Quest tracker postion reset.")
106 QH_Event({"DISPLAY_SIZE_CHANGED", "PLAYER_ENTERING_WORLD"}, function () minbutton
:moved() end)
108 QH_Hook(minbutton
, "OnClick", function ()
109 QuestHelper_Pref
.track_minimized
= not QuestHelper_Pref
.track_minimized
110 if QuestHelper_Pref
.track_minimized
then
117 minbutton
:RegisterForDrag("LeftButton")
119 QH_Hook(minbutton
, "OnDragStart", function(self
)
120 if self
:IsVisible() then
122 QH_Hook(self
, "OnUpdate", self
.moved
)
126 QH_Hook(minbutton
, "OnDragStop", function(self
)
127 QH_Hook(self
, "OnUpdate", nil)
128 self
:StopMovingOrSizing()
132 QH_Hook(minbutton
, "OnEnter", function (self
)
137 QH_Hook(minbutton
, "OnLeave", function (self
)
138 self
:SetAlpha(QuestHelper_Pref
.track_minimized
and .3 or .5)
139 sigargh
:SetAlpha(QuestHelper_Pref
.track_minimized
and .3 or .5)
142 -- used_items[objective][index]
143 -- used_count[objective] is incremented as the last valid index
144 -- so, therefore, used_items[objective][used_count[objective]] is not nil
145 local used_items
= {}
146 local used_count
= {}
148 -- it's possible for an item to be in neither used_items nor recycled_items, if it's in the process of fading out
149 local recycled_items
= {}
151 -- These two functions are basically identical. Combine them.
152 local function itemupdate(item
, delta
)
155 local a
= item
:GetAlpha()
165 local t
= item
.t
+ delta
170 local sp
= math
.sqrt(t
-t
*t
)
171 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
175 item
.x
, item
.y
= item
.ex
, item
.ey
178 item
:ClearAllPoints()
179 item
:SetPoint("TOPLEFT", tracker
, "TOPLEFT", item
.x
, -item
.y
)
182 QH_Hook(item
, "OnUpdate", nil)
186 local function itemfadeout(item
, delta
)
187 local a
= item
:GetAlpha()
195 QH_Hook(item
, "OnUpdate", nil)
196 table.insert(recycled_items
, item
)
200 local t
= item
.t
+ delta
205 local sp
= math
.sqrt(t
-t
*t
)
206 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
209 item
.x
, item
.y
= item
.ex
, item
.ey
212 item
:ClearAllPoints()
213 item
:SetPoint("TOPLEFT", tracker
, "TOPLEFT", item
.x
, -item
.y
)
216 --[[function QH_ToggleQuestLog() -- This seems to be gone in 3.0, so I'm adding it here.
217 if (QuestLogFrame:IsShown()) then
218 HideUIPanel(QuestLogFrame);
220 ShowUIPanel(QuestLogFrame);
224 -- Grim stuff with uberquest, I need a better way to handle this
225 local function itemclick(item, button)
226 if button == "RightButton" then
227 local quest = item.quest
230 local title = GetQuestLogTitle(index)
231 if not title then break end
233 if title == quest then
235 -- UberQuest needs a little extra effort to work properly.
237 if UberQuest_List:IsShown() and GetQuestLogSelection() == index then
240 QuestLog_SetSelection(index)
242 -- By hiding the list, the replaced ToggleQuestLog function should try to reshow it
243 -- and in the process update the frames to reflect the selected quest.
244 UberQuest_List:Hide()
245 UberQuest_Details:Show()
249 -- This code seems to work properly with the builtin questlog, as well as bEQL and DoubleWide.
251 if QuestLogFrame:IsShown() and GetQuestLogSelection() == index then
252 -- If the selected quest is already being shown, hide it.
255 -- Otherwise, select it and show it.
256 QuestLog_SetSelection(index)
258 if not QuestLogFrame:IsShown() then
272 local function allocateItem()
275 item
= table.remove(recycled_items
)
276 if item
then return item
end
278 item
= CreateFrame("Frame", nil, tracker
)
279 item
.text
= item
:CreateFontString()
280 item
.text
:SetShadowColor(0, 0, 0, .8)
281 item
.text
:SetShadowOffset(1, -1)
282 item
.text
:SetPoint("TOPLEFT", item
)
286 local specitem_max
= 1
287 local specitem_unused
= {}
289 -- 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
290 local function addItem(objective
, y
, meta
)
291 local obj_key
= objective
292 if obj_key
.cluster
then obj_key
= obj_key
.cluster
end
293 used_count
[obj_key
] = (used_count
[obj_key
] or 0) + 1
294 if not used_items
[obj_key
] then used_items
[obj_key
] = QuestHelper
:CreateTable("additem used_items") end
295 local item
= used_items
[obj_key
][used_count
[obj_key]]
297 local x
= meta
and 4 or 20
300 used_items
[obj_key
][used_count
[obj_key]]
= allocateItem()
301 item
= used_items
[obj_key
][used_count
[obj_key]]
304 item
.text
:SetFont(QuestHelper
.font
.serif
, 12)
305 item
.text
:SetTextColor(.82, .65, 0)
307 item
.text
:SetFont(QuestHelper
.font
.sans
, 12)
308 item
.text
:SetTextColor(.82, .82, .82)
313 item
.sx
, item
.sy
, item
.x
, item
.y
, item
.ex
, item
.ey
, item
.t
= x
+30, y
, x
, y
, x
, y
, 0
314 QH_Hook(item
, "OnUpdate", itemupdate
)
319 item
.text
:SetText(item
.obj
.tracker_desc
or "(no description)")
321 local w
, h
= item
.text
:GetWidth(), item
.text
:GetHeight()
325 if objective
.tracker_clicked
then
326 QH_Hook(item
, "OnMouseDown", function (self
, button
) if button
== "RightButton" then objective
.tracker_clicked() end end)
327 item
:EnableMouse(true)
330 if item
.ex
~= x
or item
.ey
~= y
then
331 item
.sx
, item
.sy
, item
.ex
, item
.ey
= item
.x
, item
.y
, x
, y
333 QH_Hook(item
, "OnUpdate", itemupdate
)
336 -- we're just going to recycle this each time
337 if item
.specitem
then
339 table.insert(specitem_unused
, item
.specitem
)
344 -- hacky - progress only shows up if we're not on a metaobjective. wheee
345 if objective
.type_quest
and objective
.type_quest
.index
and not objective
.progress
and GetQuestLogSpecialItemInfo(objective
.type_quest
.index
) then
346 item
.specitem
= table.remove(specitem_unused
)
347 if not item
.specitem
then
348 item
.specitem
= CreateFrame("BUTTON", "QH_SpecItem_" .. tostring(specitem_max
), item
, "WatchFrameItemButtonTemplate")
349 QuestHelper
: Assert(item
.specitem
)
351 local rangey
= _G
["QH_SpecItem_" .. tostring(specitem_max
) .. "HotKey"]
352 QuestHelper
: Assert(rangey
)
353 local fn
, fh
, ff
= rangey
:GetFont()
354 rangey
:SetFont("Fonts\\ARIALN.TTF", fh
, ff
)
355 rangey
:SetText(RANGE_INDICATOR
)
356 rangey
:ClearAllPoints()
357 rangey
:SetPoint("BOTTOMRIGHT", item
.specitem
, "BOTTOMRIGHT", 0, 2)
359 specitem_max
= specitem_max
+ 1
362 item
.specitem
:SetScale(0.9)
363 item
.specitem
:ClearAllPoints()
364 item
.specitem
:SetParent(item
)
365 item
.specitem
:SetPoint("TOPRIGHT", item
, "TOPLEFT", 0, 0)
367 local _
, tex
, charges
= GetQuestLogSpecialItemInfo(objective
.type_quest
.index
)
368 item
.specitem
:SetID(objective
.type_quest
.index
)
369 SetItemButtonTexture(item
.specitem
, tex
)
370 item
.specitem
.rangeTimer
= -1 -- This makes the little dot go away. Why does it do that?
371 item
.specitem
.charges
= charges
378 return w
+x
+4, y
+h
, y
+h
+spacer
381 local function addMetaObjective(metaobj
, items
, y
, depth
)
383 x
, y
, spacer
= addItem(metaobj
, y
, true)
384 for _
, v
in ipairs(items
) do
385 x
, y
= addItem(v
, y
, false)
387 return math
.max(y
, spacer
), depth
+ #items
+ 1
390 --[[ -- these will be plugged in later one way or another
391 local function ccode(r1, g1, b1, r2, g2, b2, p)
393 p, ip = p*255, 255-p*255
394 return string.format("|cff%02x%02x%02x", r1*ip+r2*p, g1*ip+g2*p, b1*ip+b2*p)
397 local function qname(title, level)
398 if QuestHelper_Pref.track_level and level ~= 7777 and level ~= 7778 then
399 title = string.format("[%d] %s", level, title)
402 if level == 7778 then
406 if QuestHelper_Pref.track_qcolour then
407 local player_level = QuestHelper.player_level
408 local delta = level - player_level
413 colour = "|cffff0000"
414 elseif delta >= 0 then
415 colour = ccode(1, 1, 0, 1, 0, 0, delta/5)
419 if player_level >= 60 then grey = player_level - 9
420 elseif player_level >= 40 then grey = player_level - math.floor(player_level/5) - 1
421 elseif player_level >= 6 then grey = player_level - math.floor(player_level/10) - 5
424 if level == -7778 then
425 colour = "|cff808080"
426 elseif level > grey then
427 colour = ccode(0, 1, 0, 1, 1, 0, (grey-level)/(grey-player_level))
429 colour = ccode(.4, .4, .4, .2, .8, .2, (1-level)/(1-grey))
433 title = string.format("%s%s", colour, title)
439 local function oname(text, pct)
440 if QuestHelper_Pref.track_ocolour then
441 text = string.format("%s%s", pct < 0.5 and ccode(1, 0, 0, 1, 1, 0, pct*2) or ccode(1, 1, 0, 0, 1, 0, pct*2-1), text)
448 local function removeUnusedItem(item
)
450 item
.sx
, item
.sy
, item
.dx
, item
.dy
= item
.x
, item
.y
, item
.x
+30, item
.y
451 QH_Hook(item
, "OnMouseDown", nil)
452 item
:EnableMouse(false)
453 QH_Hook(item
, "OnUpdate", itemfadeout
)
455 if item
.specitem
then
457 table.insert(specitem_unused
, item
.specitem
)
463 local was_inside
= false
467 local function addobj(objective
, seen
, obj_index_lookup
, filter
, x
, y
, gap
)
471 if objective
.cat
== "quest" then
474 quest
= objective
.quest
477 if quest
and quest
.watched
and not seen
[quest
] and (not filter
or filter(quest
)) then
480 local level
, name
= string.match(quest
.obj
, "^(%d+)/%d*/(.*)$")
483 level
, name
= string.match(quest
.obj
, "^(%d+)/(.*)$")
485 level
, name
= 1, quest
.obj
489 level
= tonumber(level
) or 1
492 local w
, h
= addItem(qname(name
, level
), true, quest
, -(y
+gap
), name
, quest
.index
)
497 for obj
in pairs(quest
.swap_after
or quest
.after
) do
499 table.insert(obj_list
, obj
)
503 table.sort(obj_list
, objlist_sort
)
505 for i
, obj
in ipairs(obj_list
) do
506 local pct
, text
= 0, obj
.obj
507 local seen_sum
, seen_max
= 0, 0
510 local seen_have
, seen_need
= QuestHelper
:CreateTable(), QuestHelper
:CreateTable()
512 for user
, progress
in pairs(obj
.progress
) do
513 seen_sum
= seen_sum
+ progress
[3]
514 seen_max
= seen_max
+ 1
515 seen_have
[progress
[1]]
= true
516 seen_need
[progress
[2]]
= true
520 pct
= seen_sum
/ seen_max
521 local list
= QuestHelper
:CreateTable()
523 for val
in pairs(seen_have
) do
524 table.insert(list
, val
)
529 local have
= table.concat(list
, ", ")
531 for i
= #list
,1,-1 do
535 for val
in pairs(seen_need
) do
536 table.insert(list
, val
)
539 if #list
~= 1 or list
[1] ~= 1 then
540 -- If there is only one thing needed, ignore the progress, it's redundant.
541 -- It's either shown or it isn't.
545 local need
= table.concat(list
, ", ")
547 text
= string.format((tonumber(have
) and tonumber(need
) and QUEST_ITEMS_NEEDED
) or QUEST_FACTION_NEEDED
,
551 QuestHelper
:ReleaseTable(list
)
554 QuestHelper
:ReleaseTable(seen_have
)
555 QuestHelper
:ReleaseTable(seen_need
)
558 if seen_sum
~= seen_max
then
560 w
, h
= addItem(oname(text
, pct
), quest
, obj
, -y
)
566 for i
= #obj_list
, 1, -1 do obj_list
[i
] = nil end
569 return x
, y
, gap
, count
573 local loading_vquest
= {tracker_desc
= QHFormat("QH_LOADING", "0")}
574 local flightpath_vquest
= {tracker_desc
= QHFormat("QH_FLIGHTPATH", "0")}
577 local hidden_vquest1
= { tracker_desc
= QHText("QUESTS_HIDDEN_1"), tracker_clicked
= QH_Hidden_Menu
}
578 local hidden_vquest2
= { tracker_desc
= " " .. QHText("QUESTS_HIDDEN_2"), tracker_clicked
= QH_Hidden_Menu
}
583 -- This is actually called surprisingly often.
584 function QH_Tracker_Rescan()
585 used_count
= QuestHelper
:CreateTable("tracker rescan used_count")
587 local mo_done
= QuestHelper
:CreateTable("tracker rescan mo_done")
588 local obj_done
= QuestHelper
:CreateTable("tracker rescan obj_done")
590 local y
, depth
= 0, 0
593 local had_pinned
= false
595 local objs
= QuestHelper
:CreateTable("tracker objs")
596 for k
, v
in pairs(pinned
) do
597 if not objs
[k
.why
] then objs
[k
.why
] = QuestHelper
:CreateTable("tracker objs sub") end
598 if not k
.ignore
and not k
.tracker_hidden
then table.insert(objs
[k
.why
], k
) end
599 obj_done
[k
.cluster
] = true
602 local sort_objs
= QuestHelper
:CreateTable("tracker sobjs")
603 for k
, v
in pairs(objs
) do
606 table.insert(sort_objs
, v
)
609 table.sort(sort_objs
, function (a
, b
) return tostring(a
.trackkey
) < tostring(b
.trackkey
) end)
611 for _
, v
in ipairs(sort_objs
) do
612 y
, depth
= addMetaObjective(v
.cluster
, v
, y
, depth
)
614 QuestHelper
:ReleaseTable(v
)
616 QuestHelper
:ReleaseTable(sort_objs
)
617 QuestHelper
:ReleaseTable(objs
)
619 if had_pinned
then y
= y
+ 10 end
622 if QuestHelper
.loading_main
then
623 loading_vquest
.tracker_desc
= QHFormat("QH_LOADING", string.format("%d", QuestHelper
.loading_main
:GetPercentage() * 100))
624 local x
, ty
= addItem(loading_vquest
, y
)
627 if QuestHelper
.flightpathing
then
628 flightpath_vquest
.tracker_desc
= QHFormat("QH_FLIGHTPATH", string.format("%d", QuestHelper
.flightpathing
:GetPercentage() * 100))
629 local x
, ty
= addItem(flightpath_vquest
, y
)
633 local metalookup
= QuestHelper
:CreateTable("tracker rescan metalookup")
634 for k
, v
in ipairs(route
) do
636 if not metalookup
[v
.why
] then metalookup
[v
.why
] = QuestHelper
:CreateTable("tracker rescan metalookup item") end
637 if not v
.tracker_hidden
then table.insert(metalookup
[v
.why
], v
) end
643 local current_mo_cluster
644 for k
, v
in ipairs(route
) do
645 if depth
> QuestHelper_Pref
.track_size
and not debug_output
then break end
646 if not v
.ignore
and not v
.why
.tracker_hidden
and not obj_done
[v
.cluster
] then
647 if current_mo
and v
.why
~= current_mo
then
648 y
, depth
= addMetaObjective(current_mo
, current_mo_cluster
, y
, depth
)
649 QuestHelper
:ReleaseTable(current_mo_cluster
)
650 current_mo
, current_mo_cluster
= nil, nil
653 if not v
.why
.tracker_split
then
654 if not mo_done
[v
.why
] then
655 y
, depth
= addMetaObjective(v
.why
, metalookup
[v
.why
], y
, depth
)
656 mo_done
[v
.why
] = true
659 if not current_mo
then
661 current_mo_cluster
= QuestHelper
:CreateTable("tracker current cluster")
663 if not v
.tracker_hidden
then table.insert(current_mo_cluster
, v
) end
669 if current_mo
and not (depth
> QuestHelper_Pref
.track_size
and not debug_output
) then
670 y
, depth
= addMetaObjective(current_mo
, current_mo_cluster
, y
, depth
)
672 if current_mo_cluster
then
673 QuestHelper
:ReleaseTable(current_mo_cluster
)
677 -- now we check to see if we need a hidden display
678 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
681 QH_Route_TraverseClusters(
684 QH_Route_IgnoredReasons_Cluster(clust
, function (reason
)
688 for _
, v
in ipairs(clust
) do
689 QH_Route_IgnoredReasons_Node(v
, function (reason
)
699 _
, y
= addItem(hidden_vquest1
, y
)
700 _
, y
= addItem(hidden_vquest2
, y
)
705 -- any manipulations of the tracker should be done by now, everything after this is bookkeeping
707 for k
, v
in pairs(used_items
) do
708 if not used_count
[k
] or used_count
[k
] < #v
then
709 local ttp
= QuestHelper
:CreateTable("used_items ttp")
710 for m
= 1, (used_count
[k
] or 0) do
711 table.insert(ttp
, v
[m
])
713 for m
= (used_count
[k
] or 0) + 1, #v
do
714 removeUnusedItem(v
[m
])
717 if used_items
[k
] then
718 QuestHelper
:ReleaseTable(used_items
[k
])
725 QuestHelper
:ReleaseTable(ttp
)
730 QuestHelper
:ReleaseTable(mo_done
)
731 QuestHelper
:ReleaseTable(obj_done
)
732 for k
, v
in pairs(metalookup
) do
733 QuestHelper
:ReleaseTable(v
)
735 QuestHelper
:ReleaseTable(metalookup
)
737 QuestHelper
:ReleaseTable(used_count
)
740 if y
~= tracker
.dh
then
742 tracker
.sh
= tracker
:GetHeight()
744 tracker
.sw
= tracker
.dw
754 if x ~= tracker.dw or y ~= tracker.dy then
756 tracker.sw, tracker.sh = tracker:GetWidth(), tracker:GetHeight()
757 tracker.dw, tracker.dh = x, y
763 local quests = QuestHelper.quest_log
767 local track_size = QuestHelper_Pref.track_size
768 local quests_added = {}
770 for quest, objs in pairs(used_items) do
771 for obj, item in pairs(objs) do
776 for i, objective in pairs(QuestHelper.route) do
777 if objective.watched then
778 obj_index_lookup[objective] = i
782 for q, data in pairs(QuestHelper.quest_log) do
783 quest_lookup[data.index] = q
786 -- Add our little "not yet loaded" notification
787 local loadedshow = false
788 if not QuestHelper.Routing.map_walker then
790 x, y, gap, count = addobj(loading_vquest, seen, nil, nil, x, y, gap)
791 added = added + count
794 if QuestHelper_Flight_Updates and QuestHelper_Flight_Updates_Current and QuestHelper_Flight_Updates > 0 and QuestHelper_Flight_Updates_Current < QuestHelper_Flight_Updates then
795 loading_vquest.obj = string.format("7777/" .. QHFormat("QH_LOADING", string.format("%d", QuestHelper_Flight_Updates_Current * 100 / QuestHelper_Flight_Updates)))
799 -- Add an extra large gap to seperate the notification from everything else
802 -- Add Quests that are watched but not in the route.
804 local uq_settings = UberQuest_Config[UnitName("player")]
806 local list = uq_settings.selected
810 local name = GetQuestLogTitle(i)
811 if not name then break end
812 quest_lookup[name] = quest_lookup[i]
815 for name in pairs(list) do
816 local q = quest_lookup[name]
817 if q and not obj_index_lookup[q] then
819 x, y, gap, count = addobj(q, seen, obj_index_lookup, nil, x, y, gap)
820 added = added + count
821 quests_added[q] = true
827 for i = 1,GetNumQuestWatches() do
828 local q = quest_lookup[GetQuestIndexForWatch(i)]
829 if q and not obj_index_lookup[q] then
831 x, y, gap, count = addobj(q, seen, obj_index_lookup, nil, x, y, gap)
832 added = added + count
837 -- Add Quests that are watched and are in the route.
838 for i, objective in ipairs(QuestHelper.route) do
840 x, y, gap, count = addobj(objective, seen, obj_index_lookup, watched_filter, x, y, gap)
841 added = added + count
842 quests_added[objective] = true
845 -- Add an extra large gap to seperate the watched objectives from the automatic objectives.
848 -- Add Quests that aren't watched and are in the route.
849 if added <= track_size then
850 for i, objective in ipairs(QuestHelper.route) do
852 x, y, gap, count = addobj(objective, seen, obj_index_lookup, nil, x, y, gap)
853 added = added + count
854 quests_added[objective] = true
856 if added > track_size then
862 if not loadedshow and added < track_size and not QuestHelper_Pref.filter_done and not QuestHelper_Pref.filter_zone and not QuestHelper_Pref.filter_watched then
865 for k, v in pairs(quest_lookup) do
866 if not quests_added[v] then
867 notadded = notadded + 1
875 x, y, gap, count = addobj(hidden_vquest1, seen, nil, nil, x, y, gap)
876 added = added + count
877 x, y, gap, count = addobj(hidden_vquest2, seen, nil, nil, x, y, gap)
878 added = added + count
882 for obj in pairs(obj_index_lookup) do
883 obj_index_lookup[obj] = nil
886 for key in pairs(quest_lookup) do
887 quest_lookup[key] = nil
890 for quest, objs in pairs(used_items) do
891 for obj, item in pairs(objs) do
892 if not item.used then
893 removeUnusedItem(quest, obj, item)
898 for key in pairs(seen) do
904 if x ~= tracker.dw or y ~= tracker.dy then
906 tracker.sw, tracker.sh = tracker:GetWidth(), tracker:GetHeight()
907 tracker.dw, tracker.dh = x, y
915 function QH_Tracker_UpdateRoute(new_route
)
920 function QH_Tracker_Pin(metaobjective
, suppress
)
921 if not pinned
[metaobjective
] then
922 pinned
[metaobjective
] = true
930 function QH_Tracker_Unpin(metaobjective
, suppress
)
931 if pinned
[metaobjective
] then
932 pinned
[metaobjective
] = nil -- nil, not false, so it'll be garbage-collected appropriately
940 function QH_Tracker_SetPin(metaobjective
, flag
, suppress
)
942 QH_Tracker_Pin(metaobjective
, suppress
)
944 QH_Tracker_Unpin(metaobjective
, suppress
)
949 local check_delay
= 4
951 -- This function does the grunt work of cursor positioning and rescaling. It does not actually reorganize items.
952 function tracker
:update(delta
)
954 -- This is called without a value when the questlog is updated.
955 -- We'll make sure we update the display on the next update.
961 local t
= self
.t
+delta
964 self
:SetWidth(self
.dw
)
965 self
:SetHeight(self
.dh
)
970 self
:SetWidth(self
.sw
*it
+self
.dw
*t
)
971 self
:SetHeight(self
.sh
*it
+self
.dh
*t
)
975 -- Manually checking if the mouse is in the frame, because if I used on OnEnter, i'd have to enable mouse input,
976 -- and if I did that, it would prevent the player from using the mouse to change the view if they clicked inside
978 local x
, y
= GetCursorPosition()
979 local s
= 1/self
:GetEffectiveScale()
982 QuestHelper
: Assert(x
)
983 QuestHelper
: Assert(y
)
984 --[[ QuestHelper: Assert(self:GetLeft())
985 QuestHelper: Assert(self:GetBottom())
986 QuestHelper: Assert(self:GetRight())
987 QuestHelper: Assert(self:GetTop())]]
989 -- Sometimes it just doesn't know its own coordinates. Not sure why. Maybe this will fix it.
990 local inside
= (self
:GetLeft() and (x
>= self
:GetLeft() and y
>= self
:GetBottom() and x
< self
:GetRight() and y
< self
:GetTop()))
991 if inside
~= was_inside
then
994 minbutton
:SetAlpha(.5)
996 elseif not QuestHelper_Pref
.track_minimized
then
997 minbutton
:SetAlpha(0)
1002 check_delay
= check_delay
+ delta
1003 if check_delay
> 1 then
1010 QH_Hook(tracker
, "OnUpdate", tracker
.update
)
1012 -- Some hooks to update the tracker when quests are added or removed. These should be moved into the quest director.
1014 local orig_AddQuestWatch, orig_RemoveQuestWatch = AddQuestWatch, RemoveQuestWatch
1016 function AddQuestWatch(...)
1018 return orig_AddQuestWatch(...)
1021 function RemoveQuestWatch(...)
1023 return orig_RemoveQuestWatch(...)
1026 -------------------------------------------------------------------------------------------------
1027 -- This batch of stuff is to make sure the original tracker (and any modifications) stay hidden
1029 local orig_TrackerBackdropOnShow
-- bEQL (and perhaps other mods) add a backdrop to the tracker
1030 local TrackerBackdropFound
= false
1032 local function TrackerBackdropOnShow(self
, ...)
1033 if QuestHelper_Pref
.track
and not QuestHelper_Pref
.hide
then
1034 TrackerBackdropFound
:Hide()
1037 if orig_TrackerBackdropOnShow
then
1038 return orig_TrackerBackdropOnShow(self
, ...)
1042 function tracker
:HideDefaultTracker()
1043 -- The easy part: hide the original tracker
1044 WatchFrame_RemoveObjectiveHandler(WatchFrame_DisplayTrackedQuests
)
1045 WatchFrame_ClearDisplay()
1048 -- The harder part: hide all those little buttons
1052 local orig
= _G
["WatchFrameItem" .. tostring(index
)]
1053 if orig
then orig
:Hide() else break end
1058 -- The harder part: check if a known backdrop is present (but we don't already know about it).
1059 -- If it is, make sure it's hidden, and hook its OnShow to make sure it stays that way.
1060 -- Unfortunately, I can't figure out a good time to check for this once, so we'll just have
1061 -- to keep checking. Hopefully, this won't happen too often.
1062 if not TrackerBackdropFound
then
1063 if QuestWatchFrameBackdrop
then
1064 -- Found bEQL's QuestWatchFrameBackdrop...
1065 TrackerBackdropFound
= QuestWatchFrameBackdrop
1068 if TrackerBackdropFound
then
1069 -- OK, we found something - so hide it, and make sure it doesn't rear its ugly head again
1070 TrackerBackdropFound
:Hide()
1072 orig_TrackerBackdropOnShow
= TrackerBackdropFound
:GetScript("OnShow")
1073 QH_Hook(TrackerBackdropFound
, "OnShow", TrackerBackdropOnShow
)
1078 function tracker
:ShowDefaultTracker()
1079 -- I like how there's code explicitly to allow us to do this without checking if it's already added
1080 WatchFrame_AddObjectiveHandler(WatchFrame_DisplayTrackedQuests
)
1081 -- Make sure the default tracker is up to date on what what's being watched and what isn't.
1084 if TrackerBackdropFound
then
1085 TrackerBackdropFound
:Show()
1089 function QuestHelper
:ShowTracker()
1090 tracker
:HideDefaultTracker()
1093 if QuestHelper_Pref
.track_minimized
then
1094 minbutton
:SetAlpha(.3)
1095 sigargh
:SetAlpha(.3)
1097 minbutton
:SetAlpha(0)
1103 function QuestHelper
:HideTracker()
1104 tracker
:ShowDefaultTracker()