369 lignes
12 Kio
Lua
369 lignes
12 Kio
Lua
|
QuestHelper_File["nag.lua"] = "1.4.0"
|
||
|
QuestHelper_Loadtime["nag.lua"] = GetTime()
|
||
|
|
||
|
local function FindStaticQuest(faction, level, name, hash)
|
||
|
local data = QuestHelper_StaticData[QuestHelper.locale]
|
||
|
data = data and data.quest
|
||
|
data = data and data[faction]
|
||
|
data = data and data[level]
|
||
|
data = data and data[name]
|
||
|
if data and data.hash and data.hash ~= hash then
|
||
|
data = data.alt and data.alt[hash]
|
||
|
end
|
||
|
return data
|
||
|
end
|
||
|
|
||
|
local function FindStaticObjective(cat, name)
|
||
|
local data = QuestHelper_StaticData[QuestHelper.locale]
|
||
|
data = data and data.objective
|
||
|
data = data and data[cat]
|
||
|
return data and data[name]
|
||
|
end
|
||
|
|
||
|
local function ListUpdated(list, static, compare, weight)
|
||
|
if not list then return false end
|
||
|
if not static then return true end
|
||
|
|
||
|
local high = 0
|
||
|
|
||
|
if #static >= 5 then
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
for _, b in ipairs(static) do
|
||
|
high = math.max(high, weight(b))
|
||
|
end
|
||
|
|
||
|
for _, a in ipairs(list) do
|
||
|
local found = false
|
||
|
|
||
|
for _, b in ipairs(static) do
|
||
|
if weight(a) < high*0.2 or compare(a, b) then
|
||
|
found = true
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if not found then return true end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
local function PositionWeight(a)
|
||
|
return a[4]
|
||
|
end
|
||
|
|
||
|
local function PositionCompare(a, b)
|
||
|
return a[1] == b[1] and
|
||
|
(a[2]-b[2])*(a[2]-b[2])+(a[3]-b[3])*(a[3]-b[3]) < 0.05*0.05
|
||
|
end
|
||
|
|
||
|
local function VendorCompare(a, b)
|
||
|
return a == b
|
||
|
end
|
||
|
|
||
|
local function VendorWeight(a)
|
||
|
return 1
|
||
|
end
|
||
|
|
||
|
local function PositionListUpdated(list, static)
|
||
|
return ListUpdated(list, static, PositionCompare, PositionWeight)
|
||
|
end
|
||
|
|
||
|
local function VendorListUpdated(list, static)
|
||
|
return ListUpdated(list, static, VendorCompare, VendorWeight)
|
||
|
end
|
||
|
|
||
|
local function DropListUpdated(list, static)
|
||
|
if not list then return false end
|
||
|
if not static then return next(list, nil) ~= nil end
|
||
|
local high = 0
|
||
|
|
||
|
for name in pairs(list) do
|
||
|
local monster_obj = FindStaticObjective("monster", name)
|
||
|
if monster_obj and monster_obj.looted and monster_obj.looted > 0 then
|
||
|
high = math.max(high, (static[name] or 0)/monster_obj.looted)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for name, v in pairs(list) do
|
||
|
local monster_obj1 = QuestHelper:GetObjective("monster", name)
|
||
|
local monster_obj2 = FindStaticObjective("monster", name)
|
||
|
|
||
|
local looted = math.ceil((monster_obj1.o.looted or 0)+((monster_obj2 and monster_obj2.looted) or 0))
|
||
|
if looted > 0 then
|
||
|
v = math.max(1, math.floor(v))/looted
|
||
|
if v > high*0.2 and not static[name] then return true end
|
||
|
end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
local function DropListMass(list)
|
||
|
if not list then return 0 end
|
||
|
local mass = 0
|
||
|
for item, count in pairs(list) do
|
||
|
mass = mass + count
|
||
|
end
|
||
|
return mass
|
||
|
end
|
||
|
|
||
|
local function PositionListMass(list)
|
||
|
if not list then return 0 end
|
||
|
local mass = 0
|
||
|
for _, pos in ipairs(list) do
|
||
|
mass = mass + pos[4]
|
||
|
end
|
||
|
return mass
|
||
|
end
|
||
|
|
||
|
local function CompareStaticQuest(info, faction, level, name, hash, data, verbose)
|
||
|
local static = FindStaticQuest(faction, level, name, hash)
|
||
|
|
||
|
if not static then
|
||
|
if data.finish or data.pos then
|
||
|
if verbose then QuestHelper:TextOut("Quest "..QuestHelper:HighlightText(name).." was missing.") end
|
||
|
info.new.quest = (info.new.quest or 0) + 1
|
||
|
end
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local updated = false
|
||
|
|
||
|
if data.finish and data.finish ~= static.finish then
|
||
|
if verbose then QuestHelper:TextOut("Quest "..QuestHelper:HighlightText(name).." was missing finish NPC "..QuestHelper:HighlightText(data.finish)..".") end
|
||
|
updated = true
|
||
|
elseif not static.finish and PositionListUpdated(data.pos, static.pos) then
|
||
|
if verbose then QuestHelper:TextOut("Quest "..QuestHelper:HighlightText(name).." was missing finish location.") end
|
||
|
updated = true
|
||
|
elseif data.item then
|
||
|
for item_name, item in pairs(data.item) do
|
||
|
local static_item = (static.item and static.item[item_name]) or FindStaticObjective("item", item_name)
|
||
|
|
||
|
if not static_item then
|
||
|
if verbose then QuestHelper:TextOut("Quest "..QuestHelper:HighlightText(name).." was missing item "..QuestHelper:HighlightText(item_name)..".") end
|
||
|
updated = true
|
||
|
break
|
||
|
elseif item.drop then
|
||
|
if DropListUpdated(item.drop, static_item.drop) then
|
||
|
if DropListMass(item.drop) > PositionListMass(static_item.pos) then
|
||
|
if verbose then QuestHelper:TextOut("Quest "..QuestHelper:HighlightText(name).." was missing drop for item "..QuestHelper:HighlightText(item_name)..".") end
|
||
|
updated = true
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
elseif item.pos and not static_item.drop and PositionListUpdated(item.pos, static_item.pos) then
|
||
|
if verbose then QuestHelper:TextOut("Quest "..QuestHelper:HighlightText(name).." was missing position for item "..QuestHelper:HighlightText(item_name)..".") end
|
||
|
updated = true
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if updated then
|
||
|
info.update.quest = (info.update.quest or 0)+1
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function CompareStaticObjective(info, cat, name, data, verbose)
|
||
|
if info.quest then
|
||
|
local static = FindStaticObjective(cat, name)
|
||
|
if not static then
|
||
|
if data.pos or data.drop or data.vendor then
|
||
|
if verbose then QuestHelper:TextOut(string.gsub(cat, "^(.)", string.upper).." "..QuestHelper:HighlightText(name).." was missing.") end
|
||
|
info.new[cat.."_obj"] = (info.new[cat.."_obj"] or 0)+1
|
||
|
end
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local updated = false
|
||
|
|
||
|
if data.vendor then
|
||
|
updated = VendorListUpdated(data.vendor, static.vendor)
|
||
|
if updated and verbose then QuestHelper:TextOut(string.gsub(cat, "^(.)", string.upper).." "..QuestHelper:HighlightText(name).." was missing vendor.") end
|
||
|
elseif data.drop and not static.vendor then
|
||
|
updated = DropListUpdated(data.drop, static.drop) and DropListMass(data.drop) > PositionListMass(static.pos)
|
||
|
if updated and verbose then QuestHelper:TextOut(string.gsub(cat, "^(.)", string.upper).." "..QuestHelper:HighlightText(name).." was missing monster drop.") end
|
||
|
elseif data.pos and not static.vendor and not static.drop then
|
||
|
if updated and verbose then QuestHelper:TextOut(Qstring.gsub(cat, "^(.)", string.upper).." "..QuestHelper:HighlightText(name).." was missing position.") end
|
||
|
updated = PositionListUpdated(data.pos, static.pos)
|
||
|
end
|
||
|
|
||
|
if updated then
|
||
|
info.update[cat.."_obj"] = (info.update[cat.."_obj"] or 0)+1
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QuestHelper:Nag(cmd)
|
||
|
do return end -- BZZT
|
||
|
|
||
|
local verbose, local_only = false, true
|
||
|
|
||
|
if QuestHelper_IsPolluted() then
|
||
|
self:TextOut(QHFormat("NAG_POLLUTED"))
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if cmd then
|
||
|
if string.find(cmd, "verbose") then verbose = true end
|
||
|
if string.find(cmd, "all") then local_only = false end
|
||
|
end
|
||
|
|
||
|
local info =
|
||
|
{
|
||
|
new = {},
|
||
|
update = {}
|
||
|
}
|
||
|
|
||
|
for version, data in pairs(QuestHelper_Quests) do
|
||
|
for faction, level_list in pairs(data) do
|
||
|
if not local_only or faction == self.faction then
|
||
|
for level, name_list in pairs(level_list) do
|
||
|
for name, data in pairs(name_list) do
|
||
|
CompareStaticQuest(info, faction, level, name, data.hash, data, verbose)
|
||
|
if data.alt then
|
||
|
for hash, data in pairs(data.alt) do
|
||
|
CompareStaticQuest(info, faction, level, name, hash, data, verbose)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for version, data in pairs(QuestHelper_Objectives) do
|
||
|
for cat, name_list in pairs(data) do
|
||
|
for name, obj in pairs(name_list) do
|
||
|
CompareStaticObjective(info, cat, name, obj, verbose)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for version, data in pairs(QuestHelper_FlightInstructors) do
|
||
|
for faction, location_list in pairs(data) do
|
||
|
if not local_only or faction == self.faction then
|
||
|
for location, npc in pairs(location_list) do
|
||
|
local data = QuestHelper_StaticData[self.locale]
|
||
|
data = data and data.flight_instructors
|
||
|
data = data and data[faction]
|
||
|
data = data and data[location]
|
||
|
|
||
|
if not data or data ~= npc then
|
||
|
if verbose then self:TextOut(QuestHelper:HighlightText(faction).." flight master "..QuestHelper:HighlightText(npc).." was missing.") end
|
||
|
info.new["fp"] = (info.new["fp"] or 0)+1
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for version, data in pairs(QuestHelper_FlightRoutes) do
|
||
|
for faction, start_list in pairs(data) do
|
||
|
if not local_only or faction == self.faction then
|
||
|
for start, dest_list in pairs(start_list) do
|
||
|
for dest, hash_list in pairs(dest_list) do
|
||
|
for hash, data in pairs(hash_list) do
|
||
|
if hash ~= "no_interrupt_count" and hash ~= "interrupt_count" then
|
||
|
local static = QuestHelper_StaticData[self.locale]
|
||
|
static = static and static.flight_routes
|
||
|
static = static and static[faction]
|
||
|
static = static and static[start]
|
||
|
static = static and static[dest]
|
||
|
static = static and static[hash]
|
||
|
|
||
|
if not static or static == true and type(data) == "number" then
|
||
|
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
|
||
|
info.new["route"] = (info.new["route"] or 0)+1
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local total = 0
|
||
|
|
||
|
for what, count in pairs(info.new) do
|
||
|
local what1 = count == 1 and QHText("NAG_SINGLE_"..string.upper(what)) or
|
||
|
QHFormat("NAG_MULTIPLE_"..string.upper(what), count)
|
||
|
|
||
|
total = total + count
|
||
|
local count2 = info.update[what]
|
||
|
if count2 then
|
||
|
total = total + count2
|
||
|
local what2 = count2 == 1 and QHText("NAG_SINGLE_"..string.upper(what)) or
|
||
|
QHFormat("NAG_MULTIPLE_"..string.upper(what), count2)
|
||
|
self:TextOut(QHFormat("NAG_MULTIPLE_NEW", what1, what2))
|
||
|
else
|
||
|
self:TextOut(QHFormat("NAG_SINGLE_NEW", what1))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for what, count in pairs(info.update) do
|
||
|
if not info.new[what] then
|
||
|
local what = count == 1 and QHText("NAG_SINGLE_"..string.upper(what)) or
|
||
|
QHFormat("NAG_MULTIPLE_"..string.upper(what), count)
|
||
|
total = total + count
|
||
|
self:TextOut(QHFormat("NAG_ADDITIONAL", what))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if total == 0 then
|
||
|
self:TextOut(QHText("NAG_NOT_NEW"))
|
||
|
else
|
||
|
self:TextOut(QHText("NAG_NEW"))
|
||
|
self:TextOut(QHText("NAG_INSTRUCTIONS"))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
local day = 24 * 60 * 60
|
||
|
|
||
|
function QHNagInit()
|
||
|
if not QuestHelper_Pref.submit_nag_next_time then
|
||
|
QuestHelper_Pref.submit_nag_next_time = time() + 7 * day + 7 * day * math.random() -- at least a week, at most 2 weeks
|
||
|
QuestHelper_Pref.submit_nag_type = "OFF"
|
||
|
end
|
||
|
|
||
|
if QuestHelper_Pref.submit_nag_next_time < time() then
|
||
|
if QuestHelper_Pref.submit_nag_type == "OFF" then
|
||
|
-- we now begin nagging for 48 hours
|
||
|
QuestHelper_Pref.submit_nag_next_time = time() + 2 * day
|
||
|
QuestHelper_Pref.submit_nag_type = "ON"
|
||
|
else
|
||
|
-- we now stop nagging for 2-3 weeks
|
||
|
QuestHelper_Pref.submit_nag_next_time = time() + 14 * day + 7 * day * math.random()
|
||
|
QuestHelper_Pref.submit_nag_type = "OFF"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if time() > 1248462000 and time() < 1248685200 then return true end -- 7/24/2009 11am PST to 7/27/2009 1am PST
|
||
|
return QuestHelper_Pref.submit_nag_type == "ON"
|
||
|
end
|
||
|
|
||
|
|
||
|
local update_nag_yell_at = nil
|
||
|
|
||
|
function QHUpdateNagInit()
|
||
|
if not QuestHelper_Pref.update_nag_last_version or QuestHelper_Pref.update_nag_last_version ~= GetAddOnMetadata("QuestHelper", "Version") then
|
||
|
QuestHelper_Pref.update_nag_last_version = GetAddOnMetadata("QuestHelper", "Version")
|
||
|
QuestHelper_Pref.update_nag_next_notify = time() + 24 * day
|
||
|
end
|
||
|
|
||
|
if QuestHelper_Pref.update_nag_next_notify < time() then
|
||
|
update_nag_yell_at = time() + 60 * 10 + 50 * 60 * math.random() -- 10 to 60 minutes from now
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function QHUpdateNagTick()
|
||
|
if update_nag_yell_at and update_nag_yell_at < time() then
|
||
|
--QuestHelper:TextOut(QHText("TIME_TO_UPDATE")) -- We're just disabling this, I think.
|
||
|
QuestHelper_Pref.update_nag_next_notify = time() + day * 6 + day * 2 * math.random()
|
||
|
update_nag_yell_at = nil
|
||
|
end
|
||
|
end
|