View Single Post
05-16-09, 04:39 AM   #4
Luzzifus
A Warpwood Thunder Caller
 
Luzzifus's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 94
How to add item set filters for ItemRack, Outfitter and Blizzards Equipment Manager

Since I spent quite some time to analyse each of those addons code to extract all the information I need and to create all the necessary callbacks, I thought I'd share my resulting code. You are of course absolutely free to use it in your own cargBags layout, however if you decide to publish it, I'd appreciate to be credited.

All three filters are also included in my own layout, you can get it here:
cargBags_Nivaya

(Note: ClosetGnome doesn't need support anymore, since it is now only an LDB plugin for switching sets from Blizzards Equipment Manager.)

I'll first explain the code for extracting the item set info from each of those addons. The basic idea is to add some specific callbacks or hooks to each addon, which notify us when sets are added, removed or changed. Those callbacks then create a table containing all set items as a key, so the final filter can do its work efficiently.

Blizzards Equipment Manager
Code:
-- This table will hold information about all items which are part of a set:
local item2setEM = {}

-- This function will extract the item set data, so it can be 
-- efficiently checked in the filter later:
local function cacheSetsEM()
    for k in pairs(item2setEM) do item2setEM[k] = nil end
    for k = 1, GetNumEquipmentSets() do
        local sName = GetEquipmentSetInfo(k)
        local set = GetEquipmentSetItemIDs(sName)
        for _,item in next, set do
            -- "item" is simply the item ID here:
            if item then item2setEM[item] = true end
        end
    end
    cargBags:UpdateBags()
end

-- This creates an invisible frame to hold the required event handlers:
local EQ_Event = CreateFrame("Frame")
EQ_Event:RegisterEvent("PLAYER_LOGIN")
EQ_Event:RegisterEvent("EQUIPMENT_SETS_CHANGED")
EQ_Event:SetScript("OnEvent", cacheSetsEM)
Outfitter
Code:
local OF = IsAddOnLoaded('Outfitter')
local item2setOF = {}
local pLevel = UnitLevel("player")
-- Outfitter doesn't use item strings or links to identify items by default, 
-- so this is the function to create an item string:
local function createItemString(i) return "item:"..i.Code..":"..i.EnchantCode..":"..i.JewelCode1..":"..i.JewelCode2..":"..i.JewelCode3..":"..i.JewelCode4..":"..i.SubCode..":"..i.UniqueID..":"..pLevel end

local function cacheSetsOF()
    for k in pairs(item2setOF) do item2setOF[k] = nil end
    -- Outfitter grants access to sets via categories,
    -- so there are two loops here:
    for _,id in ipairs(Outfitter_GetCategoryOrder()) do
        local OFsets = Outfitter_GetOutfitsByCategoryID(id)
        for _,vSet in pairs(OFsets) do
            for _,item in pairs(vSet.Items) do
                -- "item" is a table here, and since I don't want to save 
                -- the whole table, I'll create an itemstring out of it:
                if item then item2setOF[createItemString(item)] = true end
            end
        end
    end
    cargBags:UpdateBags()
end

if OF then
    -- Outfitter supports the needed callbacks by itself:
    Outfitter_RegisterOutfitEvent("ADD_OUTFIT", cacheSetsOF)
    Outfitter_RegisterOutfitEvent("DELETE_OUTFIT", cacheSetsOF)
    Outfitter_RegisterOutfitEvent("EDIT_OUTFIT", cacheSetsOF)
    if Outfitter:IsInitialized() then
        cacheSetsOF()
    else
        Outfitter_RegisterOutfitEvent('OUTFITTER_INIT', cacheSetsOF)
    end
end
ItemRack
Code:
local IR = IsAddOnLoaded('ItemRack')
local item2setIR = {}
local function cacheSetsIR()
    for k in pairs(item2setIR) do item2setIR[k] = nil end
    local IRsets = ItemRackUser.Sets
    for i in next, IRsets do
        -- Some internal sets and queues start with one of these 
        -- characters, so let's exclude them:
	if not string.find(i, "^~") then 
            for _,item in pairs(IRsets[i].equip) do
                -- "item" is a custom itemstring here:
                if item then item2setIR[item] = true end
	    end
	end
    end
end

if IR then
    cacheSetsIR()
    -- ItemRack doesn't support any callbacks by itself, so we're going to
    -- hook into the functions we need manually:
    local function ItemRackOpt_CreateHooks()
        -- Those are the actual hooks for adding, updating and deleting sets:
        local IRsaveSet = ItemRackOpt.SaveSet
        function ItemRackOpt.SaveSet(...) IRsaveSet(...); cacheSetsIR(); cargBags:UpdateBags() end
        local IRdeleteSet = ItemRackOpt.DeleteSet
        function ItemRackOpt.DeleteSet(...) IRdeleteSet(...); cacheSetsIR(); cargBags:UpdateBags() end
    end
    -- Amusingly, ItemRack puts its set updating functions into a 
    -- load-on-demand module, so we need to hook into the LoD-function first:
    local IRtoggleOpts = ItemRack.ToggleOptions
    function ItemRack.ToggleOptions(...) IRtoggleOpts(...) ItemRackOpt_CreateHooks() end
end

The filter

Finally the filter itself, use this function as an argument to SetFilter() for one of your cargBags bag objects:
Code:
local fItemSets = function(item)
    if not item.link then return false end
    -- Check ItemRack sets:
    if item2setIR[string.match(item.link,"item:(.+):%-?%d+")] then return true end
    -- Check Outfitter sets:
    local _,_,itemStr = string.find(item.link, "^|c%x+|H(.+)|h%[.*%]")
    if item2setOF[itemStr] then return true end
    -- Check Equipment Manager sets:
    local _,itemID = strsplit(":", itemStr)
    if item2setEM[tonumber(itemID)] then return true end    
    return false
end
Blizzards Equipment Manager simply uses the item ID to identify set items, ItemRack uses some custom item string and Outfitter uses a table with extracted values from the item link. I manually created an itemstring from those values in the corresponding cacheSets-function, so I don't have to match the whole table.

**edit: Updated for Blizzards Equipment Manager and removed ClosetGnome stuff, since it is not needed anymore.

Last edited by Luzzifus : 05-20-09 at 11:01 AM.
  Reply With Quote