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("LOW")
49 tracker
.dw
, tracker
.dh
= 200, 100
53 --minbutton:SetFrameStrata("HIGH")
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 local minbutton_tex
= minbutton
:CreateTexture()
61 minbutton_tex
:SetAllPoints()
62 minbutton_tex
:SetTexture(.6, .6, .6)
63 minbutton_tex
:SetParent(minbutton
)
65 local sigil
= minbutton
:CreateTexture("BACKGROUND", minbutton_tex
)
68 --sigil:SetPoint("CENTER", 0, 0)
69 sigil
:SetTexture("Interface\\AddOns\\QuestHelper\\sigil")
70 sigil
:SetPoint("CENTER", minbutton_tex
, "CENTER")
73 tracker
:SetPoint("CENTER", minbutton
)
75 function minbutton
:moved()
76 local x
, y
= self
:GetCenter()
77 local w
, h
= UIParent
:GetWidth(), UIParent
:GetHeight()
78 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 "")
80 tracker
:ClearAllPoints()
81 tracker
:SetPoint("CENTER", self
)
84 tracker
:SetPoint(anchor
, self
)
88 function QuestHelper
:ResetTrackerPosition(cmd
)
89 minbutton
:ClearAllPoints()
90 if cmd
and string.find(cmd
, "center") then
91 minbutton
:SetPoint("CENTER", nil, "CENTER", 100, 100)
93 minbutton
:SetPoint("RIGHT", nil, "RIGHT", -20, 230)
96 QuestHelper_Pref
.track_minimized
= false
98 self
:TextOut("Quest tracker postion reset.")
101 QH_Event({"DISPLAY_SIZE_CHANGED", "PLAYER_ENTERING_WORLD"}, function () minbutton
:moved() end)
103 QH_Hook(minbutton
, "OnClick", function ()
104 QuestHelper_Pref
.track_minimized
= not QuestHelper_Pref
.track_minimized
105 if QuestHelper_Pref
.track_minimized
then
112 minbutton
:RegisterForDrag("LeftButton")
114 QH_Hook(minbutton
, "OnDragStart", function(self
)
115 if self
:IsVisible() then
117 QH_Hook(self
, "OnUpdate", self
.moved
)
121 QH_Hook(minbutton
, "OnDragStop", function(self
)
122 QH_Hook(self
, "OnUpdate", nil)
123 self
:StopMovingOrSizing()
127 QH_Hook(minbutton
, "OnEnter", function (self
)
131 QH_Hook(minbutton
, "OnLeave", function (self
)
132 self
:SetAlpha(QuestHelper_Pref
.track_minimized
and .3 or .5)
135 -- used_items[objective][index]
136 -- used_count[objective] is incremented as the last valid index
137 -- so, therefore, used_items[objective][used_count[objective]] is not nil
138 local used_items
= {}
139 local used_count
= {}
141 -- it's possible for an item to be in neither used_items nor recycled_items, if it's in the process of fading out
142 local recycled_items
= {}
144 -- These two functions are basically identical. Combine them.
145 local function itemupdate(item
, delta
)
148 local a
= item
:GetAlpha()
158 local t
= item
.t
+ delta
163 local sp
= math
.sqrt(t
-t
*t
)
164 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
168 item
.x
, item
.y
= item
.ex
, item
.ey
171 item
:ClearAllPoints()
172 item
:SetPoint("TOPLEFT", tracker
, "TOPLEFT", item
.x
, -item
.y
)
175 QH_Hook(item
, "OnUpdate", nil)
179 local function itemfadeout(item
, delta
)
180 local a
= item
:GetAlpha()
188 QH_Hook(item
, "OnUpdate", nil)
189 table.insert(recycled_items
, item
)
193 local t
= item
.t
+ delta
198 local sp
= math
.sqrt(t
-t
*t
)
199 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
202 item
.x
, item
.y
= item
.ex
, item
.ey
205 item
:ClearAllPoints()
206 item
:SetPoint("TOPLEFT", tracker
, "TOPLEFT", item
.x
, -item
.y
)
209 --[[function QH_ToggleQuestLog() -- This seems to be gone in 3.0, so I'm adding it here.
210 if (QuestLogFrame:IsShown()) then
211 HideUIPanel(QuestLogFrame);
213 ShowUIPanel(QuestLogFrame);
217 -- Grim stuff with uberquest, I need a better way to handle this
218 local function itemclick(item, button)
219 if button == "RightButton" then
220 local quest = item.quest
223 local title = GetQuestLogTitle(index)
224 if not title then break end
226 if title == quest then
228 -- UberQuest needs a little extra effort to work properly.
230 if UberQuest_List:IsShown() and GetQuestLogSelection() == index then
233 QuestLog_SetSelection(index)
235 -- By hiding the list, the replaced ToggleQuestLog function should try to reshow it
236 -- and in the process update the frames to reflect the selected quest.
237 UberQuest_List:Hide()
238 UberQuest_Details:Show()
242 -- This code seems to work properly with the builtin questlog, as well as bEQL and DoubleWide.
244 if QuestLogFrame:IsShown() and GetQuestLogSelection() == index then
245 -- If the selected quest is already being shown, hide it.
248 -- Otherwise, select it and show it.
249 QuestLog_SetSelection(index)
251 if not QuestLogFrame:IsShown() then
265 local function allocateItem()
268 item
= table.remove(recycled_items
)
269 if item
then return item
end
271 item
= CreateFrame("Frame", nil, tracker
)
272 item
.text
= item
:CreateFontString()
273 item
.text
:SetShadowColor(0, 0, 0, .8)
274 item
.text
:SetShadowOffset(1, -1)
275 item
.text
:SetPoint("TOPLEFT", item
)
279 local specitem_max
= 1
280 local specitem_unused
= {}
282 -- 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
283 local function addItem(objective
, y
, meta
)
284 local obj_key
= objective
285 if obj_key
.cluster
then obj_key
= obj_key
.cluster
end
286 used_count
[obj_key
] = (used_count
[obj_key
] or 0) + 1
287 if not used_items
[obj_key
] then used_items
[obj_key
] = QuestHelper
:CreateTable("additem used_items") end
288 local item
= used_items
[obj_key
][used_count
[obj_key]]
290 local x
= meta
and 4 or 20
293 used_items
[obj_key
][used_count
[obj_key]]
= allocateItem()
294 item
= used_items
[obj_key
][used_count
[obj_key]]
297 item
.text
:SetFont(QuestHelper
.font
.serif
, 12)
298 item
.text
:SetTextColor(.82, .65, 0)
300 item
.text
:SetFont(QuestHelper
.font
.sans
, 12)
301 item
.text
:SetTextColor(.82, .82, .82)
306 item
.sx
, item
.sy
, item
.x
, item
.y
, item
.ex
, item
.ey
, item
.t
= x
+30, y
, x
, y
, x
, y
, 0
307 QH_Hook(item
, "OnUpdate", itemupdate
)
312 item
.text
:SetText(item
.obj
.tracker_desc
or "(no description)")
314 local w
, h
= item
.text
:GetWidth(), item
.text
:GetHeight()
318 if objective
.tracker_clicked
then
319 QH_Hook(item
, "OnMouseDown", function (self
, button
) if button
== "RightButton" then objective
.tracker_clicked() end end)
320 item
:EnableMouse(true)
323 if item
.ex
~= x
or item
.ey
~= y
then
324 item
.sx
, item
.sy
, item
.ex
, item
.ey
= item
.x
, item
.y
, x
, y
326 QH_Hook(item
, "OnUpdate", itemupdate
)
329 -- we're just going to recycle this each time
330 if item
.specitem
then
332 table.insert(specitem_unused
, item
.specitem
)
337 -- hacky - progress only shows up if we're not on a metaobjective. wheee
338 if objective
.type_quest
and objective
.type_quest
.index
and not objective
.progress
and GetQuestLogSpecialItemInfo(objective
.type_quest
.index
) then
339 item
.specitem
= table.remove(specitem_unused
)
340 if not item
.specitem
then
341 item
.specitem
= CreateFrame("BUTTON", "QH_SpecItem_" .. tostring(specitem_max
), item
, "WatchFrameItemButtonTemplate")
342 QuestHelper
: Assert(item
.specitem
)
344 local rangey
= _G
["QH_SpecItem_" .. tostring(specitem_max
) .. "HotKey"]
345 QuestHelper
: Assert(rangey
)
346 local fn
, fh
, ff
= rangey
:GetFont()
347 rangey
:SetFont("Fonts\\ARIALN.TTF", fh
, ff
)
348 rangey
:SetText(RANGE_INDICATOR
)
349 rangey
:ClearAllPoints()
350 rangey
:SetPoint("BOTTOMRIGHT", item
.specitem
, "BOTTOMRIGHT", 0, 2)
352 specitem_max
= specitem_max
+ 1
355 item
.specitem
:SetScale(0.9)
356 item
.specitem
:ClearAllPoints()
357 item
.specitem
:SetParent(item
)
358 item
.specitem
:SetPoint("TOPRIGHT", item
, "TOPLEFT", 0, 0)
360 local _
, tex
, charges
= GetQuestLogSpecialItemInfo(objective
.type_quest
.index
)
361 item
.specitem
:SetID(objective
.type_quest
.index
)
362 SetItemButtonTexture(item
.specitem
, tex
)
363 item
.specitem
.rangeTimer
= -1 -- This makes the little dot go away. Why does it do that?
364 item
.specitem
.charges
= charges
371 return w
+x
+4, y
+h
, y
+h
+spacer
374 local function addMetaObjective(metaobj
, items
, y
, depth
)
376 x
, y
, spacer
= addItem(metaobj
, y
, true)
377 for _
, v
in ipairs(items
) do
378 x
, y
= addItem(v
, y
, false)
380 return math
.max(y
, spacer
), depth
+ #items
+ 1
383 --[[ -- these will be plugged in later one way or another
384 local function ccode(r1, g1, b1, r2, g2, b2, p)
386 p, ip = p*255, 255-p*255
387 return string.format("|cff%02x%02x%02x", r1*ip+r2*p, g1*ip+g2*p, b1*ip+b2*p)
390 local function qname(title, level)
391 if QuestHelper_Pref.track_level and level ~= 7777 and level ~= 7778 then
392 title = string.format("[%d] %s", level, title)
395 if level == 7778 then
399 if QuestHelper_Pref.track_qcolour then
400 local player_level = QuestHelper.player_level
401 local delta = level - player_level
406 colour = "|cffff0000"
407 elseif delta >= 0 then
408 colour = ccode(1, 1, 0, 1, 0, 0, delta/5)
412 if player_level >= 60 then grey = player_level - 9
413 elseif player_level >= 40 then grey = player_level - math.floor(player_level/5) - 1
414 elseif player_level >= 6 then grey = player_level - math.floor(player_level/10) - 5
417 if level == -7778 then
418 colour = "|cff808080"
419 elseif level > grey then
420 colour = ccode(0, 1, 0, 1, 1, 0, (grey-level)/(grey-player_level))
422 colour = ccode(.4, .4, .4, .2, .8, .2, (1-level)/(1-grey))
426 title = string.format("%s%s", colour, title)
432 local function oname(text, pct)
433 if QuestHelper_Pref.track_ocolour then
434 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)
441 local function removeUnusedItem(item
)
443 item
.sx
, item
.sy
, item
.dx
, item
.dy
= item
.x
, item
.y
, item
.x
+30, item
.y
444 QH_Hook(item
, "OnMouseDown", nil)
445 item
:EnableMouse(false)
446 QH_Hook(item
, "OnUpdate", itemfadeout
)
448 if item
.specitem
then
450 table.insert(specitem_unused
, item
.specitem
)
456 local was_inside
= false
460 local function addobj(objective
, seen
, obj_index_lookup
, filter
, x
, y
, gap
)
464 if objective
.cat
== "quest" then
467 quest
= objective
.quest
470 if quest
and quest
.watched
and not seen
[quest
] and (not filter
or filter(quest
)) then
473 local level
, name
= string.match(quest
.obj
, "^(%d+)/%d*/(.*)$")
476 level
, name
= string.match(quest
.obj
, "^(%d+)/(.*)$")
478 level
, name
= 1, quest
.obj
482 level
= tonumber(level
) or 1
485 local w
, h
= addItem(qname(name
, level
), true, quest
, -(y
+gap
), name
, quest
.index
)
490 for obj
in pairs(quest
.swap_after
or quest
.after
) do
492 table.insert(obj_list
, obj
)
496 table.sort(obj_list
, objlist_sort
)
498 for i
, obj
in ipairs(obj_list
) do
499 local pct
, text
= 0, obj
.obj
500 local seen_sum
, seen_max
= 0, 0
503 local seen_have
, seen_need
= QuestHelper
:CreateTable(), QuestHelper
:CreateTable()
505 for user
, progress
in pairs(obj
.progress
) do
506 seen_sum
= seen_sum
+ progress
[3]
507 seen_max
= seen_max
+ 1
508 seen_have
[progress
[1]]
= true
509 seen_need
[progress
[2]]
= true
513 pct
= seen_sum
/ seen_max
514 local list
= QuestHelper
:CreateTable()
516 for val
in pairs(seen_have
) do
517 table.insert(list
, val
)
522 local have
= table.concat(list
, ", ")
524 for i
= #list
,1,-1 do
528 for val
in pairs(seen_need
) do
529 table.insert(list
, val
)
532 if #list
~= 1 or list
[1] ~= 1 then
533 -- If there is only one thing needed, ignore the progress, it's redundant.
534 -- It's either shown or it isn't.
538 local need
= table.concat(list
, ", ")
540 text
= string.format((tonumber(have
) and tonumber(need
) and QUEST_ITEMS_NEEDED
) or QUEST_FACTION_NEEDED
,
544 QuestHelper
:ReleaseTable(list
)
547 QuestHelper
:ReleaseTable(seen_have
)
548 QuestHelper
:ReleaseTable(seen_need
)
551 if seen_sum
~= seen_max
then
553 w
, h
= addItem(oname(text
, pct
), quest
, obj
, -y
)
559 for i
= #obj_list
, 1, -1 do obj_list
[i
] = nil end
562 return x
, y
, gap
, count
566 local loading_vquest
= {tracker_desc
= QHFormat("QH_LOADING", "0")}
567 local flightpath_vquest
= {tracker_desc
= QHFormat("QH_FLIGHTPATH", "0")}
570 local hidden_vquest1
= { tracker_desc
= QHText("QUESTS_HIDDEN_1"), tracker_clicked
= QH_Hidden_Menu
}
571 local hidden_vquest2
= { tracker_desc
= " " .. QHText("QUESTS_HIDDEN_2"), tracker_clicked
= QH_Hidden_Menu
}
576 -- This is actually called surprisingly often.
577 function QH_Tracker_Rescan()
578 used_count
= QuestHelper
:CreateTable("tracker rescan used_count")
580 local mo_done
= QuestHelper
:CreateTable("tracker rescan mo_done")
581 local obj_done
= QuestHelper
:CreateTable("tracker rescan obj_done")
583 local y
, depth
= 0, 0
586 local had_pinned
= false
588 local objs
= QuestHelper
:CreateTable("tracker objs")
589 for k
, v
in pairs(pinned
) do
590 if not objs
[k
.why
] then objs
[k
.why
] = QuestHelper
:CreateTable("tracker objs sub") end
591 if not k
.ignore
and not k
.tracker_hidden
then table.insert(objs
[k
.why
], k
) end
592 obj_done
[k
.cluster
] = true
595 local sort_objs
= QuestHelper
:CreateTable("tracker sobjs")
596 for k
, v
in pairs(objs
) do
599 table.insert(sort_objs
, v
)
602 table.sort(sort_objs
, function (a
, b
) return tostring(a
.trackkey
) < tostring(b
.trackkey
) end)
604 for _
, v
in ipairs(sort_objs
) do
605 y
, depth
= addMetaObjective(v
.cluster
, v
, y
, depth
)
607 QuestHelper
:ReleaseTable(v
)
609 QuestHelper
:ReleaseTable(sort_objs
)
610 QuestHelper
:ReleaseTable(objs
)
612 if had_pinned
then y
= y
+ 10 end
615 if QuestHelper
.loading_main
then
616 loading_vquest
.tracker_desc
= QHFormat("QH_LOADING", string.format("%d", QuestHelper
.loading_main
:GetPercentage() * 100))
617 local x
, ty
= addItem(loading_vquest
, y
)
620 if QuestHelper
.flightpathing
then
621 flightpath_vquest
.tracker_desc
= QHFormat("QH_FLIGHTPATH", string.format("%d", QuestHelper
.flightpathing
:GetPercentage() * 100))
622 local x
, ty
= addItem(flightpath_vquest
, y
)
626 local metalookup
= QuestHelper
:CreateTable("tracker rescan metalookup")
627 for k
, v
in ipairs(route
) do
629 if not metalookup
[v
.why
] then metalookup
[v
.why
] = QuestHelper
:CreateTable("tracker rescan metalookup item") end
630 if not v
.tracker_hidden
then table.insert(metalookup
[v
.why
], v
) end
636 local current_mo_cluster
637 for k
, v
in ipairs(route
) do
638 if depth
> QuestHelper_Pref
.track_size
and not debug_output
then break end
639 if not v
.ignore
and not v
.why
.tracker_hidden
and not obj_done
[v
.cluster
] then
640 if current_mo
and v
.why
~= current_mo
then
641 y
, depth
= addMetaObjective(current_mo
, current_mo_cluster
, y
, depth
)
642 QuestHelper
:ReleaseTable(current_mo_cluster
)
643 current_mo
, current_mo_cluster
= nil, nil
646 if not v
.why
.tracker_split
then
647 if not mo_done
[v
.why
] then
648 y
, depth
= addMetaObjective(v
.why
, metalookup
[v
.why
], y
, depth
)
649 mo_done
[v
.why
] = true
652 if not current_mo
then
654 current_mo_cluster
= QuestHelper
:CreateTable("tracker current cluster")
656 if not v
.tracker_hidden
then table.insert(current_mo_cluster
, v
) end
662 if current_mo
and not (depth
> QuestHelper_Pref
.track_size
and not debug_output
) then
663 y
, depth
= addMetaObjective(current_mo
, current_mo_cluster
, y
, depth
)
665 if current_mo_cluster
then
666 QuestHelper
:ReleaseTable(current_mo_cluster
)
670 -- now we check to see if we need a hidden display
671 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
674 QH_Route_TraverseClusters(
677 QH_Route_IgnoredReasons_Cluster(clust
, function (reason
)
681 for _
, v
in ipairs(clust
) do
682 QH_Route_IgnoredReasons_Node(v
, function (reason
)
692 _
, y
= addItem(hidden_vquest1
, y
)
693 _
, y
= addItem(hidden_vquest2
, y
)
698 -- any manipulations of the tracker should be done by now, everything after this is bookkeeping
700 for k
, v
in pairs(used_items
) do
701 if not used_count
[k
] or used_count
[k
] < #v
then
702 local ttp
= QuestHelper
:CreateTable("used_items ttp")
703 for m
= 1, (used_count
[k
] or 0) do
704 table.insert(ttp
, v
[m
])
706 for m
= (used_count
[k
] or 0) + 1, #v
do
707 removeUnusedItem(v
[m
])
710 if used_items
[k
] then
711 QuestHelper
:ReleaseTable(used_items
[k
])
718 QuestHelper
:ReleaseTable(ttp
)
723 QuestHelper
:ReleaseTable(mo_done
)
724 QuestHelper
:ReleaseTable(obj_done
)
725 for k
, v
in pairs(metalookup
) do
726 QuestHelper
:ReleaseTable(v
)
728 QuestHelper
:ReleaseTable(metalookup
)
730 QuestHelper
:ReleaseTable(used_count
)
733 if y
~= tracker
.dh
then
735 tracker
.sh
= tracker
:GetHeight()
737 tracker
.sw
= tracker
.dw
747 if x ~= tracker.dw or y ~= tracker.dy then
749 tracker.sw, tracker.sh = tracker:GetWidth(), tracker:GetHeight()
750 tracker.dw, tracker.dh = x, y
756 local quests = QuestHelper.quest_log
760 local track_size = QuestHelper_Pref.track_size
761 local quests_added = {}
763 for quest, objs in pairs(used_items) do
764 for obj, item in pairs(objs) do
769 for i, objective in pairs(QuestHelper.route) do
770 if objective.watched then
771 obj_index_lookup[objective] = i
775 for q, data in pairs(QuestHelper.quest_log) do
776 quest_lookup[data.index] = q
779 -- Add our little "not yet loaded" notification
780 local loadedshow = false
781 if not QuestHelper.Routing.map_walker then
783 x, y, gap, count = addobj(loading_vquest, seen, nil, nil, x, y, gap)
784 added = added + count
787 if QuestHelper_Flight_Updates and QuestHelper_Flight_Updates_Current and QuestHelper_Flight_Updates > 0 and QuestHelper_Flight_Updates_Current < QuestHelper_Flight_Updates then
788 loading_vquest.obj = string.format("7777/" .. QHFormat("QH_LOADING", string.format("%d", QuestHelper_Flight_Updates_Current * 100 / QuestHelper_Flight_Updates)))
792 -- Add an extra large gap to seperate the notification from everything else
795 -- Add Quests that are watched but not in the route.
797 local uq_settings = UberQuest_Config[UnitName("player")]
799 local list = uq_settings.selected
803 local name = GetQuestLogTitle(i)
804 if not name then break end
805 quest_lookup[name] = quest_lookup[i]
808 for name in pairs(list) do
809 local q = quest_lookup[name]
810 if q and not obj_index_lookup[q] then
812 x, y, gap, count = addobj(q, seen, obj_index_lookup, nil, x, y, gap)
813 added = added + count
814 quests_added[q] = true
820 for i = 1,GetNumQuestWatches() do
821 local q = quest_lookup[GetQuestIndexForWatch(i)]
822 if q and not obj_index_lookup[q] then
824 x, y, gap, count = addobj(q, seen, obj_index_lookup, nil, x, y, gap)
825 added = added + count
830 -- Add Quests that are watched and are in the route.
831 for i, objective in ipairs(QuestHelper.route) do
833 x, y, gap, count = addobj(objective, seen, obj_index_lookup, watched_filter, x, y, gap)
834 added = added + count
835 quests_added[objective] = true
838 -- Add an extra large gap to seperate the watched objectives from the automatic objectives.
841 -- Add Quests that aren't watched and are in the route.
842 if added <= track_size then
843 for i, objective in ipairs(QuestHelper.route) do
845 x, y, gap, count = addobj(objective, seen, obj_index_lookup, nil, x, y, gap)
846 added = added + count
847 quests_added[objective] = true
849 if added > track_size then
855 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
858 for k, v in pairs(quest_lookup) do
859 if not quests_added[v] then
860 notadded = notadded + 1
868 x, y, gap, count = addobj(hidden_vquest1, seen, nil, nil, x, y, gap)
869 added = added + count
870 x, y, gap, count = addobj(hidden_vquest2, seen, nil, nil, x, y, gap)
871 added = added + count
875 for obj in pairs(obj_index_lookup) do
876 obj_index_lookup[obj] = nil
879 for key in pairs(quest_lookup) do
880 quest_lookup[key] = nil
883 for quest, objs in pairs(used_items) do
884 for obj, item in pairs(objs) do
885 if not item.used then
886 removeUnusedItem(quest, obj, item)
891 for key in pairs(seen) do
897 if x ~= tracker.dw or y ~= tracker.dy then
899 tracker.sw, tracker.sh = tracker:GetWidth(), tracker:GetHeight()
900 tracker.dw, tracker.dh = x, y
908 function QH_Tracker_UpdateRoute(new_route
)
913 function QH_Tracker_Pin(metaobjective
, suppress
)
914 if not pinned
[metaobjective
] then
915 pinned
[metaobjective
] = true
923 function QH_Tracker_Unpin(metaobjective
, suppress
)
924 if pinned
[metaobjective
] then
925 pinned
[metaobjective
] = nil -- nil, not false, so it'll be garbage-collected appropriately
933 function QH_Tracker_SetPin(metaobjective
, flag
, suppress
)
935 QH_Tracker_Pin(metaobjective
, suppress
)
937 QH_Tracker_Unpin(metaobjective
, suppress
)
942 local check_delay
= 4
944 -- This function does the grunt work of cursor positioning and rescaling. It does not actually reorganize items.
945 function tracker
:update(delta
)
947 -- This is called without a value when the questlog is updated.
948 -- We'll make sure we update the display on the next update.
954 local t
= self
.t
+delta
957 self
:SetWidth(self
.dw
)
958 self
:SetHeight(self
.dh
)
963 self
:SetWidth(self
.sw
*it
+self
.dw
*t
)
964 self
:SetHeight(self
.sh
*it
+self
.dh
*t
)
968 -- Manually checking if the mouse is in the frame, because if I used on OnEnter, i'd have to enable mouse input,
969 -- and if I did that, it would prevent the player from using the mouse to change the view if they clicked inside
971 local x
, y
= GetCursorPosition()
972 local s
= 1/self
:GetEffectiveScale()
975 QuestHelper
: Assert(x
)
976 QuestHelper
: Assert(y
)
977 --[[ QuestHelper: Assert(self:GetLeft())
978 QuestHelper: Assert(self:GetBottom())
979 QuestHelper: Assert(self:GetRight())
980 QuestHelper: Assert(self:GetTop())]]
982 -- Sometimes it just doesn't know its own coordinates. Not sure why. Maybe this will fix it.
983 local inside
= (self
:GetLeft() and (x
>= self
:GetLeft() and y
>= self
:GetBottom() and x
< self
:GetRight() and y
< self
:GetTop()))
984 if inside
~= was_inside
then
987 minbutton
:SetAlpha(.5)
988 elseif not QuestHelper_Pref
.track_minimized
then
989 minbutton
:SetAlpha(0)
993 check_delay
= check_delay
+ delta
994 if check_delay
> 1 then
1001 QH_Hook(tracker
, "OnUpdate", tracker
.update
)
1003 -- Some hooks to update the tracker when quests are added or removed. These should be moved into the quest director.
1005 local orig_AddQuestWatch, orig_RemoveQuestWatch = AddQuestWatch, RemoveQuestWatch
1007 function AddQuestWatch(...)
1009 return orig_AddQuestWatch(...)
1012 function RemoveQuestWatch(...)
1014 return orig_RemoveQuestWatch(...)
1017 -------------------------------------------------------------------------------------------------
1018 -- This batch of stuff is to make sure the original tracker (and any modifications) stay hidden
1020 local orig_TrackerBackdropOnShow
-- bEQL (and perhaps other mods) add a backdrop to the tracker
1021 local TrackerBackdropFound
= false
1023 local function TrackerBackdropOnShow(self
, ...)
1024 if QuestHelper_Pref
.track
and not QuestHelper_Pref
.hide
then
1025 TrackerBackdropFound
:Hide()
1028 if orig_TrackerBackdropOnShow
then
1029 return orig_TrackerBackdropOnShow(self
, ...)
1033 function tracker
:HideDefaultTracker()
1034 -- The easy part: hide the original tracker
1035 WatchFrame_RemoveObjectiveHandler(WatchFrame_DisplayTrackedQuests
)
1036 WatchFrame_ClearDisplay()
1039 -- The harder part: hide all those little buttons
1043 local orig
= _G
["WatchFrameItem" .. tostring(index
)]
1044 if orig
then orig
:Hide() else break end
1049 -- The harder part: check if a known backdrop is present (but we don't already know about it).
1050 -- If it is, make sure it's hidden, and hook its OnShow to make sure it stays that way.
1051 -- Unfortunately, I can't figure out a good time to check for this once, so we'll just have
1052 -- to keep checking. Hopefully, this won't happen too often.
1053 if not TrackerBackdropFound
then
1054 if QuestWatchFrameBackdrop
then
1055 -- Found bEQL's QuestWatchFrameBackdrop...
1056 TrackerBackdropFound
= QuestWatchFrameBackdrop
1059 if TrackerBackdropFound
then
1060 -- OK, we found something - so hide it, and make sure it doesn't rear its ugly head again
1061 TrackerBackdropFound
:Hide()
1063 orig_TrackerBackdropOnShow
= TrackerBackdropFound
:GetScript("OnShow")
1064 QH_Hook(TrackerBackdropFound
, "OnShow", TrackerBackdropOnShow
)
1069 function tracker
:ShowDefaultTracker()
1070 -- I like how there's code explicitly to allow us to do this without checking if it's already added
1071 WatchFrame_AddObjectiveHandler(WatchFrame_DisplayTrackedQuests
)
1072 -- Make sure the default tracker is up to date on what what's being watched and what isn't.
1075 if TrackerBackdropFound
then
1076 TrackerBackdropFound
:Show()
1080 function QuestHelper
:ShowTracker()
1081 tracker
:HideDefaultTracker()
1084 if QuestHelper_Pref
.track_minimized
then
1085 minbutton
:SetAlpha(.3)
1087 minbutton
:SetAlpha(0)
1092 function QuestHelper
:HideTracker()
1093 tracker
:ShowDefaultTracker()