WoWInterface SVN kRestack

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /trunk
    from Rev 14 to Rev 13
    Reverse comparison

Rev 14 → Rev 13

kRestack/changelog.txt
1,9 → 1,2
v1.0 r14 release 2009-05-18
- Added support for restacking guild vault tabs.
- Hooked bag auto-stack to LOOT_OPEN and TRADE_SHOW, and guild bank auto-stack to GUILDBANKFRAME_OPENED and SetCurrentGuildBankTab(i).
- Extended auto-stack toggle to enable or disable bags, bank, or guild bank individually.
- Will now move items that can go into special class/profession bags into those bags if possible (soul shards, herbs, arrows, etc).
- Cleaned up and commented code.
 
v0.9 r13 release 2009-05-13
r13 release 2009-05-13
- Added option to auto-stack when opening bags or bank, off by default. Toggle with '/restack auto'
\ No newline at end of file
kRestack/kRestack.lua
1,93 → 1,67
--[[ kRestack() is a global function and can be used in any addon or macro
Some of the functionality is based on ArkInventory's restacking function, kudos!
 
Usage:
/restack [bags, bank, guild] - manual run
/restack auto [bags, bank, guild] - toggles auto mode
]]
Usage: /restack [bags, bank, auto]
Devs: kRestack("bags") and kRestack("bank") can be used in your addons. ]]
 
SlashCmdList["RESTACK"] = function(s) kRestack(s) end
SLASH_RESTACK1 = "/restack"
 
--[[ pretty chat colors! ]]
local col = { w = "|cffFFFFFF", g = "|cff55FF55", r = "|cffFF5555" }
local kR = "|cff44CCFFk|cffFFFFAARestack"..col.w
local container = { bags = { 0 }, bank = { -1 } }
 
