336 lines
7.4 KiB
Lua
336 lines
7.4 KiB
Lua
--[[
|
|
ItemSearch
|
|
An item text search engine of some sort
|
|
--]]
|
|
|
|
local Search = LibStub("CustomSearch-1.0")
|
|
local Unfit = LibStub("Unfit-1.0")
|
|
local Lib = LibStub:NewLibrary("LibItemSearch-1.2-ElvUI", 17)
|
|
if Lib then
|
|
Lib.Scanner = LibItemSearchTooltipScanner or CreateFrame("GameTooltip", "LibItemSearchTooltipScanner", UIParent, "GameTooltipTemplate")
|
|
Lib.Filters = {}
|
|
else
|
|
return
|
|
end
|
|
|
|
--[[ User API ]]--
|
|
|
|
function Lib:Matches(link, search)
|
|
return Search(link, search, self.Filters)
|
|
end
|
|
|
|
function Lib:Tooltip(link, search)
|
|
return link and self.Filters.tip:match(link, nil, search)
|
|
end
|
|
|
|
function Lib:TooltipPhrase(link, search)
|
|
return link and self.Filters.tipPhrases:match(link, nil, search)
|
|
end
|
|
|
|
function Lib:InSet(link, search)
|
|
if IsEquippableItem(link) then
|
|
local id = tonumber(link:match("item:(%-?%d+)"))
|
|
return self:BelongsToSet(id, (search or ""):lower())
|
|
end
|
|
end
|
|
|
|
--[[ Internal API ]]--
|
|
local function LibItemRack(id, search)
|
|
for name, set in pairs(ItemRackUser.Sets) do
|
|
if search == "any" or name:sub(1,1) ~= "" and Search:Find(search, name) then
|
|
for _, item in pairs(set.equip) do
|
|
if sameID(id, item) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function LibWardrobe(id, search)
|
|
for _, outfit in ipairs(Wardrobe.CurrentConfig.Outfit) do
|
|
local name = outfit.OutfitName
|
|
if search == "any" or Search:Find(search, name) then
|
|
for _, item in pairs(outfit.Item) do
|
|
if item.IsSlotUsed == 1 and item.ItemID == id then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function LibOutfitter(id, search)
|
|
for _, group in pairs(Outfitter.Settings.Outfits) do
|
|
for _, set in ipairs(group) do
|
|
if search == "any" or Search:Find(search, set["Name"]) then
|
|
for _, base in pairs(set["Items"]) do
|
|
if base["Code"] == id then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function LibDefault(id, search)
|
|
for i = 1, GetNumEquipmentSets() do
|
|
local name = GetEquipmentSetInfo(i)
|
|
if search == "any" or Search:Find(search, name) then
|
|
local items = GetEquipmentSetItemIDs(name)
|
|
for _, item in pairs(items) do
|
|
if id == item then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local outfit_addons = {LibDefault}
|
|
function Lib:BelongsToSet(id, search)
|
|
for g, funct in ipairs(outfit_addons) do
|
|
if funct(id, search) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
--[[ General ]]--
|
|
|
|
Lib.Filters.name = {
|
|
tags = {"n", "name"},
|
|
|
|
canSearch = function(self, operator, search)
|
|
return not operator and search
|
|
end,
|
|
|
|
match = function(self, item, _, search)
|
|
local name = item:match("%[(.-)%]")
|
|
return Search:Find(search, name)
|
|
end
|
|
}
|
|
|
|
Lib.Filters.type = {
|
|
tags = {"t", "type", "s", "slot"},
|
|
|
|
canSearch = function(self, operator, search)
|
|
return not operator and search
|
|
end,
|
|
|
|
match = function(self, item, _, search)
|
|
local type, subType, _, equipSlot = select(6, GetItemInfo(item))
|
|
return Search:Find(search, type, subType, equipSlot and equipSlot ~= "" and _G[equipSlot])
|
|
end
|
|
}
|
|
|
|
Lib.Filters.level = {
|
|
tags = {"l", "level", "lvl", "ilvl"},
|
|
|
|
canSearch = function(self, _, search)
|
|
return tonumber(search)
|
|
end,
|
|
|
|
match = function(self, link, operator, num)
|
|
local lvl = select(4, GetItemInfo(link))
|
|
if lvl then
|
|
return Search:Compare(operator, lvl, num)
|
|
end
|
|
end
|
|
}
|
|
|
|
Lib.Filters.requiredlevel = {
|
|
tags = {"r", "req", "rl", "reql", "reqlvl"},
|
|
|
|
canSearch = function(self, _, search)
|
|
return tonumber(search)
|
|
end,
|
|
|
|
match = function(self, link, operator, num)
|
|
local lvl = select(5, GetItemInfo(link))
|
|
if lvl then
|
|
return Search:Compare(operator, lvl, num)
|
|
end
|
|
end
|
|
}
|
|
|
|
Lib.Filters.sets = {
|
|
tags = {"s", "set"},
|
|
|
|
canSearch = function(self, operator, search)
|
|
return not operator and search
|
|
end,
|
|
|
|
match = function(self, link, _, search)
|
|
return Lib:InSet(link, search)
|
|
end,
|
|
}
|
|
|
|
Lib.Filters.quality = {
|
|
tags = {"q", "quality"},
|
|
keywords = {},
|
|
|
|
canSearch = function(self, _, search)
|
|
for quality, name in pairs(self.keywords) do
|
|
if name:find(search) then
|
|
return quality
|
|
end
|
|
end
|
|
end,
|
|
|
|
match = function(self, link, operator, num)
|
|
local quality = select(3, GetItemInfo(link))
|
|
return Search:Compare(operator, quality, num)
|
|
end,
|
|
}
|
|
|
|
--[[
|
|
0 Poor 9d9d9d
|
|
1 Common ffffff
|
|
2 Uncommon 1eff00
|
|
3 Rare 0070dd
|
|
4 Epic a335ee
|
|
5 Legendary ff8000
|
|
6 Artifact e6cc80
|
|
7 Heirloom 00ccff
|
|
]]
|
|
for i = 0, 7 do -- Ascension change: was `#ITEM_QUALITY_COLORS` now `7`
|
|
Lib.Filters.quality.keywords[i] = _G["ITEM_QUALITY" .. i .. "_DESC"]:lower()
|
|
end
|
|
|
|
--[[ Classic Keywords ]]--
|
|
|
|
Lib.Filters.items = {
|
|
keyword = ITEMS:lower(),
|
|
|
|
canSearch = function(self, operator, search)
|
|
return not operator and self.keyword:find(search)
|
|
end,
|
|
|
|
match = function(self, link)
|
|
return true
|
|
end
|
|
}
|
|
|
|
Lib.Filters.usable = {
|
|
keyword = USABLE_ITEMS:lower(),
|
|
|
|
canSearch = function(self, operator, search)
|
|
return not operator and self.keyword:find(search)
|
|
end,
|
|
|
|
match = function(self, link)
|
|
if not Unfit:IsItemUnusable(link) then
|
|
local lvl = select(5, GetItemInfo(link))
|
|
return lvl and (lvl ~= 0 and lvl <= UnitLevel("player"))
|
|
end
|
|
end
|
|
}
|
|
|
|
--[[ Tooltips ]]--
|
|
|
|
Lib.Filters.tip = {
|
|
tags = {"tt", "tip", "tooltip"},
|
|
onlyTags = true,
|
|
|
|
canSearch = function(self, _, search)
|
|
return search
|
|
end,
|
|
|
|
match = function(self, link, _, search)
|
|
if link:find("item:") then
|
|
Lib.Scanner:SetOwner(UIParent, "ANCHOR_NONE")
|
|
Lib.Scanner:SetHyperlink(link)
|
|
|
|
for i = 1, Lib.Scanner:NumLines() do
|
|
if Search:Find(search, _G[Lib.Scanner:GetName() .. "TextLeft" .. i]:GetText()) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
}
|
|
|
|
Lib.Filters.tipPhrases = {
|
|
canSearch = function(self, _, search)
|
|
if #search >= 3 then
|
|
for key, query in pairs(self.keywords) do
|
|
if key:find(search) then
|
|
return query
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
|
|
match = function(self, link, _, search)
|
|
local id = link:match("item:(%d+)")
|
|
if not id then
|
|
return
|
|
end
|
|
|
|
local cached = self.cache[search][id]
|
|
if cached ~= nil then
|
|
return cached
|
|
end
|
|
|
|
Lib.Scanner:SetOwner(UIParent, "ANCHOR_NONE")
|
|
Lib.Scanner:SetHyperlink(link)
|
|
|
|
local matches = false
|
|
for i = 1, Lib.Scanner:NumLines() do
|
|
if search == _G[Lib.Scanner:GetName() .. "TextLeft" .. i]:GetText() then
|
|
matches = true
|
|
break
|
|
end
|
|
end
|
|
|
|
self.cache[search][id] = matches
|
|
return matches
|
|
end,
|
|
|
|
cache = setmetatable({}, {__index = function(t, k) local v = {} t[k] = v return v end}),
|
|
keywords = {
|
|
[ITEM_SOULBOUND:lower()] = ITEM_BIND_ON_PICKUP,
|
|
[QUESTS_LABEL:lower()] = ITEM_BIND_QUEST,
|
|
|
|
["bound"] = ITEM_BIND_ON_PICKUP,
|
|
["bop"] = ITEM_BIND_ON_PICKUP,
|
|
["boe"] = ITEM_BIND_ON_EQUIP,
|
|
["bou"] = ITEM_BIND_ON_USE,
|
|
["boa"] = ITEM_BIND_TO_ACCOUNT,
|
|
}
|
|
}
|
|
|
|
-- keep track of which function handles which addon
|
|
local equipmentAddons = {
|
|
["ItemRack"] = LibItemRack,
|
|
["Wardrobe"] = LibWardrobe,
|
|
["Outfitter"] = LibOutfitter,
|
|
}
|
|
local loadedOutfitAddons = {} -- keep track of which set management addons are loaded
|
|
|
|
-- check if any addons are already loaded
|
|
for addon, funct in pairs(equipmentAddons) do
|
|
if IsAddOnLoaded(addon) then
|
|
loadedOutfitAddons[addon] = true
|
|
outfit_addons[#outfit_addons + 1] = funct
|
|
end
|
|
end
|
|
|
|
local frame, events = CreateFrame("Frame"), {}
|
|
-- watch loading addons for ones we care about
|
|
function events:ADDON_LOADED(name)
|
|
if equipmentAddons[name] and not loadedOutfitAddons[name] then
|
|
outfit_addons[#outfit_addons + 1] = equipmentAddons[name]
|
|
loadedOutfitAddons[name] = true
|
|
end
|
|
end
|
|
frame:SetScript("OnEvent", function(self, event, ...)
|
|
events[event](self, ...)
|
|
end)
|
|
for k, v in pairs(events) do
|
|
frame:RegisterEvent(k) -- Register all events for which handlers have been defined
|
|
end |