Files

283 lines
6.2 KiB
Lua

--[[
BagEvents
A library of functions for accessing and updating bag slot information
Based on SpecialEvents-Bags by Tekkub Stoutwrithe (tekkub@gmail.com)
ITEM_SLOT_ADD
args: bag, slot, link, count, locked, coolingDown
called when a new slot becomes available to the player
ITEM_SLOT_REMOVE
args: bag, slot
called when an item slot is removed from being in use
ITEM_SLOT_UPDATE
args: bag, slot, link, count, locked, coolingDown
called when an item slot's item or item count changes
ITEM_SLOT_UPDATE_COOLDOWN
args: bag, slot, coolingDown
called when an item's cooldown starts/ends
BANK_OPENED
args: none
called when the bank has opened and all of the bagnon events have SendMessaged
BANK_CLOSED
args: none
called when the bank is closed and all of the bagnon events have SendMessaged
BAG_UPDATE_TYPE
args: bag, type
called when the type of a bag changes (aka, what items you can put in it changes)
--]]
local Bagnon = LibStub('AceAddon-3.0'):GetAddon('Bagnon')
local Bucket = LibStub("AceBucket-3.0")
local BagEvents = Bagnon.Ears:New()
Bucket:Embed(BagEvents)
Bagnon.BagEvents = BagEvents
--[[ privates? ]]--
local slots = {}
local bagTypes = {}
local function ToIndex(bag, slot)
return (bag < 0 and bag*100 - slot) or bag*100 + slot
end
local function GetBagSize(bag)
return (bag == KEYRING_CONTAINER and GetKeyRingSize()) or GetContainerNumSlots(bag)
end
--[[ Startup ]]--
function BagEvents:Load()
self.atBank = false
self.firstVisit = true
self.frame = CreateFrame('Frame')
self.RegisterEvent = function(self, event)
self.frame:RegisterEvent(event)
end
self.OnEvent = function(f, event, ...)
if self[event] then
self[event](self, event, ...)
end
end
self.frame:SetScript('OnEvent', self.OnEvent)
self:RegisterEvent('PLAYER_LOGIN')
end
--[[ Update Functions ]]--
--all info
function BagEvents:AddItem(bag, slot)
local index = ToIndex(bag,slot)
if not slots[index] then slots[index] = {} end
local data = slots[index]
local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(bag, slot)
local start, duration, enable = GetContainerItemCooldown(bag, slot)
local onCooldown = (start > 0 and duration > 0 and enable > 0)
data[1] = link
data[2] = count
data[3] = locked
data[4] = onCooldown
self:SendMessage('ITEM_SLOT_ADD', bag, slot, link, count, locked, onCooldown)
end
function BagEvents:RemoveItem(bag, slot)
local data = slots[ToIndex(bag, slot)]
if data and next(data) then
local prevLink = data[1]
for i in pairs(data) do
data[i] = nil
end
self:SendMessage('ITEM_SLOT_REMOVE', bag, slot, prevLink)
end
end
function BagEvents:UpdateItem(bag, slot)
local data = slots[ToIndex(bag, slot)]
if data then
local prevLink = data[1]
local prevCount = data[2]
local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(bag, slot)
local start, duration, enable = GetContainerItemCooldown(bag, slot)
local onCooldown = (start > 0 and duration > 0 and enable > 0)
if not(prevLink == link and prevCount == count) then
data[1] = link
data[2] = count
data[3] = locked
data[4] = onCooldown
self:SendMessage('ITEM_SLOT_UPDATE', bag, slot, link, count, locked, onCooldown)
end
end
end
function BagEvents:UpdateItems(bag)
for slot = 1, GetBagSize(bag) do
self:UpdateItem(bag, slot)
end
end
--cooldowns
function BagEvents:UpdateCooldown(bag, slot)
local data = slots[ToIndex(bag,slot)]
if data and data[1] then
local start, duration, enable = GetContainerItemCooldown(bag, slot)
local onCooldown = (start > 0 and duration > 0 and enable > 0)
if data[4] ~= onCooldown then
data[4] = onCooldown
self:SendMessage('ITEM_SLOT_UPDATE_COOLDOWN', bag, slot, onCooldown)
end
end
end
function BagEvents:UpdateCooldowns(bag)
for slot = 1, GetBagSize(bag) do
self:UpdateCooldown(bag, slot)
end
end
--bag sizes
function BagEvents:UpdateBagSize(bag)
local prevSize = slots[bag*100] or 0
local newSize = GetBagSize(bag) or 0
slots[bag*100] = newSize
if prevSize > newSize then
for slot = newSize+1, prevSize do
self:RemoveItem(bag, slot)
end
elseif prevSize < newSize then
for slot = prevSize+1, newSize do
self:AddItem(bag, slot)
end
end
end
function BagEvents:UpdateBagType(bag)
local _, newType = GetContainerNumFreeSlots(bag)
local prevType = bagTypes[bag]
if newType ~= prevType then
bagTypes[bag] = newType
self:SendMessage('BAG_UPDATE_TYPE', bag, newType)
end
end
function BagEvents:UpdateBagSizes()
if self:AtBank() then
for bag = 1, NUM_BAG_SLOTS + GetNumBankSlots() do
self:UpdateBagSize(bag)
end
else
for bag = 1, NUM_BAG_SLOTS do
self:UpdateBagSize(bag)
end
end
self:UpdateBagSize(KEYRING_CONTAINER)
end
function BagEvents:UpdateBagTypes()
if self:AtBank() then
for bag = 1, NUM_BAG_SLOTS + GetNumBankSlots() do
self:UpdateBagType(bag)
end
else
for bag = 1, NUM_BAG_SLOTS do
self:UpdateBagType(bag)
end
end
end
--[[ Events ]]--
function BagEvents:PLAYER_LOGIN(...)
self:RegisterBucketEvent('BAG_UPDATE', 0.2, 'BAG_UPDATE')
self:RegisterEvent('BAG_UPDATE_COOLDOWN')
self:RegisterEvent('PLAYERBANKSLOTS_CHANGED')
self:RegisterEvent('BANKFRAME_OPENED')
self:RegisterEvent('BANKFRAME_CLOSED')
self:UpdateBagSize(KEYRING_CONTAINER)
self:UpdateItems(KEYRING_CONTAINER)
self:UpdateBagSize(BACKPACK_CONTAINER)
self:UpdateItems(BACKPACK_CONTAINER)
end
function BagEvents:BAG_UPDATE(bagIDs)
self:UpdateBagTypes()
self:UpdateBagSizes()
for bagID in pairs(bagIDs) do
self:UpdateItems(bagID)
end
end
function BagEvents:PLAYERBANKSLOTS_CHANGED(...)
self:UpdateBagTypes()
self:UpdateBagSizes()
self:UpdateItems(BANK_CONTAINER)
end
function BagEvents:BANKFRAME_OPENED(...)
self.atBank = true
if self.firstVisit then
self.firstVisit = nil
self:UpdateBagSize(BANK_CONTAINER)
self:UpdateBagTypes()
self:UpdateBagSizes()
end
self:SendMessage('BANK_OPENED')
end
function BagEvents:BANKFRAME_CLOSED(...)
self.atBank = false
self:SendMessage('BANK_CLOSED')
end
function BagEvents:BAG_UPDATE_COOLDOWN(...)
self:UpdateCooldowns(BACKPACK_CONTAINER)
for bag = 1, NUM_BAG_SLOTS do
self:UpdateCooldowns(bag)
end
end
--[[ Accessor Methods ]]--
function BagEvents:AtBank()
return self.atBank
end
--load the thing
BagEvents:Load()