Merge branch 'master' of git://cams.pavlovian.net/questhelper
[QuestHelper.git] / help.lua
blobb3490828d7917c59403ca5bc860325e37ec6ba6c
1 QuestHelper_File["help.lua"] = "Development Version"
2 QuestHelper_Loadtime["help.lua"] = GetTime()
4 local QuestHelper_Version = QuestHelper_File["help.lua"]
6 function QuestHelper:scaleString(val)
7 return self:HighlightText(math.floor(val*100+0.5).."%")
8 end
10 function QuestHelper:genericSetScale(varname, name, mn, mx, input, onchange, ...)
11 if input == "" then
12 self:TextOut(string.format("Current %s scale is %s.", name, self:scaleString(QuestHelper_Pref[varname])))
13 else
14 local scale = tonumber(input)
16 if not scale then
17 local x = string.match(input or "", "^%s*([%d%.]+)%s*%%%s*$")
18 scale = tonumber(x) or 0
19 if not scale then
20 self:TextOut("I don't know how to interpret your input.")
21 return
22 end
23 scale = scale * 0.01
24 end
26 if scale < mn then
27 self:TextOut(string.format("I won't accept a scale less than %s.", self:scaleString(mn)))
28 elseif scale > mx then
29 self:TextOut(string.format("I won't accept a scale more than %s.", self:scaleString(mx)))
30 else
31 QuestHelper_Pref[varname] = scale
32 self:TextOut(string.format("Set %s scale set to %s.", name, self:scaleString(scale)))
33 if onchange then
34 onchange(...)
35 end
36 end
37 end
38 end
40 function QuestHelper:TrackerScale(scale)
41 QuestHelper:genericSetScale("track_scale", "tracker scale", .5, 2, scale,
42 function() QuestHelper.tracker:SetScale(QuestHelper_Pref.track_scale) end)
43 end
45 function QuestHelper:SetLocale(loc)
46 if not loc or loc == "" then
47 self:TextOut(QHText("LOCALE_LIST_BEGIN"))
48 for loc, tbl in pairs(QuestHelper_Translations) do
49 self:TextOut(string.format(" %s%s %s", self:HighlightText(loc),
50 loc == QuestHelper_Pref.locale and " *" or " ",
51 tbl.LOCALE_NAME or "???"))
52 end
53 else
54 for l, tbl in pairs(QuestHelper_Translations) do
55 if string.find(string.lower(l), "^"..string.lower(loc)) or
56 string.find(string.lower(tbl.LOCALE_NAME or ""), "^"..string.lower(loc)) then
57 QuestHelper_Pref.locale = l
58 QHFormatSetLocale(l)
59 self:SetLocaleFonts()
60 self:TextOut(QHFormat("LOCALE_CHANGED", l))
61 return
62 end
63 end
65 self:TextOut(QHFormat("LOCALE_UNKNOWN", tostring(loc) or "UNKNOWN"))
66 end
67 end
69 function QuestHelper:ToggleMetric()
70 QuestHelper_Pref.metric = not QuestHelper_Pref.metric
72 if QuestHelper_Pref.metric then
73 self:TextOut("Distances are now in metres.")
74 else
75 self:TextOut("Distances are now in yards.")
76 end
77 end
79 function QuestHelper:ToggleHide()
80 QuestHelper_Pref.hide = not QuestHelper_Pref.hide
82 -- Desaturate the button texture if QuestHelper is disabled.
83 if self.MapButton then
84 -- This should always be true, but just in case...
85 self.MapButton:GetNormalTexture():SetDesaturated(QuestHelper_Pref.hide)
86 end
88 if QuestHelper_Pref.hide then
89 if QuestHelper_Pref.track then
90 self:HideTracker()
91 end
93 self.map_overlay:Hide()
94 self:TextOut("QuestHelper is now |cffff0000hidden|r.")
95 else
96 if QuestHelper_Pref.track then
97 self:ShowTracker()
98 end
100 self.map_overlay:Show()
101 self.minimap_marker:Show()
102 self:TextOut("QuestHelper is now |cff00ff00shown|r.")
104 QH_Timeslice_Bonus(20) -- Let the corutine do some overtime...
108 function QuestHelper:ToggleShare()
109 QuestHelper_Pref.share = not QuestHelper_Pref.share
110 if QuestHelper_Pref.share then
111 if QuestHelper_Pref.solo then
112 self:TextOut("Objective sharing will been |cff00ff00enabled|r when you disable solo mode.")
113 else
114 self:TextOut("Objective sharing has been |cff00ff00enabled|r.")
115 self:SetShare(true)
117 else
118 self:TextOut("Objective sharing has been |cffff0000disabled|r.")
119 if QuestHelper_Pref.solo then
120 self:TextOut("Objective sharing won't be reenabled when you disable solo mode.")
121 else
122 self:SetShare(false)
127 function QuestHelper:ToggleFlightTimes()
128 QuestHelper_Pref.flight_time = not QuestHelper_Pref.flight_time
129 if QuestHelper_Pref.flight_time then
130 self:TextOut("The flight timer has been |cff00ff00enabled|r.")
131 else
132 self:TextOut("The flight timer has been |cffff0000disabled|r.")
136 function QuestHelper:ToggleTrack()
137 QuestHelper_Pref.track = not QuestHelper_Pref.track
138 if QuestHelper_Pref.track then
139 self:ShowTracker()
140 self:TextOut("The quest tracker has been |cff00ff00enabled|r.")
141 else
142 self:HideTracker()
143 self:TextOut("The quest tracker has been |cffff0000disabled|r.")
147 function QuestHelper:ToggleTrackLevel()
148 QuestHelper_Pref.track_level = not QuestHelper_Pref.track_level
149 if QuestHelper_Pref.track_level then
150 self:TextOut("Display of levels in the quest tracker has been |cff00ff00enabled|r.")
151 else
152 self:TextOut("Display of levels in the quest tracker has been |cffff0000disabled|r.")
154 QH_UpdateQuests(true)
155 QH_Tracker_Rescan()
158 function QuestHelper:ToggleTrackQColour()
159 QuestHelper_Pref.track_qcolour = not QuestHelper_Pref.track_qcolour
160 if QuestHelper_Pref.track_qcolour then
161 self:TextOut("Colour for quest difficulty in quest tracker has been |cff00ff00enabled|r.")
162 else
163 self:TextOut("Colour for quest difficulty in quest tracker has been |cffff0000disabled|r.")
165 QH_UpdateQuests(true)
166 QH_Tracker_Rescan()
169 function QuestHelper:ToggleTrackOColour()
170 QuestHelper_Pref.track_ocolour = not QuestHelper_Pref.track_ocolour
171 if QuestHelper_Pref.track_ocolour then
172 self:TextOut("Colour for objective progress in quest tracker has been |cff00ff00enabled|r.")
173 else
174 self:TextOut("Colour for objective progress in quest tracker has been |cffff0000disabled|r.")
176 QH_UpdateQuests(true)
177 QH_Tracker_Rescan()
180 function QuestHelper:ToggleTooltip()
181 QuestHelper_Pref.tooltip = not QuestHelper_Pref.tooltip
182 if QuestHelper_Pref.tooltip then
183 self:TextOut("Objective tooltip information has been |cff00ff00enabled|r.")
184 else
185 self:TextOut("Objective tooltip information has been |cffff0000disabled|r.")
189 function QuestHelper:Purgewarning()
190 QuestHelper:TextOut("I would consider this a tragic loss, and would appreciate it if you sent me your saved data before going through with it.")
191 QuestHelper:TextOut("Enter "..self:HighlightText("/qh nag verbose").." to check and see if you're destroying anything important.")
192 QuestHelper:TextOut("Enter "..self:HighlightText("/qh submit").." for instructions on how to submit your collected data.")
193 QuestHelper:TextOut("See the "..self:HighlightText("How You Can Help").." section on the project website for instructions.")
196 function QuestHelper:Purge(code, force, noreload)
197 if code == self.purge_code or force then
198 QuestHelper_Quests = nil
199 QuestHelper_Objectives = nil
200 QuestHelper_FlightInstructors = nil
201 QuestHelper_FlightRoutes = nil
202 QuestHelper_Locale = nil
203 QuestHelper_UID = nil
204 QuestHelper_Version = nil
205 QuestHelper_SaveVersion = nil
207 QuestHelper_SaveDate = nil
208 QuestHelper_SeenRealms = nil
210 QuestHelper_Collector = nil
211 QuestHelper_Collector_Version = nil
213 if not noreload then ReloadUI() end
214 else
215 if not self.purge_code then self.purge_code = self:CreateUID(8) end
216 QuestHelper:TextOut("THIS COMMAND WILL DELETE ALL YOUR COLLECTED DATA")
217 QuestHelper:Purgewarning()
218 QuestHelper:TextOut("If you're sure you want to go through with this, enter: "..self:HighlightText("/qh purge "..self.purge_code))
222 function QuestHelper:HardReset(code)
223 if code == self.purge_code then
224 self:ResetTrackerPosition() -- do this before we kill off the prefs, since it touches a pref
225 QH_Arrow_Reset()
226 QuestHelper_Pref = nil
227 QuestHelper_ErrorList = nil -- BIZAM
228 QuestHelper_KnownFlightRoutes = nil
229 QuestHelper_Home = nil
230 QuestHelper_CharVersion = nil
231 self:Purge(nil, true)
232 else
233 if not self.purge_code then self.purge_code = self:CreateUID(8) end
234 QuestHelper:TextOut("THIS COMMAND WILL DELETE ALL YOUR COLLECTED DATA AND RESET ALL YOUR PREFERENCES")
235 QuestHelper:Purgewarning()
236 QuestHelper:TextOut("If you're sure you want to go through with this, enter: "..self:HighlightText("/qh hardreset "..self.purge_code))
240 function QuestHelper:ToggleSolo()
241 QuestHelper_Pref.solo = not QuestHelper_Pref.solo
242 if QuestHelper_Pref.solo then
243 if QuestHelper_Pref.share then
244 self:SetShare(false)
245 self:TextOut("Objective sharing has been temporarly |cffff0000disabled|r.")
247 self:TextOut("Solo mode has been |cff00ff00enabled|r.")
248 else
249 self:TextOut("Solo mode has been |cffff0000disabled|r.")
250 if QuestHelper_Pref.share then
251 self:SetShare(true)
252 self:TextOut("Objective sharing has been re|cff00ff00enabled|r.")
257 function QuestHelper:ToggleAnts()
258 if QuestHelper_Pref.show_ants then
259 QuestHelper_Pref.show_ants = false
260 self:TextOut("Ant trails have been |cffff0000disabled|r.")
261 else
262 QuestHelper_Pref.show_ants = true
263 self:TextOut("Ant trails have been |cff00ff00enabled|r.")
267 function QuestHelper:LevelOffset(offset)
268 local level = tonumber(offset)
269 if level then
270 if level > 0 then
271 self:TextOut("Allowing quests up to "..self:HighlightText(level).." level"..(level==1 and " " or "s ")..self:HighlightText("above").." you.")
272 elseif level < 0 then
273 self:TextOut("Only allowing quests "..self:HighlightText(-level).." level"..(level==-1 and " " or "s ")..self:HighlightText("below").." you.")
274 else
275 self:TextOut("Only allowing quests "..self:HighlightText("at or below").." your current level.")
278 if not QuestHelper_Pref.filter_level then
279 self:TextOut("Note: This won't have any effect until you turn the level filter on.")
282 if QuestHelper_Pref.level ~= level then
283 QuestHelper_Pref.level = level
284 QH_Route_Filter_Rescan("filter_quest_level")
286 elseif offset == "" then
287 if QuestHelper_Pref.level <= 0 then
288 self:TextOut("Level offset is currently set to "..self:HighlightText(QuestHelper_Pref.level)..".")
289 else
290 self:TextOut("Level offset is currently set to "..self:HighlightText("+"..QuestHelper_Pref.level)..".")
293 if self.party_levels then for n, l in ipairs(self.party_levels) do
294 self:TextOut("Your effective level in a "..self:HighlightText(n).." player quest is "..self:HighlightText(string.format("%.1f", l))..".")
295 end end
297 if QuestHelper_Pref.solo then
298 self:TextOut("Peers aren't considered in your effective level, because you're playing solo.")
300 else
301 self:TextOut("Expected a level offset.")
305 function QuestHelper:GroupOffset(offset)
306 local group = tonumber(offset)
307 if offset == "instance" then group = 5 end
308 if offset == "raid" then group = 10 end
309 if group == 0 then group = 1 end
310 if group then
311 self:TextOut("Allowing quests requiring at most "..self:HighlightText(group).." player"..(group==1 and " " or "s ")..".")
313 if not QuestHelper_Pref.filter_group then
314 self:TextOut("Note: This won't have any effect until you turn the group filter on.")
317 QuestHelper_Pref.filter_group_param = group
318 QH_Route_Filter_Rescan("filter_quest_level")
319 elseif offset == "" then
320 self:TextOut("Group cutoff is currently set to "..self:HighlightText(QuestHelper_Pref.filter_group_param)..".")
321 else
322 self:TextOut("Expected a player count.")
326 function QuestHelper:Filter(input)
327 input = string.upper(input)
328 if input == "ZONE" then
329 QuestHelper_Pref.filter_zone = not QuestHelper_Pref.filter_zone
330 self:TextOut("Filter "..self:HighlightText("zone").." set to "..self:HighlightText(QuestHelper_Pref.filter_zone and "active" or "inactive")..".")
331 QH_Route_Filter_Rescan("filter_zone")
332 elseif input == "DONE" then
333 QuestHelper_Pref.filter_done = not QuestHelper_Pref.filter_done
334 self:TextOut("Filter "..self:HighlightText("done").." set to "..self:HighlightText(QuestHelper_Pref.filter_done and "active" or "inactive")..".")
335 QH_Route_Filter_Rescan("filter_quest_done")
336 elseif input == "LEVEL" then
337 QuestHelper_Pref.filter_level = not QuestHelper_Pref.filter_level
338 self:TextOut("Filter "..self:HighlightText("level").." set to "..self:HighlightText(QuestHelper_Pref.filter_level and "active" or "inactive")..".")
339 QH_Route_Filter_Rescan("filter_quest_level")
340 elseif input == "GROUP" then
341 QuestHelper_Pref.filter_group = not QuestHelper_Pref.filter_group
342 self:TextOut("Filter "..self:HighlightText("group").." set to "..self:HighlightText(QuestHelper_Pref.filter_group and "active" or "inactive")..".")
343 QH_Route_Filter_Rescan("filter_quest_group")
344 elseif input == "BLOCKED" or input == "BLOCK" then
345 QuestHelper_Pref.filter_blocked = not QuestHelper_Pref.filter_blocked
346 self:TextOut("Filter "..self:HighlightText("blocked").." set to "..self:HighlightText(QuestHelper_Pref.filter_blocked and "active" or "inactive")..".")
347 QH_Route_Filter_Rescan("filter_blocked")
348 elseif input == "WATCHED" or input == "WATCH" then
349 QuestHelper_Pref.filter_watched = not QuestHelper_Pref.filter_watched
350 self:TextOut("Filter "..self:HighlightText("watched").." set to "..self:HighlightText(QuestHelper_Pref.filter_watched and "active" or "inactive")..".")
351 QH_Route_Filter_Rescan("filter_quest_watched")
352 elseif input == "WINTERGRASP" or input == "WG" then
353 QuestHelper_Pref.filter_wintergrasp = not QuestHelper_Pref.filter_wintergrasp
354 self:TextOut("Filter "..self:HighlightText("wintergrasp").." set to "..self:HighlightText(QuestHelper_Pref.filter_wintergrasp and "active" or "inactive")..".")
355 QH_Route_Filter_Rescan("filter_quest_wintergrasp")
356 elseif input == "" then
357 self:TextOut("Filter "..self:HighlightText("zone")..": "..self:HighlightText(QuestHelper_Pref.filter_zone and "active" or "inactive"))
358 self:TextOut("Filter "..self:HighlightText("level")..": "..self:HighlightText(QuestHelper_Pref.filter_level and "active" or "inactive"))
359 self:TextOut("Filter "..self:HighlightText("group")..": "..self:HighlightText(QuestHelper_Pref.filter_group and "active" or "inactive"))
360 self:TextOut("Filter "..self:HighlightText("done")..": "..self:HighlightText(QuestHelper_Pref.filter_done and "active" or "inactive"))
361 self:TextOut("Filter "..self:HighlightText("blocked")..": "..self:HighlightText(QuestHelper_Pref.filter_blocked and "active" or "inactive"))
362 self:TextOut("Filter "..self:HighlightText("watched")..": "..self:HighlightText(QuestHelper_Pref.filter_watched and "active" or "inactive"))
363 self:TextOut("Filter "..self:HighlightText("wintergrasp")..": "..self:HighlightText(QuestHelper_Pref.filter_wintergrasp and "active" or "inactive"))
364 else
365 self:TextOut("Don't know what you want filtered, expect "..self:HighlightText("zone")..", "..self:HighlightText("done")..", "..self:HighlightText("level")..", "..self:HighlightText("group")..", "..self:HighlightText("blocked")..", "..self:HighlightText("watched")..", or "..self:HighlightText("wintergrasp")..".")
369 function QuestHelper:ToggleArrow(text)
370 if text == "reset" then QH_Arrow_Reset() return end
372 QuestHelper_Pref.arrow = not QuestHelper_Pref.arrow
373 if QuestHelper_Pref.arrow then
374 QH_Arrow_Show()
375 self:TextOut(QHFormat("SETTINGS_ARROWLINK_ON", QHText("SETTINGS_ARROWLINK_ARROW")))
376 else
377 self:TextOut(QHFormat("SETTINGS_ARROWLINK_OFF", QHText("SETTINGS_ARROWLINK_ARROW")))
381 function QuestHelper:ToggleCartWP()
382 QuestHelper_Pref.cart_wp_new = not QuestHelper_Pref.cart_wp_new
383 if QuestHelper_Pref.cart_wp_new then
384 self:EnableCartographer()
385 if Cartographer_Waypoints then
386 if Waypoint and Waypoint.prototype then
387 self:TextOut("Would use "..self:HighlightText("Cartographer Waypoints").." to show objectives, but another mod is interfering with it.")
388 else
389 self:TextOut(QHFormat("SETTINGS_ARROWLINK_ON", QHText("SETTINGS_ARROWLINK_CART")))
391 else
392 self:TextOut("Would use "..self:HighlightText("Cartographer Waypoints").." to show objectives, except it doesn't seem to be present.")
394 else
395 self:DisableCartographer()
396 self:TextOut(QHFormat("SETTINGS_ARROWLINK_OFF", QHText("SETTINGS_ARROWLINK_CART")))
400 function QuestHelper:ToggleTomTomWP()
401 QuestHelper_Pref.tomtom_wp_new = not QuestHelper_Pref.tomtom_wp_new
402 if QuestHelper_Pref.tomtom_wp_new then
403 self:EnableTomTom()
404 if TomTom then
405 self:TextOut(QHFormat("SETTINGS_ARROWLINK_ON", QHText("SETTINGS_ARROWLINK_TOMTOM")))
406 else
407 self:TextOut("Would use "..self:HighlightText("TomTom").." to show objectives, except it doesn't seem to be present.")
409 else
410 self:DisableTomTom()
411 self:TextOut(QHFormat("SETTINGS_ARROWLINK_OFF", QHText("SETTINGS_ARROWLINK_TOMTOM")))
415 function QuestHelper:PrintVersion()
416 self:TextOut("Version: "..self:HighlightText(GetAddOnMetadata("QuestHelper", "Version") or "Unknown"))
419 local function RecycleStatusString(fmt, usedcount, freetable, usedtable)
420 local freetablecount = QuestHelper:TableSize(freetable)
421 if usedtable then
422 local usedtablecount = QuestHelper:TableSize(usedtable)
423 return string.format(fmt, QuestHelper:ProgressString(string.format("%d/%d", usedtablecount, usedtablecount+freetablecount), ((usedtablecount+freetablecount == 0) and 1) or (1-usedtablecount/(usedtablecount+freetablecount)))) .. string.format(" (%d \"leaked\")", usedcount - usedtablecount)
424 else
425 return string.format(fmt, QuestHelper:ProgressString(string.format("%d/%d", usedcount, usedcount+freetablecount), ((usedcount+freetablecount == 0) and 1) or (1-usedcount/(usedcount+freetablecount))))
429 function QuestHelper:Top(cmd)
430 if cmd and string.find(cmd, "all") then
431 cmd = cmd .. " collected recycle clear boot usage"
434 if cmd and string.find(cmd, "boot") then
435 local bootv = {}
436 for k, v in pairs(QuestHelper_Loadtime) do
437 table.insert(bootv, {time = v, file = k})
439 table.sort(bootv, function (a, b) return a.time < b.time end)
441 if string.find(cmd, "sort") then
442 local boott = {}
443 for i = 1, #bootv - 1 do
444 table.insert(boott, {time = bootv[i + 1].time - bootv[i].time, file = bootv[i].file})
446 table.sort(boott, function(a, b) return a.time < b.time end)
448 for _, v in pairs(boott) do
449 QuestHelper:TextOut(string.format("%s: %f", v.file, v.time))
451 QuestHelper:TextOut(string.format("%s: shrug", bootv[#bootv].file))
452 else
453 for i = 1, #bootv do
454 QuestHelper:TextOut(string.format("%f: %s", bootv[i].time - bootv[1].time, bootv[i].file))
459 local pre_ttf
460 local pre_db
461 if cmd and string.find(cmd, "collected") then
462 pre_ttf = self:DumpTableTypeFrequencies(true)
463 pre_db = DB_DumpItems()
466 if cmd and string.find(cmd, "recycle") then
467 self:DumpTableTypeFrequencies()
468 self:TextOut(RecycleStatusString("Using %s lua tables.", self.used_tables, self.free_tables, self.recycle_tabletyping))
469 self:TextOut(RecycleStatusString("Using %s texture objects.", self.used_textures, self.free_textures))
470 self:TextOut(RecycleStatusString("Using %s font objects.", self.used_text, self.free_text))
471 self:TextOut(RecycleStatusString("Using %s frame objects.", self.used_frames, self.free_frames))
474 if cmd and string.find(cmd, "usage") then
475 self:DumpTableTypeFrequencies()
478 if cmd and string.find(cmd, "cache") then
479 self:DumpCacheData()
482 if cmd and string.find(cmd, "perf") then
483 QH_Timeslice_DumpPerf()
486 local uncd = 0
487 for k, v in pairs(QuestHelper_Collector) do
488 if not v.compressed then uncd = uncd + 1 end
490 uncd = uncd - 1
491 local uncs = ""
492 if uncd > 0 then
493 uncs = string.format(" (%d uncompressed IDs)", uncd)
496 UpdateAddOnMemoryUsage()
497 local pre_gc = GetAddOnMemoryUsage("QuestHelper")
499 collectgarbage("collect")
501 UpdateAddOnMemoryUsage()
502 local post_gc = GetAddOnMemoryUsage("QuestHelper")
504 if cmd and string.find(cmd, "collected") then
505 local post_ttf = self:DumpTableTypeFrequencies(true)
507 local union = {}
508 for k, v in pairs(pre_ttf) do union[k] = (pre_ttf[k] or 0) - (post_ttf[k] or 0) end
509 for k, v in pairs(post_ttf) do union[k] = (pre_ttf[k] or 0) - (post_ttf[k] or 0) end
511 local sorted = {}
512 for k, v in pairs(union) do
513 table.insert(sorted, {k = k, d = v})
516 table.sort(sorted, function(a, b) return a.d < b.d end)
517 for _, v in pairs(sorted) do
518 if v.d > 0 then
519 QuestHelper:TextOut(string.format("%d: %s", v.d, v.k))
523 local post_db = DB_DumpItems()
525 local st = {}
526 for k, v in pairs(pre_db) do
527 if not post_db[k] then
528 table.insert(st, k)
531 table.sort(st)
533 for _, v in ipairs(st) do
534 QuestHelper:TextOut("DB: " .. v)
538 self:TextOut(string.format("QuestHelper is using %dkb (pre-collect %dkb) of RAM (%s/%s/%s/%s)%s", post_gc, pre_gc, QuestHelper_local_version, QuestHelper_toc_version, GetBuildInfo(), GetLocale(), uncs))
540 if cmd and string.find(cmd, "clear") then
541 local cleared = QH_ClearPathcache()
543 collectgarbage("collect")
544 UpdateAddOnMemoryUsage()
545 local new_post_gc = GetAddOnMemoryUsage("QuestHelper")
546 self:TextOut(string.format("QuestHelper is using %dkb/%dkb/%dkb (%d pathcache cleared) of RAM (%s/%s/%s/%s)%s", pre_gc, post_gc, new_post_gc, cleared, QuestHelper_local_version, QuestHelper_toc_version, GetBuildInfo(), GetLocale(), uncs))
548 local cleared = QuestHelper:RecycleClear()
550 collectgarbage("collect")
551 UpdateAddOnMemoryUsage()
552 local new_post_gc_2 = GetAddOnMemoryUsage("QuestHelper")
553 self:TextOut(string.format("QuestHelper is using %dkb/%dkb/%dkb/%dkb (%d recycle cleared) of RAM (%s/%s/%s/%s)%s", pre_gc, post_gc, new_post_gc, new_post_gc_2, cleared, QuestHelper_local_version, QuestHelper_toc_version, GetBuildInfo(), GetLocale(), uncs))
557 function QuestHelper:ToggleMapButton()
558 QuestHelper_Pref.map_button = not QuestHelper_Pref.map_button
560 if QuestHelper_Pref.map_button then
561 QuestHelper:InitMapButton()
562 self:TextOut("Map button has been |cff00ff00enabled|r.")
563 else
564 QuestHelper:HideMapButton()
565 self:TextOut("Map button has been |cffff0000disabled|r. Use '/qh button' to restore it.")
569 function QuestHelper:ChangeLog()
570 self:ShowText(QuestHelper_ChangeLog, string.format("QuestHelper %s ChangeLog", QuestHelper_Version))
573 function QuestHelper:Submit()
574 self:ShowText([[
575 |TInterface\AddOns\QuestHelper\Art\Upload.tga:100:300|t
576 Your data can't be submitted automatically, since AddOns can't interact with anything outside of World of Warcraft.
578 To do this would require me to create some third party software, and I don't want to include such software with QuestHelper, because that's the kind of thing that ill intended people are likely to tamper with.
580 World of Warcraft stores QuestHelper's data in a file named |cff40bbffQuestHelper.lua|r.
582 To find this file, first find the the directory you installed World of Warcraft to. In Windows, this defaults to |cff40bbffC:\Program Files\World of Warcraft|r, and on Mac, I believe this is |cff40bbff/Applications/World of Warcraft|r.
584 If you're using Windows Vista, Windows might protect the Program Files directory from changes, and redirect Warcraft's saved data to |cff40bbffC:\Users\|cffff8000USER|cff40bbff\AppData\Local\VirtualStore\Program Files\World of Warcraft|r, or possibly |cff40bbffC:\Users\Public\Games\World of Warcraft|r.
586 In that directory, the needed file is in |cff40bbffWTF/Account/|cffff8000ACCOUNT|cff40bbff/SavedVariables|r, replacing ACCOUNT with the name of your account, and in that directory, you should find |cff40bbffQuestHelper.lua|r.
588 There are other directories with the names of the realms where your characters are stored, |cffffff00but don't enter them|r. They contain information specific to your characters, such as the flight points they know about, and don't contain the quest information I want.
590 After you find |cff40bbffQuestHelper.lua|r, you can email it to me here: |cff40bbffqhaddon@gmail.com|r
591 ]], "How To Submit Your Data")
594 function QuestHelper:ShowError(params)
595 if params and params == "full" then
596 QuestHelper_ErrorCatcher_GenerateReport()
598 QuestHelper_ErrorCatcher_ReportError()
601 local commands
603 function QuestHelper:Help(argument)
604 local text = ""
605 local argument = argument and argument:upper() or ""
607 for i1, cat in ipairs(commands) do
608 text = string.format("%s|cffffff00%s|r\n\n", text, cat[1])
609 for i, data in ipairs(cat[2]) do
610 if data[1]:find(argument, 1, true) then
611 text = string.format("%s |cffff8000%s|r %s\n", text, data[1], data[2])
613 if #data[3] > 0 then
614 text = string.format("%s\n %s\n", text, #data[3] == 1 and "Example:" or "Examples:")
615 for i, pair in ipairs(data[3]) do
616 text = string.format("%s |cff40bbff%s|r\n %s\n", text, pair[1], pair[2])
620 text = text .. "\n"
623 text = text .. "\n\n"
626 self:ShowText(text == "" and ("No commands containing '"..argument.."'") or text, "QuestHelper Slash Commands")
629 function QuestHelper:Donate(argument)
630 local text = ""
631 local argument = argument and argument:upper() or ""
633 for i1, cat in ipairs(commands) do
634 text = string.format("%s|cffffff00%s|r\n\n", text, cat[1])
635 for i, data in ipairs(cat[2]) do
636 if data[1]:find(argument, 1, true) then
637 text = string.format("%s |cffff8000%s|r %s\n", text, data[1], data[2])
639 if #data[3] > 0 then
640 text = string.format("%s\n %s\n", text, #data[3] == 1 and "Example:" or "Examples:")
641 for i, pair in ipairs(data[3]) do
642 text = string.format("%s |cff40bbff%s|r\n %s\n", text, pair[1], pair[2])
646 text = text .. "\n"
649 text = text .. "\n\n"
652 self:ShowText([[
653 QuestHelper currently survives on |cffff8000your donations|r. I'm trying to make this into a full-time job so I can add more features and fix bugs, and I can't do that without paying the bills.
655 There's a lot of stuff I plan to add if I can get enough donations to live off. Some of the most-requested features include:
657 |cff40bbffReduced memory and CPU usage for smoother gameplay|r
659 |cff40bbffFlying mount support for both Northrend and Outland|r
661 |cff40bbffBetter support for Northrend "phased" quests|r
663 |cff40bbffAchievementHelper, built right into QuestHelper|r
665 |cff40bbffPaths that lead you around obstacles instead of through them|r
667 I can't guarantee these will show up soon, as there's a lot of work involved in them, but every donation - no matter how small - helps!
669 To donate, open up your web browser and go to |cffff8000http://www.quest-helper.com/donate|r. Enter however much you feel comfortable donating, then bask in the knowledge that you're supporting QuestHelper.
671 Thanks!]], "Please Donate!", 500, 20, 10)
674 commands =
676 { "Common commands", {
677 {"HIDDEN",
678 "Compiles a list of objectives that QuestHelper is hiding from you. Depending on the reason, you can also unhide the objective.",
679 {}, QH_Hidden_Menu},
681 {"HIDE",
682 "Hides QuestHelper's modifications to the minimap and world map, and pauses routing calculations.",
683 {}, QuestHelper.ToggleHide, QuestHelper},
685 {"ARROW",
686 "Toggles Questhelper's built-in directional arrow.",
687 {{"/qh arrow reset", "Reset location to the center of the screen."}},
688 QuestHelper.ToggleArrow, QuestHelper},
690 {"METRIC",
691 "Toggles distance units between metres and yards.",
692 {}, QuestHelper.ToggleMetric, QuestHelper},
694 {"CARTWP",
695 "Toggles displaying the current objective using Cartographer Waypoints (must be installed separately).",
696 {}, QuestHelper.ToggleCartWP, QuestHelper},
698 {"TOMTOM",
699 "Toggles displaying the current objective using TomTom (must be installed separately).",
700 {}, QuestHelper.ToggleTomTomWP, QuestHelper},
702 {"FIND",
703 "Search for an item, location, or npc.",
704 {{"/qh find item rune of teleport", "Finds a reagent vendor."},
705 {"/qh find npc bragok", "Finds the Ratchet flight point."},
706 {"/qh find loc stormwind 50 60", "Finds the Stormwind auction house."},
707 {"/qh find loc 50 50", "Finds the center of the zone you're in."},
708 {"/qh find something", "Searches for something in all categories."},
709 {"/qh find", "Lists objectives you manually created so that you can remove them."}}, QuestHelper.PerformSearch, QuestHelper},
711 {"SOLO",
712 "Toggles solo mode. When enabled, assumes your party members don't exist. Objective sharing with party members will also be disabled.",
713 {}, QuestHelper.ToggleSolo, QuestHelper},
716 { "Objective filtering", {
717 {"FILTER",
718 "Automatically ignores/unignores objectives based on criteria.",
720 {"/qh filter level", "Toggle showing objectives that are probably too hard, by considering the levels of you and your party members, and the offset set by the level command."},
721 {"/qh filter group", "Toggle showing objectives that require groups. Automatically disables while grouped."},
723 {"/qh filter zone", "Toggle showing objectives outside the current zone."},
724 {"/qh filter done", "Toggle showing objectives for uncompleted quests."},
726 {"/qh filter blocked", "Toggle showing blocked objectives, such as quest turn-ins for incomplete quests."},
727 {"/qh filter watched", "Toggle limiting to objectives watched in the Quest Log"},
729 {"/qh filter wintergrasp", "Toggle ignoring of PvP Wintergrasp quest objectives while not in Wintergrasp"},
730 }, QuestHelper.Filter, QuestHelper},
732 {"LEVEL",
733 "Adjusts the level offset used by the level filter. Naturally, the level filter must be turned on to have an effect.",
734 {{"/qh level", "See information related to the level filter."},
735 {"/qh level 0", "Only allow objectives at or below your current level."},
736 {"/qh level +2", "Allow objectives up to two levels above your current level."},
737 {"/qh level -1", "Only allow objectives below your current level."}}, QuestHelper.LevelOffset, QuestHelper},
739 {"GROUP",
740 "Adjusts the player cutoff used by the group filter. Naturally, the group filter must be turned on to have an effect.",
741 {{"/qh group", "See information related to the group filter."},
742 {"/qh group 0", "Only allow objectives that can be done solo."},
743 {"/qh group 2", "Allow objectives that require, at most, two groupmembers."},
744 {"/qh group 5", "Allow objectives that require, at most, five groupmembers."},
745 {"/qh group instance", "Equivalent to /qh group 5."},
746 {"/qh group raid", "Equivalent to /qh group 10. All raid quests are currently assumed to be 10-person raids."},
747 }, QuestHelper.GroupOffset, QuestHelper},
749 {"SCALE",
750 "Scales the map icons used by QuestHelper. Will accept values between 50% and 300%.",
751 {{"/qh scale 1", "Uses the default icon size."},
752 {"/qh scale 2", "Makes icons twice their default size."},
753 {"/qh scale 80%", "Makes icons slightly smaller than their default size."}},
754 QuestHelper.genericSetScale, QuestHelper, "scale", "icon scale", .5, 3},
756 {"SHARE",
757 "Toggles objective sharing between QuestHelper users.",
758 {}, QuestHelper.ToggleShare, QuestHelper},
761 { "Interface", {
762 {"TRACK",
763 "Toggles the visibility of the QuestHelper's replacement quest tracker.",
764 {}, QuestHelper.ToggleTrack, QuestHelper},
766 {"TSCALE",
767 "Scales the quest tracker provided by QuestHelper. Will accept values between 50% and 300%.",
769 QuestHelper.TrackerScale, QuestHelper},
771 {"TRESET",
772 "Reset's the position of the quest tracker provided by QuestHelper, in cause you move it somewhere inaccessable.",
773 {{"/qh treset center", "Resets to the center of the screen, instead of a more normal quest tracker location."}}, QuestHelper.ResetTrackerPosition, QuestHelper},
775 {"TLEVEL",
776 "Toggles display of levels in the quest tracker provided by QuestHelper.",
777 {}, QuestHelper.ToggleTrackLevel, QuestHelper},
779 {"TQCOL",
780 "Toggles display of colours for the difficulty level of quests in the quest tracker provided by QuestHelper.",
781 {}, QuestHelper.ToggleTrackQColour, QuestHelper},
783 {"TOCOL",
784 "Toggles display of colours for objective progress in the quest tracker provided by QuestHelper.",
785 {}, QuestHelper.ToggleTrackOColour, QuestHelper},
787 {"TOOLTIP",
788 "Toggles appending information about tracked items and NPCs to their tooltips.",
789 {}, QuestHelper.ToggleTooltip, QuestHelper},
791 {"FTIME",
792 "Toggles display of flight time estimates.", {}, QuestHelper.ToggleFlightTimes, QuestHelper},
794 {"ANTS",
795 "Toggles the display of trails on the world map on and off.",
796 {}, QuestHelper.ToggleAnts, QuestHelper},
798 {"LOCALE",
799 "Select the locale to use for displayed messages.",
800 {}, QuestHelper.SetLocale, QuestHelper},
802 {"BUTTON",
803 "Toggles the display of QuestHelper's button on the world map.",
804 {}, QuestHelper.ToggleMapButton, QuestHelper},
806 {"SETTINGS",
807 "Opens the Settings menu at the current cursor location. Note that not all settings can be changed through the menu.",
808 {}, QuestHelper.DoSettingsMenu, QuestHelper},
811 { "Data collection", {
812 {"SUBMIT",
813 "Displays instructions for submitting your collected data.",
814 {}, QuestHelper.Submit, QuestHelper},
816 --[[
817 {"NAG",
818 "Tells you if you have anything that's missing from the static database. It can only check quests from your own faction, as the quests of your opposing faction are ommitted to save memory.",
819 {{"/qh nag verbose", "Prints the specific changes that were found."}}, QuestHelper.Nag, QuestHelper},]]
821 {"PURGE",
822 "Deletes all QuestHelper's collected data.", {}, QuestHelper.Purge, QuestHelper},
824 {"HARDRESET",
825 "Deletes all QuestHelper's collected data and resets QuestHelper preferences.", {}, QuestHelper.HardReset, QuestHelper},
828 { "Performance and debug", {
829 {"PERF",
830 "Sets or shows the route workload. Higher means more agressive route updating, lower means better performance Accepts numbers between 10% and 500%.",
831 {{"/qh perf", "Show current Performance Factor"},
832 {"/qh perf 1", "Sets standard performance"},
833 {"/qh perf 50%", "Does half as much background processing"},
834 {"/qh perf 3", "Computes routes 3 times more aggressively. Better have some good horsepower!"}},
835 QuestHelper.genericSetScale, QuestHelper, "perf_scale_2", "performance factor", .1, 5},
837 {"PERFLOAD",
838 "Sets or shows the initialization workload. Higher numbers will make QuestHelper load faster, lower numbers will result in better framerate while it's loading.",
839 {{"/qh perfload", "Show current Performance Factor"},
840 {"/qh perfload 1", "Sets standard performance"},
841 {"/qh perfload 50%", "Does half as much background processing"},
842 {"/qh perfload 3", "Loads 3 times as quickly."}},
843 QuestHelper.genericSetScale, QuestHelper, "perfload_scale", "boot performance factor", .2, 5},
845 {"TOP",
846 "Displays various performance stats on QuestHelper.",
848 {"/qh top recycle", "Displays detailed information on QuestHelper's recycled item pools"},
849 {"/qh top usage", "Displays detailed information on which table types are most common"},
850 {"/qh top cache", "Displays detailed information on the internal distance cache"},
851 {"/qh top perf", "Displays detailed information on coroutine CPU usage"},
852 }, QuestHelper.Top, QuestHelper},
854 {"ERROR",
855 "Displays the first QuestHelper error that has been generated this session in a form which can be copied out of WoW.",
856 {}, QuestHelper.ShowError, QuestHelper},
858 {"POS",
859 "Prints the player's current position. Exists mainly for my own personal convenience.",
860 {}, function (qh) qh:TextOut(qh:LocationString(qh.i, qh.x, qh.y) .. " " .. qh:Location_RawString(qh:Location_RawRetrieve()) .. " " .. qh:Location_AbsoluteString(qh:Location_AbsoluteRetrieve())) end, QuestHelper},
863 { "Help", {
864 {"HELP",
865 "Displays a list of help commands. Listed commands are filtered by the passed string.",
866 {}, QuestHelper.Help, QuestHelper},
868 {"VERSION",
869 "Displays QuestHelper's version.", {}, QuestHelper.PrintVersion, QuestHelper},
871 {"CHANGES",
872 "Displays a summary of changes recently made to QuestHelper.",
873 {}, QuestHelper.ChangeLog, QuestHelper},
875 --[[{"DONATE",
876 "Displays some instructions and a link for donating.",
877 {}, QuestHelper.Donate, QuestHelper},]]
880 { "Incredibly Experimental And Unsupported", {
881 {"BONFIRES",
882 "Adds waypoints for the Midsummer Bonfires.",
883 {}, QH_AddFires},
887 function QuestHelper_SlashCommand(input)
888 local _, _, command, argument = string.find(input, "^%s*([^%s]-)%s+(.-)%s*$")
889 if not command then
890 command, argument = input, ""
893 command = string.upper(command)
895 for i1, cat in ipairs(commands) do
896 for i, data in ipairs(cat[2]) do
897 if data[1] == command then
898 local st = {}
900 for i = 5,#data do table.insert(st, data[i]) end
901 table.insert(st, argument)
903 if type(data[4]) == "function" then
904 data[4](unpack(st))
905 else
906 QuestHelper:TextOut(data[1].." is not yet implemented.")
909 return
914 QuestHelper:Help()
917 SLASH_QuestHelper1 = "/qh"
918 SLASH_QuestHelper2 = "/questhelper"
919 SlashCmdList["QuestHelper"] = function (text) QuestHelper_SlashCommand(text) end