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
26 track_minimized
=false,
38 tomtom_wp_new
= false,
44 locale
= GetLocale(), -- This variable is used for display purposes, and has nothing to do with the collected data.
45 perf_scale
= 1, -- How much background processing can the current machine handle? Higher means more load, lower means better performance.
46 perfload_scale
= 1, -- Performance scale to use on startup
50 -- 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.
51 setmetatable(QuestHelper_Pref
, {__index
=QuestHelper_DefaultPref
})
53 QuestHelper_FlightInstructors
= {}
54 QuestHelper_FlightLinks
= {}
55 QuestHelper_FlightRoutes
= {}
56 QuestHelper_KnownFlightRoutes
= {}
57 QuestHelper_SeenRealms
= {}
59 QuestHelper
.tooltip
= CreateFrame("GameTooltip", "QuestHelperTooltip", nil, "GameTooltipTemplate")
60 QuestHelper
.objective_objects
= {}
61 QuestHelper
.user_objectives
= {}
62 QuestHelper
.quest_objects
= {}
63 QuestHelper
.player_level
= 1
64 QuestHelper
.locale
= QuestHelper_Locale
66 QuestHelper
.faction
= (UnitFactionGroup("player") == "Alliance" and 1) or
67 (UnitFactionGroup("player") == "Horde" and 2)
69 assert(QuestHelper
.faction
)
71 QuestHelper
.font
= {serif
=GameFontNormal
:GetFont(), sans
=ChatFontNormal
:GetFont(), fancy
=QuestTitleFont
:GetFont()}
73 function QuestHelper
:GetFontPath(list_string
, font
)
75 for name
in string.gmatch(list_string
, "[^;]+") do
76 if font
:SetFont(name
, 10) then
78 elseif font
:SetFont("Interface\\AddOns\\QuestHelper\\Fonts\\"..name
, 10) then
79 return "Interface\\AddOns\\QuestHelper\\Fonts\\"..name
85 function QuestHelper
:SetLocaleFonts()
90 local font
= self
:CreateText(self
)
92 if QuestHelper_Locale
~= QuestHelper_Pref
.locale
then
93 -- Only use alternate fonts if using a language the client wasn't intended for.
94 local replacements
= QuestHelper_SubstituteFonts
[QuestHelper_Pref
.locale
]
96 self
.font
.sans
= self
:GetFontPath(replacements
.sans
, font
)
97 self
.font
.serif
= self
:GetFontPath(replacements
.serif
, font
)
98 self
.font
.fancy
= self
:GetFontPath(replacements
.fancy
, font
)
102 self
.font
.sans
= self
.font
.sans
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_sans.ttf", font
)
103 self
.font
.serif
= self
.font
.serif
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_serif.ttf", font
) or self
.font
.sans
104 self
.font
.fancy
= self
.font
.fancy
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_fancy.ttf", font
) or self
.font
.serif
106 self
:ReleaseText(font
)
108 self
.font
.sans
= self
.font
.sans
or ChatFontNormal
:GetFont()
109 self
.font
.serif
= self
.font
.serif
or GameFontNormal
:GetFont()
110 self
.font
.fancy
= self
.font
.fancy
or QuestTitleFont
:GetFont()
112 -- Need to change the font of the chat frame, for any messages that QuestHelper displays.
113 -- This should do nothing if not using an alternate font.
114 DEFAULT_CHAT_FRAME
:SetFont(self
.font
.sans
, select(2, DEFAULT_CHAT_FRAME
:GetFont()))
117 QuestHelper
.route
= {}
118 QuestHelper
.to_add
= {}
119 QuestHelper
.to_remove
= {}
120 QuestHelper
.quest_log
= {}
121 QuestHelper
.pos
= {nil, {}, 0, 0, 1, "You are here.", 0}
122 QuestHelper
.sharing
= false -- Will be set to true when sharing with at least one user.
124 function QuestHelper
.tooltip
:GetPrevLines() -- Just a helper to make life easier.
125 local last
= self
:NumLines()
126 local name
= self
:GetName()
127 return _G
[name
.."TextLeft"..last
], _G
[name
.."TextRight"..last
]
130 function QuestHelper
:SetTargetLocation(i
, x
, y
, toffset
)
131 -- Informs QuestHelper that you're going to be at some location in toffset seconds.
132 local c
, z
= unpack(QuestHelper_ZoneLookup
[i
])
134 self
.target
= self
:CreateTable()
135 self
.target
[2] = self
:CreateTable()
137 self
.target_time
= time()+(toffset
or 0)
139 x
, y
= self
.Astrolabe
:TranslateWorldMapPosition(c
, z
, x
, y
, c
, 0)
140 self
.target
[1] = self
.zone_nodes
[i
]
141 self
.target
[3] = x
* self
.continent_scales_x
[c
]
142 self
.target
[4] = y
* self
.continent_scales_y
[c
]
144 self
:SetTargetLocationRecalculate()
147 function QuestHelper
:SetTargetLocationRecalculate()
149 for i
, n
in ipairs(self
.target
[1]) do
150 local a
, b
= n
.x
-self
.target
[3], n
.y
-self
.target
[4]
151 self
.target
[2][i
] = math
.sqrt(a
*a
+b
*b
)
156 function QuestHelper
:UnsetTargetLocation()
157 -- Unsets the target set above.
159 self
:ReleaseTable(self
.target
[2])
160 self
:ReleaseTable(self
.target
)
162 self
.target_time
= nil
166 local interruptcount
= 0 -- counts how many "played gained control" messages we recieve, used for flight paths
167 local init_cartographer_later
= false
169 function QuestHelper
:Initialize()
170 QuestHelper_Loadtime
["init_start"] = GetTime()
172 -- Use DefaultPref as fallback for unset preference keys.
173 setmetatable(QuestHelper_Pref
, {__index
=QuestHelper_DefaultPref
})
175 local file_problem
= false
176 local expected_version
= GetAddOnMetadata("QuestHelper", "Version")
178 local expected_files
=
180 ["bst_pre.lua"] = true,
181 ["bst_post.lua"] = true,
182 ["bst_astrolabe.lua"] = true,
183 ["bst_ctl.lua"] = true,
184 ["bst_libaboutpanel.lua"] = true,
186 ["manager_event.lua"] = true,
188 ["upgrade.lua"] = true,
190 ["recycle.lua"] = true,
191 ["objective.lua"] = true,
192 ["quest.lua"] = true,
193 ["questlog.lua"] = true,
194 ["utility.lua"] = true,
195 ["dodads.lua"] = true,
196 ["graph.lua"] = true,
197 ["teleport.lua"] = true,
198 ["pathfinding.lua"] = true,
199 ["routing.lua"] = true,
200 ["custom.lua"] = true,
202 ["hidden.lua"] = true,
205 ["mapbutton.lua"] = true,
207 ["pattern.lua"] = true,
208 ["flightpath.lua"] = true,
209 ["tracker.lua"] = true,
210 ["objtips.lua"] = true,
211 ["cartographer.lua"] = true,
212 ["tomtom.lua"] = true,
213 ["textviewer.lua"] = true,
214 ["error.lua"] = true,
215 ["timeslice.lua"] = true,
218 ["tooltip.lua"] = true,
219 ["arrow.lua"] = true,
221 ["static.lua"] = true,
222 ["static_1.lua"] = true,
223 ["static_2.lua"] = true,
224 ["static_deDE.lua"] = true,
225 ["static_deDE_1.lua"] = true,
226 ["static_deDE_2.lua"] = true,
227 ["static_enUS.lua"] = true,
228 ["static_enUS_1.lua"] = true,
229 ["static_enUS_2.lua"] = true,
230 ["static_esES.lua"] = true,
231 ["static_esES_1.lua"] = true,
232 ["static_esES_2.lua"] = true,
233 ["static_frFR.lua"] = true,
234 ["static_frFR_1.lua"] = true,
235 ["static_frFR_2.lua"] = true,
236 ["static_koKR.lua"] = true,
237 ["static_koKR_1.lua"] = true,
238 ["static_koKR_2.lua"] = true,
239 ["static_ruRU.lua"] = true,
240 ["static_ruRU_1.lua"] = true,
241 ["static_ruRU_2.lua"] = true,
242 ["static_zhTW.lua"] = true,
243 ["static_zhTW_1.lua"] = true,
244 ["static_zhTW_2.lua"] = true,
246 ["collect.lua"] = true,
247 ["collect_achievement.lua"] = true,
248 ["collect_lzw.lua"] = true,
249 ["collect_traveled.lua"] = true,
250 ["collect_zone.lua"] = true,
251 ["collect_location.lua"] = true,
252 ["collect_merger.lua"] = true,
253 ["collect_monster.lua"] = true,
254 ["collect_item.lua"] = true,
255 ["collect_object.lua"] = true,
256 ["collect_loot.lua"] = true,
257 ["collect_patterns.lua"] = true,
258 ["collect_flight.lua"] = true,
259 ["collect_util.lua"] = true,
260 ["collect_quest.lua"] = true,
261 ["collect_equip.lua"] = true,
262 ["collect_notifier.lua"] = true,
263 ["collect_bitstream.lua"] = true,
264 ["collect_spec.lua"] = true,
265 ["collect_upgrade.lua"] = true,
266 ["collect_merchant.lua"] = true,
267 ["collect_warp.lua"] = true,
269 ["filter_core.lua"] = true,
270 ["filter_base.lua"] = true,
272 ["routing_debug.lua"] = true,
273 ["routing_loc.lua"] = true,
274 ["routing_route.lua"] = true,
275 ["routing_core.lua"] = true,
276 ["routing_controller.lua"] = true,
277 ["routing_hidden.lua"] = true,
279 ["director_quest.lua"] = true,
281 ["db_get.lua"] = true,
283 ["graph_core.lua"] = true,
284 ["graph_flightpath.lua"] = true,
287 local uninstallederr
= ""
289 for file
, version
in pairs(QuestHelper_File
) do
290 if not expected_files
[file
] then
291 local errmsg
= "Unexpected QuestHelper file: "..file
292 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
293 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
295 elseif version
~= expected_version
then
296 local errmsg
= "Wrong version of QuestHelper file: "..file
.." (found '"..version
.."', should be '"..expected_version
.."')"
297 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
298 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
299 if version
~= "Development Version" and expected_version
~= "Development Version" then
300 -- Developers are allowed to mix dev versions with release versions
306 for file
in pairs(expected_files
) do
307 if not QuestHelper_File
[file
] then
308 local errmsg
= "Missing QuestHelper file: "..file
309 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
310 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
311 if not (expected_version
== "Development Version" and file
:match("static.*")) then file_problem
= true end
315 -- Don't need this table anymore.
316 QuestHelper_File
= nil
318 if QuestHelper_StaticData
and not QuestHelper_StaticData
[GetLocale()] then
319 local errmsg
= "Static data does not seem to exist"
320 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
322 -- TODO: Are you sure this should be an error? Shouldn't we let people we don't have data for collect their own?
323 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
328 message(QHText("PLEASE_RESTART"))
329 QuestHelper_ErrorCatcher_ExplicitError(true, "not-installed-properly" .. "\n" .. uninstallederr
)
330 QuestHelper
= nil -- Just in case anybody else is checking for us, we're not home
334 if not GetCategoryList
or not GetQuestLogSpecialItemInfo
or not WatchFrame_RemoveObjectiveHandler
then
335 message(QHText("PRIVATE_SERVER"))
336 QuestHelper_ErrorCatcher_ExplicitError(true, "error id cakbep ten T")
341 if not DongleStub
then
342 message(QHText("NOT_UNZIPPED_CORRECTLY"))
343 QuestHelper_ErrorCatcher_ExplicitError(true, "not-unzipped-properly")
344 QuestHelper
= nil -- Just in case anybody else is checking for us, we're not home
348 QuestHelper_ErrorCatcher_CompletelyStarted()
350 if not QuestHelper_StaticData
then
351 -- If there is no static data for some mysterious reason, create an empty table so that
352 -- other parts of the code can carry on as usual, using locally collected data if it exists.
353 QuestHelper_StaticData
= {}
356 QHFormatSetLocale(QuestHelper_Pref
.locale
or GetLocale())
358 if not QuestHelper_UID
then
359 QuestHelper_UID
= self
:CreateUID()
361 QuestHelper_SaveDate
= time()
363 QuestHelper_BuildZoneLookup()
367 if QuestHelper_Locale
~= GetLocale() then
368 self
:TextOut(QHText("LOCALE_ERROR"))
372 if not self
:ZoneSanity() then
373 self
:TextOut(QHText("ZONE_LAYOUT_ERROR"))
374 message("QuestHelper: "..QHText("ZONE_LAYOUT_ERROR"))
378 QuestHelper_UpgradeDatabase(_G
)
379 QuestHelper_UpgradeComplete()
381 if QuestHelper_SaveVersion
~= 10 then
382 self
:TextOut(QHText("DOWNGRADE_ERROR"))
386 if QuestHelper_IsPolluted(_G
) then
387 self
:TextOut(QHFormat("NAG_POLLUTED"))
388 self
:Purge(nil, true, true)
391 local signature
= expected_version
.. " on " .. GetBuildInfo()
392 QuestHelper_Quests
[signature
] = QuestHelper_Quests
[signature
] or {}
393 QuestHelper_Objectives
[signature
] = QuestHelper_Objectives
[signature
] or {}
394 QuestHelper_FlightInstructors
[signature
] = QuestHelper_FlightInstructors
[signature
] or {}
395 QuestHelper_FlightRoutes
[signature
] = QuestHelper_FlightRoutes
[signature
] or {}
397 QuestHelper_Quests_Local
= QuestHelper_Quests
[signature
]
398 QuestHelper_Objectives_Local
= QuestHelper_Objectives
[signature
]
399 QuestHelper_FlightInstructors_Local
= QuestHelper_FlightInstructors
[signature
]
400 QuestHelper_FlightRoutes_Local
= QuestHelper_FlightRoutes
[signature
]
402 QuestHelper_SeenRealms
[GetRealmName()] = true -- some attempt at tracking private servers
407 self
.player_level
= UnitLevel("player")
409 self
:UnregisterEvent("VARIABLES_LOADED")
410 self
:RegisterEvent("PLAYER_TARGET_CHANGED")
411 self
:RegisterEvent("LOOT_OPENED")
412 self
:RegisterEvent("QUEST_COMPLETE")
413 self
:RegisterEvent("QUEST_LOG_UPDATE")
414 self
:RegisterEvent("QUEST_PROGRESS")
415 self
:RegisterEvent("MERCHANT_SHOW")
416 self
:RegisterEvent("QUEST_DETAIL")
417 self
:RegisterEvent("TAXIMAP_OPENED")
418 self
:RegisterEvent("PLAYER_CONTROL_GAINED")
419 self
:RegisterEvent("PLAYER_LEVEL_UP")
420 self
:RegisterEvent("PARTY_MEMBERS_CHANGED")
421 self
:RegisterEvent("CHAT_MSG_ADDON")
422 self
:RegisterEvent("CHAT_MSG_SYSTEM")
423 self
:RegisterEvent("BAG_UPDATE")
424 self
:RegisterEvent("GOSSIP_SHOW")
425 self
:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE")
426 self
:RegisterEvent("UNIT_LEVEL")
427 self
:RegisterEvent("ZONE_CHANGED")
428 self
:RegisterEvent("ZONE_CHANGED_INDOORS")
429 self
:RegisterEvent("ZONE_CHANGED_NEW_AREA")
431 self
:SetLocaleFonts()
433 if QuestHelper_Pref
.share
and not QuestHelper_Pref
.solo
then
437 if QuestHelper_Pref
.hide
then
438 self
.map_overlay
:Hide()
441 self
:HandlePartyChange()
445 for locale
in pairs(QuestHelper_StaticData
) do
446 if locale
~= self
.locale
then
447 -- Will delete references to locales you don't use.
448 QuestHelper_StaticData
[locale
] = nil
449 _G
["QuestHelper_StaticData_" .. locale
] = nil
453 local static
= QuestHelper_StaticData
[self
.locale
]
456 if static
.flight_instructors
then for faction
in pairs(static
.flight_instructors
) do
457 if faction
~= self
.faction
then
458 -- Will delete references to flight instructors that don't belong to your faction.
459 static
.flight_instructors
[faction
] = nil
463 if static
.quest
then for faction
in pairs(static
.quest
) do
464 if faction
~= self
.faction
then
465 -- Will delete references to quests that don't belong to your faction.
466 static
.quest
[faction
] = nil
471 -- Adding QuestHelper_CharVersion, so I know if I've already converted this characters saved data.
472 if not QuestHelper_CharVersion
then
473 -- Changing per-character flight routes, now only storing the flight points they have,
474 -- will attempt to guess the routes from this.
477 for i
, l
in pairs(QuestHelper_KnownFlightRoutes
) do
478 for key
in pairs(l
) do
483 QuestHelper_KnownFlightRoutes
= routes
485 -- Deleting the player's home again.
486 -- But using the new CharVersion variable I'm adding is cleaner that what I was doing, so I'll go with it.
487 QuestHelper_Home
= nil
488 QuestHelper_CharVersion
= 1
491 if not QuestHelper_Home
then
492 -- Not going to bother complaining about the player's home not being set, uncomment this when the home is used in routing.
493 -- self:TextOut(QHText("HOME_NOT_KNOWN"))
496 if QuestHelper_Pref
.map_button
then
497 QuestHelper
:InitMapButton()
500 if QuestHelper_Pref
.cart_wp_new
then
501 init_cartographer_later
= true
504 if QuestHelper_Pref
.tomtom_wp_new
then
508 self
.tracker
:SetScale(QuestHelper_Pref
.track_scale
)
510 if QuestHelper_Pref
.track
and not QuestHelper_Pref
.hide
then
514 local version
= GetAddOnMetadata("QuestHelper", "Version") or "Unknown"
516 local major
, minor
= (version_string
or ""):match("^(%d+)%.(%d+)")
517 major
, minor
= tonumber(major
), tonumber(minor
)
519 -- For versions before 0.82, we're changing the default level offset to 3.
520 if major
== 0 and minor
and minor
< 82 and QuestHelper_Pref
.level
== 2 then
521 QuestHelper_Pref
.level
= nil
524 -- For versions before 0.84...
525 if major
== 0 and minor
and minor
< 84 then
526 -- remove all keys that match their default setting.
527 for key
, val
in pairs(QuestHelper_DefaultPref
) do
528 if QuestHelper_Pref
[key
] == val
then
529 QuestHelper_Pref
[key
] = nil
534 self
:SetScript("OnUpdate", self
.OnUpdate
)
536 -- Seems to do its own garbage collection pass before fully loading, so I'll just rely on that
537 --collectgarbage("collect") -- Free everything we aren't using.
540 if self.debug_objectives then
541 for name, data in pairs(self.debug_objectives) do
542 self:LoadDebugObjective(name, data)
548 QH_Arrow_SetTextScale()
551 QH_Timeslice_Add(function ()
553 self.Routing:Initialize() -- Set up the routing task
554 end, "init")]] -- FUCK YOU BOXBOT
556 --[[ -- This is just an example of how the WoW profiler biases its profiles heavily.
562 for x = 0, 130000000, 1 do
568 for x = 0, 12000000, 1 do
575 for x = 0, 1200000, 1 do
583 local ta = debugprofilestop()
585 local tb = debugprofilestop()
587 local tc = debugprofilestop()
589 QuestHelper:TextOut(string.format("%d %d %d", ta, tb - ta, tc - tb))
590 QuestHelper:TextOut(string.format("%d %d", GetFunctionCPUUsage(A), GetFunctionCPUUsage(B)))
592 --/script SetCVar("scriptProfile", value)]]
594 LibStub("LibAboutPanelQH").new(nil, "QuestHelper")
596 QuestHelper_Loadtime
["init_end"] = GetTime()
598 QuestHelper
.loading_main
= QuestHelper
.CreateLoadingCounter()
600 QuestHelper
.loading_flightpath
= QuestHelper
.loading_main
:MakeSubcategory(1)
601 QuestHelper
.loading_preroll
= QuestHelper
.loading_main
:MakeSubcategory(1)
605 local please_donate_enabled
= false
606 local please_donate_initted
= false
608 function QuestHelper
:OnEvent(event
)
609 if event
== "VARIABLES_LOADED" then
610 local tstart
= GetTime()
612 QH_Timeslice_Increment(GetTime() - tstart
, "init")
615 local tstart
= GetTime()
618 if event == "GOSSIP_SHOW" then
619 local name, id = UnitName("npc"), self:GetUnitID("npc")
621 self:GetObjective("monster", name).o.id = id
622 --self:TextOut("NPC: "..name.." = "..id)
626 --[[if event == "PLAYER_TARGET_CHANGED" then
627 local name, id = UnitName("target"), self:GetUnitID("target")
629 self:GetObjective("monster", name).o.id = id
630 --self:TextOut("Target: "..name.." = "..id)
633 if UnitExists("target") and UnitIsVisible("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
634 local index, x, y = self:UnitPosition("target")
636 if index then -- Might not have a position if inside an instance.
639 -- Modify the weight based on how far they are from us.
640 -- We don't know the exact location (using our own location), so the farther, the less sure we are that it's correct.
641 if CheckInteractDistance("target", 3) then w = 1
642 elseif CheckInteractDistance("target", 2) then w = 0.89
643 elseif CheckInteractDistance("target", 1) or CheckInteractDistance("target", 4) then w = 0.33 end
645 local monster_objective = self:GetObjective("monster", UnitName("target"))
646 self:AppendObjectivePosition(monster_objective, index, x, y, w)
648 monster_objective.o.faction = (UnitFactionGroup("target") == "Alliance" and 1) or
649 (UnitFactionGroup("target") == "Horde" and 2) or nil
651 local level = UnitLevel("target")
652 if level and level >= 1 then
653 local w = monster_objective.o.levelw or 0
654 monster_objective.o.level = ((monster_objective.o.level or 0)*w+level)/(w+1)
655 monster_objective.o.levelw = w+1
661 --[[if event == "LOOT_OPENED" then
662 local target = UnitName("target")
663 if target and UnitIsDead("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
664 local index, x, y = self:UnitPosition("target")
666 local monster_objective = self:GetObjective("monster", target)
667 monster_objective.o.looted = (monster_objective.o.looted or 0) + 1
669 if index then -- Might not have a position if inside an instance.
670 self:AppendObjectivePosition(monster_objective, index, x, y)
673 for i = 1, GetNumLootItems() do
674 local icon, name, number, rarity = GetLootSlotInfo(i)
676 if number and number >= 1 then
677 self:AppendItemObjectiveDrop(self:GetObjective("item", name), name, target, number)
679 local total = (name:match(COPPER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) +
680 (name:match(SILVER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 100 +
681 (name:match(GOLD_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 10000
684 self:AppendObjectiveDrop(self:GetObjective("item", "money"), target, total)
690 local container = nil
692 -- Go through the players inventory and look for a locked item, we're probably looting it.
693 for bag = 0,NUM_BAG_SLOTS do
694 for slot = 1,GetContainerNumSlots(bag) do
695 local link = GetContainerItemLink(bag, slot)
696 if link and select(3, GetContainerItemInfo(bag, slot)) then
697 if container == nil then
698 -- Found a locked item and haven't previously assigned to container, assign its name, or false if we fail to parse it.
699 container = select(3, string.find(link, "|h%[(.+)%]|h|r")) or false
701 -- Already tried to assign to a container. If there are multiple locked items, we give up.
709 local container_objective = self:GetObjective("item", container)
710 container_objective.o.opened = (container_objective.o.opened or 0) + 1
712 for i = 1, GetNumLootItems() do
713 local icon, name, number, rarity = GetLootSlotInfo(i)
714 if name and number >= 1 then
715 self:AppendItemObjectiveContainer(self:GetObjective("item", name), container, number)
719 -- No idea where the items came from.
720 local index, x, y = self:PlayerPosition()
723 for i = 1, GetNumLootItems() do
724 local icon, name, number, rarity = GetLootSlotInfo(i)
725 if name and number >= 1 then
726 self:AppendItemObjectivePosition(self:GetObjective("item", name), name, index, x, y)
734 --[[if event == "CHAT_MSG_SYSTEM" then
735 local home_name = self:convertPattern(ERR_DEATHBIND_SUCCESS_S)(arg1)
738 self:TextOut(QHText("HOME_CHANGED"))
739 self:TextOut(QHText("WILL_RESET_PATH"))
741 local home = QuestHelper_Home
744 QuestHelper_Home = home
747 home[1], home[2], home[3], home[4] = self.i, self.x, self.y, home_name
748 self.defered_graph_reset = true
753 --[[if event == "CHAT_MSG_ADDON" then
754 if arg1 == "QHpr" and (arg3 == "PARTY" or arg3 == "WHISPER") and arg4 ~= UnitName("player") then
755 self:HandleRemoteData(arg2, arg4)
759 if event
== "PARTY_MEMBERS_CHANGED" or
760 event
== "UNIT_LEVEL" or
761 event
== "RAID_ROSTER_UPDATE" then
762 QH_Filter_Group_Sync()
763 QH_Route_Filter_Rescan("filter_quest_level")
766 if event
== "PLAYER_LEVEL_UP" then
767 self
.player_level
= arg1
768 QH_Route_Filter_Rescan("filter_quest_level")
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 function QuestHelper
:OnUpdate()
894 local tstart
= GetTime()
897 if not QuestHelper_Loadtime
["onupdate"] then QuestHelper_Loadtime
["onupdate"] = GetTime() end
899 if false and frams
== 60 then
901 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
903 Known bugs and issues include:
905 |cff40bbffNo support for "/qh find"|r
907 |cff40bbffNo support for in-party quest synchronization|r
909 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.
911 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.
913 Thanks for testing!]], "QuestHelper " .. version_string
, 500, 20, 10)
916 if frams
== 250 then please_donate_enabled
= false end -- TOOK TOO LONG >:(
917 if please_donate_enabled
and startup_time
and startup_time
+ 1 < GetTime() then
918 QuestHelper
:TextOut(QHText("PLEASE_DONATE"))
920 please_donate_enabled
= false
922 QHUpdateNagTick() -- These probably shouldn't be in OnUpdate. Eventually I'll move them somewhere cleaner.
924 if init_cartographer_later
and Cartographer_Waypoints
then -- there has to be a better way to do this
925 init_cartographer_later
= false
926 if QuestHelper_Pref
.cart_wp_new
then
927 self
:EnableCartographer()
931 if not ontaxi
and UnitOnTaxi("player") then
934 elseif ontaxi
and not UnitOnTaxi("player") then
935 self
:flightEnded(interruptcount
> 1)
937 ontaxi
= UnitOnTaxi("player")
939 -- For now I'm ripping out the update_count code
940 --update_count = update_count - 1
941 --if update_count <= 0 then
943 -- Reset the update count for next time around; this will make sure the body executes every time
944 -- when perf_scale >= 1, and down to 1 in 10 iterations when perf_scale < 1, or when hidden.
945 --update_count = update_count + (QuestHelper_Pref.hide and 10 or 1/QuestHelper_Pref.perf_scale)
947 --if update_count < 0 then
948 -- Make sure the count doesn't go perpetually negative; don't know what will happen if it underflows.
952 if self
.Astrolabe
.WorldMapVisible
then
953 -- We won't trust that the zone returned by Astrolabe is correct until map_shown_decay is 0.
955 elseif map_shown_decay
> 0 then
956 map_shown_decay
= map_shown_decay
- 1
958 --SetMapToCurrentZone() -- not sure why this existed
961 --[[delayed_action = delayed_action - 1
962 if delayed_action <= 0 then
964 self:HandlePartyChange()
967 local nc
, nz
, nx
, ny
= self
.Astrolabe
:GetCurrentPlayerPosition()
970 if nc
and nc
~= -1 then -- We just want the raw data here, before we've done anything clever.
971 tc
, tx
, ty
= self
.Astrolabe
:GetAbsoluteContinentPosition(nc
, nz
, nx
, ny
)
972 QuestHelper
: Assert(tc
and tx
and ty
) -- is it true? nobody knows! :D
975 if nc
and nc
== self
.c
and map_shown_decay
> 0 and self
.z
> 0 and self
.z
~= nz
then
976 -- There's a chance Astrolable will return the wrong zone if you're messing with the world map, if you can
977 -- be seen in that zone but aren't in it.
978 local nnx
, nny
= self
.Astrolabe
:TranslateWorldMapPosition(nc
, nz
, nx
, ny
, nc
, self
.z
)
979 if nnx
> 0 and nny
> 0 and nnx
< 1 and nny
< 1 then
980 nz
, nx
, ny
= self
.z
, nnx
, nny
984 if nc
and nc
> 0 and nz
== 0 and nc
== self
.c
and self
.z
> 0 then
985 nx
, ny
= self
.Astrolabe
:TranslateWorldMapPosition(nc
, nz
, nx
, ny
, nc
, self
.z
)
986 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
989 nc
, nz
, nx
, ny
= nil, nil, nil, nil
993 if nc
and nz
> 0 then
994 self
.c
, self
.z
, self
.x
, self
.y
= nc
, nz
, nx
, ny
995 local upd_zone
= false
996 if self
.i
~= QuestHelper_IndexLookup
[nc
][nz
] then upd_zone
= true end
997 self
.i
= QuestHelper_IndexLookup
[nc
][nz
]
998 if upd_zone
then QH_Route_Filter_Rescan("filter_zone") end
1001 if nc
and nz
and nx
and ny
and tc
and tx
and ty
then
1002 self
.collect_rc
, self
.collect_rz
, self
.collect_rx
, self
.collect_ry
= nc
, nz
, nx
, ny
1003 self
.collect_ac
, self
.collect_ax
, self
.collect_ay
= tc
, tx
, ty
1004 self
.collect_delayed
= false
1006 local ibi
= self
.InBrokenInstance
1007 if nc
< -77 then self
.InBrokenInstance
= true else self
.InBrokenInstance
= false end
1009 if ibi
and not self
.InBrokenInstance
then self
.minimap_marker
:OnUpdate(0) end -- poke
1011 self
.collect_delayed
= true
1012 self
.InBrokenInstance
= true
1015 QH_Timeslice_Toggle("routing", not not self
.c
)
1017 self
:PumpCommMessages()
1020 QH_Collector_OnUpdate()
1022 QH_Timeslice_Increment(GetTime() - tstart
, "onupdate")
1027 -- 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.
1028 -- 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?
1029 function QuestHelper
:Location_RawRetrieve()
1030 return self
.collect_delayed
, self
.collect_rc
, self
.collect_rz
, self
.collect_rx
, self
.collect_ry
1032 function QuestHelper
:Location_AbsoluteRetrieve()
1033 return self
.collect_delayed
, self
.collect_ac
, self
.collect_ax
, self
.collect_ay
1036 QuestHelper
:RegisterEvent("VARIABLES_LOADED")
1037 QuestHelper
:SetScript("OnEvent", QuestHelper
.OnEvent
)