local function RestackFindPartial( loc_id, cb, cs, id ) --ArkInventory.OutputDebug( "RestackFindPartial( ", loc_id, ", ", cb, ".", cs, ", ", id, " )" ) if loc_id == ArkInventory.Const.Location.Vault then local bag_id = cb local numslots = MAX_GUILDBANK_SLOTS_PER_TAB --ArkInventory.OutputDebug( "tab=", bag_id, ", slots=", numslots ) for slot_id = 1, numslots do if ( not ArkInventory.Global.Mode.Vault ) or ( bag_id ~= GetCurrentGuildBankTab( ) ) then return false -- no longer at the vault or changed tabs, abort end if slot_id ~= cs then --ArkInventory.OutputDebug( "checking slot ", slot_id, " " , count, " x ", h ) if not select( 3, GetGuildBankItemInfo( bag_id, slot_id ) ) then local h = GetGuildBankItemLink( bag_id, slot_id ) if h then local item_id = ArkInventory.ObjectStringDecodeItem( h ) if item_id == id then local stack = select( 10, ArkInventory.ObjectInfo( h ) ) local count = select( 2, GetGuildBankItemInfo( bag_id, slot_id ) ) if count < stack then ArkInventory.OutputDebug( "found > ", bag_id, ".", slot_id ) return true, bag_id, slot_id, count end end end end end end else for _, bag_id in pairs( ArkInventory.Global.Location[loc_id].Bags ) do local numslots = GetContainerNumSlots( bag_id ) --ArkInventory.OutputDebug( "bag=", bag_id, ", slots=", numslots ) for slot_id = 1, numslots do if ( loc_id == ArkInventory.Const.Location.Bank ) and ( not ArkInventory.Global.Mode.Bank ) then return false -- no longer at bank, abort end if not ( bag_id == cb and slot_id == cs ) then if not select( 3, GetContainerItemInfo( bag_id, slot_id ) ) then local h = GetContainerItemLink( bag_id, slot_id ) if h then local item_id = ArkInventory.ObjectStringDecodeItem( h ) if item_id == id then local stack = select( 10, ArkInventory.ObjectInfo( h ) ) local count = select( 2, GetContainerItemInfo( bag_id, slot_id ) ) if count < stack then ArkInventory.OutputDebug( "found > ", bag_id, ".", slot_id ) return true, bag_id, slot_id, count end end end end end end end end --ArkInventory.OutputDebug( "no other partial stacks found" ) return false end local function RestackFindSpecial( loc_id, ct ) if loc_id == ArkInventory.Const.Location.Vault then return false -- vault doesnt have special bags end for _, bag_id in pairs( ArkInventory.Global.Location[loc_id].Bags ) do local _, bt = GetContainerNumFreeSlots( bag_id ) -- only match items in normal bags to move them to profession bags if bt == 0 then for slot_id = 1, GetContainerNumSlots( bag_id ) do if ( loc_id == ArkInventory.Const.Location.Bank ) and ( not ArkInventory.Global.Mode.Bank ) then return false -- no longer at bank, abort end --ArkInventory.OutputDebug( "checking for special item at ", bag_id, ".", slot_id ) if not select( 3, GetContainerItemInfo( bag_id, slot_id ) ) then local h = GetContainerItemLink( bag_id, slot_id ) if h then -- ignore bags if select( 11, ArkInventory.ObjectInfo( h ) ) ~= "INVTYPE_BAG" then local it = GetItemFamily( h ) if bit.band( it, ct ) > 0 then ArkInventory.OutputDebug( "special > ", bag_id, ".", slot_id ) return true, bag_id, slot_id end end end end end end end --ArkInventory.OutputDebug( "no items found for special slot" ) return false end local function RestackCompactBags( loc_id ) local recheck = false for _, bag_id in pairs( ArkInventory.Global.Location[loc_id].Bags ) do for slot_id = 1, GetContainerNumSlots( bag_id ) do if ( loc_id == ArkInventory.Const.Location.Bank ) and ( not ArkInventory.Global.Mode.Bank ) then return false -- no longer at bank, abort end --ArkInventory.OutputDebug( "checking ", bag_id, ".", slot_id ) if select( 3, GetContainerItemInfo( bag_id, slot_id ) ) then ArkInventory.OutputDebug( "locked > ", bag_id, ".", slot_id ) recheck = true -- this slot is locked, move on and check it again next time else local h = GetContainerItemLink( bag_id, slot_id ) if h then local item_id = ArkInventory.ObjectStringDecodeItem( h ) local stack = select( 10, ArkInventory.ObjectInfo( h ) ) local count = select( 2, GetContainerItemInfo( bag_id, slot_id ) ) if count < stack then --ArkInventory.OutputDebug( "partial stack of ", count, "x", h, " found at ", bag_id, ".", slot_id ) local ok, pb, ps, pc = RestackFindPartial( loc_id, bag_id, slot_id, item_id ) if ok then ArkInventory.OutputDebug( "merge > ", bag_id, ".", slot_id, " + ", pb, ".", ps ) ClearCursor( ) PickupContainerItem( pb, ps ) PickupContainerItem( bag_id, slot_id ) ClearCursor( ) recheck = true end end end end end end if recheck then ArkInventory.OutputDebug( "yielding - pending bag/lock update" ) coroutine.yield( ) ArkInventory.OutputDebug( "resumed" ) end return recheck end local function RestackCompactVault( ) local loc_id = ArkInventory.Const.Location.Vault local bag_id = GetCurrentGuildBankTab( ) local _, _, isViewable, canDeposit = GetGuildBankTabInfo( bag_id ) if not ( IsGuildLeader( ) or ( isViewable and canDeposit ) ) then ArkInventory.Output( string.format( ArkInventory.Localise["RESTACK_FAIL_ACCESS"], GUILD_BANK, bag_id ) ) return end local recheck = false for slot_id = 1, MAX_GUILDBANK_SLOTS_PER_TAB do if ( not ArkInventory.Global.Mode.Vault ) or ( bag_id ~= GetCurrentGuildBankTab( ) ) then return false -- no longer at the vault or changed tabs, abort end --ArkInventory.OutputDebug( "checking vault ", bag_id, ".", slot_id ) if select( 3, GetGuildBankItemInfo( bag_id, slot_id ) ) then ArkInventory.OutputDebug( "locked > ", bag_id, ".", slot_id ) recheck = true -- this slot is locked, move on and check it again next time else local h = GetGuildBankItemLink( bag_id, slot_id ) --ArkInventory.OutputDebug( "tab=[", bag_id, "], slot=[", slot_id, "] count=[", count, "] locked=[", locked, "] item=", h ) if h then local item_id = ArkInventory.ObjectStringDecodeItem( h ) local stack = select( 10, ArkInventory.ObjectInfo( h ) ) local count = select( 2, GetGuildBankItemInfo( bag_id, slot_id ) ) if count < stack then --ArkInventory.OutputDebug( "partial > ", bag_id, ".", slot_id ) local ok, pb, ps, pc = RestackFindPartial( loc_id, bag_id, slot_id, item_id ) if ok then ArkInventory.OutputDebug( "merge > ", bag_id, ".", slot_id, " + ", pb, ".", ps ) ClearCursor( ) PickupGuildBankItem( pb, ps ) PickupGuildBankItem( bag_id, slot_id ) ClearCursor( ) ArkInventory.OutputDebug( "yielding - pending vault update" ) coroutine.yield( ) ArkInventory.OutputDebug( "resumed" ) recheck = true end end end end end return recheck end local function RestackConsolidate( loc_id ) ArkInventory.OutputDebug( "consolidating" ) local recheck = false if loc_id == ArkInventory.Const.Location.Vault then return false end -- move items into appropriate bag types with empty slots for _, bag_id in pairs( ArkInventory.Global.Location[loc_id].Bags ) do local _, bt = GetContainerNumFreeSlots( bag_id ) if bt ~= 0 then --ArkInventory.OutputDebug( "bag=[", bag_id, "], type=[", bt, "]" ) for slot_id = 1, GetContainerNumSlots( bag_id ) do if ( loc_id == ArkInventory.Const.Location.Bank ) and ( not ArkInventory.Global.Mode.Bank ) then return false -- no longer at bank, abort end --ArkInventory.OutputDebug( "checking bag=[", bag_id, "], slot=[", slot_id, "]" ) if select( 3, GetContainerItemInfo( bag_id, slot_id ) ) then ArkInventory.OutputDebug( "locked > ", bag_id, ".", slot_id ) recheck = true -- this slot is locked, move on and check it again next time else local h = GetContainerItemLink( bag_id, slot_id ) if not h then ArkInventory.OutputDebug( "empty > ", bag_id, ".", slot_id ) local ok, sb, ss = RestackFindSpecial( loc_id, bt ) if ok then ArkInventory.OutputDebug( "move> ", sb, ".", ss, " to ", bag_id, ".", slot_id ) ClearCursor( ) PickupContainerItem( sb, ss ) PickupContainerItem( bag_id, slot_id ) ClearCursor( ) end end end end end end if recheck then ArkInventory.OutputDebug( "yielding - pending bag/lock update" ) coroutine.yield( ) ArkInventory.OutputDebug( "resumed" ) end return recheck end local function RestackRun( loc_id ) -- DO NOT USE CACHED DATA FOR RESTACKING, PULL THE DATA DIRECTLY FROM WOW AGAIN, THE UI WILL CATCH UP if loc_id == ArkInventory.Const.Location.Bag or loc_id == ArkInventory.Const.Location.Key then ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Global.Location[loc_id].Name, " " , ArkInventory.Localise["START"] ) while RestackCompactBags( loc_id ) do end while RestackConsolidate( loc_id ) do end ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Global.Location[loc_id].Name, " " , ArkInventory.Localise["COMPLETE"] ) elseif loc_id == ArkInventory.Const.Location.Bank then if ArkInventory.Global.Mode.Bank then ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Global.Location[loc_id].Name, " " , ArkInventory.Localise["START"] ) while RestackCompactBags( loc_id ) do end while RestackConsolidate( loc_id ) do end ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Global.Location[loc_id].Name, " " , ArkInventory.Localise["COMPLETE"] ) end elseif loc_id == ArkInventory.Const.Location.Vault then if ArkInventory.Global.Mode.Vault then ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Global.Location[loc_id].Name, " " , ArkInventory.Localise["START"] ) while RestackCompactVault( ) do end ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Global.Location[loc_id].Name, " " , ArkInventory.Localise["COMPLETE"] ) end end end function ArkInventory.RestackResume( loc_id ) --ArkInventory.OutputDebug( "RestackResume ", loc_id ) if type( ArkInventory.Global.Thread.Restack[loc_id] ) == "thread" and coroutine.status( ArkInventory.Global.Thread.Restack[loc_id] ) == "suspended" then -- resume current thread coroutine.resume( ArkInventory.Global.Thread.Restack[loc_id] ) end end local function RestackLocation( loc_id ) if type( ArkInventory.Global.Thread.Restack[loc_id] ) ~= "thread" or coroutine.status( ArkInventory.Global.Thread.Restack[loc_id] ) == "dead" then -- thread not active, create a new one ArkInventory.Global.Thread.Restack[loc_id] = coroutine.create( function ( ) RestackRun( loc_id ) end ) -- run it coroutine.resume( ArkInventory.Global.Thread.Restack[loc_id] ) else -- restack already in progress ArkInventory.OutputError( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Global.Location[loc_id].Name, " " , ArkInventory.Localise["RESTACK_FAIL_WAIT"] ) -- give it a push, just in case coroutine.resume( ArkInventory.Global.Thread.Restack[loc_id] ) end end function ArkInventory.Restack( ) --ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Localise["START"] ) for k, v in pairs( ArkInventory.Global.Location ) do if v.canRestack then RestackLocation( k ) end end --ArkInventory.Output( ArkInventory.Localise["RESTACK"], ": ", ArkInventory.Localise["COMPLETE"] ) end