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
32 for _
, b
in ipairs(static
) do
33 high
= math
.max(high
, weight(b
))
36 for _
, a
in ipairs(list
) do
39 for _
, b
in ipairs(static
) do
40 if weight(a
) < high
*0.2 or compare(a
, b
) then
46 if not found
then return true end
51 local function PositionWeight(a
)
55 local function PositionCompare(a
, b
)
56 return a
[1] == b
[1] and
57 (a
[2]-b
[2])*(a
[2]-b
[2])+(a
[3]-b
[3])*(a
[3]-b
[3]) < 0.05*0.05
60 local function VendorCompare(a
, b
)
64 local function VendorWeight(a
)
68 local function PositionListUpdated(list
, static
)
69 return ListUpdated(list
, static
, PositionCompare
, PositionWeight
)
72 local function VendorListUpdated(list
, static
)
73 return ListUpdated(list
, static
, VendorCompare
, VendorWeight
)
76 local function DropListUpdated(list
, static
)
77 if not list
then return false end
78 if not static
then return next(list
, nil) ~= nil end
81 for name
in pairs(list
) do
82 local monster_obj
= FindStaticObjective("monster", name
)
83 if monster_obj
and monster_obj
.looted
and monster_obj
.looted
> 0 then
84 high
= math
.max(high
, (static
[name
] or 0)/monster_obj
.looted
)
88 for name
, v
in pairs(list
) do
89 local monster_obj1
= QuestHelper
:GetObjective("monster", name
)
90 local monster_obj2
= FindStaticObjective("monster", name
)
92 local looted
= math
.ceil((monster_obj1
.o
.looted
or 0)+((monster_obj2
and monster_obj2
.looted
) or 0))
94 v
= math
.max(1, math
.floor(v
))/looted
95 if v
> high
*0.2 and not static
[name
] then return true end
101 local function DropListMass(list
)
102 if not list
then return 0 end
104 for item
, count
in pairs(list
) do
110 local function PositionListMass(list
)
111 if not list
then return 0 end
113 for _
, pos
in ipairs(list
) do
119 local function CompareStaticQuest(info
, faction
, level
, name
, hash
, data
, verbose
)
120 local static
= FindStaticQuest(faction
, level
, name
, hash
)
123 if data
.finish
or data
.pos
then
124 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing.") end
125 info
.new
.quest
= (info
.new
.quest
or 0) + 1
130 local updated
= false
132 if data
.finish
and data
.finish
~= static
.finish
then
133 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing finish NPC "..QuestHelper
:HighlightText(data
.finish
)..".") end
135 elseif not static
.finish
and PositionListUpdated(data
.pos
, static
.pos
) then
136 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing finish location.") end
138 elseif data
.item
then
139 for item_name
, item
in pairs(data
.item
) do
140 local static_item
= (static
.item
and static
.item
[item_name
]) or FindStaticObjective("item", item_name
)
142 if not static_item
then
143 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing item "..QuestHelper
:HighlightText(item_name
)..".") end
146 elseif item
.drop
then
147 if DropListUpdated(item
.drop
, static_item
.drop
) then
148 if DropListMass(item
.drop
) > PositionListMass(static_item
.pos
) then
149 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing drop for item "..QuestHelper
:HighlightText(item_name
)..".") end
154 elseif item
.pos
and not static_item
.drop
and PositionListUpdated(item
.pos
, static_item
.pos
) then
155 if verbose
then QuestHelper
:TextOut("Quest "..QuestHelper
:HighlightText(name
).." was missing position for item "..QuestHelper
:HighlightText(item_name
)..".") end
163 info
.update
.quest
= (info
.update
.quest
or 0)+1
167 local function CompareStaticObjective(info
, cat
, name
, data
, verbose
)
169 local static
= FindStaticObjective(cat
, name
)
171 if data
.pos
or data
.drop
or data
.vendor
then
172 if verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing.") end
173 info
.new
[cat
.."_obj"] = (info
.new
[cat
.."_obj"] or 0)+1
178 local updated
= false
181 updated
= VendorListUpdated(data
.vendor
, static
.vendor
)
182 if updated
and verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing vendor.") end
183 elseif data
.drop
and not static
.vendor
then
184 updated
= DropListUpdated(data
.drop
, static
.drop
) and DropListMass(data
.drop
) > PositionListMass(static
.pos
)
185 if updated
and verbose
then QuestHelper
:TextOut(string.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing monster drop.") end
186 elseif data
.pos
and not static
.vendor
and not static
.drop
then
187 if updated
and verbose
then QuestHelper
:TextOut(Qstring
.gsub(cat
, "^(.)", string.upper
).." "..QuestHelper
:HighlightText(name
).." was missing position.") end
188 updated
= PositionListUpdated(data
.pos
, static
.pos
)
192 info
.update
[cat
.."_obj"] = (info
.update
[cat
.."_obj"] or 0)+1
197 function QuestHelper
:Nag(cmd
)
198 local verbose
, local_only
= false, true
200 if QuestHelper_IsPolluted() then
201 self
:TextOut(QHFormat("NAG_POLLUTED"))
206 if string.find(cmd
, "verbose") then verbose
= true end
207 if string.find(cmd
, "all") then local_only
= false end
216 for version
, data
in pairs(QuestHelper_Quests
) do
217 for faction
, level_list
in pairs(data
) do
218 if not local_only
or faction
== self
.faction
then
219 for level
, name_list
in pairs(level_list
) do
220 for name
, data
in pairs(name_list
) do
221 CompareStaticQuest(info
, faction
, level
, name
, data
.hash
, data
, verbose
)
223 for hash
, data
in pairs(data
.alt
) do
224 CompareStaticQuest(info
, faction
, level
, name
, hash
, data
, verbose
)
233 for version
, data
in pairs(QuestHelper_Objectives
) do
234 for cat
, name_list
in pairs(data
) do
235 for name
, obj
in pairs(name_list
) do
236 CompareStaticObjective(info
, cat
, name
, obj
, verbose
)
241 for version
, data
in pairs(QuestHelper_FlightInstructors
) do
242 for faction
, location_list
in pairs(data
) do
243 if not local_only
or faction
== self
.faction
then
244 for location
, npc
in pairs(location_list
) do
245 local data
= QuestHelper_StaticData
[self
.locale
]
246 data
= data
and data
.flight_instructors
247 data
= data
and data
[faction
]
248 data
= data
and data
[location
]
250 if not data
or data
~= npc
then
251 if verbose
then self
:TextOut(QuestHelper
:HighlightText(faction
).." flight master "..QuestHelper
:HighlightText(npc
).." was missing.") end
252 info
.new
["fp"] = (info
.new
["fp"] or 0)+1
259 for version
, data
in pairs(QuestHelper_FlightRoutes
) do
260 for faction
, start_list
in pairs(data
) do
261 if not local_only
or faction
== self
.faction
then
262 for start
, dest_list
in pairs(start_list
) do
263 for dest
, hash_list
in pairs(dest_list
) do
264 for hash
, data
in pairs(hash_list
) do
265 if hash
~= "no_interrupt_count" and hash
~= "interrupt_count" then
266 local static
= QuestHelper_StaticData
[self
.locale
]
267 static
= static
and static
.flight_routes
268 static
= static
and static
[faction
]
269 static
= static
and static
[start
]
270 static
= static
and static
[dest
]
271 static
= static
and static
[hash
]
273 if not static
or static
== true and type(data
) == "number" then
274 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
275 info
.new
["route"] = (info
.new
["route"] or 0)+1
287 for what
, count
in pairs(info
.new
) do
288 local what1
= count
== 1 and QHText("NAG_SINGLE_"..string.upper(what
)) or
289 QHFormat("NAG_MULTIPLE_"..string.upper(what
), count
)
291 total
= total
+ count
292 local count2
= info
.update
[what
]
294 total
= total
+ count2
295 local what2
= count2
== 1 and QHText("NAG_SINGLE_"..string.upper(what
)) or
296 QHFormat("NAG_MULTIPLE_"..string.upper(what
), count2
)
297 self
:TextOut(QHFormat("NAG_MULTIPLE_NEW", what1
, what2
))
299 self
:TextOut(QHFormat("NAG_SINGLE_NEW", what1
))
303 for what
, count
in pairs(info
.update
) do
304 if not info
.new
[what
] then
305 local what
= count
== 1 and QHText("NAG_SINGLE_"..string.upper(what
)) or
306 QHFormat("NAG_MULTIPLE_"..string.upper(what
), count
)
307 total
= total
+ count
308 self
:TextOut(QHFormat("NAG_ADDITIONAL", what
))
313 self
:TextOut(QHText("NAG_NOT_NEW"))
315 self
:TextOut(QHText("NAG_NEW"))
316 self
:TextOut(QHText("NAG_INSTRUCTIONS"))