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.

253 lines
9.1 KiB

local ADDON_NAME, ns = ...
-------------------------------------------------------------------------------
------------------------------ DATAMINE TOOLTIP -------------------------------
-------------------------------------------------------------------------------
local function CreateDatamineTooltip (name)
local f = CreateFrame("GameTooltip", name, UIParent, "GameTooltipTemplate")
f:SetOwner(UIParent, "ANCHOR_NONE")
return f
end
local NameResolver = {
cache = {},
prepared = {},
preparer = CreateDatamineTooltip(ADDON_NAME.."_NamePreparer"),
resolver = CreateDatamineTooltip(ADDON_NAME.."_NameResolver")
}
function NameResolver:IsLink (link)
if link == nil then return link end
return strsub(link, 1, 5) == 'unit:'
end
function NameResolver:Prepare (link)
if self:IsLink(link) and not (self.cache[link] or self.prepared[link]) then
-- use a separate tooltip to spam load NPC names, doing this with the
-- main tooltip can sometimes cause it to become unresponsive and never
-- update its text until a reload
self.preparer:SetHyperlink(link)
self.prepared[link] = true
end
end
function NameResolver:Resolve (link)
-- may be passed a raw name or a hyperlink to be resolved
if not self:IsLink(link) then return link or UNKNOWN end
-- all npcs must be prepared ahead of time to avoid breaking the resolver
if not self.prepared[link] then
ns.Debug('ERROR: npc link not prepared:', link)
end
local name = self.cache[link]
if name == nil then
self.resolver:SetHyperlink(link)
name = _G[self.resolver:GetName().."TextLeft1"]:GetText() or UNKNOWN
if name == UNKNOWN then
ns.Debug('NameResolver returned UNKNOWN, recreating tooltip ...')
self.resolver = CreateDatamineTooltip(ADDON_NAME.."_NameResolver")
else
self.cache[link] = name
end
end
return name
end
-------------------------------------------------------------------------------
-------------------------------- LINK RENDERER --------------------------------
-------------------------------------------------------------------------------
local function PrepareLinks(str)
if not str then return end
for type, id in str:gmatch('{(%l+):(%d+)(%l*)}') do
id = tonumber(id)
if type == 'npc' then
NameResolver:Prepare(("unit:Creature-0-0-0-0-%d"):format(id))
elseif type == 'item' then
C_Item.RequestLoadItemDataByID(id) -- prime item info
elseif type == 'daily' or type == 'quest' then
C_QuestLog.RequestLoadQuestByID(id) -- prime quest title
elseif type == 'spell' then
C_Spell.RequestLoadSpellData(id) -- prime spell info
end
end
end
local function RenderLinks(str, nameOnly)
-- render numberic ids
local links, _ = str:gsub('{(%l+):(%d+)(%l*)}', function (type, id, suffix)
id = tonumber(id)
if type == 'npc' then
local name = NameResolver:Resolve(("unit:Creature-0-0-0-0-%d"):format(id))
name = name..(suffix or '')
if nameOnly then return name end
return ns.color.NPC(name)
elseif type == 'achievement' then
if nameOnly then
local _, name = GetAchievementInfo(id)
if name then return name end
else
local link = GetAchievementLink(id)
if link then
return ns.GetIconLink('achievement', 15)..link
end
end
elseif type == 'currency' then
local info = C_CurrencyInfo.GetCurrencyInfo(id)
if info then
if nameOnly then return info.name end
local link = C_CurrencyInfo.GetCurrencyLink(id, 0)
if link then
return '|T'..info.iconFileID..':0:0:1:-1|t '..link
end
end
elseif type == 'faction' then
local name = GetFactionInfoByID(id)
if nameOnly then return name end
return ns.color.NPC(name) -- TODO: colorize based on standing?
elseif type == 'item' then
local name, link, _, _, _, _, _, _, _, icon = GetItemInfo(id)
if link and icon then
if nameOnly then return name..(suffix or '') end
return '|T'..icon..':0:0:1:-1|t '..link
end
elseif type == 'daily' or type == 'quest' then
local name = C_QuestLog.GetTitleForQuestID(id)
if name then
if nameOnly then return name end
local icon = (type == 'daily') and 'quest_ab' or 'quest_ay'
return ns.GetIconLink(icon, 12)..ns.color.Yellow('['..name..']')
end
elseif type == 'spell' then
local name, _, icon = GetSpellInfo(id)
if name and icon then
if nameOnly then return name end
local spell = ns.color.Spell('|Hspell:'..id..'|h['..name..']|h')
return '|T'..icon..':0:0:1:-1|t '..spell
end
end
return type..'+'..id
end)
-- render non-numeric ids
links, _ = links:gsub('{(%l+):([^}]+)}', function (type, id)
if type == 'wq' then
local icon = ns.GetIconLink('world_quest', 16, 0, -1)
return icon..ns.color.Yellow('['..id..']')
end
return type..'+'..id
end)
return links
end
-------------------------------------------------------------------------------
-------------------------------- BAG FUNCTIONS --------------------------------
-------------------------------------------------------------------------------
local function IterateBagSlots()
local bag, slot, slots = nil, 1, 1
return function ()
if bag == nil or slot == slots then
repeat
bag = (bag or -1) + 1
slot = 1
slots = GetContainerNumSlots(bag)
until slots > 0 or bag > 4
if bag > 4 then return end
else
slot = slot + 1
end
return bag, slot
end
end
local function PlayerHasItem(item, count)
for bag, slot in IterateBagSlots() do
if GetContainerItemID(bag, slot) == item then
if count and count > 1 then
return select(2, GetContainerItemInfo(bag, slot)) >= count
else return true end
end
end
return false
end
-------------------------------------------------------------------------------
------------------------------ DATABASE FUNCTIONS -----------------------------
-------------------------------------------------------------------------------
local function GetDatabaseTable(...)
local db = _G[ADDON_NAME.."DB"]
for _, key in ipairs({...}) do
if db[key] == nil then db[key] = {} end
db = db[key]
end
return db
end
-------------------------------------------------------------------------------
------------------------------ LOCALE FUNCTIONS -------------------------------
-------------------------------------------------------------------------------
--[[
Wrap the AceLocale NewLocale() function to return a slightly modified locale
table. This table will ignore assignments of `nil`, allowing locales to include
noop translation lines in their files without overriding the default enUS
strings. This allows us to keep all the locale files in sync with the exact
same keys in the exact same order even before actual translations are done.
--]]
local AceLocale = LibStub("AceLocale-3.0")
local LOCALES = {}
local function NewLocale (locale)
if LOCALES[locale] then return LOCALES[locale] end
local L = AceLocale:NewLocale(ADDON_NAME, locale, (locale == 'enUS'), true)
if not L then return end
local wrapper = {}
setmetatable(wrapper, {
__index = function (self, key) return L[key] end,
__newindex = function (self, key, value)
if value == nil then return end
L[key] = value
end
})
return wrapper
end
-------------------------------------------------------------------------------
------------------------------ TABLE CONVERTERS -------------------------------
-------------------------------------------------------------------------------
local function AsTable (value, class)
-- normalize to table of scalars
if type(value) == 'nil' then return end
if type(value) ~= 'table' then return {value} end
if class and ns.IsInstance(value, class) then return {value} end
return value
end
local function AsIDTable (value)
-- normalize to table of id objects
if type(value) == 'nil' then return end
if type(value) ~= 'table' then return {{id=value}} end
if value.id then return {value} end
for i, v in ipairs(value) do
if type(v) == 'number' then value[i] = {id=v} end
end
return value
end
-------------------------------------------------------------------------------
ns.AsIDTable = AsIDTable
ns.AsTable = AsTable
ns.GetDatabaseTable = GetDatabaseTable
ns.NameResolver = NameResolver
ns.NewLocale = NewLocale
ns.PlayerHasItem = PlayerHasItem
ns.PrepareLinks = PrepareLinks
ns.RenderLinks = RenderLinks