Automated update from: http://smariot.no-ip.org/translate
[QuestHelper.git] / main.lua
blob404da5b67a89074a024dd428df55b48337d0ffd0
1 QuestHelper_File["main.lua"] = "Development Version"
2 QuestHelper_Loadtime["main.lua"] = GetTime()
4 local version_string = QuestHelper_File["main.lua"] -- we pretty much save this only so we can inform the user that they're using a beta version
6 -- Just to make sure it's always 'seen' (there's nothing that can be seen, but still...), and therefore always updating.
7 QuestHelper:SetFrameStrata("TOOLTIP")
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 local 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 filter_group=true,
25 filter_group_param=2,
26 filter_wintergrasp=true,
27 filter_raid_accessible=true,
28 zones="next",
29 track=true,
30 track_minimized=false,
31 track_scale=1,
32 track_level=true,
33 track_qcolour=true,
34 track_ocolour=true,
35 track_size=10,
36 blizzmap = false,
37 tooltip=true,
38 share = true,
39 scale = 1,
40 solo = false,
41 comm = false,
42 show_ants = true,
43 level = 3,
44 hide = false,
45 cart_wp_new = false,
46 tomtom_wp_new = false,
47 arrow = true,
48 arrow_locked = false,
49 arrow_arrowsize = 1,
50 arrow_textsize = 1,
51 metric = (QuestHelper_Locale ~= "enUS" and QuestHelper_Locale ~= "esMX"),
52 flight_time = true,
53 locale = GetLocale(), -- This variable is used for display purposes, and has nothing to do with the collected data.
54 perf_scale_2 = 1, -- How much background processing can the current machine handle? Higher means more load, lower means better performance.
55 perfload_scale = 1, -- Performance scale to use on startup
56 map_button = true,
57 travel_time = false,
58 mini_opacity = 1,
61 -- We do it here also in case things decide they care about preferences before the init function is called. Shouldn't happen, but maybe does.
62 setmetatable(QuestHelper_Pref, {__index=QuestHelper_DefaultPref})
64 QuestHelper_FlightInstructors = {}
65 QuestHelper_FlightLinks = {}
66 QuestHelper_FlightRoutes = {}
67 QuestHelper_KnownFlightRoutes = {}
68 QuestHelper_SeenRealms = {}
70 QuestHelper.tooltip = CreateFrame("GameTooltip", "QuestHelperTooltip", nil, "GameTooltipTemplate")
71 QuestHelper.objective_objects = {}
72 QuestHelper.user_objectives = {}
73 QuestHelper.quest_objects = {}
74 QuestHelper.player_level = 1
75 QuestHelper.locale = QuestHelper_Locale
77 QuestHelper.faction = (UnitFactionGroup("player") == "Alliance" and 1) or
78 (UnitFactionGroup("player") == "Horde" and 2)
80 assert(QuestHelper.faction)
82 QuestHelper.font = {serif=GameFontNormal:GetFont(), sans=ChatFontNormal:GetFont(), fancy=QuestTitleFont:GetFont()}
84 function QuestHelper:GetFontPath(list_string, font)
85 if list_string then
86 for name in string.gmatch(list_string, "[^;]+") do
87 if font:SetFont(name, 10) then
88 return name
89 elseif font:SetFont("Interface\\AddOns\\QuestHelper\\Fonts\\"..name, 10) then
90 return "Interface\\AddOns\\QuestHelper\\Fonts\\"..name
91 end
92 end
93 end
94 end
96 function QuestHelper:SetLocaleFonts()
97 self.font.sans = nil
98 self.font.serif = nil
99 self.font.fancy = nil
101 local font = self:CreateText(self)
103 if QuestHelper_Locale ~= QuestHelper_Pref.locale then
104 -- Only use alternate fonts if using a language the client wasn't intended for.
105 local replacements = QuestHelper_SubstituteFonts[QuestHelper_Pref.locale]
106 if replacements then
107 self.font.sans = self:GetFontPath(replacements.sans, font)
108 self.font.serif = self:GetFontPath(replacements.serif, font)
109 self.font.fancy = self:GetFontPath(replacements.fancy, font)
113 self.font.sans = self.font.sans or self:GetFontPath(QuestHelper_Pref.locale.."_sans.ttf", font)
114 self.font.serif = self.font.serif or self:GetFontPath(QuestHelper_Pref.locale.."_serif.ttf", font) or self.font.sans
115 self.font.fancy = self.font.fancy or self:GetFontPath(QuestHelper_Pref.locale.."_fancy.ttf", font) or self.font.serif
117 self:ReleaseText(font)
119 self.font.sans = self.font.sans or ChatFontNormal:GetFont()
120 self.font.serif = self.font.serif or GameFontNormal:GetFont()
121 self.font.fancy = self.font.fancy or QuestTitleFont:GetFont()
123 -- Need to change the font of the chat frame, for any messages that QuestHelper displays.
124 -- This should do nothing if not using an alternate font.
125 --DEFAULT_CHAT_FRAME:SetFont(self.font.sans, select(2, DEFAULT_CHAT_FRAME:GetFont()))
126 -- what why did we ever do this
129 QuestHelper.route = {}
130 QuestHelper.to_add = {}
131 QuestHelper.to_remove = {}
132 QuestHelper.quest_log = {}
133 QuestHelper.pos = {nil, {}, 0, 0, 1, "You are here.", 0}
134 QuestHelper.sharing = false -- Will be set to true when sharing with at least one user.
136 function QuestHelper.tooltip:GetPrevLines() -- Just a helper to make life easier.
137 local last = self:NumLines()
138 local name = self:GetName()
139 return _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
142 function QuestHelper:SetTargetLocation(i, x, y, toffset)
143 -- Informs QuestHelper that you're going to be at some location in toffset seconds.
144 local c, z = unpack(QuestHelper_ZoneLookup[i])
146 self.target = self:CreateTable()
147 self.target[2] = self:CreateTable()
149 self.target_time = time()+(toffset or 0)
151 x, y = self.Astrolabe:TranslateWorldMapPosition(c, z, x, y, c, 0)
152 self.target[1] = self.zone_nodes[i]
153 self.target[3] = x * self.continent_scales_x[c]
154 self.target[4] = y * self.continent_scales_y[c]
156 self:SetTargetLocationRecalculate()
159 function QuestHelper:SetTargetLocationRecalculate()
160 if self.target then
161 for i, n in ipairs(self.target[1]) do
162 local a, b = n.x-self.target[3], n.y-self.target[4]
163 self.target[2][i] = math.sqrt(a*a+b*b)
168 function QuestHelper:UnsetTargetLocation()
169 -- Unsets the target set above.
170 if self.target then
171 self:ReleaseTable(self.target[2])
172 self:ReleaseTable(self.target)
173 self.target = nil
174 self.target_time = nil
178 local interruptcount = 0 -- counts how many "played gained control" messages we recieve, used for flight paths
179 local init_cartographer_later = false
182 local startup_time
183 local please_submit_enabled = true
184 local please_submit_initted = false
186 local spawned = false
187 QH_Event("ADDON_LOADED", function (addonid)
188 if addonid ~= "QuestHelper" then return end
190 -- ONLY FAST STUFF ALLOWED IN HERE
192 -- Use DefaultPref as fallback for unset preference keys.
193 setmetatable(QuestHelper_Pref, {__index=QuestHelper_DefaultPref})
194 QuestHelper: Assert(QuestHelper_Pref.perfload_scale) -- if this fails, something is very botched
196 if not QuestHelper_Pref.track or QuestHelper_Pref.hide then
197 QuestHelper:HideTracker()
198 else
199 QuestHelper:ShowTracker() -- to respect the minimized setting
202 local self = QuestHelper -- whee hack hack hack
204 QuestHelper_Loadtime["init2_start"] = GetTime()
206 local file_problem_version = false
208 local expected_version = GetAddOnMetadata("QuestHelper", "Version")
210 local expected_files =
212 ["bst_pre.lua"] = true,
213 ["bst_post.lua"] = true,
214 ["bst_astrolabe.lua"] = true,
215 ["bst_ctl.lua"] = true,
216 ["bst_libaboutpanel.lua"] = true,
217 ["bst_range.lua"] = true,
219 ["manager_event.lua"] = true,
220 ["manager_achievement.lua"] = true,
221 ["manager_completed.lua"] = true,
223 ["upgrade.lua"] = true,
224 ["main.lua"] = true,
225 ["recycle.lua"] = true,
226 ["objective.lua"] = true,
227 ["quest.lua"] = true,
228 ["utility.lua"] = true,
229 ["dodads.lua"] = true,
230 ["dodads_triangles.lua"] = true,
231 ["teleport.lua"] = true,
232 ["pathfinding.lua"] = true,
233 ["routing.lua"] = true,
234 ["custom.lua"] = true,
235 ["menu.lua"] = true,
236 ["nag.lua"] = true,
237 ["comm.lua"] = true,
238 ["mapbutton.lua"] = true,
239 ["help.lua"] = true,
240 ["pattern.lua"] = true,
241 ["flightpath.lua"] = true,
242 ["tracker.lua"] = true,
243 ["objtips.lua"] = true,
244 ["cartographer.lua"] = true,
245 ["cartographer_is_terrible.lua"] = true,
246 ["tomtom.lua"] = true,
247 ["textviewer.lua"] = true,
248 ["error.lua"] = true,
249 ["timeslice.lua"] = true,
250 ["lang.lua"] = true,
251 ["core.lua"] = true,
252 ["tooltip.lua"] = true,
253 ["arrow.lua"] = true,
254 ["radar.lua"] = true,
256 ["config.lua"] = true,
258 ["static.lua"] = true,
259 ["static_1.lua"] = true,
260 ["static_2.lua"] = true,
261 ["static_deDE.lua"] = true,
262 ["static_deDE_1.lua"] = true,
263 ["static_deDE_2.lua"] = true,
264 ["static_enUS.lua"] = true,
265 ["static_enUS_1.lua"] = true,
266 ["static_enUS_2.lua"] = true,
267 ["static_esES.lua"] = true,
268 ["static_esES_1.lua"] = true,
269 ["static_esES_2.lua"] = true,
270 ["static_esMX.lua"] = true,
271 ["static_esMX_1.lua"] = true,
272 ["static_esMX_2.lua"] = true,
273 ["static_frFR.lua"] = true,
274 ["static_frFR_1.lua"] = true,
275 ["static_frFR_2.lua"] = true,
276 ["static_koKR.lua"] = true,
277 ["static_koKR_1.lua"] = true,
278 ["static_koKR_2.lua"] = true,
279 ["static_ruRU.lua"] = true,
280 ["static_ruRU_1.lua"] = true,
281 ["static_ruRU_2.lua"] = true,
282 ["static_zhTW.lua"] = true,
283 ["static_zhTW_1.lua"] = true,
284 ["static_zhTW_2.lua"] = true,
286 ["collect.lua"] = true,
287 ["collect_achievement.lua"] = true,
288 ["collect_lzw.lua"] = true,
289 ["collect_traveled.lua"] = true,
290 ["collect_zone.lua"] = true,
291 ["collect_location.lua"] = true,
292 ["collect_merger.lua"] = true,
293 ["collect_monster.lua"] = true,
294 ["collect_item.lua"] = true,
295 ["collect_object.lua"] = true,
296 ["collect_loot.lua"] = true,
297 ["collect_patterns.lua"] = true,
298 ["collect_flight.lua"] = true,
299 ["collect_util.lua"] = true,
300 ["collect_quest.lua"] = true,
301 ["collect_equip.lua"] = true,
302 ["collect_notifier.lua"] = true,
303 ["collect_bitstream.lua"] = true,
304 ["collect_spec.lua"] = true,
305 ["collect_upgrade.lua"] = true,
306 ["collect_merchant.lua"] = true,
307 ["collect_warp.lua"] = true,
309 ["filter_core.lua"] = true,
310 ["filter_base.lua"] = true,
312 ["routing_debug.lua"] = true,
313 ["routing_loc.lua"] = true,
314 ["routing_route.lua"] = true,
315 ["routing_core.lua"] = true,
316 ["routing_controller.lua"] = true,
317 ["routing_hidden.lua"] = true,
319 ["director_quest.lua"] = true,
320 ["director_achievement.lua"] = true,
321 ["director_find.lua"] = true,
323 ["db_get.lua"] = true,
325 ["graph_core.lua"] = true,
326 ["graph_flightpath.lua"] = true,
328 ["AstrolabeQH/Astrolabe.lua"] = true,
329 ["AstrolabeQH/AstrolabeMapMonitor.lua"] = true,
332 local uninstallederr = ""
334 for file, version in pairs(QuestHelper_File) do
335 if not expected_files[file] then
336 local errmsg = "Unexpected QuestHelper file: "..file
337 DEFAULT_CHAT_FRAME:AddMessage(errmsg)
338 uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
339 file_problem_version = true
340 elseif version ~= expected_version then
341 local errmsg = "Wrong version of QuestHelper file: "..file.." (found '"..version.."', should be '"..expected_version.."')"
342 DEFAULT_CHAT_FRAME:AddMessage(errmsg)
343 uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
344 if version ~= "Development Version" and expected_version ~= "Development Version" then
345 -- Developers are allowed to mix dev versions with release versions
346 file_problem_version = true
351 for file in pairs(expected_files) do
352 if not QuestHelper_File[file] then
353 local errmsg = "Missing QuestHelper file: "..file
354 DEFAULT_CHAT_FRAME:AddMessage(errmsg)
355 uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
356 if not (expected_version == "Development Version" and file:match("static.*")) then file_problem_version = true end
360 -- Don't need this table anymore.
361 QuestHelper_File = nil
363 if QuestHelper_StaticData and not QuestHelper_StaticData[GetLocale()] then
364 local errmsg = "Static data does not seem to exist"
365 DEFAULT_CHAT_FRAME:AddMessage(errmsg)
367 uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
368 file_problem_version = true
371 if file_problem_version then
372 QH_fixedmessage(QHText("PLEASE_RESTART"))
373 QuestHelper_ErrorCatcher_ExplicitError(false, "not-installed-properly" .. "\n" .. uninstallederr)
374 QuestHelper = nil -- Just in case anybody else is checking for us, we're not home
375 return
378 if not GetCategoryList or not GetQuestLogSpecialItemInfo or not WatchFrame_RemoveObjectiveHandler then
379 QH_fixedmessage(QHText("PRIVATE_SERVER"))
380 QuestHelper_ErrorCatcher_ExplicitError(false, "error id cakbep ten T")
381 QuestHelper = nil
382 return
385 if not DongleStub or not QH_Astrolabe_Ready then
386 QH_fixedmessage(QHText("NOT_UNZIPPED_CORRECTLY"))
387 QuestHelper_ErrorCatcher_ExplicitError(false, "not-unzipped-properly")
388 QuestHelper = nil -- Just in case anybody else is checking for us, we're not home
389 return
392 QuestHelper_ErrorCatcher_CompletelyStarted()
394 if not QuestHelper_StaticData then
395 -- If there is no static data for some mysterious reason, create an empty table so that
396 -- other parts of the code can carry on as usual, using locally collected data if it exists.
397 QuestHelper_StaticData = {}
400 QHFormatSetLocale(QuestHelper_Pref.locale or GetLocale())
402 if not QuestHelper_UID then
403 QuestHelper_UID = self:CreateUID()
405 QuestHelper_SaveDate = time()
408 QH_Timeslice_Add(function ()
409 QuestHelper_Loadtime["init3_start"] = GetTime()
411 QuestHelper.loading_main = QuestHelper.CreateLoadingCounter()
413 QuestHelper.loading_init3 = QuestHelper.loading_main:MakeSubcategory(0.3)
414 QuestHelper.loading_flightpath = QuestHelper.loading_main:MakeSubcategory(1)
415 QuestHelper.loading_preroll = QuestHelper.loading_main:MakeSubcategory(1)
417 local stt = 0
419 -- This is where the slow stuff goes
420 QuestHelper_BuildZoneLookup()
421 QH_Graph_Init()
422 load_graph_links()
424 if QuestHelper_Locale ~= GetLocale() then
425 self:TextOut(QHText("LOCALE_ERROR"))
426 return
429 if not self:ZoneSanity() then
430 self:TextOut(QHFormat("ZONE_LAYOUT_ERROR", expected_version))
431 QH_fixedmessage(QHFormat("ZONE_LAYOUT_ERROR", expected_version))
432 QuestHelper = nil
433 return
436 QuestHelper_UpgradeDatabase(_G)
437 QuestHelper_UpgradeComplete()
439 if QuestHelper_IsPolluted(_G) then
440 self:TextOut(QHFormat("NAG_POLLUTED"))
441 self:Purge(nil, true, true)
444 local signature = expected_version .. " on " .. GetBuildInfo()
445 QuestHelper_Quests[signature] = QuestHelper_Quests[signature] or {}
446 QuestHelper_Objectives[signature] = QuestHelper_Objectives[signature] or {}
447 QuestHelper_FlightInstructors[signature] = QuestHelper_FlightInstructors[signature] or {}
448 QuestHelper_FlightRoutes[signature] = QuestHelper_FlightRoutes[signature] or {}
450 QuestHelper_Quests_Local = QuestHelper_Quests[signature]
451 QuestHelper_Objectives_Local = QuestHelper_Objectives[signature]
452 QuestHelper_FlightInstructors_Local = QuestHelper_FlightInstructors[signature]
453 QuestHelper_FlightRoutes_Local = QuestHelper_FlightRoutes[signature]
455 QuestHelper_SeenRealms[GetRealmName()] = true -- some attempt at tracking private servers
457 QuestHelper.loading_init3:SetPercentage(0.1)
458 QH_Collector_Init()
459 QuestHelper.loading_init3:SetPercentage(0.5)
460 DB_Init()
461 QuestHelper.loading_init3:SetPercentage(0.9)
463 self.player_level = UnitLevel("player")
465 self:SetLocaleFonts()
467 if QuestHelper_Pref.share and not QuestHelper_Pref.solo then
468 self:EnableSharing()
471 if QuestHelper_Pref.hide then
472 self.map_overlay:Hide()
475 self:HandlePartyChange()
477 self:Nag("all")
479 for locale in pairs(QuestHelper_StaticData) do
480 if locale ~= self.locale then
481 -- Will delete references to locales you don't use.
482 QuestHelper_StaticData[locale] = nil
483 _G["QuestHelper_StaticData_" .. locale] = nil
487 local static = QuestHelper_StaticData[self.locale]
489 if static then
490 if static.flight_instructors then for faction in pairs(static.flight_instructors) do
491 if faction ~= self.faction then
492 -- Will delete references to flight instructors that don't belong to your faction.
493 static.flight_instructors[faction] = nil
495 end end
497 if static.quest then for faction in pairs(static.quest) do
498 if faction ~= self.faction then
499 -- Will delete references to quests that don't belong to your faction.
500 static.quest[faction] = nil
502 end end
505 -- Adding QuestHelper_CharVersion, so I know if I've already converted this characters saved data.
506 if not QuestHelper_CharVersion then
507 -- Changing per-character flight routes, now only storing the flight points they have,
508 -- will attempt to guess the routes from this.
509 local routes = {}
511 for i, l in pairs(QuestHelper_KnownFlightRoutes) do
512 for key in pairs(l) do
513 routes[key] = true
517 QuestHelper_KnownFlightRoutes = routes
519 -- Deleting the player's home again.
520 -- But using the new CharVersion variable I'm adding is cleaner that what I was doing, so I'll go with it.
521 QuestHelper_Home = nil
522 QuestHelper_CharVersion = 1
525 if not QuestHelper_Home then
526 -- Not going to bother complaining about the player's home not being set, uncomment this when the home is used in routing.
527 -- self:TextOut(QHText("HOME_NOT_KNOWN"))
530 if QuestHelper_Pref.map_button then
531 QuestHelper:InitMapButton()
534 if QuestHelper_Pref.cart_wp_new then
535 init_cartographer_later = true
538 if QuestHelper_Pref.tomtom_wp_new then
539 self:EnableTomTom()
542 self.tracker:SetScale(QuestHelper_Pref.track_scale)
544 local version = GetAddOnMetadata("QuestHelper", "Version") or "Unknown"
546 local major, minor = (version_string or ""):match("^(%d+)%.(%d+)")
547 major, minor = tonumber(major), tonumber(minor)
549 -- For versions before 0.82, we're changing the default level offset to 3.
550 if major == 0 and minor and minor < 82 and QuestHelper_Pref.level == 2 then
551 QuestHelper_Pref.level = nil
554 -- For versions before 0.84...
555 if major == 0 and minor and minor < 84 then
556 -- remove all keys that match their default setting.
557 for key, val in pairs(QuestHelper_DefaultPref) do
558 if QuestHelper_Pref[key] == val then
559 QuestHelper_Pref[key] = nil
564 QH_Hook(self, "OnUpdate", self.OnUpdate)
566 -- Seems to do its own garbage collection pass before fully loading, so I'll just rely on that
567 --collectgarbage("collect") -- Free everything we aren't using.
569 --[[
570 if self.debug_objectives then
571 for name, data in pairs(self.debug_objectives) do
572 self:LoadDebugObjective(name, data)
574 end]]
576 -- wellllp
577 QH_Arrow_SetScale()
578 QH_Arrow_SetTextScale()
580 --[[
581 QH_Timeslice_Add(function ()
582 self:ResetPathing()
583 self.Routing:Initialize() -- Set up the routing task
584 end, "init")]] -- FUCK YOU BOXBOT
586 --[[ -- This is just an example of how the WoW profiler biases its profiles heavily.
587 function C()
590 function A()
591 q = 0
592 for x = 0, 130000000, 1 do
596 function B()
597 q = 0
598 for x = 0, 12000000, 1 do
603 function B2()
604 q = 0
605 for x = 0, 1200000, 1 do
606 --q = q + x
611 debugprofilestart()
613 local ta = debugprofilestop()
615 local tb = debugprofilestop()
617 local tc = debugprofilestop()
619 QuestHelper:TextOut(string.format("%d %d %d", ta, tb - ta, tc - tb))
620 QuestHelper:TextOut(string.format("%d %d", GetFunctionCPUUsage(A), GetFunctionCPUUsage(B)))
622 --/script SetCVar("scriptProfile", value)]]
625 QH_Event("CHAT_MSG_ADDON", function (...)
626 if arg1 == "QHpr" and arg4 ~= UnitName("player") then
627 QH_Questcomm_Msg(arg2, arg4)
629 end)
631 QH_Event({"PARTY_MEMBERS_CHANGED", "UNIT_LEVEL", "RAID_ROSTER_UPDATE"}, function ()
632 QH_Filter_Group_Sync()
633 QH_Route_Filter_Rescan("filter_quest_level")
634 --QH_Route_Filter_Rescan("filter_quest_group")
635 --QH_Route_Filter_Rescan("filter_quest_raid_accessible") -- These should be in right now, but for simplicity's sake we're actually scanning everything when we get a rescan request. So they're unnecessary. PUT THEM BACK should they become necessary.
636 end)
638 QH_Event({"PARTY_MEMBERS_CHANGED", "RAID_ROSTER_UPDATE"}, function ()
639 QH_Questcomm_Sync()
640 end)
642 QH_Event("PLAYER_LEVEL_UP", function ()
643 self.player_level = arg1
644 QH_Route_Filter_Rescan("filter_quest_level")
645 end)
647 QH_Event("TAXIMAP_OPENED", function ()
648 self:taxiMapOpened()
649 end)
651 QH_Event({"ZONE_CHANGED", "ZONE_CHANGED_INDOORS", "ZONE_CHANGED_NEW_AREA"}, function()
652 QH_Route_Filter_Rescan(nil, true)
653 end)
655 QH_Event("CHAT_MSG_CHANNEL_NOTICE", function()
656 if please_submit_enabled and not please_submit_initted then
657 please_submit_enabled = QHNagInit()
658 startup_time = GetTime()
659 please_submit_initted = true
661 end)
663 QuestHelper.loading_init3:SetPercentage(1.0) -- victory
665 QuestHelper_Loadtime["init3_end"] = GetTime()
666 end, "preinit")
668 QuestHelper_Loadtime["init2_end"] = GetTime()
669 end)
672 --[==[
673 function QuestHelper:OnEvent(event)
674 local tstart = GetTime()
676 --[[
677 if event == "GOSSIP_SHOW" then
678 local name, id = UnitName("npc"), self:GetUnitID("npc")
679 if name and id then
680 self:GetObjective("monster", name).o.id = id
681 --self:TextOut("NPC: "..name.." = "..id)
683 end]]
685 --[[if event == "PLAYER_TARGET_CHANGED" then
686 local name, id = UnitName("target"), self:GetUnitID("target")
687 if name and id then
688 self:GetObjective("monster", name).o.id = id
689 --self:TextOut("Target: "..name.." = "..id)
692 if UnitExists("target") and UnitIsVisible("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
693 local index, x, y = self:UnitPosition("target")
695 if index then -- Might not have a position if inside an instance.
696 local w = 0.1
698 -- Modify the weight based on how far they are from us.
699 -- We don't know the exact location (using our own location), so the farther, the less sure we are that it's correct.
700 if CheckInteractDistance("target", 3) then w = 1
701 elseif CheckInteractDistance("target", 2) then w = 0.89
702 elseif CheckInteractDistance("target", 1) or CheckInteractDistance("target", 4) then w = 0.33 end
704 local monster_objective = self:GetObjective("monster", UnitName("target"))
705 self:AppendObjectivePosition(monster_objective, index, x, y, w)
707 monster_objective.o.faction = (UnitFactionGroup("target") == "Alliance" and 1) or
708 (UnitFactionGroup("target") == "Horde" and 2) or nil
710 local level = UnitLevel("target")
711 if level and level >= 1 then
712 local w = monster_objective.o.levelw or 0
713 monster_objective.o.level = ((monster_objective.o.level or 0)*w+level)/(w+1)
714 monster_objective.o.levelw = w+1
718 end]]
720 --[[if event == "LOOT_OPENED" then
721 local target = UnitName("target")
722 if target and UnitIsDead("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
723 local index, x, y = self:UnitPosition("target")
725 local monster_objective = self:GetObjective("monster", target)
726 monster_objective.o.looted = (monster_objective.o.looted or 0) + 1
728 if index then -- Might not have a position if inside an instance.
729 self:AppendObjectivePosition(monster_objective, index, x, y)
732 for i = 1, GetNumLootItems() do
733 local icon, name, number, rarity = GetLootSlotInfo(i)
734 if name then
735 if number and number >= 1 then
736 self:AppendItemObjectiveDrop(self:GetObjective("item", name), name, target, number)
737 else
738 local total = (name:match(COPPER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) +
739 (name:match(SILVER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 100 +
740 (name:match(GOLD_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 10000
742 if total > 0 then
743 self:AppendObjectiveDrop(self:GetObjective("item", "money"), target, total)
748 else
749 local container = nil
751 -- Go through the players inventory and look for a locked item, we're probably looting it.
752 for bag = 0,NUM_BAG_SLOTS do
753 for slot = 1,GetContainerNumSlots(bag) do
754 local link = GetContainerItemLink(bag, slot)
755 if link and select(3, GetContainerItemInfo(bag, slot)) then
756 if container == nil then
757 -- Found a locked item and haven't previously assigned to container, assign its name, or false if we fail to parse it.
758 container = select(3, string.find(link, "|h%[(.+)%]|h|r")) or false
759 else
760 -- Already tried to assign to a container. If there are multiple locked items, we give up.
761 container = false
767 if container then
768 local container_objective = self:GetObjective("item", container)
769 container_objective.o.opened = (container_objective.o.opened or 0) + 1
771 for i = 1, GetNumLootItems() do
772 local icon, name, number, rarity = GetLootSlotInfo(i)
773 if name and number >= 1 then
774 self:AppendItemObjectiveContainer(self:GetObjective("item", name), container, number)
777 else
778 -- No idea where the items came from.
779 local index, x, y = self:PlayerPosition()
781 if index then
782 for i = 1, GetNumLootItems() do
783 local icon, name, number, rarity = GetLootSlotInfo(i)
784 if name and number >= 1 then
785 self:AppendItemObjectivePosition(self:GetObjective("item", name), name, index, x, y)
791 end]]
793 --[[if event == "CHAT_MSG_SYSTEM" then
794 local home_name = self:convertPattern(ERR_DEATHBIND_SUCCESS_S)(arg1)
795 if home_name then
796 if self.i then
797 self:TextOut(QHText("HOME_CHANGED"))
798 self:TextOut(QHText("WILL_RESET_PATH"))
800 local home = QuestHelper_Home
801 if not home then
802 home = {}
803 QuestHelper_Home = home
806 home[1], home[2], home[3], home[4] = self.i, self.x, self.y, home_name
807 self.defered_graph_reset = true
810 end]]
815 --[[if event == "QUEST_DETAIL" then
816 if not self.quest_giver then self.quest_giver = {} end
817 local npc = UnitName("npc")
818 if npc then
819 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
820 local index, x, y = self:UnitPosition("npc")
822 if index then -- Might not have a position if inside an instance.
823 local npc_objective = self:GetObjective("monster", npc)
824 self:AppendObjectivePosition(npc_objective, index, x, y)
825 self.quest_giver[GetTitleText()] = npc
828 end]]
830 --[[if event == "QUEST_COMPLETE" or event == "QUEST_PROGRESS" then
831 local quest = GetTitleText()
832 if quest then
833 local level, hash = self:GetQuestLevel(quest)
834 if not level or level < 1 then
835 --self:TextOut("Don't know quest level for ".. quest.."!")
836 return
838 local q = self:GetQuest(quest, level, hash)
840 if q.need_hash then
841 q.o.hash = hash
844 local unit = UnitName("npc")
845 if unit then
846 q.o.finish = unit
847 q.o.pos = nil
849 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
850 local index, x, y = self:UnitPosition("npc")
851 if index then -- Might not have a position if inside an instance.
852 local npc_objective = self:GetObjective("monster", unit)
853 self:AppendObjectivePosition(npc_objective, index, x, y)
855 elseif not q.o.finish then
856 local index, x, y = self:PlayerPosition()
857 if index then -- Might not have a position if inside an instance.
858 self:AppendObjectivePosition(q, index, x, y)
862 end]]
864 --[[if event == "MERCHANT_SHOW" then
865 local npc_name = UnitName("npc")
866 if npc_name then
867 local npc_objective = self:GetObjective("monster", npc_name)
868 local index = 1
869 while true do
870 local item_name = GetMerchantItemInfo(index)
871 if item_name then
872 index = index + 1
873 local item_objective = self:GetObjective("item", item_name)
874 if not item_objective.o.vendor then
875 item_objective.o.vendor = {npc_name}
876 else
877 local known = false
878 for i, vendor in ipairs(item_objective.o.vendor) do
879 if npc_name == vendor then
880 known = true
881 break
884 if not known then
885 table.insert(item_objective.o.vendor, npc_name)
888 else
889 break
893 end]]
895 if event == "TAXIMAP_OPENED" then
896 self:taxiMapOpened()
899 --[[if event == "PLAYER_CONTROL_GAINED" then
900 interruptcount = interruptcount + 1
901 end]]
903 --[[if event == "BAG_UPDATE" then
904 for slot = 1,GetContainerNumSlots(arg1) do
905 local link = GetContainerItemLink(arg1, slot)
906 if link then
907 local id, name = select(3, string.find(link, "|Hitem:(%d+):.-|h%[(.-)%]|h"))
908 if name then
909 self:GetObjective("item", name).o.id = tonumber(id)
913 end]]
917 if event == "ZONE_CHANGED" or event == "ZONE_CHANGED_INDOORS" or event == "ZONE_CHANGED_NEW_AREA" then
918 QH_Route_Filter_Rescan()
921 QH_Timeslice_Increment(GetTime() - tstart, "event")
922 end]==]
924 local map_shown_decay = 0
925 local delayed_action = 100
926 --local update_count = 0
927 local ontaxi = false
928 local frams = 0
930 QH_OnUpdate_High(function ()
931 local self = QuestHelper -- hoorj
932 local tstart = GetTime()
933 frams = frams + 1
935 if not QuestHelper_Loadtime["onupdate"] then QuestHelper_Loadtime["onupdate"] = GetTime() end
937 if false and frams == 60 then
938 self:ShowText([[
939 This is a |cffff8000beta of QuestHelper|r. Be warned: It may crash. It may lock up. It may give bad advice. It may spew errors. It shouldn't spam people, delete your hard-won epics, or make your computer catch on fire, but technically I'm giving no guarantees. |cffff8000If you want a polished, functioning product, close WoW, download the official QH release from curse.com, and use that.|r
941 Known bugs and issues include:
943 |cff40bbffNo support for "/qh find"|r
945 |cff40bbffNo support for in-party quest synchronization|r
947 These may not be fixed before the official 1.0 release - I'm hoping to get them all finished up in time for 1.1.
949 If you encounter any issue besides the ones listed here, please please please report it, if you're reading this you know how to get in contact with me anyway.
951 Thanks for testing!]], "QuestHelper " .. version_string, 500, 20, 10)
954 --if frams == 5000 then please_submit_enabled = false end -- TOOK TOO LONG >:(
955 if please_submit_enabled and startup_time and startup_time + 10 < GetTime() then
956 QuestHelper:TextOut(QHText("PLEASE_SUBMIT"))
957 startup_time = nil
958 please_submit_enabled = false
960 QHUpdateNagTick() -- These probably shouldn't be in OnUpdate. Eventually I'll move them somewhere cleaner.
962 if init_cartographer_later and Cartographer_Waypoints then -- there has to be a better way to do this
963 init_cartographer_later = false
964 if QuestHelper_Pref.cart_wp_new then
965 self:EnableCartographer()
969 if not ontaxi and UnitOnTaxi("player") then
970 self:flightBegan()
971 interruptcount = 0
972 elseif ontaxi and not UnitOnTaxi("player") then
973 self:flightEnded(interruptcount > 1)
975 ontaxi = UnitOnTaxi("player")
977 -- For now I'm ripping out the update_count code
978 --update_count = update_count - 1
979 --if update_count <= 0 then
981 -- Reset the update count for next time around; this will make sure the body executes every time
982 -- when perf_scale_2 >= 1, and down to 1 in 10 iterations when perf_scale_2 < 1, or when hidden.
983 --update_count = update_count + (QuestHelper_Pref.hide and 10 or 1/QuestHelper_Pref.perf_scale_2)
985 --if update_count < 0 then
986 -- Make sure the count doesn't go perpetually negative; don't know what will happen if it underflows.
987 --update_count = 0
988 --end
990 if self.Astrolabe.WorldMapVisible then
991 -- We won't trust that the zone returned by Astrolabe is correct until map_shown_decay is 0.
992 map_shown_decay = 2
993 elseif map_shown_decay > 0 then
994 map_shown_decay = map_shown_decay - 1
995 else
996 --SetMapToCurrentZone() -- not sure why this existed
999 --[[delayed_action = delayed_action - 1
1000 if delayed_action <= 0 then
1001 delayed_action = 100
1002 self:HandlePartyChange()
1003 end]]
1005 local nc, nz, nx, ny = self.Astrolabe:GetCurrentPlayerPosition()
1006 local tc, tx, ty
1008 if nc and nc ~= -1 then -- We just want the raw data here, before we've done anything clever.
1009 tc, tx, ty = self.Astrolabe:GetAbsoluteContinentPosition(nc, nz, nx, ny)
1010 QuestHelper: Assert(tc and tx and ty) -- is it true? nobody knows! :D
1013 if nc and nc == self.c and map_shown_decay > 0 and self.z > 0 and self.z ~= nz then
1014 -- There's a chance Astrolable will return the wrong zone if you're messing with the world map, if you can
1015 -- be seen in that zone but aren't in it.
1016 local nnx, nny = self.Astrolabe:TranslateWorldMapPosition(nc, nz, nx, ny, nc, self.z)
1017 if nnx > 0 and nny > 0 and nnx < 1 and nny < 1 then
1018 nz, nx, ny = self.z, nnx, nny
1022 if nc and nc > 0 and nz == 0 and nc == self.c and self.z > 0 then
1023 nx, ny = self.Astrolabe:TranslateWorldMapPosition(nc, nz, nx, ny, nc, self.z)
1024 if nx and ny --[[and nx > -0.1 and ny > -0.1 and nx < 1.1 and ny < 1.1]] then -- removing the conditional because I think I can use the data even when it's a little wonky
1025 nz = self.z
1026 else
1027 nc, nz, nx, ny = nil, nil, nil, nil
1031 if nc and nz > 0 and QuestHelper_IndexLookup[nc] then -- QuestHelper_IndexLookup is only initialized after we've finished the preinit step
1032 self.c, self.z, self.x, self.y = nc, nz, nx, ny
1033 local upd_zone = false
1034 if self.i ~= QuestHelper_IndexLookup[nc][nz] then upd_zone = true end
1035 self.i = QuestHelper_IndexLookup[nc][nz]
1036 if upd_zone then QH_Route_Filter_Rescan("filter_zone") end
1039 if nc and nz and nx and ny and tc and tx and ty then
1040 self.collect_rc, self.collect_rz, self.collect_rx, self.collect_ry = nc, nz, nx, ny
1041 self.collect_ac, self.collect_ax, self.collect_ay = tc, tx, ty
1042 self.collect_delayed = false
1044 local ibi = self.InBrokenInstance
1045 if nc < -77 then self.InBrokenInstance = true else self.InBrokenInstance = false end
1047 if ibi and not self.InBrokenInstance then self.minimap_marker:OnUpdate(0) end -- poke
1048 else
1049 self.collect_delayed = true
1050 self.InBrokenInstance = true
1053 if not UnitOnTaxi("player") and not UnitIsDeadOrGhost("player") then
1054 QuestHelper.routing_ac, QuestHelper.routing_ax, QuestHelper.routing_ay, QuestHelper.routing_c, QuestHelper.routing_z = QuestHelper.collect_ac, QuestHelper.collect_ax, QuestHelper.collect_ay, QuestHelper.c, QuestHelper.z
1057 QH_Timeslice_Toggle("routing", not not self.c)
1059 self:PumpCommMessages()
1060 --end
1061 end)
1063 -- Some or all of these may be nil. c,x,y should be enough for a location - c is the pure continent (currently either 0 or 3 for Azeroth or Outland, or -77 for the DK starting zone) and x,y are the coordinates within that continent.
1064 -- rc and rz are the continent and zone that Questhelper thinks it's within. For various reasons, this isn't perfect. TODO: Base it off the map zone name identifiers instead of the map itself?
1065 function QuestHelper:Location_RawRetrieve()
1066 return self.collect_delayed, self.collect_rc, self.collect_rz, self.collect_rx, self.collect_ry
1068 function QuestHelper:Location_AbsoluteRetrieve()
1069 return self.collect_delayed, self.collect_ac, self.collect_ax, self.collect_ay
1072 --QH_Hook(QuestHelper, "OnEvent", QuestHelper.OnEvent)