1 local function FindStaticQuest(faction
, level
, name
, hash
)
2 local data
= QuestHelper_StaticData
[QuestHelper
.locale
]
3 data
= data
and data
.quest
4 data
= data
and data
[faction
]
5 data
= data
and data
[level
]
6 data
= data
and data
[name
]
7 if data
and data
.hash
and data
.hash
~= hash
then
8 data
= data
.alt
and data
.alt
[hash
]
13 local function FindStaticObjective(cat
, name
)
14 local data
= QuestHelper_StaticData
[QuestHelper
.locale
]
15 data
= data
and data
.objective
16 data
= data
and data
[cat
]
17 return data
and data
[name
]
20 local function ListUpdated(list
, static
, compare
, weight
)
21 if not list
then return false end
22 if not static
then return true end
26 for _
, b
in ipairs(static
) do
27 high
= math
.max(high
, weight(b
))
30 for _
, a
in ipairs(list
) do
33 for _
, b
in ipairs(static
) do
34 if weight(a
) < high
*0.2 or compare(a
, b
) then
40 if not found
then return true end
45 local function PositionWeight(a
)
49 local function PositionCompare(a
, b
)
50 return a
[1] == b
[1] and
51 (a
[2]-b
[2])*(a
[2]-b
[2])+(a
[3]-b
[3])*(a
[3]-b
[3]) < 0.05*0.05
54 local function VendorCompare(a
, b
)
58 local function VendorWeight(a
)
62 local function PositionListUpdated(list
, static
)
63 return ListUpdated(list
, static
, PositionCompare
, PositionWeight
)
66 local function VendorListUpdated(list
, static
)
67 return ListUpdated(list
, static
, VendorCompare
, VendorWeight
)
70 local function DropListUpdated(list
, static
)
71 if not list
then return false end
72 if not static
then return next(list
, nil) ~= nil end
75 for name
in pairs(list
) do
76 local monster_obj
= FindStaticObjective("monster", name
)
77 if monster_obj
and monster_obj
.looted
and monster_obj
.looted
> 0 then
78 high
= math
.max(high
, (static
[name
] or 0)/monster_obj
.looted
)
82 for name
, v
in pairs(list
) do
83 local monster_obj1
= QuestHelper
:GetObjective("monster", name
)
84 local monster_obj2
= FindStaticObjective("monster", name
)
86 local looted
= math
.ceil((monster_obj1
.looted
or 0)+((monster_obj2
and monster_obj2
.looted
) or 0))
88 v
= math
.max(1, math
.floor(v
))/looted
89 if v
> high
*0.2 and not static
[name
] then return true end
95 local function DropListMass(list
)
96 if not list
then return 0 end
98 for item
, count
in pairs(list
) do
104 local function PositionListMass(list
)
105 if not list
then return 0 end
107 for _
, pos
in ipairs(list
) do
113 local function CompareStaticQuest(info
, faction
, level
, name
, hash
, data
, verbose
)
114 local static
= FindStaticQuest(faction
, level
, name
, hash
)
117 if data
.finish
or data
.pos
then
118 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing.") end
119 info
.new
.quest
= (info
.new
.quest
or 0) + 1
124 local updated
= false
126 if data
.finish
and data
.finish
~= static
.finish
then
127 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing finish NPC "..QuestHelper
:HighlightText(data
.finish
)..".") end
129 elseif not static
.finish
and PositionListUpdated(data
.pos
, static
.pos
) then
130 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing finish location.") end
132 elseif data
.item
then
133 for item_name
, item
in pairs(data
.item
) do
134 local static_item
= (static
.item
and static
.item
[item_name
]) or FindStaticObjective("item", item_name
)
136 if not static_item
then
137 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing item "..QuestHelper
:HighlightText(item_name
)..".") end
140 elseif item
.drop
then
141 if DropListUpdated(item
.drop
, static_item
.drop
) then
142 if DropListMass(item
.drop
) > PositionListMass(static_item
.pos
) then
143 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing drop for item "..QuestHelper
:HighlightText(item_name
)..".") end
148 elseif item
.pos
and not static_item
.drop
and PositionListUpdated(item
.pos
, static_item
.pos
) then
149 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing position for item "..QuestHelper
:HighlightText(item_name
)..".") end
157 info
.update
.quest
= (info
.update
.quest
or 0)+1
161 local function CompareStaticObjective(info
, cat
, name
, data
, verbose
)
163 local static
= FindStaticObjective(cat
, name
)
165 if data
.pos
or data
.drop
or data
.vendor
then
166 if verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing.") end
167 info
.new
[cat
.."_obj"] = (info
.new
[cat
.."_obj"] or 0)+1
172 local updated
= false
175 updated
= VendorListUpdated(data
.vendor
, static
.vendor
)
176 if updated
and verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing vendor.") end
177 elseif data
.drop
and not static
.vendor
then
178 updated
= DropListUpdated(data
.drop
, static
.drop
) and DropListMass(data
.drop
) > PositionListMass(static
.pos
)
179 if updated
and verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing monster drop.") end
180 elseif data
.pos
and not static
.vendor
and not static
.drop
then
181 if updated
and verbose
then QuestHelper
:TextOut(Qstring
.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing position.") end
182 updated
= PositionListUpdated(data
.pos
, static
.pos
)
186 info
.update
[cat
.."_obj"] = (info
.update
[cat
.."_obj"] or 0)+1
191 function QuestHelper
:Nag(cmd
)
192 local verbose
, local_only
= false, true
195 if string.find(cmd
, "verbose") then verbose
= true end
196 if string.find(cmd
, "all") then local_only
= false end
205 for faction
, level_list
in pairs(QuestHelper_Quests
) do
206 if not local_only
or faction
== self
.faction
then
207 for level
, name_list
in pairs(level_list
) do
208 for name
, data
in pairs(name_list
) do
209 CompareStaticQuest(info
, faction
, level
, name
, data
.hash
, data
, verbose
)
211 for hash
, data
in pairs(data
.alt
) do
212 CompareStaticQuest(info
, faction
, level
, name
, hash
, data
, verbose
)
220 for cat
, name_list
in pairs(QuestHelper_Objectives
) do
221 for name
, obj
in pairs(name_list
) do
222 CompareStaticObjective(info
, cat
, name
, obj
, verbose
)
226 for faction
, location_list
in pairs(QuestHelper_FlightInstructors
) do
227 if not local_only
or faction
== self
.faction
then
228 for location
, npc
in pairs(location_list
) do
229 local data
= QuestHelper_StaticData
[self
.locale
]
230 data
= data
and data
.flight_instructors
231 data
= data
and data
[faction
]
232 data
= data
and data
[location
]
234 if not data
or data
~= npc
then
235 if verbose
then self
:TextOut(QuestHelper
:HighlightText(faction
).." flight master "..QuestHelper
:HighlightText(npc
).." was missing.") end
236 info
.new
["fp"] = (info
.new
["fp"] or 0)+1
242 for faction
, start_list
in pairs(QuestHelper_FlightRoutes
) do
243 if not local_only
or faction
== self
.faction
then
244 for start
, dest_list
in pairs(start_list
) do
245 for dest
, hash_list
in pairs(dest_list
) do
246 for hash
, data
in pairs(hash_list
) do
247 local static
= QuestHelper_StaticData
[self
.locale
]
248 static
= static
and static
.flight_routes
249 static
= static
and static
[faction
]
250 static
= static
and static
[start
]
251 static
= static
and static
[dest
]
252 static
= static
and static
[hash
]
254 if not static
or static
== true and type(data
) == "number" then
255 if verbose
then self
:TextOut("Flight time from "..QuestHelper
:HighlightText((select(3, string.find(start
, "^(.*),")) or start
)).." to "..QuestHelper
:HighlightText((select(3, string.find(dest
, "^(.*),")) or dest
)).." was missing.") end
256 info
.new
["route"] = (info
.new
["route"] or 0)+1
266 for what
, count
in pairs(info
.new
) do
267 total
= total
+ count
268 local count2
= info
.update
[what
]
270 total
= total
+ count2
271 self
:TextOut(QHFormat("NAG_MULTIPLE_NEW", count
, count2
, QHText("NAG_"..string.upper(what
))))
273 self
:TextOut(QHFormat("NAG_SINGLE_NEW", QHFormat(count
==1 and "NAG_SINGLE" or "NAG_PLURAL", count
, QHText("NAG_"..string.upper(what
)))))
277 for what
, count
in pairs(info
.update
) do
278 if not info
.new
[what
] then
279 total
= total
+ count
280 self
:TextOut(QHFormat("NAG_ADDITIONAL", QHFormat(count
==1 and "NAG_SINGLE" or "NAG_PLURAL", count
, QHText("NAG_"..string.upper(what
)))))
285 self
:TextOut(QHText("NAG_NOT_NEW"))
287 self
:TextOut(QHText("NAG_NEW"))
290 DEFAULT_CHAT_FRAME
:AddMessage("|TInterface\\AddOns\\QuestHelper\\Art\\Upload.tga:300:90|t")