You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
10 KiB

-- ----------------------------------------------------------------------------
-- Upvalued Lua API.
-- ----------------------------------------------------------------------------
-- Functions
local pairs = _G.pairs
-- Libraries
local string = _G.string
local table = _G.table
-- ----------------------------------------------------------------------------
-- AddOn namespace.
-- ----------------------------------------------------------------------------
local AddOnFolderName, private = ...
local Data = private.Data
local Enum = private.Enum
local LibStub = _G.LibStub
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
local HereBeDragons = LibStub("HereBeDragons-2.0")
local NPCScan = LibStub("AceAddon-3.0"):NewAddon(AddOnFolderName, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceBucket-3.0", "LibSink-2.0", "LibToast-1.0")
-- ----------------------------------------------------------------------------
-- Debugger.
-- ----------------------------------------------------------------------------
do
local TextDump = LibStub("LibTextDump-1.0")
local DEBUGGER_WIDTH = 750
local DEBUGGER_HEIGHT = 800
local debugger
local function GetDebugger()
if not debugger then
debugger = TextDump:New(("%s Debug Output"):format(AddOnFolderName), DEBUGGER_WIDTH, DEBUGGER_HEIGHT)
end
return debugger
end
private.GetDebugger = GetDebugger
function private.Debug(...)
local message = string.format(...)
GetDebugger():AddLine(message, "%X")
return message
end
end
-- ----------------------------------------------------------------------------
-- Variables.
-- ----------------------------------------------------------------------------
local NPCIDFromName = {}
private.NPCIDFromName = NPCIDFromName
local QuestIDFromName = {}
private.QuestIDFromName = QuestIDFromName
-- ----------------------------------------------------------------------------
-- AddOn Methods.
-- ----------------------------------------------------------------------------
function NPCScan:OnInitialize()
-- ----------------------------------------------------------------------------
-- Data initialization
-- ----------------------------------------------------------------------------
local DefaultPreferences = private.DefaultPreferences
local UIMapType = _G.Enum.UIMapType
for _, achievementID in pairs(Enum.AchievementID) do
DefaultPreferences.profile.detection.achievementIDs[achievementID] = Enum.DetectionGroupStatus.Enabled
end
for _, continentID in pairs(Enum.ContinentID) do
local continent = Data.Continents[continentID]
if not continent then
continent = {
Maps = {}
}
Data.Continents[continentID] = continent
end
continent.ID = continentID
continent.name = HereBeDragons:GetLocalizedMap(Enum.ContinentMapID[continentID])
DefaultPreferences.profile.detection.continentIDs[continentID] = Enum.DetectionGroupStatus.Enabled
end
for mapID, map in pairs(Data.Maps) do
local parentMapInfo = _G.MapUtil.GetMapParentInfo(mapID, UIMapType.Continent)
or _G.MapUtil.GetMapParentInfo(mapID, UIMapType.World)
or _G.MapUtil.GetMapParentInfo(mapID, UIMapType.Cosmic)
local continentID = parentMapInfo and Enum.MapContinentID[parentMapInfo.mapID] or Enum.ContinentID.Cosmic
local mapInfo = _G.C_Map.GetMapInfo(mapID)
if mapInfo.mapType == UIMapType.Dungeon or mapInfo.mapType == UIMapType.Orphan then
map.isDungeon = true
end
map.continentID = continentID
map.ID = mapID
map.name = HereBeDragons:GetLocalizedMap(mapID) or _G.UNKNOWN
Data.Continents[continentID].Maps[mapID] = map
end
local db = LibStub("AceDB-3.0"):New("NPCScanDB", DefaultPreferences, "Default")
db.RegisterCallback(self, "OnProfileChanged", "RefreshPreferences")
db.RegisterCallback(self, "OnProfileCopied", "RefreshPreferences")
db.RegisterCallback(self, "OnProfileReset", "RefreshPreferences")
self:DefineSinkToast(AddOnFolderName, [[Interface\LFGFRAME\BattlenetWorking0]])
self:SetSinkStorage(db.profile.alert.output)
private.db = db
-- ----------------------------------------------------------------------------
-- DB migrations
-- ----------------------------------------------------------------------------
local sharedMediaNames = db.profile.alert.sound.sharedMediaNames
for index = 1, 50 do
local actualName = sharedMediaNames[index]
if actualName then
sharedMediaNames[actualName] = true
sharedMediaNames[index] = nil
end
end
self:RegisterChatCommand("npcscan", "ChatCommand")
end
function NPCScan:OnEnable()
-- ----------------------------------------------------------------------------
-- Build lookup tables.
-- ----------------------------------------------------------------------------
for mapID, map in pairs(Data.Maps) do
for npcID in pairs(map.NPCs) do
local npc = private.InitializeNPC(npcID)
map.NPCs[npcID] = npc
npc.mapIDs = npc.mapIDs or {}
npc.mapIDs[#npc.mapIDs + 1] = mapID
table.sort(npc.mapIDs, private.SortByMapNameThenByID)
end
end
private.InitializeAchievements()
local hasChecked = {}
local questMapIDs = {
[Enum.MapID.Argus] = true,
[Enum.MapID.BrokenIsles] = true,
[Enum.MapID.KulTiras] = true,
[Enum.MapID.Zandalar] = true,
}
local vignetteMapIDs = {
[Enum.MapID.Argus] = true,
[Enum.MapID.BrokenIsles] = true,
[Enum.MapID.Draenor] = true,
[Enum.MapID.KulTiras] = true,
[Enum.MapID.Pandaria] = true,
[Enum.MapID.Zandalar] = true,
}
for mapID, map in pairs(Data.Maps) do
local continent = _G.MapUtil.GetMapParentInfo(mapID, _G.Enum.UIMapType.Continent, true)
local missingData = {}
local mapHeaderPrinted
for npcID in pairs(map.NPCs) do
local npc = map.NPCs[npcID]
if not hasChecked[npcID] then
local questID = npc.questID or npc.achievementQuestID
if not questID and not npc.worldQuestID and (not continent or questMapIDs[continent.mapID]) then
missingData[npcID] = "questID"
end
if not npc.vignetteID and (not continent or vignetteMapIDs[continent.mapID]) then
if missingData[npcID] then
missingData[npcID] = ("%s, vignetteID"):format(missingData[npcID])
else
missingData[npcID] = "vignetteID"
end
end
hasChecked[npcID] = true
end
end
for npcID, missingText in pairs(missingData) do
if not mapHeaderPrinted then
mapHeaderPrinted = true
private.Debug("-- ----------------------------------------------------------------------------")
private.Debug("-- %s (%d)", HereBeDragons:GetLocalizedMap(mapID) or _G.UNKNOWN, mapID)
private.Debug("-- ----------------------------------------------------------------------------")
end
private.Debug("NPC %d (%s) is missing: %s.", npcID, self:GetNPCNameFromID(npcID), missingText)
end
end
-- Handle custom additions.
for npcID, npcName in pairs(private.db.locale.npcNames) do
NPCIDFromName[npcName] = npcID
end
self:SetupOptions()
self:InitializeTargetButton()
self:RegisterBucketEvent("CRITERIA_UPDATE", 5)
self:RegisterEvent("LOOT_CLOSED")
self:RegisterEvent("NAME_PLATE_UNIT_ADDED")
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("PLAYER_TARGET_CHANGED")
self:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
self:RegisterEvent("VIGNETTE_MINIMAP_UPDATED")
self:RegisterBucketEvent("VIGNETTES_UPDATED", 0.5)
HereBeDragons.RegisterCallback(NPCScan, "PlayerZoneChanged", "UpdateScanList")
self:UpdateScanList()
private.Overlays.Register()
end
function NPCScan:RefreshPreferences()
end
do
local DatamineTooltip = _G.CreateFrame("GameTooltip", "NPCScanDatamineTooltip", _G.UIParent, "GameTooltipTemplate")
DatamineTooltip:SetOwner(_G.WorldFrame, "ANCHOR_NONE")
function NPCScan:GetNPCNameFromID(npcID)
local npcName = private.db.locale.npcNames[npcID]
if not npcName then
DatamineTooltip:SetHyperlink(("unit:Creature-0-0-0-0-%d"):format(npcID))
npcName = _G["NPCScanDatamineTooltipTextLeft1"]:GetText()
if npcName and npcName ~= "" then
private.db.locale.npcNames[npcID] = npcName
NPCIDFromName[npcName] = npcID
else
npcName = _G.UNKNOWN
end
end
return npcName
end
function NPCScan:GetQuestNameFromID(questID)
local questName = private.db.locale.questNames[questID]
if not questName then
questName = _G.C_QuestLog.GetTitleForQuestID(questID)
if questName and questName ~= "" then
private.db.locale.questNames[questID] = questName
private.QuestIDFromName[questName] = questID
else
questName = _G.UNKNOWN
end
end
return questName:gsub("Vignette: ", "")
end
end
do
local SUBCOMMAND_FUNCS
function NPCScan:ChatCommand(input)
SUBCOMMAND_FUNCS =
SUBCOMMAND_FUNCS or
{
ADD = private.AddUserDefinedNPC,
COMPARE = private.CompareData,
REMOVE = private.RemoveUserDefinedNPC,
SEARCH = function(subject)
AceConfigDialog:Open(AddOnFolderName)
AceConfigDialog:SelectGroup(AddOnFolderName, "npcOptions", "search")
private.PerformNPCSearch(subject)
end,
--[===[@debug@
DEBUG = function()
local debugger = private.GetDebugger()
if debugger:Lines() == 0 then
debugger:AddLine("Nothing to report.")
debugger:Display()
debugger:Clear()
return
end
debugger:Display()
end,
DUMP = function(dumpType, parameters)
local func = private.DUMP_COMMANDS[dumpType]
if func then
private.TextDump = private.TextDump or _G.LibStub("LibTextDump-1.0"):New(AddOnFolderName)
func(parameters)
else
NPCScan:Print("Unknown dump command. Valid commands:")
for command in pairs(private.DUMP_COMMANDS) do
NPCScan:Printf(" %s", command)
end
end
end
--@end-debug@]===]
}
local subcommand, arg1, arg2 = self:GetArgs(input, 3)
if subcommand then
local func = SUBCOMMAND_FUNCS[subcommand:upper()]
if func then
func(arg1, arg2)
end
else
AceConfigDialog:Open(AddOnFolderName)
end
end
end -- do-block