1
0
Bifurcation 0
Ce dépôt a été archivé le 2020-03-15. Vous pouvez voir ses fichiers ou le cloner, mais pas ouvrir de ticket ou de demandes d'ajout, ni soumettre de changements.
questhelperredux/QuestHelper/main.lua

709 lignes
25 KiB
Lua

QuestHelper_File["main.lua"] = "4.0.1.$svnversion$"
QuestHelper_Loadtime["main.lua"] = GetTime()
local GetTime = QuestHelper_GetTime
local version_string = QuestHelper_File["main.lua"] -- we pretty much save this only so we can inform the user that they're using a beta version
function QuestHelper:GetFontPath(list_string, font)
if list_string then
for name in string.gmatch(list_string, "[^;]+") do
if font:SetFont(name, 10) then
return name
elseif font:SetFont("Interface\\AddOns\\QuestHelper\\Fonts\\"..name, 10) then
return "Interface\\AddOns\\QuestHelper\\Fonts\\"..name
end
end
end
end
function QuestHelper:SetLocaleFonts()
self.font.sans = nil
self.font.serif = nil
self.font.fancy = nil
local font = self:CreateText(self)
if QuestHelper_Locale ~= QuestHelper_Pref.locale then
-- Only use alternate fonts if using a language the client wasn't intended for.
local replacements = QuestHelper_SubstituteFonts[QuestHelper_Pref.locale]
if replacements then
self.font.sans = self:GetFontPath(replacements.sans, font)
self.font.serif = self:GetFontPath(replacements.serif, font)
self.font.fancy = self:GetFontPath(replacements.fancy, font)
end
end
self.font.sans = self.font.sans or self:GetFontPath(QuestHelper_Pref.locale.."_sans.ttf", font)
self.font.serif = self.font.serif or self:GetFontPath(QuestHelper_Pref.locale.."_serif.ttf", font) or self.font.sans
self.font.fancy = self.font.fancy or self:GetFontPath(QuestHelper_Pref.locale.."_fancy.ttf", font) or self.font.serif
self:ReleaseText(font)
self.font.sans = self.font.sans or ChatFontNormal:GetFont()
self.font.serif = self.font.serif or GameFontNormal:GetFont()
self.font.fancy = self.font.fancy or QuestTitleFont:GetFont()
-- Need to change the font of the chat frame, for any messages that QuestHelper displays.
-- This should do nothing if not using an alternate font.
--DEFAULT_CHAT_FRAME:SetFont(self.font.sans, select(2, DEFAULT_CHAT_FRAME:GetFont()))
-- what why did we ever do this
end
function QuestHelper.tooltip:GetPrevLines() -- Just a helper to make life easier.
local last = self:NumLines()
local name = self:GetName()
return _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
end
local continentMapIDs = { -- [c] = id
[1] = 13,
[2] = 14,
[3] = 466,
[4] = 485,
[5] = 751,
[6] = 862
}
function QuestHelper:SetTargetLocation(M, F, x, y, toffset)
-- Informs QuestHelper that you're going to be at some location in toffset seconds.
--local c, z = unpack(QuestHelper_ZoneLookup[i])
self.target = self:CreateTable()
self.target[2] = self:CreateTable()
self.target_time = time()+(toffset or 0)
local pM, pF = self.Astrolabe:GetCurrentPlayerPosition()
x, y = self.Astrolabe:TranslateWorldMapPosition(M, F, x, y, pM, pF)
error("HAVE NOT FIGURED OUT THE self.target TABLE")
self.target[1] = self.zone_nodes[i]
self.target[3] = x -- * self.continent_scales_x[c]
self.target[4] = y -- * self.continent_scales_y[c]
self:SetTargetLocationRecalculate()
end
function QuestHelper:SetTargetLocationRecalculate()
if self.target then
for i, n in ipairs(self.target[1]) do
local a, b = n.x-self.target[3], n.y-self.target[4]
self.target[2][i] = math.sqrt(a*a+b*b)
end
end
end
function QuestHelper:UnsetTargetLocation()
-- Unsets the target set above.
if self.target then
self:ReleaseTable(self.target[2])
self:ReleaseTable(self.target)
self.target = nil
self.target_time = nil
end
end
local interruptcount = 0 -- counts how many "played gained control" messages we recieve, used for flight paths
local startup_time
local please_submit_enabled = true
local please_submit_initted = false
local spawned = false
local function QH_QueryQuestsCompletedHandler()
QHQuestsCompleted = GetQuestsCompleted()
end
local function QH_QueryQuestsCompleted()
--[[
QH_Event("QUEST_QUERY_COMPLETE", QH_QueryQuestsCompletedHandler)
QueryQuestsCompleted()
--]]
end
local function ShouldTrackingBeEnabled(yn)
DEFAULT_CHAT_FRAME:AddMessage("Tracking not currently available.")
if yn then
-- QuestHelper:ShowTracker() -- to respect the minimized setting
else
-- QuestHelper:HideTracker()
end
end
local function FileCheck()
local file_problem_version = false
-- Why are we checking to make sure these files load?
-- Most if not all are named in the toc file.
-- Duh... There's a lot of files, ergo a method to make sure all expected files have been named in the toc file and check for files that are unexpected too.
local expected_files =
{
["bst_pre.lua"] = true,
["manager_event.lua"] = true,
["manager_achievement.lua"] = true,
["manager_completed.lua"] = true,
-- ["upgrade.lua"] = true,
["pref.lua"] = true,
["vars.lua"] = true,
["init_timeslice.lua"] = true,
["main.lua"] = true,
["recycle.lua"] = true,
["objective.lua"] = true,
["quest.lua"] = true,
["utility.lua"] = true,
["dodads.lua"] = true,
["dodads_triangles.lua"] = true,
["teleport.lua"] = true,
-- ["pathfinding.lua"] = true,
["routing.lua"] = true,
["custom.lua"] = true,
["menu.lua"] = true,
["nag.lua"] = true,
["comm.lua"] = true,
-- ["mapbutton.lua"] = true,
["help.lua"] = true,
["pattern.lua"] = true,
-- ["flightpath.lua"] = true,
-- ["tracker.lua"] = true,
["objtips.lua"] = true,
["tomtom.lua"] = true,
["textviewer.lua"] = true,
["error.lua"] = true,
["timeslice.lua"] = true,
-- ["lang.lua"] = true,
["core.lua"] = true,
-- ["tooltip.lua"] = true,
["arrow.lua"] = true,
-- ["radar.lua"] = true,
["config.lua"] = true,
["collect.lua"] = true,
["collect_achievement.lua"] = true,
["collect_lzw.lua"] = true,
["collect_traveled.lua"] = true,
["collect_zone.lua"] = true,
["collect_hearth.lua"] = true,
["collect_location.lua"] = true,
["collect_merger.lua"] = true,
["collect_monster.lua"] = true,
["collect_item.lua"] = true,
["collect_object.lua"] = true,
["collect_loot.lua"] = true,
["collect_patterns.lua"] = true,
["collect_flight.lua"] = true,
["collect_util.lua"] = true,
["collect_quest.lua"] = true,
["collect_equip.lua"] = true,
["collect_notifier.lua"] = true,
["collect_bitstream.lua"] = true,
["collect_spec.lua"] = true,
["collect_upgrade.lua"] = true,
["collect_merchant.lua"] = true,
["collect_warp.lua"] = true,
-- ["filter_core.lua"] = true,
-- ["filter_base.lua"] = true,
-- ["routing_debug.lua"] = true,
-- ["routing_loc.lua"] = true,
-- ["routing_route.lua"] = true,
-- ["routing_core.lua"] = true,
-- ["routing_controller.lua"] = true,
-- ["routing_hidden.lua"] = true,
-- ["director_quest.lua"] = true,
-- ["director_achievement.lua"] = true,
-- ["director_find.lua"] = true,
-- ["db_get.lua"] = true,
-- ["graph_core.lua"] = true,
-- ["graph_flightpath.lua"] = true,
--* ["AstrolabeQH/Astrolabe.lua"] = true,
--* ["AstrolabeQH/AstrolabeMapMonitor.lua"] = true,
}
local uninstallederr = ""
for file, version in pairs(QuestHelper_File) do
if not expected_files[file] then
local errmsg = "Unexpected QuestHelper file: "..file
DEFAULT_CHAT_FRAME:AddMessage(errmsg)
uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
file_problem_version = true
elseif version ~= expected_version then
local errmsg = "Wrong version of QuestHelper file: "..file.." (found '"..version.."', should be '"..expected_version.."')"
DEFAULT_CHAT_FRAME:AddMessage(errmsg)
uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
--[[ Nope, no one is allowed to do this. We've got a number of people doing just that... And they're not developers. Though this check always fails because I don't use "Development Version" to tell QH that it is a dev version.
if version ~= "Development Version" and expected_version ~= "Development Version" then
-- Developers are allowed to mix dev versions with release versions
file_problem_version = true
end
--]]
end
end
for file in pairs(expected_files) do
if not QuestHelper_File[file] then
local errmsg = "Missing QuestHelper file: "..file
DEFAULT_CHAT_FRAME:AddMessage(errmsg)
uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
if not (expected_version == "Development Version" and file:match("static.*")) then file_problem_version = true end
end
end
-- Don't need this table anymore.
QuestHelper_File = nil
return uninstallederr, file_problem_version
end
local function FinalProblemChecks(uninstallederr, file_problem_version)
if QuestHelper_StaticData and not QuestHelper_StaticData[GetLocale()] then
local errmsg = "Static data does not seem to exist"
DEFAULT_CHAT_FRAME:AddMessage(errmsg)
uninstallederr = uninstallederr .. " " .. errmsg .. "\n"
file_problem_version = true
end
if file_problem_version then
QH_fixedmessage(QHText("PLEASE_RESTART"))
QuestHelper_ErrorCatcher_ExplicitError(false, "not-installed-properly" .. "\n" .. uninstallederr)
QuestHelper = nil -- Just in case anybody else is checking for us, we're not home
return
end
if not GetCategoryList or not GetQuestLogSpecialItemInfo or not WatchFrame_RemoveObjectiveHandler then
QH_fixedmessage(QHText("PRIVATE_SERVER"))
QuestHelper_ErrorCatcher_ExplicitError(false, "error id cakbep ten T")
QuestHelper = nil
return
end
if not DongleStub then
QH_fixedmessage("NOT_UNZIPPED_CORRECTLY")
QuestHelber_ErrorCatcher_ExplicitError(false, "no DongleStub")
QuestHelper = nil
return
end
if not QuestHelper.Astrolabe then
QH_fixedmessage(QHText("NOT_UNZIPPED_CORRECTLY"))
QuestHelper_ErrorCatcher_ExplicitError(false, "no QH_Astrolabe_Ready")
QuestHelper = nil -- Just in case anybody else is checking for us, we're not home
return
end
return true
end
function QuestHelper_AddonLoadedHandler(addonid)
if addonid ~= "QuestHelper" then return end
-- ONLY FAST STUFF ALLOWED IN HERE
QH_QueryQuestsCompleted()
-- Use DefaultPref as fallback for unset preference keys.
setmetatable(QuestHelper_Pref, {__index=QuestHelper_DefaultPref})
QuestHelper: Assert(QuestHelper_Pref.perfload_scale) -- if this fails, something is very botched
ShouldTrackingBeEnabled(QuestHelper_Pref.track and not QuestHelper_Pref.hide)
local self = QuestHelper -- whee hack hack hack
QuestHelper_Loadtime["init2_start"] = GetTime()
-- File Check
local uninstallederr, file_problem_version = FileCheck()
if not FinalProblemChecks(uninstallederr, file_problem_version) then return end -- Something is borked.
QuestHelper_ErrorCatcher_CompletelyStarted()
if not QuestHelper_StaticData then
-- If there is no static data for some mysterious reason, create an empty table so that
-- other parts of the code can carry on as usual, using locally collected data if it exists.
QuestHelper_StaticData = {}
end
QHFormatSetLocale(QuestHelper_Pref.locale or GetLocale())
if not QuestHelper_UID and not QuestHelper_Collector.UID then
QuestHelper_Collector.UID = self:CreateUID()
elseif QuestHelper_UID then
QuestHelper_Collector.UID = QuestHelper_UID
QuestHelper_UID = nil -- We are moving this into Collector.
end
QuestHelper_SaveDate = time()
QH_Timeslice_Add(QH_Init_Timeslice, "preinit")
QuestHelper_Loadtime["init2_end"] = GetTime()
end
QH_Event("ADDON_LOADED", QuestHelper_AddonLoadedHandler)
--[==[
function QuestHelper:OnEvent(event)
local tstart = GetTime()
--[[
if event == "GOSSIP_SHOW" then
local name, id = UnitName("npc"), self:GetUnitID("npc")
if name and id then
self:GetObjective("monster", name).o.id = id
--self:TextOut("NPC: "..name.." = "..id)
end
end]]
--[[if event == "PLAYER_TARGET_CHANGED" then
local name, id = UnitName("target"), self:GetUnitID("target")
if name and id then
self:GetObjective("monster", name).o.id = id
--self:TextOut("Target: "..name.." = "..id)
end
if UnitExists("target") and UnitIsVisible("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
local index, x, y = self:UnitPosition("target")
if index then -- Might not have a position if inside an instance.
local w = 0.1
-- Modify the weight based on how far they are from us.
-- We don't know the exact location (using our own location), so the farther, the less sure we are that it's correct.
if CheckInteractDistance("target", 3) then w = 1
elseif CheckInteractDistance("target", 2) then w = 0.89
elseif CheckInteractDistance("target", 1) or CheckInteractDistance("target", 4) then w = 0.33 end
local monster_objective = self:GetObjective("monster", UnitName("target"))
self:AppendObjectivePosition(monster_objective, index, x, y, w)
monster_objective.o.faction = (UnitFactionGroup("target") == "Alliance" and 1) or
(UnitFactionGroup("target") == "Horde" and 2) or nil
local level = UnitLevel("target")
if level and level >= 1 then
local w = monster_objective.o.levelw or 0
monster_objective.o.level = ((monster_objective.o.level or 0)*w+level)/(w+1)
monster_objective.o.levelw = w+1
end
end
end
end]]
--[[if event == "LOOT_OPENED" then
local target = UnitName("target")
if target and UnitIsDead("target") and UnitCreatureType("target") ~= "Critter" and not UnitIsPlayer("target") and not UnitPlayerControlled("target") then
local index, x, y = self:UnitPosition("target")
local monster_objective = self:GetObjective("monster", target)
monster_objective.o.looted = (monster_objective.o.looted or 0) + 1
if index then -- Might not have a position if inside an instance.
self:AppendObjectivePosition(monster_objective, index, x, y)
end
for i = 1, GetNumLootItems() do
local icon, name, number, rarity = GetLootSlotInfo(i)
if name then
if number and number >= 1 then
self:AppendItemObjectiveDrop(self:GetObjective("item", name), name, target, number)
else
local total = (name:match(COPPER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) +
(name:match(SILVER_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 100 +
(name:match(GOLD_AMOUNT:gsub("%%d", "%(%%d+%)")) or 0) * 10000
if total > 0 then
self:AppendObjectiveDrop(self:GetObjective("item", "money"), target, total)
end
end
end
end
else
local container = nil
-- Go through the players inventory and look for a locked item, we're probably looting it.
for bag = 0,NUM_BAG_SLOTS do
for slot = 1,GetContainerNumSlots(bag) do
local link = GetContainerItemLink(bag, slot)
if link and select(3, GetContainerItemInfo(bag, slot)) then
if container == nil then
-- Found a locked item and haven't previously assigned to container, assign its name, or false if we fail to parse it.
container = select(3, string.find(link, "|h%[(.+)%]|h|r")) or false
else
-- Already tried to assign to a container. If there are multiple locked items, we give up.
container = false
end
end
end
end
if container then
local container_objective = self:GetObjective("item", container)
container_objective.o.opened = (container_objective.o.opened or 0) + 1
for i = 1, GetNumLootItems() do
local icon, name, number, rarity = GetLootSlotInfo(i)
if name and number >= 1 then
self:AppendItemObjectiveContainer(self:GetObjective("item", name), container, number)
end
end
else
-- No idea where the items came from.
local index, x, y = self:PlayerPosition()
if index then
for i = 1, GetNumLootItems() do
local icon, name, number, rarity = GetLootSlotInfo(i)
if name and number >= 1 then
self:AppendItemObjectivePosition(self:GetObjective("item", name), name, index, x, y)
end
end
end
end
end
end]]
--[[if event == "CHAT_MSG_SYSTEM" then
local home_name = self:convertPattern(ERR_DEATHBIND_SUCCESS_S)(arg1)
if home_name then
if self.i then
self:TextOut(QHText("HOME_CHANGED"))
self:TextOut(QHText("WILL_RESET_PATH"))
local home = QuestHelper_Home
if not home then
home = {}
QuestHelper_Home = home
end
home[1], home[2], home[3], home[4] = self.i, self.x, self.y, home_name
self.defered_graph_reset = true
end
end
end]]
--[[if event == "QUEST_DETAIL" then
if not self.quest_giver then self.quest_giver = {} end
local npc = UnitName("npc")
if npc then
-- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
local index, x, y = self:UnitPosition("npc")
if index then -- Might not have a position if inside an instance.
local npc_objective = self:GetObjective("monster", npc)
self:AppendObjectivePosition(npc_objective, index, x, y)
self.quest_giver[GetTitleText()] = npc
end
end
end]]
--[[if event == "QUEST_COMPLETE" or event == "QUEST_PROGRESS" then
local quest = GetTitleText()
if quest then
local level, hash = self:GetQuestLevel(quest)
if not level or level < 1 then
--self:TextOut("Don't know quest level for ".. quest.."!")
return
end
local q = self:GetQuest(quest, level, hash)
if q.need_hash then
q.o.hash = hash
end
local unit = UnitName("npc")
if unit then
q.o.finish = unit
q.o.pos = nil
-- Some NPCs aren't actually creatures, and so their positions might not be marked by PLAYER_TARGET_CHANGED.
local index, x, y = self:UnitPosition("npc")
if index then -- Might not have a position if inside an instance.
local npc_objective = self:GetObjective("monster", unit)
self:AppendObjectivePosition(npc_objective, index, x, y)
end
elseif not q.o.finish then
local index, x, y = self:PlayerPosition()
if index then -- Might not have a position if inside an instance.
self:AppendObjectivePosition(q, index, x, y)
end
end
end
end]]
--[[if event == "MERCHANT_SHOW" then
local npc_name = UnitName("npc")
if npc_name then
local npc_objective = self:GetObjective("monster", npc_name)
local index = 1
while true do
local item_name = GetMerchantItemInfo(index)
if item_name then
index = index + 1
local item_objective = self:GetObjective("item", item_name)
if not item_objective.o.vendor then
item_objective.o.vendor = {npc_name}
else
local known = false
for i, vendor in ipairs(item_objective.o.vendor) do
if npc_name == vendor then
known = true
break
end
end
if not known then
table.insert(item_objective.o.vendor, npc_name)
end
end
else
break
end
end
end
end]]
--[[
if event == "TAXIMAP_OPENED" then
self:taxiMapOpened()
end
]]
--[[if event == "PLAYER_CONTROL_GAINED" then
interruptcount = interruptcount + 1
end]]
--[[if event == "BAG_UPDATE" then
for slot = 1,GetContainerNumSlots(arg1) do
local link = GetContainerItemLink(arg1, slot)
if link then
local id, name = select(3, string.find(link, "|Hitem:(%d+):.-|h%[(.-)%]|h"))
if name then
self:GetObjective("item", name).o.id = tonumber(id)
end
end
end
end]]
if event == "ZONE_CHANGED" or event == "ZONE_CHANGED_INDOORS" or event == "ZONE_CHANGED_NEW_AREA" then
QH_Route_Filter_Rescan()
end
QH_Timeslice_Increment(GetTime() - tstart, "event")
end]==]
local map_shown_decay = 0
local delayed_action = 100
--local update_count = 0
local ontaxi = false
local frams = 0
QH_OnUpdate_High(function ()
local self = QuestHelper -- hoorj
local tstart = GetTime()
frams = frams + 1
if not QuestHelper_Loadtime["onupdate"] then QuestHelper_Loadtime["onupdate"] = GetTime() end
if false and frams == 60 then
self:ShowText([[
This is a |cffff8000beta of QuestHelper|r. Be warned: It may crash. It may lock up. It may give bad advice. It may spew errors. It shouldn't spam people, delete your hard-won epics, or make your computer catch on fire, but technically I'm giving no guarantees. |cffff8000If you want a polished, functioning product, close WoW, download the official QH release from curse.com, and use that.|r
Known bugs and issues include:
|cff40bbffNo support for "/qh find"|r
|cff40bbffNo support for in-party quest synchronization|r
These may not be fixed before the official 1.0 release - I'm hoping to get them all finished up in time for 1.1.
If you encounter any issue besides the ones listed here, please please please report it, if you're reading this you know how to get in contact with me anyway.
Thanks for testing!]], "QuestHelper " .. version_string, 500, 20, 10)
end
--if frams == 5000 then please_submit_enabled = false end -- TOOK TOO LONG >:(
if please_submit_enabled and startup_time and startup_time + 10 < GetTime() then
QuestHelper:TextOut(QHText("PLEASE_SUBMIT"))
startup_time = nil
please_submit_enabled = false
end
QHUpdateNagTick() -- These probably shouldn't be in OnUpdate. Eventually I'll move them somewhere cleaner.
--[[
if not ontaxi and UnitOnTaxi("player") then
self:flightBegan()
interruptcount = 0
elseif ontaxi and not UnitOnTaxi("player") then
self:flightEnded(interruptcount > 1)
end
ontaxi = UnitOnTaxi("player")
]]
-- For now I'm ripping out the update_count code
--update_count = update_count - 1
--if update_count <= 0 then
-- Reset the update count for next time around; this will make sure the body executes every time
-- when perf_scale_2 >= 1, and down to 1 in 10 iterations when perf_scale_2 < 1, or when hidden.
--update_count = update_count + (QuestHelper_Pref.hide and 10 or 1/QuestHelper_Pref.perf_scale_2)
--if update_count < 0 then
-- Make sure the count doesn't go perpetually negative; don't know what will happen if it underflows.
--update_count = 0
--end
if self.Astrolabe.WorldMapVisible then
-- We won't trust that the zone returned by Astrolabe is correct until map_shown_decay is 0.
map_shown_decay = 2
elseif map_shown_decay > 0 then
map_shown_decay = map_shown_decay - 1
else
--SetMapToCurrentZone() -- not sure why this existed
end
--[[delayed_action = delayed_action - 1
if delayed_action <= 0 then
delayed_action = 100
self:HandlePartyChange()
end]]
local nm, nf, nx, ny = self.Astrolabe:GetCurrentPlayerPosition()
if nm and nf and nx and ny then
self.collect_rm, self.collect_rf, self.collect_rx, self.collect_ry = nm, nf, nx, ny
self.minimap_marker:OnUpdate(0) -- poke
end
if not UnitOnTaxi("player") and not UnitIsDeadOrGhost("player") then
QuestHelper.routing_x, QuestHelper.routing_y, QuestHelper.routing_m, QuestHelper.routing_f = QuestHelper.collect_rx, QuestHelper.collect_ry, QuestHelper.rm, QuestHelper.rf
end
QH_Timeslice_Toggle("routing", not not self.m)
self:PumpCommMessages()
--end
end)
-- Some or all of these may be nil. c,x,y should be enough for a location - c is the pure continent (currently either 0 or 3 for Azeroth or Outland, or -77 for the DK starting zone) and x,y are the coordinates within that continent.
-- rc and rz are the continent and zone that Questhelper thinks it's within. For various reasons, this isn't perfect. TODO: Base it off the map zone name identifiers instead of the map itself?
function QuestHelper:Location_RawRetrieve()
return self.collect_rm, self.collect_rf, self.collect_rx, self.collect_ry
end
--[[
function QuestHelper:Location_AbsoluteRetrieve()
return self.collect_delayed, self.collect_ac, self.collect_ax, self.collect_ay
end
--]]
--QH_Hook(QuestHelper, "OnEvent", QuestHelper.OnEvent)