--[[ set user's container identifers ]]
local container = { bags = { 0 }, bank = { -1 }, guild = { 42 } }
for i = 1, NUM_BAG_SLOTS do table.insert(container.bags, i) end
for i = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do table.insert(container.bank, i) end
 
--[[ initiate defaults ]]
if type(AutoRestack) ~= "table" then
AutoRestack = { }
elseif AutoRestack.bags == nil then
table.insert(AutoRestack.bags, true)
elseif AutoRestack.bank == nil then
table.insert(AutoRestack.bank, true)
elseif AutoRestack.guild == nil then
table.insert(AutoRestack.guild, false)
end
 
--[[ watching some events ]]
local frame = CreateFrame("FRAME")
local events = { "BANKFRAME_OPENED", "LOOT_OPENED", "TRADE_SHOW", "GUILDBANKFRAME_OPENED" }
for _, r in pairs(events) do frame:RegisterEvent(r) end
frame:SetScript("OnEvent", function(_, e)
if AutoRestack.bank and e == events[1] then
frame:RegisterEvent("BANKFRAME_OPENED")
frame:SetScript("OnEvent", function(_, event)
if event == "BANKFRAME_OPENED" and AutoRestack then
kRestack("bank", true)
elseif AutoRestack.bags and (e == events[2] or e == events[3]) then
kRestack("bags", true)
elseif AutoRestack.guild and e == events[4] then
kRestack("guild", true)
end
end)
 
--[[ hooking auto-stacking to togglebackpack and guild bank tab switching ]]
local oToggleBackpack = ToggleBackpack
ToggleBackpack = function()
if AutoRestack.bags then kRestack("bags", true) end
if AutoRestack and not InCombatLockdown() and (type(restacker) ~= "thread" or coroutine.status(restacker) == "dead") then
kRestack("bags", true)
end
return oToggleBackpack()
end
 
local oSetCurrentGuildBankTab = SetCurrentGuildBankTab
SetCurrentGuildBankTab = function(tab)
if AutoRestack.guild and (type(restacker) ~= "thread" or coroutine.status(restacker) == "dead") then
kRestack("guild", true, tab)
return oSetCurrentGuildBankTab(tab)
end
local function DecodeItemId(itemlink)
return select(3, strfind(itemlink, "item:(%d+)"))
end
 
local function coYield(loc, lb, ls, count)
--[[ yielding function; can't be stacking too fast or else bad stuff happens ]]
frame:SetScript("OnUpdate", function()
if coroutine.status(restacker) == "suspended" then
local locked = true
if loc == "guild" then
locked = select(2, GetGuildBankItemInfo(lb, ls)) == count and true or false
else
locked = select(3, GetContainerItemInfo(lb, ls))
local function RestackFindPartial(cb, cs, id, loc)
for _, bag in pairs(container[loc]) do
for slot = GetContainerNumSlots(bag), 1, -1 do
if not (bag == cb and slot == cs) then
local item = GetContainerItemLink(bag, slot)
if item then
local itemId = DecodeItemId(item)
if itemId == id then
local _, count, locked = GetContainerItemInfo(bag, slot)
local stack = select(8, GetItemInfo(itemId))
if stack > count then return true, bag, slot end
end
end
end
if not locked then coroutine.resume(restacker) end
end
end)
coroutine.yield()
end
return false
end
 
local function getPartial(cb, cs, id, loc)
local vault = loc == "guild"
local function RestackFindSpecial(ct, loc)
for _, bag in pairs(container[loc]) do
local slots = vault and MAX_GUILDBANK_SLOTS_PER_TAB or GetContainerNumSlots(bag)
for slot = slots, 1, -1 do
bag = vault and cb or bag
if not (bag == cb and slot == cs) then
local item = vault and GetGuildBankItemLink(bag, slot) or GetContainerItemLink(bag, slot)
local _, bt = GetContainerNumFreeSlots(bag)
if bt == 0 then
for slot = 1, GetContainerNumSlots(bag) do
local item = GetContainerItemLink(bag, slot)
if item then
local itemid = select(3, strfind(item, "item:(%d+)"))
if itemid == id then
local stack = select(8, GetItemInfo(itemid))
local count = vault and select(2, GetGuildBankItemInfo(bag, slot)) or select(2, GetContainerItemInfo(bag, slot))
if stack > count then return true, bag, slot end
local itemEquipLoc = select(8, GetItemInfo(h))
if itemEquipLoc ~= "INVTYPE_BAG" then
local it = GetItemFamily(h)
if bit.band(it, ct) > 0 then return true, bag, slot end
end
end
end
96,125 → 70,133
return false
end
 
--[[ main function ]]
function kRestack(loc, nowarn, tab)
if loc ~= "bags" and loc ~= "bank" and loc ~= "guild" then
--[[ more slash commands ]]
if loc == "resume" then
if coroutine.status(restacker) == "suspended" then
print(kR..col.w, "Resuming suspended thread.")
coroutine.resume(restacker)
else
print(kR..col.w, "No suspended threads to resume.")
end
else
loc = select(3, strfind(loc, "auto (%a+)"))
if loc == "bags" or loc == "bank" or loc == "guild" then
local togl
if not AutoRestack[loc] then
AutoRestack[loc] = true
togl = col.g.."ON"
local function RestackBags(loc)
local changed = false
for _, bag in pairs(container[loc]) do
for slot = 1, GetContainerNumSlots(bag) do
while true do
local locked = select(3, GetContainerItemInfo(bag, slot))
if locked then
coroutine.yield()
else
AutoRestack[loc] = false
togl = col.r.."OFF"
break
end
loc = loc == "bags" and "your backpack" or loc
loc = loc == "bank" and "your bank" or loc
loc = loc == "guild" and "the guild vault" or loc
print(kR, "Auto-stacking for", loc, "toggled", togl)
else
local bags = AutoRestack.bags and col.g or col.r
local bank = AutoRestack.bank and col.g or col.r
local guild = AutoRestack.guild and col.g or col.r
end
 
print(kR, "Usage:")
print(col.w.."- /restack [bags, bank, guild] - Run restacker manually")
print(col.w.."- /restack auto ["..bags.."bags"..col.w..",", bank.."bank"..col.w..",", guild.."guild"..col.w.."] - Toggle auto-stacking")
local item = GetContainerItemLink(bag, slot)
 
if item then
local itemId = DecodeItemId(item)
local stack = select(8, GetItemInfo(itemId))
local count = select(2, GetContainerItemInfo(bag, slot))
 
if stack > count then
local locked, ok, pb, ps, pc
 
while true do
ok, pbag, pslot = RestackFindPartial(bag, slot, itemId, loc)
locked = ok and select(3, GetContainerItemInfo(pbag, pslot)) or false
 
if locked then
coroutine.yield()
else
break
end
end
 
if ok then
ClearCursor()
PickupContainerItem(pbag, pslot)
PickupContainerItem(bag, slot)
ClearCursor()
changed = true
end
end
end
end
end
return changed
end
 
function kRestack(loc, nowarn)
if loc ~= "bags" and loc ~= "bank" then
local col = { w = "|cffFFFFFF", g = "|cff55FF55", r = "|cffFF5555" }
local krstr = "|cff44CCFFk|cffFFFFAARestack"..col.w
if loc == "auto" then
local togl
if not AutoRestack then
AutoRestack = true
togl = col.g.."ON"
else
AutoRestack = false
togl = col.r.."OFF"
end
print(krstr, "Auto-stacking toggled", togl)
else
local status = AutoRestack and col.g.."on" or col.r.."off"
print(krstr, "Usage:")
print("- /restack [bags, bank]")
print("- /restack auto - toggles auto-stacking ("..status..col.w..")")
end
 
do return end
end
 
 
if type(restacker) ~= "thread" or coroutine.status(restacker) == "dead" then
frame:SetScript("OnUpdate", function()
if type(restacker) == "thread" then coroutine.resume(restacker) end
end)
restacker = coroutine.create(function()
--[[ core restacking function ]]
local changed = true
while changed do
changed = false
vault = loc == "guild"
if vault then
vbag = tab or GetCurrentGuildBankTab()
local _, _, isViewable, canDeposit = GetGuildBankTabInfo(vbag)
if not (IsGuildLeader() or (isViewable and canDeposit)) then break end
end
for _, bag in pairs(container[loc]) do
bag = vault and vbag or bag
for slot = 1, (vault and MAX_GUILDBANK_SLOTS_PER_TAB or GetContainerNumSlots(bag)) do
while true and not vault do
local locked = select(3, GetContainerItemInfo(bag, slot))
if locked then coYield(loc, bag, slot) else break end
end
local item = vault and GetGuildBankItemLink(bag, slot) or GetContainerItemLink(bag, slot)
if item then
local itemid = select(3, strfind(item, "item:(%d+)"))
local stack = select(8, GetItemInfo(itemid))
local count = vault and select(2, GetGuildBankItemInfo(bag, slot)) or select(2, GetContainerItemInfo(bag, slot))
local moved = false
while changed == true do
changed = RestackBags(loc)
end
 
for _, bag in pairs(container[loc]) do
local _, bt = GetContainerNumFreeSlots(bag)
if bt ~= 0 then
for slot = 1, GetContainerNumSlots(bag) do
while true do
local locked = select( 3, GetContainerItemInfo(bag, slot))
 
--[[ do "special" things with "special" items by moving them to "special" bags ]]
if not vault then
for _, sbag in pairs(container[loc]) do
if sbag > 0 and GetContainerNumSlots(sbag) > 0 then
local bagID = ContainerIDToInventoryID(sbag)
local bagType = GetItemFamily(GetInventoryItemLink("player", bagID))
local itemType = GetItemFamily(item)
if bagType > 0 and bagType == itemType and bag ~= sbag then
PickupContainerItem(bag, slot)
PutItemInBag(bagID)
moved = true
end
end
end
if locked then
coroutine.yield()
else
break
end
 
if count < stack and not moved then
--[[ found a partial stack ]]
local locked, found, pbag, pslot
while true do
--[[ look for another partial stack ]]
found, pbag, pslot = getPartial(bag, slot, itemid, loc)
if vault then break end
locked = found and select(3, GetContainerItemInfo(pbag, pslot)) or false
if locked then coYield(loc, pbag, pslot) else break end
end
 
local item = GetContainerItemLink(bag, slot)
 
if not item then
local locked, ok, sbag, sslot
 
while true do
ok, sbag, sslot = RestackFindSpecial(bt, loc)
locked = ok and select(3, GetContainerItemInfo(sbag, sslot)) or false
 
if locked then
coroutine.yield()
else
break
end
 
if found then
--[[ stack 'em up ]]
ClearCursor()
if vault then
PickupGuildBankItem(pbag, pslot)
PickupGuildBankItem(bag, slot)
ClearCursor()
coYield(loc, bag, slot, count)
else
PickupContainerItem(pbag, pslot)
PickupContainerItem(bag, slot)
end
changed = true
end
end
 
if ok then
ClearCursor()
PickupContainerItem(sbag, sslot)
PickupContainerItem(bag, slot)
ClearCursor()
end
end
end
end
end
--[[ turn off yielding function ]]
frame:SetScript("OnUpdate", nil)
frame:SetScript("OnUpdate", function() end)
end)
coroutine.resume(restacker)
else
if not nowarn then
--[[ user is impatient or there is a stall, tell them so ]]
print(kR..col.r, "Restacking is already in progress. (use '/restack resume' if stuck)")
print("|cff33A1DEk|cffFFFFFFRestack |cffFF5555Restacking is already in progress, please wait.")
end
end
end
end
kRestack/kRestack.toc
1,8 → 1,8
## Interface: 30100
## Title: kRestack
## Version: 1.0 rwowi:revision
## Version: 0.9.wowi:revision
## SavedVariablesPerCharacter: AutoRestack
## Author: Katae of Anvilmar
## Notes: Function for restacking inventory items.
## SavedVariablesPerCharacter: AutoRestack
 
kRestack.lua
\ No newline at end of file