1 QuestHelper_File
["upgrade.lua"] = "Development Version"
2 QuestHelper_Loadtime
["upgrade.lua"] = GetTime()
14 [9]="Dustwallow Marsh",
21 [16]="Stonetalon Mountains",
26 [21]="Thousand Needles",
28 [23]="Un'Goro Crater",
30 {[0]="Eastern Kingdoms",
31 [1]="Alterac Mountains",
32 [2]="Arathi Highlands",
35 [5]="Burning Steppes",
39 [9]="Eastern Plaguelands",
41 [11]="Eversong Woods",
43 [13]="Hillsbrad Foothills",
45 [15]="Isle of Quel'Danas",
47 [17]="Redridge Mountains",
49 [19]="Silvermoon City",
50 [20]="Silverpine Forest",
51 [21]="Stormwind City",
52 [22]="Stranglethorn Vale",
53 [23]="Swamp of Sorrows",
54 [24]="The Hinterlands",
55 [25]="Tirisfal Glades",
57 [27]="Western Plaguelands",
61 [1]="Blade's Edge Mountains",
62 [2]="Hellfire Peninsula",
65 [5]="Shadowmoon Valley",
67 [7]="Terokkar Forest",
71 [2]="Crystalsong Forest",
78 [9]="The Storm Peaks",
82 [-77]={[0]="ScarletEnclave_Continent", [1]="ScarletEnclave"},
86 -- This will be translated to [LOCALE_NAME] = INDEX by QuestHelper_BuildZoneLookup.
87 -- Additionally, [CONT_INDEX][ZONE_INDEX] = INDEX will also be added.
88 QuestHelper_IndexLookup
=
89 {["Hinterlands"] = {42, 2, 24},
90 ["Moonglade"] = {20, 1, 12},
91 ["ThousandNeedles"] = {14, 1, 21},
92 ["Winterspring"] = {19, 1, 24},
93 ["BloodmystIsle"] = {9, 1, 4},
94 ["TerokkarForest"] = {55, 3, 7},
95 ["Arathi"] = {39, 2, 2},
96 ["EversongWoods"] = {41, 2, 11},
97 ["Dustwallow"] = {10, 1, 9},
98 ["Badlands"] = {27, 2, 3},
99 ["Darkshore"] = {16, 1, 5},
100 ["Ogrimmar"] = {1, 1, 14},
101 ["BladesEdgeMountains"] = {54, 3, 1},
102 ["Undercity"] = {45, 2, 26},
103 ["Desolace"] = {4, 1, 7},
104 ["Netherstorm"] = {59, 3, 4},
105 ["Barrens"] = {11, 1, 19},
106 ["Tanaris"] = {8, 1, 17},
107 ["Stormwind"] = {36, 2, 21},
108 ["Zangarmarsh"] = {57, 3, 8},
109 ["Durotar"] = {7, 1, 8},
110 ["Hellfire"] = {56, 3, 2},
111 ["Silithus"] = {5, 1, 15},
112 ["ShattrathCity"] = {60, 3, 6},
113 ["ShadowmoonValley"] = {53, 3, 5},
114 ["SwampOfSorrows"] = {46, 2, 23},
115 ["SilvermoonCity"] = {52, 2, 19},
116 ["Darnassis"] = {21, 1, 6},
117 ["AzuremystIsle"] = {3, 1, 3},
118 ["Elwynn"] = {37, 2, 10},
119 ["Stranglethorn"] = {38, 2, 22},
120 ["EasternPlaguelands"] = {34, 2, 9},
121 ["Duskwood"] = {31, 2, 8},
122 ["WesternPlaguelands"] = {50, 2, 27},
123 ["Westfall"] = {49, 2, 28},
124 ["Ashenvale"] = {2, 1, 1},
125 ["Teldrassil"] = {24, 1, 18},
126 ["Redridge"] = {30, 2, 17},
127 ["UngoroCrater"] = {18, 1, 23},
128 ["Mulgore"] = {22, 1, 13},
129 ["Ironforge"] = {25, 2, 14},
130 ["Felwood"] = {13, 1, 10},
131 ["Hilsbrad"] = {48, 2, 13},
132 ["DeadwindPass"] = {47, 2, 6},
133 ["BurningSteppes"] = {40, 2, 5},
134 ["Ghostlands"] = {44, 2, 12},
135 ["Tirisfal"] = {43, 2, 25},
136 ["TheExodar"] = {12, 1, 20},
137 ["Wetlands"] = {51, 2, 29},
138 ["SearingGorge"] = {32, 2, 18},
139 ["BlastedLands"] = {33, 2, 4},
140 ["Silverpine"] = {35, 2, 20},
141 ["LochModan"] = {29, 2, 16},
142 ["Feralas"] = {17, 1, 11},
143 ["DunMorogh"] = {28, 2, 7},
144 ["Alterac"] = {26, 2, 1},
145 ["ThunderBluff"] = {23, 1, 22},
146 ["Aszhara"] = {15, 1, 2},
147 ["StonetalonMountains"] = {6, 1, 16},
148 ["Nagrand"] = {58, 3, 3},
149 ["Kalimdor"] = {61, 1, 0},
150 ["Azeroth"] = {62, 2, 0},
151 ["Expansion01"] = {63, 3, 0},
152 ["Sunwell"] = {64, 2, 15},
154 ["Northrend"] = {76, 4, 0},
155 ["BoreanTundra"] = {65, 4, 1},
156 ["CrystalsongForest"] = {66, 4, 2},
157 ["Dalaran"] = {67, 4, 3},
158 ["Dragonblight"] = {68, 4, 4},
159 ["GrizzlyHills"] = {69, 4, 5},
160 ["HowlingFjord"] = {70, 4, 6},
161 ["IcecrownGlacier"] = {71, 4, 7},
162 ["SholazarBasin"] = {72, 4, 8},
163 ["TheStormPeaks"] = {73, 4, 9},
164 ["LakeWintergrasp"] = {74, 4, 10},
165 ["ZulDrak"] = {75, 4, 11},
167 ["ScarletEnclave_Continent"] = {77, -77, 0},
168 ["ScarletEnclave"] = {78, -77, 1},
171 QuestHelper_RestrictedZones
= { -- Everything defaults to "nil"
176 for i
, j
in pairs(QuestHelper_IndexLookup
) do next_index
= math
.max(next_index
, j
[1]+1) end
178 -- Maps zone names and indexes to a two element array, containing zone index a continent/zone
179 QuestHelper_ZoneLookup
= {}
181 -- Maps indexes to zone names.
182 QuestHelper_NameLookup
= {}
186 function QuestHelper_BuildZoneLookup()
187 if built
then return end
190 if GetMapContinents
and GetMapZones
then
191 -- Called from inside the WoW client.
193 local original_lookup
, original_zones
= QuestHelper_IndexLookup
, QuestHelper_Zones
194 QuestHelper_IndexLookup
= {}
195 QuestHelper_Zones
= {}
197 for c
, cname
in pairs(QuestHelper
.Astrolabe
:GetMapVirtualContinents()) do
198 QuestHelper_Zones
[c
] = {}
199 local tpx
= QuestHelper
.Astrolabe
:GetMapVirtualZones(c
)
201 for z
, zname
in pairs(tpx
) do
203 local base_name
= QuestHelper
.Astrolabe
:GetMapTexture(c
, z
)
205 local index
= original_lookup
[base_name
] and original_lookup
[base_name
][1]
207 local altered_index
= "!!! QuestHelper_IndexLookup entry needs update: [%q] = {%s, %s, %s}"
208 local altered_zone
= "!!! QuestHelper_Zones entry needs update: [%s][%s] = %q -- was %s"
211 QuestHelper
:TextOut(altered_index
:format(base_name
, next_index
, c
, z
))
212 next_index
= next_index
+ 1
214 if QuestHelper_Locale
== "enUS" then
215 if original_lookup
[base_name
][2] ~= c
or original_lookup
[base_name
][3] ~= z
then
216 QuestHelper
:TextOut(altered_index
:format(base_name
, index
, c
, z
))
219 if not original_zones
[c
] or original_zones
[c
][z
] ~= zname
then
220 QuestHelper
:TextOut(altered_zone
:format(c
, z
, zname
, original_zones
[c
] and original_zones
[c
][z
] or "missing"))
225 if not QuestHelper_IndexLookup
[c
] then QuestHelper_IndexLookup
[c
] = {} end
226 QuestHelper_IndexLookup
[c
][z
] = index
227 QuestHelper_IndexLookup
[zname
] = index
229 QuestHelper_NameLookup
[index
] = zname
231 QuestHelper_ZoneLookup
[zname
] = pair
232 QuestHelper_ZoneLookup
[index
] = pair
234 QuestHelper_Zones
[c
][z
] = zname
239 for name
, index
in pairs(original_lookup
) do
240 if index
[2] == -1 then
241 assert(not QuestHelper_IndexLookup
[name
])
242 QuestHelper_IndexLookup
[name
] = index
[1]
246 -- Called from some lua script.
247 local original_lookup
= QuestHelper_IndexLookup
248 QuestHelper_IndexLookup
= {}
250 for base_name
, i
in pairs(original_lookup
) do
252 local pair
= {i
[2], i
[3]}
253 local name
= QuestHelper_Zones
[pair
[1]]
[pair
[2]]
255 assert(index
and name
)
257 if not QuestHelper_IndexLookup
[pair
[1]]
then QuestHelper_IndexLookup
[pair
[1]]
= {} end
258 QuestHelper_IndexLookup
[pair
[1]]
[pair
[2]]
= index
259 QuestHelper_IndexLookup
[name
] = index
261 QuestHelper_NameLookup
[index
] = name
263 QuestHelper_ZoneLookup
[name
] = pair
264 QuestHelper_ZoneLookup
[index
] = pair
269 local convert_lookup
=
270 {{2, 15, 3, 9, 16, 21, 4, 7, 10, 13, 17, 20, 22, 1, 5, 6, 8, 24, 11, 12, 14, 23, 18, 19},
271 {26, 39, 27, 33, 40, 47, 28, 31, 34, 37, 41, 44, 48, 25, 29, 30, 32, 52, 35, 36, 38, 46, 42, 43, 45, 50, 49, 51},
272 {54, 56, 58, 59, 53, 60, 55, 57}}
274 function QuestHelper_ValidPosition(c
, z
, x
, y
)
275 return type(x
) == "number" and type(y
) == "number" and x
> -0.1 and y
> -0.1 and x
< 1.1 and y
< 1.1 and c
and convert_lookup
[c
] and z
and convert_lookup
[c
][z
] and true
278 function QuestHelper_PrunePositionList(list
)
279 if type(list
) ~= "table" then
286 if QuestHelper_ValidPosition(unpack(list
[i
])) and type(pos
[5]) == "number" and pos
[5] >= 1 then
289 local rem
= table.remove(list
, i
)
293 return #list
> 0 and list
or nil
296 local function QuestHelper_ConvertPosition(pos
)
297 pos
[2] = convert_lookup
[pos
[1]]
[pos
[2]]
301 local function QuestHelper_ConvertPositionList(list
)
303 for i
, pos
in pairs(list
) do
304 QuestHelper_ConvertPosition(pos
)
309 local function QuestHelper_ConvertFaction(faction
)
310 if faction
== 1 or faction
== "Alliance" or faction
== FACTION_ALLIANCE
then return 1
311 elseif faction
== 2 or faction
== "Horde" or faction
== FACTION_HORDE
then return 2
313 assert(false, "Unknown faction: "..faction
.."'")
317 function QuestHelper_UpgradeDatabase(data
)
318 if data
.QuestHelper_SaveVersion
== 1 then
320 -- Reputation objectives weren't parsed correctly before.
321 if data
.QuestHelper_Objectives
["reputation"] then
322 for faction
, objective
in pairs(data
.QuestHelper_Objectives
["reputation"]) do
323 local real_faction
= string.find(faction
, "%s*(.+)%s*:%s*") or faction
324 if faction
~= real_faction
then
325 data
.QuestHelper_Objectives
["reputation"][real_faction
] = data
.QuestHelper_Objectives
["reputation"][faction
]
326 data
.QuestHelper_Objectives
["reputation"][faction
] = nil
331 -- Items that wern't in the local cache when I read the quest log ended up with empty names.
332 if data
.QuestHelper_Objectives
["item"] then
333 data
.QuestHelper_Objectives
["item"][" "] = nil
336 data
.QuestHelper_SaveVersion
= 2
339 if data
.QuestHelper_SaveVersion
== 2 then
341 -- The hashes for the quests were wrong. Damnit!
342 for faction
, level_list
in pairs(data
.QuestHelper_Quests
) do
343 for level
, quest_list
in pairs(level_list
) do
344 for quest_name
, quest_data
in pairs(quest_list
) do
345 quest_data
.hash
= nil
351 -- None of the information I collected about quest items previously can be trusted.
352 -- I also didn't properly mark quest items as such, so I'll have to remove the information for non
355 if data
.QuestHelper_Objectives
["item"] then
356 for item
, item_data
in pairs(data
.QuestHelper_Objectives
["item"]) do
357 -- I'll remerge the bad data later if I find out its not used solely for quests.
358 item_data
.bad_pos
= item_data
.bad_pos
or item_data
.pos
359 item_data
.bad_drop
= item_data
.bad_drop
or item_data
.drop
363 -- In the future i'll delete the bad_x data.
364 -- When I do, either just delete it, or of all the monsters or positions match the monsters and positions of the
365 -- quest, merge them into that.
369 data
.QuestHelper_SaveVersion
= 3
372 if data
.QuestHelper_SaveVersion
== 3 then
373 -- We'll go through this and make sure all the position lists are correct.
374 for faction
, level_list
in pairs(data
.QuestHelper_Quests
) do
375 for level
, quest_list
in pairs(level_list
) do
376 for quest_name
, quest_data
in pairs(quest_list
) do
377 quest_data
.pos
= QuestHelper_PrunePositionList(quest_data
.pos
)
378 if quest_data
.item
then for name
, data
in pairs(quest_data
.item
) do
379 data
.pos
= QuestHelper_PrunePositionList(data
.pos
)
381 if quest_data
.alt
then for hash
, data
in pairs(quest_data
.alt
) do
382 data
.pos
= QuestHelper_PrunePositionList(data
.pos
)
383 if data
.item
then for name
, data
in pairs(data
.item
) do
384 data
.pos
= QuestHelper_PrunePositionList(data
.pos
)
391 for cat
, list
in pairs(data
.QuestHelper_Objectives
) do
392 for name
, data
in pairs(list
) do
393 data
.pos
= QuestHelper_PrunePositionList(data
.pos
)
397 if data
.QuestHelper_ZoneTransition
then
398 for c
, z1list
in pairs(data
.QuestHelper_ZoneTransition
) do
399 for z1
, z2list
in pairs(z1list
) do
400 for z2
, poslist
in pairs(z2list
) do
401 z2list
[z2
] = QuestHelper_PrunePositionList(poslist
)
407 data
.QuestHelper_SaveVersion
= 4
410 if data
.QuestHelper_SaveVersion
== 4 then
411 -- Zone transitions have been obsoleted by a bug.
412 data
.QuestHelper_ZoneTransition
= nil
413 data
.QuestHelper_SaveVersion
= 5
416 if data
.QuestHelper_SaveVersion
== 5 then
417 -- For version 6, I'm converting area positions from a continent/zone index pair to a single index.
419 if data
.QuestHelper_FlightRoutes
then
420 local old_routes
= data
.QuestHelper_FlightRoutes
421 data
.QuestHelper_FlightRoutes
= {}
422 for c
, value
in pairs(old_routes
) do
423 data
.QuestHelper_FlightRoutes
[QuestHelper_IndexLookup
[c
][0]]
= value
427 for faction
, level_list
in pairs(data
.QuestHelper_Quests
) do
428 for level
, quest_list
in pairs(level_list
) do
429 for quest_name
, quest_data
in pairs(quest_list
) do
430 QuestHelper_ConvertPositionList(quest_data
.pos
)
431 if quest_data
.item
then for name
, data
in pairs(quest_data
.item
) do
432 QuestHelper_ConvertPositionList(data
.pos
)
434 if quest_data
.alt
then for hash
, data
in pairs(quest_data
.alt
) do
435 QuestHelper_ConvertPositionList(data
.pos
)
436 if data
.item
then for name
, data
in pairs(data
.item
) do
437 QuestHelper_ConvertPositionList(data
.pos
)
444 for cat
, list
in pairs(data
.QuestHelper_Objectives
) do
445 for name
, data
in pairs(list
) do
446 QuestHelper_ConvertPositionList(data
.pos
)
450 data
.QuestHelper_SaveVersion
= 6
453 if data
.QuestHelper_SaveVersion
== 6 then
454 -- Redoing how flightpaths work, previously collected flightpath data is now obsolete.
455 data
.QuestHelper_FlightRoutes
= {}
457 -- FlightInstructors table should be fine, will leave it.
458 -- Upgrading per-character data is handled in main.lua.
460 -- Also converting factions to numbers, 1 for Alliance, 2 for Horde.
461 local replacement
= {}
462 for faction
, dat
in pairs(data
.QuestHelper_Quests
) do
463 replacement
[QuestHelper_ConvertFaction(faction
)] = dat
465 data
.QuestHelper_Quests
= replacement
468 if data
.QuestHelper_FlightInstructors
then for faction
, dat
in pairs(data
.QuestHelper_FlightInstructors
) do
469 replacement
[QuestHelper_ConvertFaction(faction
)] = dat
471 data
.QuestHelper_FlightInstructors
= replacement
473 for cat
, list
in pairs(data
.QuestHelper_Objectives
) do
474 for name
, obj
in pairs(list
) do
476 obj
.faction
= QuestHelper_ConvertFaction(obj
.faction
)
481 data
.QuestHelper_SaveVersion
= 7
484 if data
.QuestHelper_SaveVersion
== 7 then
485 -- It sure took me long enough to discover that I broke vendor objectives.
486 -- their factions were strings and didn't match the number value of QuestHelper.faction
488 for cat
, list
in pairs(data
.QuestHelper_Objectives
) do
489 for name
, obj
in pairs(list
) do
490 if type(obj
.faction
) == "string" then
491 obj
.faction
= (obj
.faction
== "Alliance" and 1) or (obj
.faction
== "Horde" and 2) or nil
496 data
.QuestHelper_SaveVersion
= 8
499 if data
.QuestHelper_SaveVersion
== 8 then
500 -- Two things we're doing here
501 -- First, wrath-ize Stormwind coordinates
504 for cat, list in pairs(QuestHelper_Objectives) do
505 for name, obj in pairs(list) do
507 for i, cpos in pairs(obj.pos) do
508 QuestHelper_ConvertCoordsToWrath(cpos, true)
512 end]] -- okay we're not actually doing this, coordinates are staying native
514 -- Second, split up the entire thing into versions
515 local function versionize(item
)
516 --if not item or type(item) ~= "table" then return end -- blue magician doesn't know what the fuck
519 local foundthings
= false
520 for k
, v
in pairs(item
) do
524 if not foundthings
then return end -- just to avoid extra keys hanging around in people's tables
526 for key
in pairs(item
) do
530 item
["unknown on unknown"] = temp
533 versionize(data
.QuestHelper_Quests
)
534 versionize(data
.QuestHelper_Objectives
)
535 versionize(data
.QuestHelper_FlightInstructors
)
536 versionize(data
.QuestHelper_FlightRoutes
)
538 data
.QuestHelper_SaveVersion
= 9
541 if data
.QuestHelper_SaveVersion
== 9 then
542 -- The only thing we're doing here is moving the QuestHelper_ErrorList into QuestHelper_Errors
543 data
.QuestHelper_Errors
= {}
544 data
.QuestHelper_Errors
.crashes
= {}
546 if data
.QuestHelper_ErrorList
then
547 for k
, v
in pairs(data
.QuestHelper_ErrorList
) do
548 data
.QuestHelper_Errors
.crashes
[k
] = v
552 data
.QuestHelper_ErrorList
= nil
554 data
.QuestHelper_SaveVersion
= 10
558 function QuestHelper_UpgradeComplete()
559 -- This function deletes everything related to upgrading, as it isn't going to be needed again.
563 QuestHelper_BuildZoneLookup
= nil
564 QuestHelper_ValidPosition
= nil
565 QuestHelper_PrunePositionList
= nil
566 QuestHelper_ConvertPosition
= nil
567 QuestHelper_ConvertPositionList
= nil
568 QuestHelper_ConvertFaction
= nil
569 QuestHelper_UpgradeDatabase
= nil
570 QuestHelper_UpgradeComplete
= nil
573 -- These are used to convert coordinates back and forth from "Wrath" to "Native". "Force" is used to convert back and forth from "Wrath" to "BC".
574 -- Both changes the data in-place and returns the data.
575 function QuestHelper_ConvertCoordsToWrath(data
, force
)
576 if (force
or not QuestHelper
:IsWrath()) then
577 if data
[1] == 36 then -- Stormwind
578 data
[2] = data
[2] * 0.77324 + 0.197
579 data
[3] = data
[3] * 0.77324 + 0.245
580 elseif data
[1] == 34 then -- EPL
581 data
[2] = data
[2] * 0.960 - 0.0254
582 data
[3] = data
[3] * 0.960 - 0.03532
588 function QuestHelper_ConvertCoordsFromWrath(data
, force
)
589 if (force
or not QuestHelper
:IsWrath()) then
590 if data
[1] == 36 then -- Stormwind
591 data
[2] = (data
[2] - 0.197) / 0.77324
592 data
[3] = (data
[3] - 0.245) / 0.77324
593 elseif data
[1] == 34 then -- EPL
594 data
[2] = (data
[2] + 0.0254) / 0.960
595 data
[3] = (data
[3] + 0.03532) / 0.960
601 local QuestHelper_PrivateServerBlacklist_Find
= {
608 local QuestHelper_PrivateServerBlacklist_Exact
= {
612 "Columbian Drug Dealer",
613 "PlayBoy Fun Vendor",
615 "Accessories Vendor",
616 "General Goods Vendor",
626 "Fooooood and Drinks!",
627 "I Sell Consumables",
629 "Bobby", -- I have no idea if this is an actual private server NPC
632 local matchstring
= nil
634 function QuestHelper_IsPolluted(input
)
635 if not input
then input
= _G
end
637 for version
, data
in pairs(input
.QuestHelper_Objectives
) do
638 for cat
, name_list
in pairs(data
) do
639 for name
, obj
in pairs(name_list
) do
640 for k
, v
in pairs(QuestHelper_PrivateServerBlacklist_Find
) do
641 if string.find(name
, v
) then
642 for _
, __
in pairs(obj
) do
643 return true -- if there's nothing actually in the object, the player may not have contributed data, he may have just gotten smacked by old corrupted data.
647 for k
, v
in pairs(QuestHelper_PrivateServerBlacklist_Exact
) do
649 for _
, __
in pairs(obj
) do
650 return true -- if there's nothing actually in the object, the player may not have contributed data, he may have just gotten smacked by old corrupted data.