1 QuestHelper_File
["nag.lua"] = "Development Version"
3 local function FindStaticQuest(faction
, level
, name
, hash
)
4 local data
= QuestHelper_StaticData
[QuestHelper
.locale
]
5 data
= data
and data
.quest
6 data
= data
and data
[faction
]
7 data
= data
and data
[level
]
8 data
= data
and data
[name
]
9 if data
and data
.hash
and data
.hash
~= hash
then
10 data
= data
.alt
and data
.alt
[hash
]
15 local function FindStaticObjective(cat
, name
)
16 local data
= QuestHelper_StaticData
[QuestHelper
.locale
]
17 data
= data
and data
.objective
18 data
= data
and data
[cat
]
19 return data
and data
[name
]
22 local function ListUpdated(list
, static
, compare
, weight
)
23 if not list
then return false end
24 if not static
then return true end
28 for _
, b
in ipairs(static
) do
29 high
= math
.max(high
, weight(b
))
32 for _
, a
in ipairs(list
) do
35 for _
, b
in ipairs(static
) do
36 if weight(a
) < high
*0.2 or compare(a
, b
) then
42 if not found
then return true end
47 local function PositionWeight(a
)
51 local function PositionCompare(a
, b
)
52 return a
[1] == b
[1] and
53 (a
[2]-b
[2])*(a
[2]-b
[2])+(a
[3]-b
[3])*(a
[3]-b
[3]) < 0.05*0.05
56 local function VendorCompare(a
, b
)
60 local function VendorWeight(a
)
64 local function PositionListUpdated(list
, static
)
65 return ListUpdated(list
, static
, PositionCompare
, PositionWeight
)
68 local function VendorListUpdated(list
, static
)
69 return ListUpdated(list
, static
, VendorCompare
, VendorWeight
)
72 local function DropListUpdated(list
, static
)
73 if not list
then return false end
74 if not static
then return next(list
, nil) ~= nil end
77 for name
in pairs(list
) do
78 local monster_obj
= FindStaticObjective("monster", name
)
79 if monster_obj
and monster_obj
.looted
and monster_obj
.looted
> 0 then
80 high
= math
.max(high
, (static
[name
] or 0)/monster_obj
.looted
)
84 for name
, v
in pairs(list
) do
85 local monster_obj1
= QuestHelper
:GetObjective("monster", name
)
86 local monster_obj2
= FindStaticObjective("monster", name
)
88 local looted
= math
.ceil((monster_obj1
.looted
or 0)+((monster_obj2
and monster_obj2
.looted
) or 0))
90 v
= math
.max(1, math
.floor(v
))/looted
91 if v
> high
*0.2 and not static
[name
] then return true end
97 local function DropListMass(list
)
98 if not list
then return 0 end
100 for item
, count
in pairs(list
) do
106 local function PositionListMass(list
)
107 if not list
then return 0 end
109 for _
, pos
in ipairs(list
) do
115 local function CompareStaticQuest(info
, faction
, level
, name
, hash
, data
, verbose
)
116 local static
= FindStaticQuest(faction
, level
, name
, hash
)
119 if data
.finish
or data
.pos
then
120 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing.") end
121 info
.new
.quest
= (info
.new
.quest
or 0) + 1
126 local updated
= false
128 if data
.finish
and data
.finish
~= static
.finish
then
129 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing finish NPC "..QuestHelper
:HighlightText(data
.finish
)..".") end
131 elseif not static
.finish
and PositionListUpdated(data
.pos
, static
.pos
) then
132 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing finish location.") end
134 elseif data
.item
then
135 for item_name
, item
in pairs(data
.item
) do
136 local static_item
= (static
.item
and static
.item
[item_name
]) or FindStaticObjective("item", item_name
)
138 if not static_item
then
139 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing item "..QuestHelper
:HighlightText(item_name
)..".") end
142 elseif item
.drop
then
143 if DropListUpdated(item
.drop
, static_item
.drop
) then
144 if DropListMass(item
.drop
) > PositionListMass(static_item
.pos
) then
145 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing drop for item "..QuestHelper
:HighlightText(item_name
)..".") end
150 elseif item
.pos
and not static_item
.drop
and PositionListUpdated(item
.pos
, static_item
.pos
) then
151 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing position for item "..QuestHelper
:HighlightText(item_name
)..".") end
159 info
.update
.quest
= (info
.update
.quest
or 0)+1
163 local function CompareStaticObjective(info
, cat
, name
, data
, verbose
)
165 local static
= FindStaticObjective(cat
, name
)
167 if data
.pos
or data
.drop
or data
.vendor
then
168 if verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing.") end
169 info
.new
[cat
.."_obj"] = (info
.new
[cat
.."_obj"] or 0)+1
174 local updated
= false
177 updated
= VendorListUpdated(data
.vendor
, static
.vendor
)
178 if updated
and verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing vendor.") end
179 elseif data
.drop
and not static
.vendor
then
180 updated
= DropListUpdated(data
.drop
, static
.drop
) and DropListMass(data
.drop
) > PositionListMass(static
.pos
)
181 if updated
and verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing monster drop.") end
182 elseif data
.pos
and not static
.vendor
and not static
.drop
then
183 if updated
and verbose
then QuestHelper
:TextOut(Qstring
.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing position.") end
184 updated
= PositionListUpdated(data
.pos
, static
.pos
)
188 info
.update
[cat
.."_obj"] = (info
.update
[cat
.."_obj"] or 0)+1
193 function QuestHelper
:Nag(cmd
)
194 local verbose
, local_only
= false, true
197 if string.find(cmd
, "verbose") then verbose
= true end
198 if string.find(cmd
, "all") then local_only
= false end
207 for faction
, level_list
in pairs(QuestHelper_Quests
) do
208 if not local_only
or faction
== self
.faction
then
209 for level
, name_list
in pairs(level_list
) do
210 for name
, data
in pairs(name_list
) do
211 CompareStaticQuest(info
, faction
, level
, name
, data
.hash
, data
, verbose
)
213 for hash
, data
in pairs(data
.alt
) do
214 CompareStaticQuest(info
, faction
, level
, name
, hash
, data
, verbose
)
222 for cat
, name_list
in pairs(QuestHelper_Objectives
) do
223 for name
, obj
in pairs(name_list
) do
224 CompareStaticObjective(info
, cat
, name
, obj
, verbose
)
228 for faction
, location_list
in pairs(QuestHelper_FlightInstructors
) do
229 if not local_only
or faction
== self
.faction
then
230 for location
, npc
in pairs(location_list
) do
231 local data
= QuestHelper_StaticData
[self
.locale
]
232 data
= data
and data
.flight_instructors
233 data
= data
and data
[faction
]
234 data
= data
and data
[location
]
236 if not data
or data
~= npc
then
237 if verbose
then self
:TextOut(QuestHelper
:HighlightText(faction
).." flight master "..QuestHelper
:HighlightText(npc
).." was missing.") end
238 info
.new
["fp"] = (info
.new
["fp"] or 0)+1
244 for faction
, start_list
in pairs(QuestHelper_FlightRoutes
) do
245 if not local_only
or faction
== self
.faction
then
246 for start
, dest_list
in pairs(start_list
) do
247 for dest
, hash_list
in pairs(dest_list
) do
248 for hash
, data
in pairs(hash_list
) do
249 local static
= QuestHelper_StaticData
[self
.locale
]
250 static
= static
and static
.flight_routes
251 static
= static
and static
[faction
]
252 static
= static
and static
[start
]
253 static
= static
and static
[dest
]
254 static
= static
and static
[hash
]
256 if not static
or static
== true and type(data
) == "number" then
257 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
258 info
.new
["route"] = (info
.new
["route"] or 0)+1
268 for what
, count
in pairs(info
.new
) do
269 total
= total
+ count
270 local count2
= info
.update
[what
]
272 total
= total
+ count2
273 self
:TextOut(QHFormat("NAG_MULTIPLE_NEW", count
, count2
, QHText("NAG_"..string.upper(what
))))
275 self
:TextOut(QHFormat("NAG_SINGLE_NEW", QHFormat(count
==1 and "NAG_SINGLE" or "NAG_PLURAL", count
, QHText("NAG_"..string.upper(what
)))))
279 for what
, count
in pairs(info
.update
) do
280 if not info
.new
[what
] then
281 total
= total
+ count
282 self
:TextOut(QHFormat("NAG_ADDITIONAL", QHFormat(count
==1 and "NAG_SINGLE" or "NAG_PLURAL", count
, QHText("NAG_"..string.upper(what
)))))
287 self
:TextOut(QHText("NAG_NOT_NEW"))
289 self
:TextOut(QHText("NAG_NEW"))
292 self
:TextOut(QHText("NAG_INSTRUCTIONS"))