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,
41 tomtom_wp_new
= false,
47 locale
= GetLocale(), -- This variable is used for display purposes, and has nothing to do with the collected data.
48 perf_scale
= 1, -- How much background processing can the current machine handle? Higher means more load, lower means better performance.
49 perfload_scale
= 1, -- Performance scale to use on startup
53 -- 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.
54 setmetatable(QuestHelper_Pref
, {__index
=QuestHelper_DefaultPref
})
56 QuestHelper_FlightInstructors
= {}
57 QuestHelper_FlightLinks
= {}
58 QuestHelper_FlightRoutes
= {}
59 QuestHelper_KnownFlightRoutes
= {}
60 QuestHelper_SeenRealms
= {}
62 QuestHelper
.tooltip
= CreateFrame("GameTooltip", "QuestHelperTooltip", nil, "GameTooltipTemplate")
63 QuestHelper
.objective_objects
= {}
64 QuestHelper
.user_objectives
= {}
65 QuestHelper
.quest_objects
= {}
66 QuestHelper
.player_level
= 1
67 QuestHelper
.locale
= QuestHelper_Locale
69 QuestHelper
.faction
= (UnitFactionGroup("player") == "Alliance" and 1) or
70 (UnitFactionGroup("player") == "Horde" and 2)
72 assert(QuestHelper
.faction
)
74 QuestHelper
.font
= {serif
=GameFontNormal
:GetFont(), sans
=ChatFontNormal
:GetFont(), fancy
=QuestTitleFont
:GetFont()}
76 function QuestHelper
:GetFontPath(list_string
, font
)
78 for name
in string.gmatch(list_string
, "[^;]+") do
79 if font
:SetFont(name
, 10) then
81 elseif font
:SetFont("Interface\\AddOns\\QuestHelper\\Fonts\\"..name
, 10) then
82 return "Interface\\AddOns\\QuestHelper\\Fonts\\"..name
88 function QuestHelper
:SetLocaleFonts()
93 local font
= self
:CreateText(self
)
95 if QuestHelper_Locale
~= QuestHelper_Pref
.locale
then
96 -- Only use alternate fonts if using a language the client wasn't intended for.
97 local replacements
= QuestHelper_SubstituteFonts
[QuestHelper_Pref
.locale
]
99 self
.font
.sans
= self
:GetFontPath(replacements
.sans
, font
)
100 self
.font
.serif
= self
:GetFontPath(replacements
.serif
, font
)
101 self
.font
.fancy
= self
:GetFontPath(replacements
.fancy
, font
)
105 self
.font
.sans
= self
.font
.sans
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_sans.ttf", font
)
106 self
.font
.serif
= self
.font
.serif
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_serif.ttf", font
) or self
.font
.sans
107 self
.font
.fancy
= self
.font
.fancy
or self
:GetFontPath(QuestHelper_Pref
.locale
.."_fancy.ttf", font
) or self
.font
.serif
109 self
:ReleaseText(font
)
111 self
.font
.sans
= self
.font
.sans
or ChatFontNormal
:GetFont()
112 self
.font
.serif
= self
.font
.serif
or GameFontNormal
:GetFont()
113 self
.font
.fancy
= self
.font
.fancy
or QuestTitleFont
:GetFont()
115 -- Need to change the font of the chat frame, for any messages that QuestHelper displays.
116 -- This should do nothing if not using an alternate font.
117 DEFAULT_CHAT_FRAME
:SetFont(self
.font
.sans
, select(2, DEFAULT_CHAT_FRAME
:GetFont()))
120 QuestHelper
.route
= {}
121 QuestHelper
.to_add
= {}
122 QuestHelper
.to_remove
= {}
123 QuestHelper
.quest_log
= {}
124 QuestHelper
.pos
= {nil, {}, 0, 0, 1, "You are here.", 0}
125 QuestHelper
.sharing
= false -- Will be set to true when sharing with at least one user.
127 function QuestHelper
.tooltip
:GetPrevLines() -- Just a helper to make life easier.
128 local last
= self
:NumLines()
129 local name
= self
:GetName()
130 return _G
[name
.."TextLeft"..last
], _G
[name
.."TextRight"..last
]
133 function QuestHelper
:SetTargetLocation(i
, x
, y
, toffset
)
134 -- Informs QuestHelper that you're going to be at some location in toffset seconds.
135 local c
, z
= unpack(QuestHelper_ZoneLookup
[i
])
137 self
.target
= self
:CreateTable()
138 self
.target
[2] = self
:CreateTable()
140 self
.target_time
= time()+(toffset
or 0)
142 x
, y
= self
.Astrolabe
:TranslateWorldMapPosition(c
, z
, x
, y
, c
, 0)
143 self
.target
[1] = self
.zone_nodes
[i
]
144 self
.target
[3] = x
* self
.continent_scales_x
[c
]
145 self
.target
[4] = y
* self
.continent_scales_y
[c
]
147 self
:SetTargetLocationRecalculate()
150 function QuestHelper
:SetTargetLocationRecalculate()
152 for i
, n
in ipairs(self
.target
[1]) do
153 local a
, b
= n
.x
-self
.target
[3], n
.y
-self
.target
[4]
154 self
.target
[2][i
] = math
.sqrt(a
*a
+b
*b
)
159 function QuestHelper
:UnsetTargetLocation()
160 -- Unsets the target set above.
162 self
:ReleaseTable(self
.target
[2])
163 self
:ReleaseTable(self
.target
)
165 self
.target_time
= nil
169 local interruptcount
= 0 -- counts how many "played gained control" messages we recieve, used for flight paths
170 local init_cartographer_later
= false
172 function QuestHelper
:Initialize()
173 QuestHelper_Loadtime
["init_start"] = GetTime()
175 -- Use DefaultPref as fallback for unset preference keys.
176 setmetatable(QuestHelper_Pref
, {__index
=QuestHelper_DefaultPref
})
178 local file_problem
= false
179 local expected_version
= GetAddOnMetadata("QuestHelper", "Version")
181 local expected_files
=
183 ["bst_pre.lua"] = true,
184 ["bst_post.lua"] = true,
185 ["bst_astrolabe.lua"] = true,
186 ["bst_ctl.lua"] = true,
187 ["bst_libaboutpanel.lua"] = true,
189 ["manager_event.lua"] = true,
191 ["upgrade.lua"] = true,
193 ["recycle.lua"] = true,
194 ["objective.lua"] = true,
195 ["quest.lua"] = true,
196 ["questlog.lua"] = true,
197 ["utility.lua"] = true,
198 ["dodads.lua"] = true,
199 ["teleport.lua"] = true,
200 ["pathfinding.lua"] = true,
201 ["routing.lua"] = true,
202 ["custom.lua"] = true,
204 ["hidden.lua"] = true,
207 ["mapbutton.lua"] = true,
209 ["pattern.lua"] = true,
210 ["flightpath.lua"] = true,
211 ["tracker.lua"] = true,
212 ["objtips.lua"] = true,
213 ["cartographer.lua"] = true,
214 ["tomtom.lua"] = true,
215 ["textviewer.lua"] = true,
216 ["error.lua"] = true,
217 ["timeslice.lua"] = true,
220 ["tooltip.lua"] = true,
221 ["arrow.lua"] = true,
223 ["static.lua"] = true,
224 ["static_1.lua"] = true,
225 ["static_2.lua"] = true,
226 ["static_deDE.lua"] = true,
227 ["static_deDE_1.lua"] = true,
228 ["static_deDE_2.lua"] = true,
229 ["static_enUS.lua"] = true,
230 ["static_enUS_1.lua"] = true,
231 ["static_enUS_2.lua"] = true,
232 ["static_esES.lua"] = true,
233 ["static_esES_1.lua"] = true,
234 ["static_esES_2.lua"] = true,
235 ["static_esMX.lua"] = true,
236 ["static_esMX_1.lua"] = true,
237 ["static_esMX_2.lua"] = true,
238 ["static_frFR.lua"] = true,
239 ["static_frFR_1.lua"] = true,
240 ["static_frFR_2.lua"] = true,
241 ["static_koKR.lua"] = true,
242 ["static_koKR_1.lua"] = true,
243 ["static_koKR_2.lua"] = true,
244 ["static_ruRU.lua"] = true,
245 ["static_ruRU_1.lua"] = true,
246 ["static_ruRU_2.lua"] = true,
247 ["static_zhTW.lua"] = true,
248 ["static_zhTW_1.lua"] = true,
249 ["static_zhTW_2.lua"] = true,
251 ["collect.lua"] = true,
252 ["collect_achievement.lua"] = true,
253 ["collect_lzw.lua"] = true,
254 ["collect_traveled.lua"] = true,
255 ["collect_zone.lua"] = true,
256 ["collect_location.lua"] = true,
257 ["collect_merger.lua"] = true,
258 ["collect_monster.lua"] = true,
259 ["collect_item.lua"] = true,
260 ["collect_object.lua"] = true,
261 ["collect_loot.lua"] = true,
262 ["collect_patterns.lua"] = true,
263 ["collect_flight.lua"] = true,
264 ["collect_util.lua"] = true,
265 ["collect_quest.lua"] = true,
266 ["collect_equip.lua"] = true,
267 ["collect_notifier.lua"] = true,
268 ["collect_bitstream.lua"] = true,
269 ["collect_spec.lua"] = true,
270 ["collect_upgrade.lua"] = true,
271 ["collect_merchant.lua"] = true,
272 ["collect_warp.lua"] = true,
274 ["filter_core.lua"] = true,
275 ["filter_base.lua"] = true,
277 ["routing_debug.lua"] = true,
278 ["routing_loc.lua"] = true,
279 ["routing_route.lua"] = true,
280 ["routing_core.lua"] = true,
281 ["routing_controller.lua"] = true,
282 ["routing_hidden.lua"] = true,
284 ["director_quest.lua"] = true,
286 ["db_get.lua"] = true,
288 ["graph_core.lua"] = true,
289 ["graph_flightpath.lua"] = true,
292 local uninstallederr
= ""
294 for file
, version
in pairs(QuestHelper_File
) do
295 if not expected_files
[file
] then
296 local errmsg
= "Unexpected QuestHelper file: "..file
297 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
298 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
300 elseif version
~= expected_version
then
301 local errmsg
= "Wrong version of QuestHelper file: "..file
.." (found '"..version
.."', should be '"..expected_version
.."')"
302 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
303 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
304 if version
~= "Development Version" and expected_version
~= "Development Version" then
305 -- Developers are allowed to mix dev versions with release versions
311 for file
in pairs(expected_files
) do
312 if not QuestHelper_File
[file
] then
313 local errmsg
= "Missing QuestHelper file: "..file
314 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
315 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
316 if not (expected_version
== "Development Version" and file
:match("static.*")) then file_problem
= true end
320 -- Don't need this table anymore.
321 QuestHelper_File
= nil
323 if QuestHelper_StaticData
and not QuestHelper_StaticData
[GetLocale()] then
324 local errmsg
= "Static data does not seem to exist"
325 DEFAULT_CHAT_FRAME
:AddMessage(errmsg
)
327 -- TODO: Are you sure this should be an error? Shouldn't we let people we don't have data for collect their own?
328 uninstallederr
= uninstallederr
.. " " .. errmsg
.. "\n"
333 message(QHText("PLEASE_RESTART"))
334 QuestHelper_ErrorCatcher_ExplicitError(true, "not-installed-properly" .. "\n" .. uninstallederr
)
335 QuestHelper
= nil -- Just in case anybody else is checking for us, we're not home
339 if not GetCategoryList
or not GetQuestLogSpecialItemInfo
or not WatchFrame_RemoveObjectiveHandler
then
340 message(QHText("PRIVATE_SERVER"))
341 QuestHelper_ErrorCatcher_ExplicitError(true, "error id cakbep ten T")
346 if not DongleStub
then
347 message(QHText("NOT_UNZIPPED_CORRECTLY"))
348 QuestHelper_ErrorCatcher_ExplicitError(true, "not-unzipped-properly")
349 QuestHelper
= nil -- Just in case anybody else is checking for us, we're not home
353 QuestHelper_ErrorCatcher_CompletelyStarted()
355 if not QuestHelper_StaticData
then
356 -- If there is no static data for some mysterious reason, create an empty table so that
357 -- other parts of the code can carry on as usual, using locally collected data if it exists.
358 QuestHelper_StaticData
= {}
361 QHFormatSetLocale(QuestHelper_Pref
.locale
or GetLocale())
363 if not QuestHelper_UID
then
364 QuestHelper_UID
= self
:CreateUID()
366 QuestHelper_SaveDate
= time()
368 QuestHelper_BuildZoneLookup()
372 if QuestHelper_Locale
~= GetLocale() then
373 self
:TextOut(QHText("LOCALE_ERROR"))
377 if not self
:ZoneSanity() then
378 self
:TextOut(QHText("ZONE_LAYOUT_ERROR"))
379 message("QuestHelper: "..QHText("ZONE_LAYOUT_ERROR"))
383 QuestHelper_UpgradeDatabase(_G
)
384 QuestHelper_UpgradeComplete()
386 if QuestHelper_SaveVersion
~= 10 then
387 self
:TextOut(QHText("DOWNGRADE_ERROR"))
391 if QuestHelper_IsPolluted(_G
) then
392 self
:TextOut(QHFormat("NAG_POLLUTED"))
393 self
:Purge(nil, true, true)
396 local signature
= expected_version
.. " on " .. GetBuildInfo()
397 QuestHelper_Quests
[signature
] = QuestHelper_Quests
[signature
] or {}
398 QuestHelper_Objectives
[signature
] = QuestHelper_Objectives
[signature
] or {}
399 QuestHelper_FlightInstructors
[signature
] = QuestHelper_FlightInstructors
[signature
] or {}
400 QuestHelper_FlightRoutes
[signature
] = QuestHelper_FlightRoutes
[signature
] or {}
402 QuestHelper_Quests_Local
= QuestHelper_Quests
[signature
]
403 QuestHelper_Objectives_Local
= QuestHelper_Objectives
[signature
]
404 QuestHelper_FlightInstructors_Local
= QuestHelper_FlightInstructors
[signature
]
405 QuestHelper_FlightRoutes_Local
= QuestHelper_FlightRoutes
[signature
]
407 QuestHelper_SeenRealms
[GetRealmName()] = true -- some attempt at tracking private servers
412 self
.player_level
= UnitLevel("player")
414 self
:UnregisterEvent("VARIABLES_LOADED")
415 self
:RegisterEvent("PLAYER_TARGET_CHANGED")
416 self
:RegisterEvent("LOOT_OPENED")
417 self
:RegisterEvent("QUEST_COMPLETE")
418 self
:RegisterEvent("QUEST_LOG_UPDATE")
419 self
:RegisterEvent("QUEST_PROGRESS")
420 self
:RegisterEvent("MERCHANT_SHOW")
421 self
:RegisterEvent("QUEST_DETAIL")
422 self
:RegisterEvent("TAXIMAP_OPENED")
423 self
:RegisterEvent("PLAYER_CONTROL_GAINED")
424 self
:RegisterEvent("PLAYER_LEVEL_UP")
425 self
:RegisterEvent("PARTY_MEMBERS_CHANGED")
426 self
:RegisterEvent("CHAT_MSG_ADDON")
427 self
:RegisterEvent("CHAT_MSG_SYSTEM")
428 self
:RegisterEvent("BAG_UPDATE")
429 self
:RegisterEvent("GOSSIP_SHOW")
430 self
:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE")
431 self
:RegisterEvent("UNIT_LEVEL")
432 self
:RegisterEvent("ZONE_CHANGED")
433 self
:RegisterEvent("ZONE_CHANGED_INDOORS")
434 self
:RegisterEvent("ZONE_CHANGED_NEW_AREA")
436 self
:SetLocaleFonts()
438 if QuestHelper_Pref
.share
and not QuestHelper_Pref
.solo
then
442 if QuestHelper_Pref
.hide
then
443 self
.map_overlay
:Hide()
446 self
:HandlePartyChange()
450 for locale
in pairs(QuestHelper_StaticData
) do
451 if locale
~= self
.locale
then
452 -- Will delete references to locales you don't use.
453 QuestHelper_StaticData
[locale
] = nil
454 _G
["QuestHelper_StaticData_" .. locale
] = nil
458 local static
= QuestHelper_StaticData
[self
.locale
]
461 if static
.flight_instructors
then for faction
in pairs(static
.flight_instructors
) do
462 if faction
~= self
.faction
then
463 -- Will delete references to flight instructors that don't belong to your faction.
464 static
.flight_instructors
[faction
] = nil
468 if static
.quest
then for faction
in pairs(static
.quest
) do
469 if faction
~= self
.faction
then
470 -- Will delete references to quests that don't belong to your faction.
471 static
.quest
[faction
] = nil
476 -- Adding QuestHelper_CharVersion, so I know if I've already converted this characters saved data.
477 if not QuestHelper_CharVersion
then
478 -- Changing per-character flight routes, now only storing the flight points they have,
479 -- will attempt to guess the routes from this.
482 for i
, l
in pairs(QuestHelper_KnownFlightRoutes
) do
483 for key
in pairs(l
) do
488 QuestHelper_KnownFlightRoutes
= routes
490 -- Deleting the player's home again.
491 -- But using the new CharVersion variable I'm adding is cleaner that what I was doing, so I'll go with it.
492 QuestHelper_Home
= nil
493 QuestHelper_CharVersion
= 1
496 if not QuestHelper_Home
then
497 -- Not going to bother complaining about the player's home not being set, uncomment this when the home is used in routing.
498 -- self:TextOut(QHText("HOME_NOT_KNOWN"))
501 if QuestHelper_Pref
.map_button
then
502 QuestHelper
:InitMapButton()
505 if QuestHelper_Pref
.cart_wp_new
then
506 init_cartographer_later
= true
509 if QuestHelper_Pref
.tomtom_wp_new
then
513 self
.tracker
:SetScale(QuestHelper_Pref
.track_scale
)
515 if QuestHelper_Pref
.track
and not QuestHelper_Pref
.hide
then
519 local version
= GetAddOnMetadata("QuestHelper", "Version") or "Unknown"
521 local major
, minor
= (version_string
or ""):match("^(%d+)%.(%d+)")
522 major
, minor
= tonumber(major
), tonumber(minor
)
524 -- For versions before 0.82, we're changing the default level offset to 3.
525 if major
== 0 and minor
and minor
< 82 and QuestHelper_Pref
.level
== 2 then
526 QuestHelper_Pref
.level
= nil
529 -- For versions before 0.84...
530 if major
== 0 and minor
and minor
< 84 then
531 -- remove all keys that match their default setting.
532 for key
, val
in pairs(QuestHelper_DefaultPref
) do
533 if QuestHelper_Pref
[key
] == val
then
534 QuestHelper_Pref
[key
] = nil
539 self
:SetScript("OnUpdate", self
.OnUpdate
)
541 -- Seems to do its own garbage collection pass before fully loading, so I'll just rely on that
542 --collectgarbage("collect") -- Free everything we aren't using.
545 if self.debug_objectives then
546 for name, data in pairs(self.debug_objectives) do
547 self:LoadDebugObjective(name, data)
553 QH_Arrow_SetTextScale()
556 QH_Timeslice_Add(function ()
558 self.Routing:Initialize() -- Set up the routing task
559 end, "init")]] -- FUCK YOU BOXBOT
561 --[[ -- This is just an example of how the WoW profiler biases its profiles heavily.
567 for x = 0, 130000000, 1 do
573 for x = 0, 12000000, 1 do
580 for x = 0, 1200000, 1 do
588 local ta = debugprofilestop()
590 local tb = debugprofilestop()
592 local tc = debugprofilestop()
594 QuestHelper:TextOut(string.format("%d %d %d", ta, tb - ta, tc - tb))
595 QuestHelper:TextOut(string.format("%d %d", GetFunctionCPUUsage(A), GetFunctionCPUUsage(B)))
597 --/script SetCVar("scriptProfile", value)]]
599 LibStub("LibAboutPanelQH").new(nil, "QuestHelper")
601 QuestHelper_Loadtime
["init_end"] = GetTime()
603 QuestHelper
.loading_main
= QuestHelper
.CreateLoadingCounter()
605 QuestHelper
.loading_flightpath
= QuestHelper
.loading_main
:MakeSubcategory(1)
606 QuestHelper
.loading_preroll
= QuestHelper
.loading_main
:MakeSubcategory(1)
610 local please_donate_enabled
= false
611 local please_donate_initted
= false
613 function QuestHelper
:OnEvent(event
)
614 if event
== "VARIABLES_LOADED" then
615 local tstart
= GetTime()
617 QH_Timeslice_Increment(GetTime() - tstart
, "init")
620 local tstart
= GetTime()
623 if event == "GOSSIP_SHOW" then
624 local name, id = UnitName("npc"), self:GetUnitID("npc")
626 self:GetObjective("monster", name).o.id = id
627 --self:TextOut("NPC: "..name.." = "..id)
631 --[[if event == "PLAYER_TARGET_CHANGED" then
632 local name, id = UnitName("target"), self:GetUnitID("target")
634 self:GetObjective("monster", name).o.id = id
635 --self:TextOut("Target: "..name.." = "..id)
638 if UnitExists("target") and UnitIsVisible("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
639 local index, x, y = self:UnitPosition("target")
641 if index then -- Might not have a position if inside an instance.
644 -- Modify the weight based on how far they are from us.
645 -- We don't know the exact location (using our own location), so the farther, the less sure we are that it's correct.
646 if CheckInteractDistance("target", 3) then w = 1
647 elseif CheckInteractDistance("target", 2) then w = 0.89
648 elseif CheckInteractDistance("target", 1) or CheckInteractDistance("target", 4) then w = 0.33 end
650 local monster_objective = self:GetObjective("monster", UnitName("target"))
651 self:AppendObjectivePosition(monster_objective, index, x, y, w)
653 monster_objective.o.faction = (UnitFactionGroup("target") == "Alliance" and 1) or
654 (UnitFactionGroup("target") == "Horde" and 2) or nil
656 local level = UnitLevel("target")
657 if level and level >= 1 then
658 local w = monster_objective.o.levelw or 0
659 monster_objective.o.level = ((monster_objective.o.level or 0)*w+level)/(w+1)
660 monster_objective.o.levelw = w+1
666 --[[if event == "LOOT_OPENED" then
667 local target = UnitName("target")
668 if target and UnitIsDead("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
669 local index, x, y = self:UnitPosition("target")
671 local monster_objective = self:GetObjective("monster", target)
672 monster_objective.o.looted = (monster_objective.o.looted or 0) + 1
674 if index then -- Might not have a position if inside an instance.
675 self:AppendObjectivePosition(monster_objective, index, x, y)
678 for i = 1, GetNumLootItems() do
679 local icon, name, number, rarity = GetLootSlotInfo(i)
681 if number and number >= 1 then
682 self:AppendItemObjectiveDrop(self:GetObjective("item", name), name, target, number)
684 local total = (name:match(COPPER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) +
685 (name:match(SILVER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 100 +
686 (name:match(GOLD_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 10000
689 self:AppendObjectiveDrop(self:GetObjective("item", "money"), target, total)
695 local container = nil
697 -- Go through the players inventory and look for a locked item, we're probably looting it.
698 for bag = 0,NUM_BAG_SLOTS do
699 for slot = 1,GetContainerNumSlots(bag) do
700 local link = GetContainerItemLink(bag, slot)
701 if link and select(3, GetContainerItemInfo(bag, slot)) then
702 if container == nil then
703 -- Found a locked item and haven't previously assigned to container, assign its name, or false if we fail to parse it.
704 container = select(3, string.find(link, "|h%[(.+)%]|h|r")) or false
706 -- Already tried to assign to a container. If there are multiple locked items, we give up.
714 local container_objective = self:GetObjective("item", container)
715 container_objective.o.opened = (container_objective.o.opened or 0) + 1
717 for i = 1, GetNumLootItems() do
718 local icon, name, number, rarity = GetLootSlotInfo(i)
719 if name and number >= 1 then
720 self:AppendItemObjectiveContainer(self:GetObjective("item", name), container, number)
724 -- No idea where the items came from.
725 local index, x, y = self:PlayerPosition()
728 for i = 1, GetNumLootItems() do
729 local icon, name, number, rarity = GetLootSlotInfo(i)
730 if name and number >= 1 then
731 self:AppendItemObjectivePosition(self:GetObjective("item", name), name, index, x, y)
739 --[[if event == "CHAT_MSG_SYSTEM" then
740 local home_name = self:convertPattern(ERR_DEATHBIND_SUCCESS_S)(arg1)
743 self:TextOut(QHText("HOME_CHANGED"))
744 self:TextOut(QHText("WILL_RESET_PATH"))
746 local home = QuestHelper_Home
749 QuestHelper_Home = home
752 home[1], home[2], home[3], home[4] = self.i, self.x, self.y, home_name
753 self.defered_graph_reset = true
758 --[[if event == "CHAT_MSG_ADDON" then
759 if arg1 == "QHpr" and (arg3 == "PARTY" or arg3 == "WHISPER") and arg4 ~= UnitName("player") then
760 self:HandleRemoteData(arg2, arg4)
764 if event
== "PARTY_MEMBERS_CHANGED" or
765 event
== "UNIT_LEVEL" or
766 event
== "RAID_ROSTER_UPDATE" then
767 QH_Filter_Group_Sync()
768 QH_Route_Filter_Rescan("filter_quest_level")
771 if event
== "PLAYER_LEVEL_UP" then
772 self
.player_level
= arg1
773 QH_Route_Filter_Rescan("filter_quest_level")
777 --[[if event == "QUEST_DETAIL" then
778 if not self.quest_giver then self.quest_giver = {} end
779 local npc = UnitName("npc")
781 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
782 local index, x, y = self:UnitPosition("npc")
784 if index then -- Might not have a position if inside an instance.
785 local npc_objective = self:GetObjective("monster", npc)
786 self:AppendObjectivePosition(npc_objective, index, x, y)
787 self.quest_giver[GetTitleText()] = npc
792 --[[if event == "QUEST_COMPLETE" or event == "QUEST_PROGRESS" then
793 local quest = GetTitleText()
795 local level, hash = self:GetQuestLevel(quest)
796 if not level or level < 1 then
797 --self:TextOut("Don't know quest level for ".. quest.."!")
800 local q = self:GetQuest(quest, level, hash)
806 local unit = UnitName("npc")
811 -- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
812 local index, x, y = self:UnitPosition("npc")
813 if index then -- Might not have a position if inside an instance.
814 local npc_objective = self:GetObjective("monster", unit)
815 self:AppendObjectivePosition(npc_objective, index, x, y)
817 elseif not q.o.finish then
818 local index, x, y = self:PlayerPosition()
819 if index then -- Might not have a position if inside an instance.
820 self:AppendObjectivePosition(q, index, x, y)
826 --[[if event == "MERCHANT_SHOW" then
827 local npc_name = UnitName("npc")
829 local npc_objective = self:GetObjective("monster", npc_name)
832 local item_name = GetMerchantItemInfo(index)
835 local item_objective = self:GetObjective("item", item_name)
836 if not item_objective.o.vendor then
837 item_objective.o.vendor = {npc_name}
840 for i, vendor in ipairs(item_objective.o.vendor) do
841 if npc_name == vendor then
847 table.insert(item_objective.o.vendor, npc_name)
857 if event
== "TAXIMAP_OPENED" then
861 --[[if event == "PLAYER_CONTROL_GAINED" then
862 interruptcount = interruptcount + 1
865 --[[if event == "BAG_UPDATE" then
866 for slot = 1,GetContainerNumSlots(arg1) do
867 local link = GetContainerItemLink(arg1, slot)
869 local id, name = select(3, string.find(link, "|Hitem:(%d+):.-|h%[(.-)%]|h"))
871 self:GetObjective("item", name).o.id = tonumber(id)
877 if event
== "CHAT_MSG_CHANNEL_NOTICE" and please_donate_enabled
and not please_donate_initted
then
878 please_donate_enabled
= QHNagInit()
879 startup_time
= GetTime()
880 please_donate_initted
= true
885 if event
== "ZONE_CHANGED" or event
== "ZONE_CHANGED_INDOORS" or event
== "ZONE_CHANGED_NEW_AREA" then
886 QH_Route_Filter_Rescan()
889 QH_Timeslice_Increment(GetTime() - tstart
, "event")
892 local map_shown_decay
= 0
893 local delayed_action
= 100
894 --local update_count = 0
898 function QuestHelper
:OnUpdate()
899 local tstart
= GetTime()
902 if not QuestHelper_Loadtime
["onupdate"] then QuestHelper_Loadtime
["onupdate"] = GetTime() end
904 if false and frams
== 60 then
906 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
908 Known bugs and issues include:
910 |cff40bbffNo support for "/qh find"|r
912 |cff40bbffNo support for in-party quest synchronization|r
914 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.
916 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.
918 Thanks for testing!]], "QuestHelper " .. version_string
, 500, 20, 10)
921 if frams
== 250 then please_donate_enabled
= false end -- TOOK TOO LONG >:(
922 if please_donate_enabled
and startup_time
and startup_time
+ 1 < GetTime() then
923 QuestHelper
:TextOut(QHText("PLEASE_DONATE"))
925 please_donate_enabled
= false
927 QHUpdateNagTick() -- These probably shouldn't be in OnUpdate. Eventually I'll move them somewhere cleaner.
929 if init_cartographer_later
and Cartographer_Waypoints
then -- there has to be a better way to do this
930 init_cartographer_later
= false
931 if QuestHelper_Pref
.cart_wp_new
then
932 self
:EnableCartographer()
936 if not ontaxi
and UnitOnTaxi("player") then
939 elseif ontaxi
and not UnitOnTaxi("player") then
940 self
:flightEnded(interruptcount
> 1)
942 ontaxi
= UnitOnTaxi("player")
944 -- For now I'm ripping out the update_count code
945 --update_count = update_count - 1
946 --if update_count <= 0 then
948 -- Reset the update count for next time around; this will make sure the body executes every time
949 -- when perf_scale >= 1, and down to 1 in 10 iterations when perf_scale < 1, or when hidden.
950 --update_count = update_count + (QuestHelper_Pref.hide and 10 or 1/QuestHelper_Pref.perf_scale)
952 --if update_count < 0 then
953 -- Make sure the count doesn't go perpetually negative; don't know what will happen if it underflows.
957 if self
.Astrolabe
.WorldMapVisible
then
958 -- We won't trust that the zone returned by Astrolabe is correct until map_shown_decay is 0.
960 elseif map_shown_decay
> 0 then
961 map_shown_decay
= map_shown_decay
- 1
963 --SetMapToCurrentZone() -- not sure why this existed
966 --[[delayed_action = delayed_action - 1
967 if delayed_action <= 0 then
969 self:HandlePartyChange()
972 local nc
, nz
, nx
, ny
= self
.Astrolabe
:GetCurrentPlayerPosition()
975 if nc
and nc
~= -1 then -- We just want the raw data here, before we've done anything clever.
976 tc
, tx
, ty
= self
.Astrolabe
:GetAbsoluteContinentPosition(nc
, nz
, nx
, ny
)
977 QuestHelper
: Assert(tc
and tx
and ty
) -- is it true? nobody knows! :D
980 if nc
and nc
== self
.c
and map_shown_decay
> 0 and self
.z
> 0 and self
.z
~= nz
then
981 -- There's a chance Astrolable will return the wrong zone if you're messing with the world map, if you can
982 -- be seen in that zone but aren't in it.
983 local nnx
, nny
= self
.Astrolabe
:TranslateWorldMapPosition(nc
, nz
, nx
, ny
, nc
, self
.z
)
984 if nnx
> 0 and nny
> 0 and nnx
< 1 and nny
< 1 then
985 nz
, nx
, ny
= self
.z
, nnx
, nny
989 if nc
and nc
> 0 and nz
== 0 and nc
== self
.c
and self
.z
> 0 then
990 nx
, ny
= self
.Astrolabe
:TranslateWorldMapPosition(nc
, nz
, nx
, ny
, nc
, self
.z
)
991 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
994 nc
, nz
, nx
, ny
= nil, nil, nil, nil
998 if nc
and nz
> 0 then
999 self
.c
, self
.z
, self
.x
, self
.y
= nc
, nz
, nx
, ny
1000 local upd_zone
= false
1001 if self
.i
~= QuestHelper_IndexLookup
[nc
][nz
] then upd_zone
= true end
1002 self
.i
= QuestHelper_IndexLookup
[nc
][nz
]
1003 if upd_zone
then QH_Route_Filter_Rescan("filter_zone") end
1006 if nc
and nz
and nx
and ny
and tc
and tx
and ty
then
1007 self
.collect_rc
, self
.collect_rz
, self
.collect_rx
, self
.collect_ry
= nc
, nz
, nx
, ny
1008 self
.collect_ac
, self
.collect_ax
, self
.collect_ay
= tc
, tx
, ty
1009 self
.collect_delayed
= false
1011 local ibi
= self
.InBrokenInstance
1012 if nc
< -77 then self
.InBrokenInstance
= true else self
.InBrokenInstance
= false end
1014 if ibi
and not self
.InBrokenInstance
then self
.minimap_marker
:OnUpdate(0) end -- poke
1016 self
.collect_delayed
= true
1017 self
.InBrokenInstance
= true
1020 QH_Timeslice_Toggle("routing", not not self
.c
)
1022 self
:PumpCommMessages()
1025 QH_Collector_OnUpdate()
1027 QH_Timeslice_Increment(GetTime() - tstart
, "onupdate")
1032 -- 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.
1033 -- 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?
1034 function QuestHelper
:Location_RawRetrieve()
1035 return self
.collect_delayed
, self
.collect_rc
, self
.collect_rz
, self
.collect_rx
, self
.collect_ry
1037 function QuestHelper
:Location_AbsoluteRetrieve()
1038 return self
.collect_delayed
, self
.collect_ac
, self
.collect_ax
, self
.collect_ay
1041 QuestHelper
:RegisterEvent("VARIABLES_LOADED")
1042 QuestHelper
:SetScript("OnEvent", QuestHelper
.OnEvent
)