diff --git a/Roomba.lua b/Roomba.lua
index ce5a067..d8fa115 100644
--- a/Roomba.lua
+++ b/Roomba.lua
@@ -4,44 +4,54 @@
-
]]
-Roomba = {}
+Roomba = ZO_Object:Subclass()
+
+function Roomba:New(...)
+ local roomba = ZO_Object.New(self)
+ roomba:Initialize(...)
+ return roomba
+end
+
+function Roomba:Initialize(control)
+ self.control = control
+ control.ref = self
+ self:InitializeFrame()
+ self:InitializeSettings()
+end
local LAM = LibStub:GetLibrary("LibAddonMenu-1.0")
local BACKPACK = ZO_PlayerInventoryBackpack.data
local GUILDBANK = ZO_GuildBankBackpack.data
-local DELAY = 150
-
-
+local WM = WINDOW_MANAGER
+local DELAY = 100
+local settings = {}
+local format = " %3d"
local containerHooks = { INVENTORY_BACKPACK, INVENTORY_BANK, INVENTORY_GUILD_BANK }
-
-Roomba.currentInventory = {}
-Roomba.guildInfo = {}
+local currentRun = {}
local function GetItemID(link)
return tonumber(string.match(string.match(link, "%d+:"), "%d+"))
end
-function Roomba.dmsg(msg)
- if Roomba.Debugging then d(msg) end
+function Roomba:dmsg(msg)
+ if settings.Debugging then d(msg) end
end
-local dmsg = Roomba.dmsg
-
-function GetInstanceId(target, slotId)
+local function GetInstanceId(target, slotId)
for i,v in ipairs(target) do
if v.data.slotIndex == slotId then return v.data.itemInstanceId end
end
return nil
end
-function FindSlot(target, slotId)
+local function FindSlot(target, slotId)
for i,v in ipairs(target) do
if v.data.slotIndex == slotId then return i,v.data end
end
return nil
end
-local function ClearGuildDetails(guildId)
+local function ClearGuildDetails(guildId)
return { name = GetGuildName(guildId),
lookUp = {},
duplicates = {},
@@ -49,52 +59,49 @@ local function ClearGuildDetails(guildId)
}
end
+function TableEntryCount(t)
+ local i = next(t)
+ local c = 0
+ while i do
+ c = c + 1
+ i = next(t, i)
+ end
+ return c
+end
+
-- Who is your Guild and what do they do
-local function GetGuildDetails()
+function Roomba:GetGuildDetails()
+ d("Wiping Guilds")
for guildIndex = 1, GetNumGuilds() do
local guildId = GetGuildId(guildIndex)
if DoesGuildHavePrivilege(guildId, GUILD_PRIVILEGE_BANK_DEPOSIT) then
- Roomba.guildInfo[guildId] = true
+ self.guildInfo[guildId] = true
end
end
end
-- Okay, let's see.
-- First we'll take current bag inventory.
-local function CheckWeHaveEnoughRoom()
- return CheckInventorySpaceAndWarn(2)
-end
-
--- Now take stock of everything so we don't accidentally move stuff out
--- of our inventory into the bank
-local function AuditCurrentInventory()
- local _, totalSlots = GetBagInfo(INVENTORY_BACKPACK)
- Roomba.currentInventory = {}
- for slot=1, totalSlots do
- local id = GetItemInstanceId(INVENTORY_BACKPACK, slot)
- local count = GetItemTotalCount(INVENTORY_BACKPACK, slot)
- Roomba.currentInventory[slot] = id
- end
+function Roomba:CheckWeHaveEnoughRoom()
+ return CheckInventorySpaceAndWarn(5)
end
-
-local function HaveStuffToStack()
- local bank = Roomba.guildInfo[GetSelectedGuildBankId()]
+function Roomba:HaveStuffToStack()
+ local bank = self.guildInfo[GetSelectedGuildBankId()]
if type(bank) == "table" and next(bank.duplicates) then return true end
return false
end
local checkingBank = false
-local currentBank = 1
-- Bank is ready! Find those duplicates!
-function Roomba.RoombaReady()
+function Roomba:RoombaReady()
if not checkingBank then checkingBank = true else return end
- local bank = Roomba.guildInfo[GetSelectedGuildBankId()]
+ local bank = self.guildInfo[GetSelectedGuildBankId()]
if not bank then return end
- Roomba.guildInfo[GetSelectedGuildBankId()] = ClearGuildDetails(GetSelectedGuildBankId())
- bank = Roomba.guildInfo[GetSelectedGuildBankId()]
- dmsg("Bank is ready: " .. #GUILDBANK)
+ self.guildInfo[GetSelectedGuildBankId()] = ClearGuildDetails(GetSelectedGuildBankId())
+ bank = self.guildInfo[GetSelectedGuildBankId()]
+ self:dmsg("Bank is ready")
-- We only need to store A) slots with items
for index, slot in ipairs(GUILDBANK) do
if slot.data.equipType == 0 then -- Equipped gear cannot be stacked
@@ -110,14 +117,15 @@ function Roomba.RoombaReady()
bank.lookUp[id] = {} -- It's a new item!
end
-- Now group all items by id
- table.insert(bank.lookUp[id], {slot = slot.data.slotIndex, count = count})
+ table.insert(bank.lookUp[id], {slot = slot.data.slotIndex, count = count, texture = slot.data.iconFile})
end
end
end
zo_callLater(function() checkingBank = nil end, 3000)
- if KEYBIND_STRIP:HasKeybindButtonGroup(Roomba.runDescriptor) then
- KEYBIND_STRIP:UpdateKeybindButtonGroup(Roomba.runDescriptor)
- end
+ if KEYBIND_STRIP:HasKeybindButtonGroup(self.runDescriptor) then
+ KEYBIND_STRIP:UpdateKeybindButtonGroup(self.runDescriptor)
+ end
+ currentRun = {}
end
--[[
@@ -136,6 +144,7 @@ local cSlotIdx = nil
local cSlot = nil
local baseSlot = nil
+
local inBagCollection = {}
local function ResetAll()
@@ -145,67 +154,67 @@ local function ResetAll()
baseSlot = nil
end
-function Roomba.SelectGuildBank(...)
+function Roomba:SelectGuildBank(...)
local eventId, guildBankId = ...
- currentBank = guildBankId
+ self.currentBank = guildBankId
checkingBank = nil
end
-transitBag = {}
+local transitBag = {}
local currentReturnIndex
-function Roomba.ReturnItemsToBank(...)
+function Roomba:ReturnItemsToBank(...)
local error = ...
local slot
-- Now that we've stacked it all lets move it back
- dmsg("Getting next to move back to bank")
+ self:dmsg("Getting next to move back to bank")
currentReturnIndex, slot = next(inBagCollection)
if slot then
if error then
- dmsg("trying again")
- return zo_callLater(Roomba.ReturnItemsToBank, 2000)
+ self:dmsg("trying again")
+ return zo_callLater(function(...) self:ReturnItemsToBank() end, 2000)
end
if FindSlot(BACKPACK, slot.bagSlot) then
- dmsg("Moving stuff back from ".. slot.bagSlot)
+ self:dmsg("Moving stuff back from ".. slot.bagSlot)
return TransferToGuildBank(INVENTORY_BACKPACK, slot.bagSlot)
else
-- we have a space, move to next
table.remove(inBagCollection, currentReturnIndex)
- return zo_callLater(Roomba.ReturnItemsToBank, DELAY)
+ return zo_callLater(function(...) self:ReturnItemsToBank(...) end, DELAY)
end
else
-- No more to move, we're complete
- dmsg("unregistering")
+ self:dmsg("unregistering")
EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankError", EVENT_GUILD_BANK_TRANSFER_ERROR)
EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankSuccess", EVENT_GUILD_BANK_ITEM_ADDED)
-- Kick off the next transaction
- dmsg("Finished processing item")
+ self:dmsg("Finished processing item")
ResetAll()
- return zo_callLater(Roomba.BeginProcess, DELAY)
+ return zo_callLater(function() self:BeginProcess() end, DELAY)
end
end
-function Roomba.BankItemsReceived(...)
- local _, gslot = ...
+function Roomba:BankItemsReceived(...)
+ local eventId, gslot = ...
local id = GetInstanceId(GUILDBANK, gslot)
if id ~= cInstanceId then return end
- dmsg("Moved successfully to slot " ..gslot)
+ self:dmsg("Moved successfully to slot " ..gslot)
-- We've moved one back! Remove it from contention
local slot = table.remove(inBagCollection, currentReturnIndex)
currentReturnIndex = nil
- dmsg("Clearing slot " .. slot.bagSlot)
- return zo_callLater(Roomba.ReturnItemsToBank, DELAY)
+ self:dmsg("Clearing slot " .. slot.bagSlot)
+ return zo_callLater(function(...) self:ReturnItemsToBank() end, DELAY)
end
-function Roomba.StartStacking()
- dmsg("Found an item to stack")
+function Roomba:StartStacking()
+ self:dmsg("Found an item to stack")
baseSlot = nil
EVENT_MANAGER:UnregisterForEvent("RoombaInventoryAdded", EVENT_INVENTORY_SINGLE_SLOT_UPDATE)
for _,slot in pairs(inBagCollection) do
if not baseSlot then
-- We want to stack everything on this
- dmsg("Setting ".. slot.bagSlot .." as base slot")
+ self:dmsg("Setting ".. slot.bagSlot .." as base slot")
baseSlot = slot
else
baseSlot.count, baseSlot.stack = GetSlotStackSize(INVENTORY_BACKPACK, slot.bagSlot)
@@ -222,30 +231,30 @@ function Roomba.StartStacking()
if (result) then result = CallSecureProtected("PlaceInInventory", INVENTORY_BACKPACK, baseSlot.bagSlot) end
end
ClearCursor()
- dmsg("Stacked item in backpack")
+ self:dmsg("Stacked item in backpack")
end
end
baseSlot = nil
-- These events will loop the move back to the guild bank
- EVENT_MANAGER:RegisterForEvent("RoombaGuildBankError", EVENT_GUILD_BANK_TRANSFER_ERROR, Roomba.ReturnItemsToBank)
- EVENT_MANAGER:RegisterForEvent("RoombaGuildBankSuccess", EVENT_GUILD_BANK_ITEM_ADDED, Roomba.BankItemsReceived)
- return zo_callLater(Roomba.ReturnItemsToBank, 1000)
+ EVENT_MANAGER:RegisterForEvent("RoombaGuildBankError", EVENT_GUILD_BANK_TRANSFER_ERROR, function(...) self:ReturnItemsToBank() end)
+ EVENT_MANAGER:RegisterForEvent("RoombaGuildBankSuccess", EVENT_GUILD_BANK_ITEM_ADDED, function(...) self:BankItemsReceived(...) end)
+ return zo_callLater(function(...) self:ReturnItemsToBank() end, 1000)
end
-- Event called that item has arrived
-function Roomba.ReceiveItems(...)
+function Roomba:ReceiveItems(...)
if baseSlot then return end -- We're still stacking
local _, bagId, slotId = ...
if bagId ~= INVENTORY_BACKPACK then return end
if not cInstanceId then return end
if IsItemJunk(INVENTORY_BACKPACK, slotId) then
SetItemIsJunk(INVENTORY_BACKPACK, slotId, false)
- return zo_callLater(function(...) Roomba.ReceiveItems(...) end, 1000)
+ return zo_callLater(function(...) self:ReceiveItems(...) end, 1000)
end
if not GetInstanceId(BACKPACK, slotId) then return end -- are we empty
if GetInstanceId(BACKPACK, slotId) ~= cInstanceId then return end
- dmsg("Checking " .. bagId .. " inventory slot " .. slotId .. " to match ".. cInstanceId .. " with " .. (GetInstanceId(BACKPACK, slotId) or "nothing"))
+ self:dmsg("Checking " .. bagId .. " inventory slot " .. slotId .. " to match ".. cInstanceId .. " with " .. (GetInstanceId(BACKPACK, slotId) or "nothing"))
cSlot.bagSlot = slotId
table.insert(inBagCollection, cSlot)
-- If we have another slot to move
@@ -253,45 +262,56 @@ function Roomba.ReceiveItems(...)
cSlotIdx, cSlot = next(cDuplicateList, cSlotIdx)
TransferFromGuildBank(cSlot.slot)
else -- No more slots to move, let's stack them
- return zo_callLater(Roomba.StartStacking, DELAY)
+ return zo_callLater(function() self:StartStacking() end, DELAY)
end
end
-function Roomba.BeginProcess()
- local bank = Roomba.guildInfo[currentBank]
+function Roomba:BeginProcess()
+ local bank = self.guildInfo[self.currentBank]
if not bank then return end
+ self:dmsg("Checking for space")
+ if not self:CheckWeHaveEnoughRoom() then return end
cSlotIdx = nil
-- Pull the next job off the stack
cInstanceId, cDuplicateList = next(bank.duplicates, cInstanceId)
+
+ if cInstanceId then currentRun[cInstanceId] = true end
+
+ self.control:SetHidden(false)
+ local index = TableEntryCount(currentRun)
+ local total = TableEntryCount(bank.duplicates)
+ ZO_StatusBar_SmoothTransition(self.speedRow.bar, index , total, FORCE_VALUE)
+ self.speedRow.name:SetText(string.format(format, (index/total)*100) .. "%")
+
if cDuplicateList then -- First off the rank
cSlotIdx, cSlot = next(cDuplicateList, cSlotIdx)
+
+ self.icon:SetTexture(cSlot.texture)
-- Clear this batch
inBagCollection = {}
-- And start off the job
- dmsg("Stacking up ".. zo_strformat(SI_TOOLTIP_ITEM_NAME, GetItemLink(3, cSlot.slot, LINK_STYLE_DEFAULT)))
+ self:dmsg("Stacking up ".. zo_strformat(SI_TOOLTIP_ITEM_NAME, GetItemLink(3, cSlot.slot, LINK_STYLE_DEFAULT)))
-- If it suddenly doesn't exist, try the next in the list
- if not FindSlot(GUILDBANK, cSlot.slot) then return zo_callLater(Roomba.BeginProcess, DELAY) end
+ if not FindSlot(GUILDBANK, cSlot.slot) then return zo_callLater(function() self:BeginProcess() end, DELAY) end
- EVENT_MANAGER:RegisterForEvent("RoombaInventoryAdded", EVENT_INVENTORY_SINGLE_SLOT_UPDATE, Roomba.ReceiveItems)
+ EVENT_MANAGER:RegisterForEvent("RoombaInventoryAdded", EVENT_INVENTORY_SINGLE_SLOT_UPDATE, function(...) self:ReceiveItems(...) end)
TransferFromGuildBank(cSlot.slot)
else
- dmsg("Nothing to restack")
+ self:dmsg("Nothing to restack")
-- Now rescan and show/hide roomba button
- Roomba.RoombaReady()
+ self.control:SetHidden(true)
+
+ self:RoombaReady()
return false
end
return true
end
-local function IsUsePossible(name)
- return true
-end
-
local function RoombaLoaded(eventCode, addOnName)
if(addOnName ~= "Roomba") then
@@ -299,48 +319,69 @@ local function RoombaLoaded(eventCode, addOnName)
end
local defaults = {
+ Debugging = true
}
+ ROOMBA:GetGuildDetails()
+ ZO_CreateStringId("SI_BINDING_NAME_RUN_ROOMBA", "Run Roomba")
+ ZO_CreateStringId("SI_BINDING_NAME_RESCAN_ROOMBA", "Rescan Bank")
+ settings = ZO_SavedVars:New("Roomba_Settings", 3, nil, defaults)
+ SLASH_COMMANDS["/roombadebug"] = function() settings.Debugging = not settings.Debugging d("Turning debug ".. (settings.Debugging and "on" or "off")) end
- GetGuildDetails()
-
- SLASH_COMMANDS["/roombadebug"] = function() Roomba.Debugging = not Roomba.Debugging d("Turning debug ".. (Roomba.Debugging and "on" or "off")) end
+end
- ZO_CreateStringId("SI_BINDING_NAME_RUN_ROOMBA", "Run Roomba")
- ZO_CreateStringId("SI_BINDING_NAME_RESCAN_ROOMBA", "Rescan Bank")
+function Roomba:InitializeSettings()
+
+ self.guildInfo = {}
+ self.currentBank = 1
- Roomba.runDescriptor = {
+ self.runDescriptor = {
alignment = KEYBIND_STRIP_ALIGN_LEFT,
{
name = "Run Roomba", -- or function that returns a name
keybind = "RUN_ROOMBA",
- callback = function(descriptor) Roomba.BeginProcess() end, -- First and only argument is this descriptor table
- visible = function(descriptor) return HaveStuffToStack() end, -- An optional predicate, if present returning true indicates that this descriptor is visible, otherwise it is not
- icon = [[Roomba\media\Roomba.dds]], -- or a function that returns an icon path, an optional icon to display to the right of the name
+ control = self,
+ callback = function(descriptor) self:BeginProcess() end,
+ visible = function(descriptor) return self:HaveStuffToStack() end,
+ icon = [[Roomba\media\Roomba.dds]],
},
{
- name = "Scan Bank", -- or function that returns a name
+ name = "Scan Bank",
keybind = "RESCAN_ROOMBA",
- callback = function(descriptor) Roomba.RoombaReady() end, -- First and only argument is this descriptor table
- visible = function(descriptor) return ZO_GuildBankBackpackLoading:IsHidden() end, -- An optional predicate, if present returning true indicates that this descriptor is visible, otherwise it is not
- icon = [[Roomba\media\RoombaSearch.dds]], -- or a function that returns an icon path, an optional icon to display to the right of the name
+ control = self,
+ callback = function(descriptor) self:RoombaReady() end,
+ visible = function(descriptor) return ZO_GuildBankBackpackLoading:IsHidden() end,
+ icon = [[Roomba\media\RoombaSearch.dds]],
},
-
}
+ local bGroup = self.runDescriptor
- settings = ZO_SavedVars:New("Roomba_Settings", 3, nil, defaults)
-
-- Guild bank is evented to be ready, but wait a short while before processing.
- EVENT_MANAGER:RegisterForEvent("RoombaReady", EVENT_GUILD_BANK_ITEMS_READY, function() zo_callLater(Roomba.RoombaReady, 1000) end)
+ EVENT_MANAGER:RegisterForEvent("RoombaReady", EVENT_GUILD_BANK_ITEMS_READY, function() zo_callLater(function() self:RoombaReady() end, 1000) end)
-- Clear the flag when swapping banks
- EVENT_MANAGER:RegisterForEvent("RoombaSelected", EVENT_GUILD_BANK_SELECTED, Roomba.SelectGuildBank)
+ EVENT_MANAGER:RegisterForEvent("RoombaSelected", EVENT_GUILD_BANK_SELECTED, function(...) self:SelectGuildBank(...) end)
EVENT_MANAGER:RegisterForEvent("RoombaGuildBankOpen", EVENT_OPEN_GUILD_BANK, function()
- if not KEYBIND_STRIP:HasKeybindButtonGroup(Roomba.runDescriptor) then
- KEYBIND_STRIP:AddKeybindButtonGroup(Roomba.runDescriptor)
+ if not KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then
+ KEYBIND_STRIP:AddKeybindButtonGroup(bGroup)
end end)
- EVENT_MANAGER:RegisterForEvent("RoombaGuildBankOpen", EVENT_CLOSE_GUILD_BANK, function()
- if KEYBIND_STRIP:HasKeybindButtonGroup(Roomba.runDescriptor) then
- KEYBIND_STRIP:RemoveKeybindButtonGroup(Roomba.runDescriptor)
- end end)
+ EVENT_MANAGER:RegisterForEvent("RoombaGuildBankClose", EVENT_CLOSE_GUILD_BANK, function()
+ if KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then
+ KEYBIND_STRIP:RemoveKeybindButtonGroup(bGroup)
+ end
+ self.control:SetHidden(true)
+ end)
+end
+
+function Roomba:InitializeFrame()
+ self.speedRow = self.control:GetNamedChild("SpeedRow")
+ self.speedRow.name:SetText(" 0%")
+ self.icon = self.control:GetNamedChild("Icon")
+ ZO_StatusBar_SetGradientColor(self.speedRow.bar, ZO_XP_BAR_GRADIENT_COLORS)
+ ZO_StatusBar_SmoothTransition(self.speedRow.bar, 0, 20, FORCE_VALUE)
+end
+
+function Roomba_Initialize(control)
+ ROOMBA = Roomba:New(control)
end
+
EVENT_MANAGER:RegisterForEvent("RoombaLoaded", EVENT_ADD_ON_LOADED, RoombaLoaded)
\ No newline at end of file
diff --git a/Roomba.txt b/Roomba.txt
index 9cda37e..823d32a 100644
--- a/Roomba.txt
+++ b/Roomba.txt
@@ -5,8 +5,8 @@
## SavedVariables: Roomba_Settings
libs/LibStub/LibStub.lua
-libs/AceTimer-3.0/AceTimer-3.0.lua
-libs\LibAddonMenu-1.0\LibAddonMenu-1.0.lua
+libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
Roomba.lua
+Roomba.xml
bindings.xml
\ No newline at end of file
diff --git a/Roomba.xml b/Roomba.xml
new file mode 100644
index 0000000..bcf29a8
--- /dev/null
+++ b/Roomba.xml
@@ -0,0 +1,26 @@
+<GuiXml>
+ <Controls>
+ <TopLevelControl name="RoombaWindow" hidden="true" mouseEnabled="true">
+ <Dimensions x="565" />
+ <Anchor point="TOPLEFT" relativeTo="ZO_SharedRightPanelBackground" offsetY="90" />
+ <Anchor point="BOTTOMLEFT" relativeTo="ZO_SharedRightPanelBackground" offsetY="-20" />
+ <OnInitialized>
+ Roomba_Initialize(self)
+ </OnInitialized>
+ <Controls>
+ <Texture name="$(parent)BG" textureFile="EsoUI/Art/Miscellaneous/listItem_backdrop.dds">
+ <AnchorFill />
+ <TextureCoords left="0" right="1" top="0" bottom=".8125" />
+ </Texture>
+ <Texture name="$(parent)Icon">
+ <Dimensions x="80" y="80" />
+ <Anchor point="BOTTOM" relativePoint="CENTER" offsetX="20" offsetY="-40" />
+ </Texture>
+
+ <Control name="$(parent)SpeedRow" inherits="ZO_StableAttributeRow">
+ <Anchor point="TOP" relativeTo="$(parent)Icon" relativePoint="BOTTOM" offsetY="30" offsetX="30"/>
+ </Control>
+ </Controls>
+ </TopLevelControl>
+ </Controls>
+</GuiXml>
\ No newline at end of file
diff --git a/bindings.xml b/bindings.xml
index ce3d2f6..8610eca 100644
--- a/bindings.xml
+++ b/bindings.xml
@@ -2,10 +2,10 @@
<Layer name="General">
<Category name="Roomba">
<Action name="RUN_ROOMBA">
- <Down>Roomba.BeginProcess()</Down>
+ <Down>ROOMBA:BeginProcess()</Down>
</Action>
<Action name="RESCAN_ROOMBA">
- <Down>Roomba.RoombaReady()</Down>
+ <Down>ROOMBA:RoombaReady()</Down>
</Action>
</Category>
</Layer>