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_SaveVersion
= 10
10 QuestHelper_CharVersion
= 1
11 QuestHelper_Locale
= GetLocale() -- This variable is used only for the collected data, and has nothing to do with displayed text.
12 QuestHelper_Quests
= {}
13 QuestHelper_Objectives
= {}
18 QuestHelper_DefaultPref
=
23 filter_blocked
=false, -- Hides blocked objectives, such as quest turn-ins for incomplete quests
24 filter_watched
=false, -- Limits to Watched objectives
27 filter_wintergrasp
=true,
29 track_minimized
=false,
44 tomtom_wp_new
= false,
49 metric
= (QuestHelper_Locale
~= "enUS" and QuestHelper_Locale
~= "esMX"),
51 locale
= GetLocale(), -- This variable is used for display purposes, and has nothing to do with the collected data.
52 perf_scale_2
= 1, -- How much background processing can the current machine handle? Higher means more load, lower means better performance.
53 perfload_scale
= 1, -- Performance scale to use on startup
57 -- 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.
58 setmetatable(QuestHelper_Pref
, {__index
=QuestHelper_DefaultPref
})
60 QuestHelper_FlightInstructors
= {}
61 QuestHelper_FlightLinks
= {}
62 QuestHelper_FlightRoutes
= {}
63 QuestHelper_KnownFlightRoutes
= {}
64 QuestHelper_SeenRealms
= {}
66 QuestHelper
.tooltip
= CreateFrame("GameTooltip", "QuestHelperTooltip", nil, "GameTooltipTemplate")
67 QuestHelper
.objective_objects
= {}
68 QuestHelper
.user_objectives
= {}
69 QuestHelper
.quest_objects
= {}
70 QuestHelper
.player_level
= 1
71 QuestHelper
.locale
= QuestHelper_Locale
73 QuestHelper
.faction
= (UnitFactionGroup("player") == "Alliance" and 1) or
74 (UnitFactionGroup("player") == "Horde" and 2)
76 assert(QuestHelper
.faction
)
78 QuestHelper
.font
= {serif
=GameFontNormal
:GetFont(), sans
=ChatFontNormal
:GetFont(), fancy
=QuestTitleFont
:GetFont()}
80 function QuestHelper
:GetFontPath(list_string
, font
)
82 for name
in string.gmatch(list_string
, "[^;]+") do
83 if font
:SetFont(name
, 10) then
85 elseif font
:SetFont("Interface\\AddOns\\QuestHelper\\Fonts\\"..name
, 10) then
86 return "Interface\\AddOns\\QuestHelper\\Fonts\\"..name
92 function QuestHelper
:SetLocaleFonts()
97 local font
= self
:CreateText(self
)
99 if QuestHelper_Locale
~= QuestHelper_Pref
.locale
then
100 -- Only use alternate fonts if using a language the client wasn't intended for.
101 local replacements
= QuestHelper_SubstituteFonts
[QuestHelper_Pref
.locale
]
103 self
.font
.sans
= self
:GetFontPath(replacements
.sans
, font
)
104 self
.font
.serif
= self
:GetFontPath(replacements
.serif
, font
)
105 self
.font
.fancy
= self
:GetFontPath(replacements
.fancy
, font
)
109 self
.font
.sans
= self
.font
.sans
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_sans.ttf", font
)
110 self
.font
.serif
= self
.font
.serif
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_serif.ttf", font
) or self
.font
.sans
111 self
.font
.fancy
= self
.font
.fancy
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_fancy.ttf", font
) or self
.font
.serif
113 self
:ReleaseText(font
)
115 self
.font
.sans
= self
.font
.sans
or ChatFontNormal
:GetFont()
116 self
.font
.serif
= self
.font
.serif
or GameFontNormal
:GetFont()
117 self
.font
.fancy
= self
.font
.fancy
or QuestTitleFont
:GetFont()
119 -- Need to change the font of the chat frame, for any messages that QuestHelper displays.
120 -- This should do nothing if not using an alternate font.
121 DEFAULT_CHAT_FRAME
:SetFont(self
.font
.sans
, select(2, DEFAULT_CHAT_FRAME
:GetFont()))
124 QuestHelper
.route
= {}
125 QuestHelper
.to_add
= {}
126 QuestHelper
.to_remove
= {}
127 QuestHelper
.quest_log
= {}
128 QuestHelper
.pos
= {nil, {}, 0, 0, 1, "You are here.", 0}
129 QuestHelper
.sharing
= false -- Will be set to true when sharing with at least one user.
131 function QuestHelper
.tooltip
:GetPrevLines() -- Just a helper to make life easier.
132 local last
= self
:NumLines()
133 local name
= self
:GetName()
134 return _G
[name
.."TextLeft"..last
], _G
[name
.."TextRight"..last
]
137 function QuestHelper
:SetTargetLocation(i
, x
, y
, toffset
)
138 -- Informs QuestHelper that you're going to be at some location in toffset seconds.
139 local c
, z
= unpack(QuestHelper_ZoneLookup
[i
])
141 self
.target
= self
:CreateTable()
142 self
.target
[2] = self
:CreateTable()
144 self
.target_time
= time()+(toffset
or 0)
146 x
, y
= self
.Astrolabe
:TranslateWorldMapPosition(c
, z
, x
, y
, c
, 0)
147 self
.target
[1] = self
.zone_nodes
[i
]
148 self
.target
[3] = x
* self
.continent_scales_x
[c
]
149 self
.target
[4] = y
* self
.continent_scales_y
[c
]
151 self
:SetTargetLocationRecalculate()
154 function QuestHelper
:SetTargetLocationRecalculate()
156 for i
, n
in ipairs(self
.target
[1]) do
157 local a
, b
= n
.x
-self
.target
[3], n
.y
-self
.target
[4]
158 self
.target
[2][i
] = math
.sqrt(a
*a
+b
*b
)
163 function QuestHelper
:UnsetTargetLocation()
164 -- Unsets the target set above.
166 self
:ReleaseTable(self
.target
[2])
167 self
:ReleaseTable(self
.target
)
169 self
.target_time
= nil
173 local interruptcount
= 0 -- counts how many "played gained control" messages we recieve, used for flight paths
174 local init_cartographer_later
= false
176 QH_Event("ADDON_LOADED", function (addonid
)
177 if addonid
~= "QuestHelper" then return end
178 local self
= QuestHelper
-- whee hack hack hack
180 QuestHelper_Loadtime
["init_start"] = GetTime()
182 -- Use DefaultPref as fallback for unset preference keys.
183 setmetatable(QuestHelper_Pref
, {__index
=QuestHelper_DefaultPref
})
185 local file_problem
= false
186 local expected_version
= GetAddOnMetadata("QuestHelper", "Version")
188 local expected_files
=
190 ["bst_pre.lua"] = true,
191 ["bst_post.lua"] = true,
192 ["bst_astrolabe.lua"] = true,
193 ["bst_ctl.lua"] = true,
194 ["bst_libaboutpanel.lua"] = true,
196 ["manager_event.lua"] = true,
198 ["upgrade.lua"] = true,
200 ["recycle.lua"] = true,
201 ["objective.lua"] = true,
202 ["quest.lua"] = true,
203 ["utility.lua"] = true,
204 ["dodads.lua"] = true,
205 ["dodads_triangles.lua"] = true,
206 ["teleport.lua"] = true,
207 ["pathfinding.lua"] = true,
208 ["routing.lua"] = true,
209 ["custom.lua"] = true,
213 ["mapbutton.lua"] = true,
215 ["pattern.lua"] = true,
216 ["flightpath.lua"] = true,
217 ["tracker.lua"] = true,
218 ["objtips.lua"] = true,
219 ["cartographer.lua"] = true,
220 ["cartographer_is_terrible.lua"] = true,
221 ["tomtom.lua"] = true,
222 ["textviewer.lua"] = true,
223 ["error.lua"] = true,
224 ["timeslice.lua"] = true,
227 ["tooltip.lua"] = true,
228 ["arrow.lua"] = true,
230 ["static.lua"] = true,
231 ["static_1.lua"] = true,
232 ["static_2.lua"] = true,
233 ["static_deDE.lua"] = true,
234 ["static_deDE_1.lua"] = true,
235 ["static_deDE_2.lua"] = true,
236 ["static_enUS.lua"] = true,
237 ["static_enUS_1.lua"] = true,
238 ["static_enUS_2.lua"] = true,
239 ["static_esES.lua"] = true,
240 ["static_esES_1.lua"] = true,
241 ["static_esES_2.lua"] = true,
242 ["static_esMX.lua"] = true,
243 ["static_esMX_1.lua"] = true,
244 ["static_esMX_2.lua"] = true,
245 ["static_frFR.lua"] = true,
246 ["static_frFR_1.lua"] = true,
247 ["static_frFR_2.lua"] = true,
248 ["static_koKR.lua"] = true,
249 ["static_koKR_1.lua"] = true,
250 ["static_koKR_2.lua"] = true,
251 ["static_ruRU.lua"] = true,
252 ["static_ruRU_1.lua"] = true,
253 ["static_ruRU_2.lua"] = true,
254 ["static_zhTW.lua"] = true,
255 ["static_zhTW_1.lua"] = true,
256 ["static_zhTW_2.lua"] = true,
258 ["collect.lua"] = true,
259 ["collect_achievement.lua"] = true,
260 ["collect_lzw.lua"] = true,
261 ["collect_traveled.lua"] = true,
262 ["collect_zone.lua"] = true,
263 ["collect_location.lua"] = true,
264 ["collect_merger.lua"] = true,
265 ["collect_monster.lua"] = true,
266 ["collect_item.lua"] = true,
267 ["collect_object.lua"] = true,
268 ["collect_loot.lua"] = true,
269 ["collect_patterns.lua"] = true,
270 ["collect_flight.lua"] = true,
271 ["collect_util.lua"] = true,
272 ["collect_quest.lua"] = true,
273 ["collect_equip.lua"] = true,
274 ["collect_notifier.lua"] = true,
275 ["collect_bitstream.lua"] = true,
276 ["collect_spec.lua"] = true,
277 ["collect_upgrade.lua"] = true,
278 ["collect_merchant.lua"] = true,
279 ["collect_warp.lua"] = true,
281 ["filter_core.lua"] = true,
282 ["filter_base.lua"] = true,
284 ["routing_debug.lua"] = true,
285 ["routing_loc.lua"] = true,
286 ["routing_route.lua"] = true,
287 ["routing_core.lua"] = true,
288 ["routing_controller.lua"] = true,
289 ["routing_hidden.lua"] = true,
291 ["director_quest.lua"] = true,
292 ["director_achievement.lua"] = true,
294 ["db_get.lua"] = true,
296 ["graph_core.lua"] = true,
297 ["graph_flightpath.lua"] = true,
300 local uninstallederr
= ""
302 for file
, version
in pairs(QuestHelper_File
) do
303 if not expected_files
[file
] then
304 local errmsg
= "Unexpected QuestHelper file: "..file
305 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
306 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
308 elseif version
~= expected_version
then
309 local errmsg
= "Wrong version of QuestHelper file: "..file
.." (found '"..version
.."', should be '"..expected_version
.."')"
310 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
311 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
312 if version
~= "Development Version" and expected_version
~= "Development Version" then
313 -- Developers are allowed to mix dev versions with release versions
319 for file
in pairs(expected_files
) do
320 if not QuestHelper_File
[file
] then
321 local errmsg
= "Missing QuestHelper file: "..file
322 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
323 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
324 if not (expected_version
== "Development Version" and file
:match("static.*")) then file_problem
= true end
328 -- Don't need this table anymore.
329 QuestHelper_File
= nil
331 if QuestHelper_StaticData
and not QuestHelper_StaticData
[GetLocale()] then
332 local errmsg
= "Static data does not seem to exist"
333 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
335 -- TODO: Are you sure this should be an error? Shouldn't we let people we don't have data for collect their own?
336 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
341 message(QHText("PLEASE_RESTART"))
342 QuestHelper_ErrorCatcher_ExplicitError(true, "not-installed-properly" .. "\n" .. uninstallederr
)
343 QuestHelper
= nil -- Just in case anybody else is checking for us, we're not home
347 if not GetCategoryList
or not GetQuestLogSpecialItemInfo
or not WatchFrame_RemoveObjectiveHandler
then
348 message(QHText("PRIVATE_SERVER"))
349 QuestHelper_ErrorCatcher_ExplicitError(true, "error id cakbep ten T")
354 if not DongleStub
then
355 message(QHText("NOT_UNZIPPED_CORRECTLY"))
356 QuestHelper_ErrorCatcher_ExplicitError(true, "not-unzipped-properly")
357 QuestHelper
= nil -- Just in case anybody else is checking for us, we're not home
361 QuestHelper_ErrorCatcher_CompletelyStarted()
363 if not QuestHelper_StaticData
then
364 -- If there is no static data for some mysterious reason, create an empty table so that
365 -- other parts of the code can carry on as usual, using locally collected data if it exists.
366 QuestHelper_StaticData
= {}
369 QHFormatSetLocale(QuestHelper_Pref
.locale
or GetLocale())
371 if not QuestHelper_UID
then
372 QuestHelper_UID
= self
:CreateUID()
374 QuestHelper_SaveDate
= time()
376 QuestHelper_BuildZoneLookup()
380 if QuestHelper_Locale
~= GetLocale() then
381 self
:TextOut(QHText("LOCALE_ERROR"))
385 if not self
:ZoneSanity() then
386 self
:TextOut(QHText("ZONE_LAYOUT_ERROR"))
387 message("QuestHelper: "..QHText("ZONE_LAYOUT_ERROR"))
391 QuestHelper_UpgradeDatabase(_G
)
392 QuestHelper_UpgradeComplete()
394 if QuestHelper_SaveVersion
~= 10 then
395 self
:TextOut(QHText("DOWNGRADE_ERROR"))
399 if QuestHelper_IsPolluted(_G
) then
400 self
:TextOut(QHFormat("NAG_POLLUTED"))
401 self
:Purge(nil, true, true)
404 local signature
= expected_version
.. " on " .. GetBuildInfo()
405 QuestHelper_Quests
[signature
] = QuestHelper_Quests
[signature
] or {}
406 QuestHelper_Objectives
[signature
] = QuestHelper_Objectives
[signature
] or {}
407 QuestHelper_FlightInstructors
[signature
] = QuestHelper_FlightInstructors
[signature
] or {}
408 QuestHelper_FlightRoutes
[signature
] = QuestHelper_FlightRoutes
[signature
] or {}
410 QuestHelper_Quests_Local
= QuestHelper_Quests
[signature
]
411 QuestHelper_Objectives_Local
= QuestHelper_Objectives
[signature
]
412 QuestHelper_FlightInstructors_Local
= QuestHelper_FlightInstructors
[signature
]
413 QuestHelper_FlightRoutes_Local
= QuestHelper_FlightRoutes
[signature
]
415 QuestHelper_SeenRealms
[GetRealmName()] = true -- some attempt at tracking private servers
420 self
.player_level
= UnitLevel("player")
422 self
:SetLocaleFonts()
424 if QuestHelper_Pref
.share
and not QuestHelper_Pref
.solo
then
428 if QuestHelper_Pref
.hide
then
429 self
.map_overlay
:Hide()
432 self
:HandlePartyChange()
436 for locale
in pairs(QuestHelper_StaticData
) do
437 if locale
~= self
.locale
then
438 -- Will delete references to locales you don't use.
439 QuestHelper_StaticData
[locale
] = nil
440 _G
["QuestHelper_StaticData_" .. locale
] = nil
444 local static
= QuestHelper_StaticData
[self
.locale
]
447 if static
.flight_instructors
then for faction
in pairs(static
.flight_instructors
) do
448 if faction
~= self
.faction
then
449 -- Will delete references to flight instructors that don't belong to your faction.
450 static
.flight_instructors
[faction
] = nil
454 if static
.quest
then for faction
in pairs(static
.quest
) do
455 if faction
~= self
.faction
then
456 -- Will delete references to quests that don't belong to your faction.
457 static
.quest
[faction
] = nil
462 -- Adding QuestHelper_CharVersion, so I know if I've already converted this characters saved data.
463 if not QuestHelper_CharVersion
then
464 -- Changing per-character flight routes, now only storing the flight points they have,
465 -- will attempt to guess the routes from this.
468 for i
, l
in pairs(QuestHelper_KnownFlightRoutes
) do
469 for key
in pairs(l
) do
474 QuestHelper_KnownFlightRoutes
= routes
476 -- Deleting the player's home again.
477 -- But using the new CharVersion variable I'm adding is cleaner that what I was doing, so I'll go with it.
478 QuestHelper_Home
= nil
479 QuestHelper_CharVersion
= 1
482 if not QuestHelper_Home
then
483 -- Not going to bother complaining about the player's home not being set, uncomment this when the home is used in routing.
484 -- self:TextOut(QHText("HOME_NOT_KNOWN"))
487 if QuestHelper_Pref
.map_button
then
488 QuestHelper
:InitMapButton()
491 if QuestHelper_Pref
.cart_wp_new
then
492 init_cartographer_later
= true
495 if QuestHelper_Pref
.tomtom_wp_new
then
499 self
.tracker
:SetScale(QuestHelper_Pref
.track_scale
)
501 if QuestHelper_Pref
.track
and not QuestHelper_Pref
.hide
then
505 local version
= GetAddOnMetadata("QuestHelper", "Version") or "Unknown"
507 local major
, minor
= (version_string
or ""):match("^(%d+)%.(%d+)")
508 major
, minor
= tonumber(major
), tonumber(minor
)
510 -- For versions before 0.82, we're changing the default level offset to 3.
511 if major
== 0 and minor
and minor
< 82 and QuestHelper_Pref
.level
== 2 then
512 QuestHelper_Pref
.level
= nil
515 -- For versions before 0.84...
516 if major
== 0 and minor
and minor
< 84 then
517 -- remove all keys that match their default setting.
518 for key
, val
in pairs(QuestHelper_DefaultPref
) do
519 if QuestHelper_Pref
[key
] == val
then
520 QuestHelper_Pref
[key
] = nil
525 QH_Hook(self
, "OnUpdate", self
.OnUpdate
)
527 -- Seems to do its own garbage collection pass before fully loading, so I'll just rely on that
528 --collectgarbage("collect") -- Free everything we aren't using.
531 if self.debug_objectives then
532 for name, data in pairs(self.debug_objectives) do
533 self:LoadDebugObjective(name, data)
539 QH_Arrow_SetTextScale()
542 QH_Timeslice_Add(function ()
544 self.Routing:Initialize() -- Set up the routing task
545 end, "init")]] -- FUCK YOU BOXBOT
547 --[[ -- This is just an example of how the WoW profiler biases its profiles heavily.
553 for x = 0, 130000000, 1 do
559 for x = 0, 12000000, 1 do
566 for x = 0, 1200000, 1 do
574 local ta = debugprofilestop()
576 local tb = debugprofilestop()
578 local tc = debugprofilestop()
580 QuestHelper:TextOut(string.format("%d %d %d", ta, tb - ta, tc - tb))
581 QuestHelper:TextOut(string.format("%d %d", GetFunctionCPUUsage(A), GetFunctionCPUUsage(B)))
583 --/script SetCVar("scriptProfile", value)]]
585 LibStub("LibAboutPanelQH").new(nil, "QuestHelper")
587 QuestHelper_Loadtime
["init_end"] = GetTime()
589 QuestHelper
.loading_main
= QuestHelper
.CreateLoadingCounter()
591 QuestHelper
.loading_flightpath
= QuestHelper
.loading_main
:MakeSubcategory(1)
592 QuestHelper
.loading_preroll
= QuestHelper
.loading_main
:MakeSubcategory(1)
594 QH_Event("CHAT_MSG_ADDON", function (...)
595 if arg1
== "QHpr" and arg4
~= UnitName("player") then
596 QH_Questcomm_Msg(arg2
, arg4
)
600 QH_Event({"PARTY_MEMBERS_CHANGED", "UNIT_LEVEL", "RAID_ROSTER_UPDATE"}, function ()
601 QH_Filter_Group_Sync()
602 QH_Route_Filter_Rescan("filter_quest_level")
603 QH_Route_Filter_Rescan("filter_quest_group")
606 QH_Event({"PARTY_MEMBERS_CHANGED", "RAID_ROSTER_UPDATE"}, function ()
610 QH_Event("PLAYER_LEVEL_UP", function ()
611 self
.player_level
= arg1
612 QH_Route_Filter_Rescan("filter_quest_level")
615 QH_Event("TAXIMAP_OPENED", function ()
619 QH_Event({"ZONE_CHANGED", "ZONE_CHANGED_INDOORS", "ZONE_CHANGED_NEW_AREA"}, function()
620 QH_Route_Filter_Rescan()
626 local please_donate_enabled
= false
627 local please_donate_initted
= false
630 function QuestHelper
:OnEvent(event
)
631 local tstart
= GetTime()
634 if event == "GOSSIP_SHOW" then
635 local name, id = UnitName("npc"), self:GetUnitID("npc")
637 self:GetObjective("monster", name).o.id = id
638 --self:TextOut("NPC: "..name.." = "..id)
642 --[[if event == "PLAYER_TARGET_CHANGED" then
643 local name, id = UnitName("target"), self:GetUnitID("target")
645 self:GetObjective("monster", name).o.id = id
646 --self:TextOut("Target: "..name.." = "..id)
649 if UnitExists("target") and UnitIsVisible("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
650 local index, x, y = self:UnitPosition("target")
652 if index then -- Might not have a position if inside an instance.
655 -- Modify the weight based on how far they are from us.
656 -- We don't know the exact location (using our own location), so the farther, the less sure we are that it's correct.
657 if CheckInteractDistance("target", 3) then w = 1
658 elseif CheckInteractDistance("target", 2) then w = 0.89
659 elseif CheckInteractDistance("target", 1) or CheckInteractDistance("target", 4) then w = 0.33 end
661 local monster_objective = self:GetObjective("monster", UnitName("target"))
662 self:AppendObjectivePosition(monster_objective, index, x, y, w)
664 monster_objective.o.faction = (UnitFactionGroup("target") == "Alliance" and 1) or
665 (UnitFactionGroup("target") == "Horde" and 2) or nil
667 local level = UnitLevel("target")
668 if level and level >= 1 then
669 local w = monster_objective.o.levelw or 0
670 monster_objective.o.level = ((monster_objective.o.level or 0)*w+level)/(w+1)
671 monster_objective.o.levelw = w+1
677 --[[if event == "LOOT_OPENED" then
678 local target = UnitName("target")
679 if target and UnitIsDead("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
680 local index, x, y = self:UnitPosition("target")
682 local monster_objective = self:GetObjective("monster", target)
683 monster_objective.o.looted = (monster_objective.o.looted or 0) + 1
685 if index then -- Might not have a position if inside an instance.
686 self:AppendObjectivePosition(monster_objective, index, x, y)
689 for i = 1, GetNumLootItems() do
690 local icon, name, number, rarity = GetLootSlotInfo(i)
692 if number and number >= 1 then
693 self:AppendItemObjectiveDrop(self:GetObjective("item", name), name, target, number)
695 local total = (name:match(COPPER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) +
696 (name:match(SILVER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 100 +
697 (name:match(GOLD_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 10000
700 self:AppendObjectiveDrop(self:GetObjective("item", "money"), target, total)
706 local container = nil
708 -- Go through the players inventory and look for a locked item, we're probably looting it.
709 for bag = 0,NUM_BAG_SLOTS do
710 for slot = 1,GetContainerNumSlots(bag) do
711 local link = GetContainerItemLink(bag, slot)
712 if link and select(3, GetContainerItemInfo(bag, slot)) then
713 if container == nil then
714 -- Found a locked item and haven't previously assigned to container, assign its name, or false if we fail to parse it.
715 container = select(3, string.find(link, "|h%[(.+)%]|h|r")) or false
717 -- Already tried to assign to a container. If there are multiple locked items, we give up.
725 local container_objective = self:GetObjective("item", container)
726 container_objective.o.opened = (container_objective.o.opened or 0) + 1
728 for i = 1, GetNumLootItems() do
729 local icon, name, number, rarity = GetLootSlotInfo(i)
730 if name and number >= 1 then
731 self:AppendItemObjectiveContainer(self:GetObjective("item", name), container, number)
735 -- No idea where the items came from.
736 local index, x, y = self:PlayerPosition()
739 for i = 1, GetNumLootItems() do
740 local icon, name, number, rarity = GetLootSlotInfo(i)
741 if name and number >= 1 then
742 self:AppendItemObjectivePosition(self:GetObjective("item", name), name, index, x, y)
750 --[[if event == "CHAT_MSG_SYSTEM" then
751 local home_name = self:convertPattern(ERR_DEATHBIND_SUCCESS_S)(arg1)
754 self:TextOut(QHText("HOME_CHANGED"))
755 self:TextOut(QHText("WILL_RESET_PATH"))
757 local home = QuestHelper_Home
760 QuestHelper_Home = home
763 home[1], home[2], home[3], home[4] = self.i, self.x, self.y, home_name
764 self.defered_graph_reset = true
772 --[[if event == "QUEST_DETAIL" then
773 if not self.quest_giver then self.quest_giver = {} end
774 local npc = UnitName("npc")
776 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
777 local index, x, y = self:UnitPosition("npc")
779 if index then -- Might not have a position if inside an instance.
780 local npc_objective = self:GetObjective("monster", npc)
781 self:AppendObjectivePosition(npc_objective, index, x, y)
782 self.quest_giver[GetTitleText()] = npc
787 --[[if event == "QUEST_COMPLETE" or event == "QUEST_PROGRESS" then
788 local quest = GetTitleText()
790 local level, hash = self:GetQuestLevel(quest)
791 if not level or level < 1 then
792 --self:TextOut("Don't know quest level for ".. quest.."!")
795 local q = self:GetQuest(quest, level, hash)
801 local unit = UnitName("npc")
806 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
807 local index, x, y = self:UnitPosition("npc")
808 if index then -- Might not have a position if inside an instance.
809 local npc_objective = self:GetObjective("monster", unit)
810 self:AppendObjectivePosition(npc_objective, index, x, y)
812 elseif not q.o.finish then
813 local index, x, y = self:PlayerPosition()
814 if index then -- Might not have a position if inside an instance.
815 self:AppendObjectivePosition(q, index, x, y)
821 --[[if event == "MERCHANT_SHOW" then
822 local npc_name = UnitName("npc")
824 local npc_objective = self:GetObjective("monster", npc_name)
827 local item_name = GetMerchantItemInfo(index)
830 local item_objective = self:GetObjective("item", item_name)
831 if not item_objective.o.vendor then
832 item_objective.o.vendor = {npc_name}
835 for i, vendor in ipairs(item_objective.o.vendor) do
836 if npc_name == vendor then
842 table.insert(item_objective.o.vendor, npc_name)
852 if event
== "TAXIMAP_OPENED" then
856 --[[if event == "PLAYER_CONTROL_GAINED" then
857 interruptcount = interruptcount + 1
860 --[[if event == "BAG_UPDATE" then
861 for slot = 1,GetContainerNumSlots(arg1) do
862 local link = GetContainerItemLink(arg1, slot)
864 local id, name = select(3, string.find(link, "|Hitem:(%d+):.-|h%[(.-)%]|h"))
866 self:GetObjective("item", name).o.id = tonumber(id)
872 if event
== "CHAT_MSG_CHANNEL_NOTICE" and please_donate_enabled
and not please_donate_initted
then
873 please_donate_enabled
= QHNagInit()
874 startup_time
= GetTime()
875 please_donate_initted
= true
880 if event
== "ZONE_CHANGED" or event
== "ZONE_CHANGED_INDOORS" or event
== "ZONE_CHANGED_NEW_AREA" then
881 QH_Route_Filter_Rescan()
884 QH_Timeslice_Increment(GetTime() - tstart
, "event")
887 local map_shown_decay
= 0
888 local delayed_action
= 100
889 --local update_count = 0
893 QH_OnUpdate_High(function ()
894 local self
= QuestHelper
-- hoorj
895 local tstart
= GetTime()
898 if not QuestHelper_Loadtime
["onupdate"] then QuestHelper_Loadtime
["onupdate"] = GetTime() end
900 if false and frams
== 60 then
902 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
904 Known bugs and issues include:
906 |cff40bbffNo support for "/qh find"|r
908 |cff40bbffNo support for in-party quest synchronization|r
910 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.
912 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.
914 Thanks for testing!]], "QuestHelper " .. version_string
, 500, 20, 10)
917 if frams
== 250 then please_donate_enabled
= false end -- TOOK TOO LONG >:(
918 if please_donate_enabled
and startup_time
and startup_time
+ 1 < GetTime() then
919 QuestHelper
:TextOut(QHText("PLEASE_DONATE"))
921 please_donate_enabled
= false
923 QHUpdateNagTick() -- These probably shouldn't be in OnUpdate. Eventually I'll move them somewhere cleaner.
925 if init_cartographer_later
and Cartographer_Waypoints
then -- there has to be a better way to do this
926 init_cartographer_later
= false
927 if QuestHelper_Pref
.cart_wp_new
then
928 self
:EnableCartographer()
932 if not ontaxi
and UnitOnTaxi("player") then
935 elseif ontaxi
and not UnitOnTaxi("player") then
936 self
:flightEnded(interruptcount
> 1)
938 ontaxi
= UnitOnTaxi("player")
940 -- For now I'm ripping out the update_count code
941 --update_count = update_count - 1
942 --if update_count <= 0 then
944 -- Reset the update count for next time around; this will make sure the body executes every time
945 -- when perf_scale_2 >= 1, and down to 1 in 10 iterations when perf_scale_2 < 1, or when hidden.
946 --update_count = update_count + (QuestHelper_Pref.hide and 10 or 1/QuestHelper_Pref.perf_scale_2)
948 --if update_count < 0 then
949 -- Make sure the count doesn't go perpetually negative; don't know what will happen if it underflows.
953 if self
.Astrolabe
.WorldMapVisible
then
954 -- We won't trust that the zone returned by Astrolabe is correct until map_shown_decay is 0.
956 elseif map_shown_decay
> 0 then
957 map_shown_decay
= map_shown_decay
- 1
959 --SetMapToCurrentZone() -- not sure why this existed
962 --[[delayed_action = delayed_action - 1
963 if delayed_action <= 0 then
965 self:HandlePartyChange()
968 local nc
, nz
, nx
, ny
= self
.Astrolabe
:GetCurrentPlayerPosition()
971 if nc
and nc
~= -1 then -- We just want the raw data here, before we've done anything clever.
972 tc
, tx
, ty
= self
.Astrolabe
:GetAbsoluteContinentPosition(nc
, nz
, nx
, ny
)
973 QuestHelper
: Assert(tc
and tx
and ty
) -- is it true? nobody knows! :D
976 if nc
and nc
== self
.c
and map_shown_decay
> 0 and self
.z
> 0 and self
.z
~= nz
then
977 -- There's a chance Astrolable will return the wrong zone if you're messing with the world map, if you can
978 -- be seen in that zone but aren't in it.
979 local nnx
, nny
= self
.Astrolabe
:TranslateWorldMapPosition(nc
, nz
, nx
, ny
, nc
, self
.z
)
980 if nnx
> 0 and nny
> 0 and nnx
< 1 and nny
< 1 then
981 nz
, nx
, ny
= self
.z
, nnx
, nny
985 if nc
and nc
> 0 and nz
== 0 and nc
== self
.c
and self
.z
> 0 then
986 nx
, ny
= self
.Astrolabe
:TranslateWorldMapPosition(nc
, nz
, nx
, ny
, nc
, self
.z
)
987 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
990 nc
, nz
, nx
, ny
= nil, nil, nil, nil
994 if nc
and nz
> 0 then
995 self
.c
, self
.z
, self
.x
, self
.y
= nc
, nz
, nx
, ny
996 local upd_zone
= false
997 if self
.i
~= QuestHelper_IndexLookup
[nc
][nz
] then upd_zone
= true end
998 self
.i
= QuestHelper_IndexLookup
[nc
][nz
]
999 if upd_zone
then QH_Route_Filter_Rescan("filter_zone") end
1002 if nc
and nz
and nx
and ny
and tc
and tx
and ty
then
1003 self
.collect_rc
, self
.collect_rz
, self
.collect_rx
, self
.collect_ry
= nc
, nz
, nx
, ny
1004 self
.collect_ac
, self
.collect_ax
, self
.collect_ay
= tc
, tx
, ty
1005 self
.collect_delayed
= false
1007 local ibi
= self
.InBrokenInstance
1008 if nc
< -77 then self
.InBrokenInstance
= true else self
.InBrokenInstance
= false end
1010 if ibi
and not self
.InBrokenInstance
then self
.minimap_marker
:OnUpdate(0) end -- poke
1012 self
.collect_delayed
= true
1013 self
.InBrokenInstance
= true
1016 if not UnitOnTaxi("player") and not UnitIsDeadOrGhost("player") then
1017 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
1020 QH_Timeslice_Toggle("routing", not not self
.c
)
1022 self
:PumpCommMessages()
1026 -- 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.
1027 -- 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?
1028 function QuestHelper
:Location_RawRetrieve()
1029 return self
.collect_delayed
, self
.collect_rc
, self
.collect_rz
, self
.collect_rx
, self
.collect_ry
1031 function QuestHelper
:Location_AbsoluteRetrieve()
1032 return self
.collect_delayed
, self
.collect_ac
, self
.collect_ax
, self
.collect_ay
1035 --QH_Hook(QuestHelper, "OnEvent", QuestHelper.OnEvent)