remove extra +x
[QuestHelper.git] / main.lua
blobcde5827dc6e4205b4afe4a6b91b5b4a8f8d7b418
1 QuestHelper_File["main.lua"] = "Development Version"
3 QuestHelper = CreateFrame("Frame", "QuestHelper", nil)
5 -- Just to make sure it's always 'seen' (there's nothing that can be seen, but still...), and therefore always updating.
6 QuestHelper:SetFrameStrata("TOOLTIP")
8 QuestHelper_SaveVersion = 10
9 QuestHelper_CharVersion = 1
10 QuestHelper_Locale = GetLocale() -- This variable is used only for the collected data, and has nothing to do with displayed text.
11 QuestHelper_Quests = {}
12 QuestHelper_Objectives = {}
14 QuestHelper_Pref =
17 QuestHelper_DefaultPref =
19 filter_level=true,
20 filter_zone=false,
21 filter_done=false,
22 filter_blocked=false, -- Hides blocked objectives, such as quest turn-ins for incomplete quests
23 filter_watched=false, -- Limits to Watched objectives
24 track=true,
25 track_minimized=false,
26 track_scale=1,
27 track_level=true,
28 track_qcolour=true,
29 track_ocolour=true,
30 track_size=8,
31 tooltip=true,
32 share = true,
33 scale = 1,
34 solo = false,
35 comm = false,
36 show_ants = true,
37 level = 2,
38 hide = false,
39 cart_wp = true,
40 tomtom_wp = true,
41 flight_time = true,
42 locale = GetLocale(), -- This variable is used for display purposes, and has nothing to do with the collected data.
43 perf_scale = 1, -- How much background processing can the current machine handle? Higher means more load, lower means better performance.
44 map_button = true
47 QuestHelper_FlightInstructors = {}
48 QuestHelper_FlightLinks = {}
49 QuestHelper_FlightRoutes = {}
50 QuestHelper_KnownFlightRoutes = {}
51 QuestHelper_SeenRealms = {}
53 QuestHelper.tooltip = CreateFrame("GameTooltip", "QuestHelperTooltip", nil, "GameTooltipTemplate")
54 QuestHelper.objective_objects = {}
55 QuestHelper.user_objectives = {}
56 QuestHelper.quest_objects = {}
57 QuestHelper.player_level = 1
58 QuestHelper.locale = QuestHelper_Locale
60 QuestHelper.faction = (UnitFactionGroup("player") == "Alliance" and 1) or
61 (UnitFactionGroup("player") == "Horde" and 2)
63 assert(QuestHelper.faction)
65 QuestHelper.font = {serif=GameFontNormal:GetFont(), sans=ChatFontNormal:GetFont(), fancy=QuestTitleFont:GetFont()}
67 function QuestHelper:GetFontPath(list_string, font)
68 if list_string then
69 for name in string.gmatch(list_string, "[^;]+") do
70 if font:SetFont(name, 10) then
71 return name
72 elseif font:SetFont("Interface\\AddOns\\QuestHelper\\Fonts\\"..name, 10) then
73 return "Interface\\AddOns\\QuestHelper\\Fonts\\"..name
74 end
75 end
76 end
77 end
79 function QuestHelper:SetLocaleFonts()
80 self.font.sans = nil
81 self.font.serif = nil
82 self.font.fancy = nil
84 local font = self:CreateText(self)
86 if QuestHelper_Locale ~= QuestHelper_Pref.locale then
87 -- Only use alternate fonts if using a language the client wasn't intended for.
88 local replacements = QuestHelper_SubstituteFonts[QuestHelper_Pref.locale]
89 if replacements then
90 self.font.sans = self:GetFontPath(replacements.sans, font)
91 self.font.serif = self:GetFontPath(replacements.serif, font)
92 self.font.fancy = self:GetFontPath(replacements.fancy, font)
93 end
94 end
96 self.font.sans = self.font.sans or self:GetFontPath(QuestHelper_Pref.locale.."_sans.ttf", font)
97 self.font.serif = self.font.serif or self:GetFontPath(QuestHelper_Pref.locale.."_serif.ttf", font) or self.font.sans
98 self.font.fancy = self.font.fancy or self:GetFontPath(QuestHelper_Pref.locale.."_fancy.ttf", font) or self.font.serif
100 self:ReleaseText(font)
102 self.font.sans = self.font.sans or ChatFontNormal:GetFont()
103 self.font.serif = self.font.serif or GameFontNormal:GetFont()
104 self.font.fancy = self.font.fancy or QuestTitleFont:GetFont()
106 -- Need to change the font of the chat frame, for any messages that QuestHelper displays.
107 -- This should do nothing if not using an alternate font.
108 DEFAULT_CHAT_FRAME:SetFont(self.font.sans, select(2, DEFAULT_CHAT_FRAME:GetFont()))
110 if QuestHelperWorldMapButton then
111 QuestHelperWorldMapButton:SetFont(self.font.serif, select(2, QuestHelperWorldMapButton:GetFont()))
115 QuestHelper.route = {}
116 QuestHelper.to_add = {}
117 QuestHelper.to_remove = {}
118 QuestHelper.quest_log = {}
119 QuestHelper.pos = {nil, {}, 0, 0, 1, "You are here.", 0}
120 QuestHelper.sharing = false -- Will be set to true when sharing with at least one user.
122 function QuestHelper.tooltip:GetPrevLines() -- Just a helper to make life easier.
123 local last = self:NumLines()
124 local name = self:GetName()
125 return _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
128 function QuestHelper:SetTargetLocation(i, x, y, toffset)
129 -- Informs QuestHelper that you're going to be at some location in toffset seconds.
130 local c, z = unpack(QuestHelper_ZoneLookup[i])
132 self.target = self:CreateTable()
133 self.target[2] = self:CreateTable()
135 self.target_time = time()+(toffset or 0)
137 x, y = self.Astrolabe:TranslateWorldMapPosition(c, z, x, y, c, 0)
138 self.target[1] = self.zone_nodes[i]
139 self.target[3] = x * self.continent_scales_x[c]
140 self.target[4] = y * self.continent_scales_y[c]
142 self:SetTargetLocationRecalculate()
145 function QuestHelper:SetTargetLocationRecalculate()
146 if self.target then
147 for i, n in ipairs(self.target[1]) do
148 local a, b = n.x-self.target[3], n.y-self.target[4]
149 self.target[2][i] = math.sqrt(a*a+b*b)
154 function QuestHelper:UnsetTargetLocation()
155 -- Unsets the target set above.
156 if self.target then
157 self:ReleaseTable(self.target[2])
158 self:ReleaseTable(self.target)
159 self.target = nil
160 self.target_time = nil
164 local interruptcount = 0 -- counts how many "played gained control" messages we recieve, used for flight paths
165 local init_cartographer_later = false
167 function QuestHelper:Initialize()
168 local file_problem = false
169 local expected_version = GetAddOnMetadata("QuestHelper", "Version")
170 --local expected_version = QuestHelper_File["main.lua"] -- it was a good idea. Damn you, Curse Client.
172 local expected_files =
174 ["upgrade.lua"] = true,
175 ["main.lua"] = true,
176 ["recycle.lua"] = true,
177 ["objective.lua"] = true,
178 ["quest.lua"] = true,
179 ["questlog.lua"] = true,
180 ["utility.lua"] = true,
181 ["dodads.lua"] = true,
182 ["graph.lua"] = true,
183 ["teleport.lua"] = true,
184 ["pathfinding.lua"] = true,
185 ["routing.lua"] = true,
186 ["custom.lua"] = true,
187 ["menu.lua"] = true,
188 ["hidden.lua"] = true,
189 ["nag.lua"] = true,
190 ["comm.lua"] = true,
191 ["mapbutton.lua"] = true,
192 ["help.lua"] = true,
193 ["pattern.lua"] = true,
194 ["flightpath.lua"] = true,
195 ["tracker.lua"] = true,
196 ["objtips.lua"] = true,
197 ["cartographer.lua"] = true,
198 ["tomtom.lua"] = true,
199 ["textviewer.lua"] = true,
200 ["error.lua"] = true,
201 ["collect.lua"] = true,
202 ["collect_achievement.lua"] = true,
205 for file, version in pairs(QuestHelper_File) do
206 if not expected_files[file] then
207 DEFAULT_CHAT_FRAME:AddMessage("Unexpected QuestHelper file: "..file)
208 file_problem = true
209 elseif version ~= expected_version then
210 DEFAULT_CHAT_FRAME:AddMessage("Wrong version of QuestHelper file: "..file.." (found '"..version.."', should be '"..expected_version.."')")
211 if version ~= "Development Version" and expected_version ~= "Development Version" then
212 -- Developers are allowed to mix dev versions with release versions
213 file_problem = true
218 for file in pairs(expected_files) do
219 if not QuestHelper_File[file] then
220 DEFAULT_CHAT_FRAME:AddMessage("Missing QuestHelper file: "..file)
221 file_problem = true
225 -- Don't need this table anymore.
226 QuestHelper_File = nil
228 if QuestHelper_StaticData and not QuestHelper_StaticData["enUS"] then
229 file_problem = true
230 DEFAULT_CHAT_FRAME:AddMessage("Static data does not seem to exist")
233 if file_problem then
234 DEFAULT_CHAT_FRAME:AddMessage("QuestHelper hasn't been installed properly.")
235 message("There was an error starting QuestHelper. Please exit World of Warcraft entirely and try again.")
236 QuestHelper = nil -- Just in case anybody else is checking for us, we're not home
237 return
240 QuestHelper_ErrorCatcher_CompletelyStarted()
242 if not QuestHelper_StaticData then
243 -- If there is no static data for some mysterious reason, create an empty table so that
244 -- other parts of the code can carry on as usual, using locally collected data if it exists.
245 QuestHelper_StaticData = {}
248 QHFormatSetLocale(QuestHelper_Pref.locale or GetLocale())
250 if not QuestHelper_UID then
251 QuestHelper_UID = self:CreateUID()
253 QuestHelper_SaveDate = time()
255 self.Astrolabe = DongleStub("Astrolabe-0.4-QuestHelper")
256 QuestHelper_BuildZoneLookup()
258 if QuestHelper_Locale ~= GetLocale() then
259 self:TextOut(QHText("LOCALE_ERROR"))
260 return
263 if not self:ZoneSanity() then
264 self:TextOut(QHText("ZONE_LAYOUT_ERROR"))
265 message("QuestHelper: "..QHText("ZONE_LAYOUT_ERROR"))
266 return
269 QuestHelper_UpgradeDatabase(_G)
270 QuestHelper_UpgradeComplete()
272 if QuestHelper_SaveVersion ~= 10 then
273 self:TextOut(QHText("DOWNGRADE_ERROR"))
274 return
277 if QuestHelper_IsPolluted(_G) then
278 self:TextOut(QHFormat("NAG_POLLUTED"))
279 self:Purge(nil, true, true)
282 local signature = expected_version .. " on " .. GetBuildInfo()
283 QuestHelper_Quests[signature] = QuestHelper_Quests[signature] or {}
284 QuestHelper_Objectives[signature] = QuestHelper_Objectives[signature] or {}
285 QuestHelper_FlightInstructors[signature] = QuestHelper_FlightInstructors[signature] or {}
286 QuestHelper_FlightRoutes[signature] = QuestHelper_FlightRoutes[signature] or {}
288 QuestHelper_Quests_Local = QuestHelper_Quests[signature]
289 QuestHelper_Objectives_Local = QuestHelper_Objectives[signature]
290 QuestHelper_FlightInstructors_Local = QuestHelper_FlightInstructors[signature]
291 QuestHelper_FlightRoutes_Local = QuestHelper_FlightRoutes[signature]
293 QuestHelper_SeenRealms[GetRealmName()] = true -- some attempt at tracking private servers
295 self.player_level = UnitLevel("player")
297 self:UnregisterEvent("VARIABLES_LOADED")
298 self:RegisterEvent("PLAYER_TARGET_CHANGED")
299 self:RegisterEvent("LOOT_OPENED")
300 self:RegisterEvent("QUEST_COMPLETE")
301 self:RegisterEvent("QUEST_LOG_UPDATE")
302 self:RegisterEvent("QUEST_PROGRESS")
303 self:RegisterEvent("MERCHANT_SHOW")
304 self:RegisterEvent("QUEST_DETAIL")
305 self:RegisterEvent("TAXIMAP_OPENED")
306 self:RegisterEvent("PLAYER_CONTROL_GAINED")
307 self:RegisterEvent("PLAYER_LEVEL_UP")
308 self:RegisterEvent("PARTY_MEMBERS_CHANGED")
309 self:RegisterEvent("CHAT_MSG_ADDON")
310 self:RegisterEvent("CHAT_MSG_SYSTEM")
311 self:RegisterEvent("BAG_UPDATE")
312 self:RegisterEvent("GOSSIP_SHOW")
314 for key, def in pairs(QuestHelper_DefaultPref) do
315 if QuestHelper_Pref[key] == nil then
316 QuestHelper_Pref[key] = def
320 self:SetLocaleFonts()
322 if QuestHelper_Pref.share and not QuestHelper_Pref.solo then
323 self:EnableSharing()
326 if QuestHelper_Pref.hide then
327 self.map_overlay:Hide()
330 self:HandlePartyChange()
332 self:Nag("all")
334 for locale in pairs(QuestHelper_StaticData) do
335 if locale ~= self.locale then
336 -- Will delete references to locales you don't use.
337 QuestHelper_StaticData[locale] = nil
338 _G["QuestHelper_StaticData_" .. locale] = nil
342 local static = QuestHelper_StaticData[self.locale]
344 if static then
345 if static.flight_instructors then for faction in pairs(static.flight_instructors) do
346 if faction ~= self.faction then
347 -- Will delete references to flight instructors that don't belong to your faction.
348 static.flight_instructors[faction] = nil
350 end end
352 if static.quest then for faction in pairs(static.quest) do
353 if faction ~= self.faction then
354 -- Will delete references to quests that don't belong to your faction.
355 static.quest[faction] = nil
357 end end
359 if not QuestHelper:IsWrath() then
360 for cat, list in pairs(static.objective) do
361 for name, obj in pairs(list) do
362 if obj.pos then
363 for i, cpos in pairs(obj.pos) do
364 QuestHelper_ConvertCoordsFromWrath(cpos)
372 self:ResetPathing()
374 -- Adding QuestHelper_CharVersion, so I know if I've already converted this characters saved data.
375 if not QuestHelper_CharVersion then
376 -- Changing per-character flight routes, now only storing the flight points they have,
377 -- will attempt to guess the routes from this.
378 local routes = {}
380 for i, l in pairs(QuestHelper_KnownFlightRoutes) do
381 for key in pairs(l) do
382 routes[key] = true
386 QuestHelper_KnownFlightRoutes = routes
388 -- Deleting the player's home again.
389 -- But using the new CharVersion variable I'm adding is cleaner that what I was doing, so I'll go with it.
390 QuestHelper_Home = nil
391 QuestHelper_CharVersion = 1
394 if not QuestHelper_Home then
395 -- Not going to bother complaining about the player's home not being set, uncomment this when the home is used in routing.
396 -- self:TextOut(QHText("HOME_NOT_KNOWN"))
399 self.minimap_dodad = self:CreateMipmapDodad()
401 if QuestHelper_Pref.map_button then
402 QuestHelper:InitMapButton()
405 if QuestHelper_Pref.cart_wp then
406 init_cartographer_later = true
409 if QuestHelper_Pref.tomtom_wp then
410 self:EnableTomTom()
413 self.tracker:SetScale(QuestHelper_Pref.track_scale)
415 if QuestHelper_Pref.track and not QuestHelper_Pref.hide then
416 self:ShowTracker()
419 local version = GetAddOnMetadata("QuestHelper", "Version") or "Unknown"
420 if QuestHelper_Version ~= version then
421 QuestHelper_Version = version
422 self:ChangeLog()
425 self:SetScript("OnUpdate", self.OnUpdate)
427 collectgarbage("collect") -- Free everything we aren't using.
429 if self.debug_objectives then
430 for name, data in pairs(self.debug_objectives) do
431 self:LoadDebugObjective(name, data)
435 self.Routing:Initialize() -- Set up the routing task
437 --[[ -- This is just an example of how the WoW profiler biases its profiles heavily.
438 function C()
441 function A()
442 q = 0
443 for x = 0, 130000000, 1 do
447 function B()
448 q = 0
449 for x = 0, 12000000, 1 do
454 function B2()
455 q = 0
456 for x = 0, 1200000, 1 do
457 --q = q + x
462 debugprofilestart()
464 local ta = debugprofilestop()
466 local tb = debugprofilestop()
468 local tc = debugprofilestop()
470 QuestHelper:TextOut(string.format("%d %d %d", ta, tb - ta, tc - tb))
471 QuestHelper:TextOut(string.format("%d %d", GetFunctionCPUUsage(A), GetFunctionCPUUsage(B)))
473 --/script SetCVar("scriptProfile", value)]]
476 function QuestHelper:OnEvent(event)
477 if event == "VARIABLES_LOADED" then
478 self:Initialize()
481 if event == "GOSSIP_SHOW" then
482 local name, id = UnitName("npc"), self:GetUnitID("npc")
483 if name and id then
484 self:GetObjective("monster", name).o.id = id
485 --self:TextOut("NPC: "..name.." = "..id)
489 if event == "PLAYER_TARGET_CHANGED" then
490 local name, id = UnitName("target"), self:GetUnitID("target")
491 if name and id then
492 self:GetObjective("monster", name).o.id = id
493 --self:TextOut("Target: "..name.." = "..id)
496 if UnitExists("target") and UnitIsVisible("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
497 local index, x, y = self:UnitPosition("target")
499 if index then -- Might not have a position if inside an instance.
500 local w = 0.1
502 -- Modify the weight based on how far they are from us.
503 -- We don't know the exact location (using our own location), so the farther, the less sure we are that it's correct.
504 if CheckInteractDistance("target", 3) then w = 1
505 elseif CheckInteractDistance("target", 2) then w = 0.89
506 elseif CheckInteractDistance("target", 1) or CheckInteractDistance("target", 4) then w = 0.33 end
508 local monster_objective = self:GetObjective("monster", UnitName("target"))
509 self:AppendObjectivePosition(monster_objective, index, x, y, w)
511 monster_objective.o.faction = (UnitFactionGroup("target") == "Alliance" and 1) or
512 (UnitFactionGroup("target") == "Horde" and 2) or nil
514 local level = UnitLevel("target")
515 if level and level >= 1 then
516 local w = monster_objective.o.levelw or 0
517 monster_objective.o.level = ((monster_objective.o.level or 0)*w+level)/(w+1)
518 monster_objective.o.levelw = w+1
524 if event == "LOOT_OPENED" then
525 local target = UnitName("target")
526 if target and UnitIsDead("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
527 local index, x, y = self:UnitPosition("target")
529 local monster_objective = self:GetObjective("monster", target)
530 monster_objective.o.looted = (monster_objective.o.looted or 0) + 1
532 if index then -- Might not have a position if inside an instance.
533 self:AppendObjectivePosition(monster_objective, index, x, y)
536 for i = 1, GetNumLootItems() do
537 local icon, name, number, rarity = GetLootSlotInfo(i)
538 if name then
539 if number and number >= 1 then
540 self:AppendItemObjectiveDrop(self:GetObjective("item", name), name, target, number)
541 else
542 local total = (name:match(COPPER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) +
543 (name:match(SILVER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 100 +
544 (name:match(GOLD_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 10000
546 if total > 0 then
547 self:AppendObjectiveDrop(self:GetObjective("item", "money"), target, total)
552 else
553 local container = nil
555 -- Go through the players inventory and look for a locked item, we're probably looting it.
556 for bag = 0,NUM_BAG_SLOTS do
557 for slot = 1,GetContainerNumSlots(bag) do
558 local link = GetContainerItemLink(bag, slot)
559 if link and select(3, GetContainerItemInfo(bag, slot)) then
560 if container == nil then
561 -- Found a locked item and haven't previously assigned to container, assign its name, or false if we fail to parse it.
562 container = select(3, string.find(link, "|h%[(.+)%]|h|r")) or false
563 else
564 -- Already tried to assign to a container. If there are multiple locked items, we give up.
565 container = false
571 if container then
572 local container_objective = self:GetObjective("item", container)
573 container_objective.o.opened = (container_objective.o.opened or 0) + 1
575 for i = 1, GetNumLootItems() do
576 local icon, name, number, rarity = GetLootSlotInfo(i)
577 if name and number >= 1 then
578 self:AppendItemObjectiveContainer(self:GetObjective("item", name), container, number)
581 else
582 -- No idea where the items came from.
583 local index, x, y = self:PlayerPosition()
585 if index then
586 for i = 1, GetNumLootItems() do
587 local icon, name, number, rarity = GetLootSlotInfo(i)
588 if name and number >= 1 then
589 self:AppendItemObjectivePosition(self:GetObjective("item", name), name, index, x, y)
597 if event == "CHAT_MSG_SYSTEM" then
598 local home_name = self:convertPattern(ERR_DEATHBIND_SUCCESS_S)(arg1)
599 if home_name then
600 if self.i then
601 self:TextOut(QHText("HOME_CHANGED"))
602 self:TextOut(QHText("WILL_RESET_PATH"))
604 local home = QuestHelper_Home
605 if not home then
606 home = {}
607 QuestHelper_Home = home
610 home[1], home[2], home[3], home[4] = self.i, self.x, self.y, home_name
611 self.defered_graph_reset = true
616 if event == "CHAT_MSG_ADDON" then
617 if arg1 == "QHpr" and (arg3 == "PARTY" or arg3 == "WHISPER") and arg4 ~= UnitName("player") then
618 self:HandleRemoteData(arg2, arg4)
622 if event == "PARTY_MEMBERS_CHANGED" then
623 self:HandlePartyChange()
626 if event == "QUEST_LOG_UPDATE" or
627 event == "PLAYER_LEVEL_UP" or
628 event == "PARTY_MEMBERS_CHANGED" then
629 self.defered_quest_scan = true
632 if event == "QUEST_DETAIL" then
633 if not self.quest_giver then self.quest_giver = {} end
634 local npc = UnitName("npc")
635 if npc then
636 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
637 local index, x, y = self:UnitPosition("npc")
639 if index then -- Might not have a position if inside an instance.
640 local npc_objective = self:GetObjective("monster", npc)
641 self:AppendObjectivePosition(npc_objective, index, x, y)
642 self.quest_giver[GetTitleText()] = npc
647 if event == "QUEST_COMPLETE" or event == "QUEST_PROGRESS" then
648 local quest = GetTitleText()
649 if quest then
650 local level, hash = self:GetQuestLevel(quest)
651 if not level or level < 1 then
652 --self:TextOut("Don't know quest level for ".. quest.."!")
653 return
655 local q = self:GetQuest(quest, level, hash)
657 if q.need_hash then
658 q.o.hash = hash
661 local unit = UnitName("npc")
662 if unit then
663 q.o.finish = unit
664 q.o.pos = nil
666 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
667 local index, x, y = self:UnitPosition("npc")
668 if index then -- Might not have a position if inside an instance.
669 local npc_objective = self:GetObjective("monster", unit)
670 self:AppendObjectivePosition(npc_objective, index, x, y)
672 elseif not q.o.finish then
673 local index, x, y = self:PlayerPosition()
674 if index then -- Might not have a position if inside an instance.
675 self:AppendObjectivePosition(q, index, x, y)
681 if event == "MERCHANT_SHOW" then
682 local npc_name = UnitName("npc")
683 if npc_name then
684 local npc_objective = self:GetObjective("monster", npc_name)
685 local index = 1
686 while true do
687 local item_name = GetMerchantItemInfo(index)
688 if item_name then
689 index = index + 1
690 local item_objective = self:GetObjective("item", item_name)
691 if not item_objective.o.vendor then
692 item_objective.o.vendor = {npc_name}
693 else
694 local known = false
695 for i, vendor in ipairs(item_objective.o.vendor) do
696 if npc_name == vendor then
697 known = true
698 break
701 if not known then
702 table.insert(item_objective.o.vendor, npc_name)
705 else
706 break
712 if event == "TAXIMAP_OPENED" then
713 self:taxiMapOpened()
716 if event == "PLAYER_CONTROL_GAINED" then
717 interruptcount = interruptcount + 1
720 if event == "BAG_UPDATE" then
721 for slot = 1,GetContainerNumSlots(arg1) do
722 local link = GetContainerItemLink(arg1, slot)
723 if link then
724 local id, name = select(3, string.find(link, "|Hitem:(%d+):.-|h%[(.-)%]|h"))
725 if name then
726 self:GetObjective("item", name).o.id = tonumber(id)
733 local map_shown_decay = 0
734 local delayed_action = 100
735 local update_count = 0
736 local ontaxi = false
738 function QuestHelper:OnUpdate()
740 if init_cartographer_later and Cartographer_Waypoints then -- there has to be a better way to do this
741 init_cartographer_later = false
742 if QuestHelper_Pref.cart_wp then
743 self:EnableCartographer()
747 if not ontaxi and UnitOnTaxi("player") then
748 self:flightBegan()
749 interruptcount = 0
750 elseif ontaxi and not UnitOnTaxi("player") then
751 self:flightEnded(interruptcount > 1)
753 ontaxi = UnitOnTaxi("player")
755 update_count = update_count - 1
757 if update_count <= 0 then
759 -- Reset the update count for next time around; this will make sure the body executes every time
760 -- when perf_scale >= 1, and down to 1 in 10 iterations when perf_scale < 1, or when hidden.
761 update_count = update_count + (QuestHelper_Pref.hide and 10 or 1/QuestHelper_Pref.perf_scale)
763 if update_count < 0 then
764 -- Make sure the count doesn't go perpetually negative; don't know what will happen if it underflows.
765 update_count = 0
768 if self.Astrolabe.WorldMapVisible then
769 -- We won't trust that the zone returned by Astrolabe is correct until map_shown_decay is 0.
770 map_shown_decay = 2
771 elseif map_shown_decay > 0 then
772 map_shown_decay = map_shown_decay - 1
773 else
774 --SetMapToCurrentZone() -- not sure why this existed
777 delayed_action = delayed_action - 1
778 if delayed_action <= 0 then
779 delayed_action = 100
780 self:HandlePartyChange()
783 local nc, nz, nx, ny = self.Astrolabe:GetCurrentPlayerPosition()
785 if nc and nc == self.c and map_shown_decay > 0 and self.z > 0 and self.z ~= nz then
786 -- There's a chance Astrolable will return the wrong zone if you're messing with the world map, if you can
787 -- be seen in that zone but aren't in it.
788 local nnx, nny = self.Astrolabe:TranslateWorldMapPosition(nc, nz, nx, ny, nc, self.z)
789 if nnx > 0 and nny > 0 and nnx < 1 and nny < 1 then
790 nz, nx, ny = self.z, nnx, nny
794 if nc and nc > 0 and nz == 0 and nc == self.c and self.z > 0 then
795 nx, ny = self.Astrolabe:TranslateWorldMapPosition(nc, nz, nx, ny, nc, self.z)
796 if nx and ny and nx > -0.1 and ny > -0.1 and nx < 1.1 and ny < 1.1 then
797 nz = self.z
798 else
799 nc, nz, nx, ny = nil, nil, nil, nil
803 if nc and nz > 0 then
804 self.c, self.z, self.x, self.y = nc, nz, nx, ny
805 self.i = QuestHelper_IndexLookup[nc][nz]
808 if self.defered_quest_scan and not self.graph_in_limbo then
809 self.defered_quest_scan = false
810 self:ScanQuestLog()
813 if self.c then
814 self:RunCoroutine()
817 local level = UnitLevel("player")
818 if level >= 58 and self.player_level < 58 then
819 self.defered_graph_reset = true
821 self.player_level = level
823 self:PumpCommMessages()
827 QuestHelper:RegisterEvent("VARIABLES_LOADED")
828 QuestHelper:SetScript("OnEvent", QuestHelper.OnEvent)