API 100008

CrazyDutchGuy [07-31-14 - 19:46]
API 100008
Filename
.gitignore
Roomba.lua
Roomba.txt
Roomba.xml
bindings.xml
libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
libs/LibStub/LibStub.lua
diff --git a/.gitignore b/.gitignore
index 9f11b75..aba02a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-.idea/
+.idea/
diff --git a/Roomba.lua b/Roomba.lua
index 8e63872..6f3af5b 100644
--- a/Roomba.lua
+++ b/Roomba.lua
@@ -1,390 +1,390 @@
---[[
--- Roomba
- - (Thanks to BalkiTheWise for the name)
- -
- ]]
-
-Roomba = ZO_Object:Subclass()
-
-function Roomba:New(...)
-    local roomba = ZO_Object.New(self)
-    roomba:Initialise(...)
-    return roomba
-end
-
-local LAM = LibStub:GetLibrary("LibAddonMenu-1.0")
-local BACKPACK = ZO_PlayerInventoryBackpack.data
-local GUILDBANK = ZO_GuildBankBackpack.data
-local WM = WINDOW_MANAGER
-local DELAY = 100
-local settings = {}
-local format = "                     %3d"
-local containerHooks = { INVENTORY_BACKPACK, INVENTORY_BANK, INVENTORY_GUILD_BANK }
-local currentRun = {}
-
-local function GetItemID(link)
-	return tonumber(string.match(string.match(link, "%d+:"), "%d+"))
-end
-
-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
-
-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)
-	return {	name = GetGuildName(guildId),
-				lookUp = {},
-				duplicates = {},
-				index = {}
-			}
-end
-
-local 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(self)
-	for guildIndex = 1, GetNumGuilds()	do
-		local guildId = GetGuildId(guildIndex)
-		if DoesGuildHavePrivilege(guildId, GUILD_PRIVILEGE_BANK_DEPOSIT) then
-			self.guildInfo[guildId] = true
-		end
-	end
-end
-
--- Okay, let's see.
--- First we'll take current bag inventory.
-function Roomba:CheckWeHaveEnoughRoom()
-	return CheckInventorySpaceAndWarn(5)
-end
-
-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
-
--- Bank is ready! Find those duplicates!
-function Roomba:RoombaReady()
-	if ZO_GuildBankBackpack:IsHidden() then return end
-	-- Are we in the process of checking the bank?
-	if not checkingBank then checkingBank = true else return end
-
-	local selectedBankId = GetSelectedGuildBankId()
-
-	if not self.guildInfo[selectedBankId] then return end
-
-	self.guildInfo[selectedBankId] = ClearGuildDetails(selectedBankId)
-	local bank = self.guildInfo[selectedBankId]
-
-	-- 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
-            local id = slot.data.itemInstanceId
-            local count, stack = GetSlotStackSize(slot.data.bagId, slot.data.slotIndex)
-            -- and B) slots with items that aren't full stacks or single unstackables
-            if count ~= stack then
-                if bank.lookUp[id] then -- If we've run across this item before
-                    if not bank.duplicates[id] then -- store the table reference as a duplicate
-                        bank.duplicates[id] = bank.lookUp[id]
-                    end
-                else
-                    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, texture = slot.data.iconFile, name = slot.data.name})
-            end
-        end
-    end
-    zo_callLater(function() checkingBank = nil end, 3000)
-    if KEYBIND_STRIP:HasKeybindButtonGroup(self.runDescriptor) then
-    	KEYBIND_STRIP:UpdateKeybindButtonGroup(self.runDescriptor)
-    end
-    currentRun = {}
-    self.control:SetHidden(true)
-end
-
---[[
-Right, so this got complicated. Simply calling TransferFromGuildBank did not seem reliable, it would perhaps
-transfer one item in the loop, and disregard the rest.
-
-So instead we're going event based responses. This has the problem of breaking up the flow in a way that might
-be a little complicated to follow, but I'll try to make it simple, if for the basic reason that I have to read
-this crap afterwards.
-
-Let's hope this works.
-]]--
-
-local cInstanceId = nil
-local cDuplicateList = nil
-local cSlotIdx = nil
-local cSlot = nil
-local baseSlot = nil
-local inBagCollection = nil
-local transitBag = nil
-local currentReturnIndex = nil
-
-local function ResetAll()
-	cSlotIdx = nil
-	cSlot = nil
-	inBagCollection = {}
-	baseSlot = nil
-end
-
-function Roomba:SelectGuildBank(...)
-	local eventId, guildBankId = ...
-	self.currentBank = guildBankId
-	checkingBank = nil
-end
-
-function Roomba:ReturnItemsToBank(...)
-    local error = ...
-    local slot
-	-- Now that we've stacked it all lets move it back
-    currentReturnIndex, slot = next(inBagCollection)
-    if slot then
-        if error then
-            return zo_callLater(function(...) self:ReturnItemsToBank() end, 2000)
-        end
-        if FindSlot(BACKPACK, slot.bagSlot) then
-            self.text:SetText("Returning restacked " .. cSlot.name .. " to the Guild Bank")
-            return TransferToGuildBank(INVENTORY_BACKPACK, slot.bagSlot)
-        else
-            -- we have a space, move to next
-            table.remove(inBagCollection, currentReturnIndex)
-            return zo_callLater(function(...) self:ReturnItemsToBank(...) end, DELAY)
-        end
-    else
-        -- No more to move, we're complete
-        EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankError", EVENT_GUILD_BANK_TRANSFER_ERROR)
-        EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankSuccess", EVENT_GUILD_BANK_ITEM_ADDED)
-        -- Kick off the next transaction
-        ResetAll()
-        return zo_callLater(function() self:BeginProcess() end, DELAY)
-    end
-end
-
-function Roomba:BankItemsReceived(...)
-	local eventId, gslot = ...
-    local id = GetInstanceId(GUILDBANK, gslot)
-    if id ~= cInstanceId then return end
-    -- We've moved one back! Remove it from contention
-    local slot = table.remove(inBagCollection, currentReturnIndex)
-    currentReturnIndex = nil
-    return zo_callLater(function(...) self:ReturnItemsToBank() end, DELAY)
-end
-
-
-function Roomba:StartStacking()
-	baseSlot = nil
-    EVENT_MANAGER:UnregisterForEvent("RoombaInventoryAdded", EVENT_INVENTORY_SINGLE_SLOT_UPDATE)
-    self.text:SetText("Stacking " .. cSlot.name .. " in inventory")
-	for _,slot in pairs(inBagCollection) do
-		if not baseSlot then
-			-- We want to stack everything on this
-			baseSlot = slot
-		else
-            baseSlot.count, baseSlot.stack = GetSlotStackSize(INVENTORY_BACKPACK, slot.bagSlot)
-			-- Find out how much we can fit
-			-- If it's too much, move all we can and target this slot as the next to fill
-			if (baseSlot.stack - baseSlot.count) < slot.count then
-				result = CallSecureProtected("PickupInventoryItem", INVENTORY_BACKPACK, slot.bagSlot)
-				if (result) then
-					result = CallSecureProtected("PlaceInInventory", INVENTORY_BACKPACK, baseSlot.bagSlot)
-				end
-				baseSlot = slot
-			else -- Just move it all over
-				result = CallSecureProtected("PickupInventoryItem", INVENTORY_BACKPACK, slot.bagSlot, slot.count)
-				if (result) then result = CallSecureProtected("PlaceInInventory", INVENTORY_BACKPACK, baseSlot.bagSlot) end
-			end
-			ClearCursor()
-		end
-	end
-	baseSlot = nil
-    -- These events will loop the move back to the guild bank
-	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, DELAY)
-end
-
-
--- Event called that item has arrived
-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(...) self:ReceiveItems(...) end, 1000)
-	end
-    if not GetInstanceId(BACKPACK, slotId) then return end -- are we empty
-	if GetInstanceId(BACKPACK, slotId) ~= cInstanceId then return end
-    cSlot.bagSlot = slotId
-	table.insert(inBagCollection, cSlot)
-	-- If we have another slot to move
-	if next(cDuplicateList, cSlotIdx) then
-		cSlotIdx, cSlot = next(cDuplicateList, cSlotIdx)
-		TransferFromGuildBank(cSlot.slot)
-	else -- No more slots to move, let's stack them
-		return zo_callLater(function() self:StartStacking() end, DELAY)
-	end
-end
-
-function Roomba:BeginProcess()
-	if ZO_GuildBankBackpack:IsHidden() then return end
-    local bank = self.guildInfo[self.currentBank]
-    if not bank then return end
-    if not self:CheckWeHaveEnoughRoom() then return end
-
-	ZO_MenuBar_SelectLastVisibleButton(ZO_PlayerInventoryTabs)
-
-    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
-
-        -- If it suddenly doesn't exist, try the next in the list
-        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, function(...) self:ReceiveItems(...) end)
-        self.text:SetText("Retrieving " .. cSlot.name .. " from Guild Bank")
-        TransferFromGuildBank(cSlot.slot)
-    else
-        -- Now rescan and show/hide roomba button
-        self.control:SetHidden(true)
-        self.text:SetText("Complete")
-        self:RoombaReady()
-        return false
-    end
-    return true
-end
-
-local function RoombaLoaded(eventCode, addOnName)
-
-	if(addOnName ~= "Roomba") then
-        return
-    end
-
-	ZO_CreateStringId("SI_BINDING_NAME_RUN_ROOMBA", "Run Roomba")
-	ZO_CreateStringId("SI_BINDING_NAME_RESCAN_ROOMBA", "Rescan Bank")
-end
-
-function Roomba:InitialiseSettings()
-
-	self.guildInfo = {}
-	self.currentBank = 1
-	self.CurrentState = CurrentState
-	GetGuildDetails(self)
-
-	self.runDescriptor = {
-		alignment = KEYBIND_STRIP_ALIGN_LEFT,
-		{
-		    name = "Run Roomba", -- or function that returns a name
-		    keybind = "RUN_ROOMBA",
-		    control = self,
-		    callback = function(descriptor) self:BeginProcess() end,
-		    visible = function(descriptor) return self:HaveStuffToStack() end,
-		    icon = [[Roomba\media\Roomba.dds]],
-		},
-		{
-		    name = "Scan Bank",
-		    keybind = "RESCAN_ROOMBA",
-		    control = self,
-		    callback = function(descriptor) self:RoombaReady() end,
-		    visible = function(descriptor) return ZO_GuildBankBackpackLoading:IsHidden() end,
-		    icon = [[Roomba\media\RoombaSearch.dds]],
-		},
-	}
-
-end
-
-function Roomba:Initialise(control)
-	self.control = control
-	self:InitialiseFrame()
-	self:InitialiseSettings()
-
-	local bGroup = self.runDescriptor
-
-	EVENT_MANAGER:RegisterForEvent("RoombaGuildBankOpen", EVENT_OPEN_GUILD_BANK, function()
-																	self:InitialiseEvents()
-																	if not KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then
-																		KEYBIND_STRIP:AddKeybindButtonGroup(bGroup)
-																	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)
-																	ResetAll()
-																	self:UninitialiseEvents()
-																	end)
-end
-
-function Roomba:InitialiseEvents()
-    -- 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(function() self:RoombaReady() end, 1000) end)
-	-- Clear the flag when swapping banks
-	EVENT_MANAGER:RegisterForEvent("RoombaSelected", EVENT_GUILD_BANK_SELECTED, function(...) self:SelectGuildBank(...) end)
-end
-
-function Roomba:UninitialiseEvents()
-	EVENT_MANAGER:UnregisterForEvent("RoombaInventoryAdded", EVENT_INVENTORY_SINGLE_SLOT_UPDATE)
-	EVENT_MANAGER:UnregisterForEvent("RoombaSelected", EVENT_GUILD_BANK_SELECTED)
-	EVENT_MANAGER:UnregisterForEvent("RoombaReady", EVENT_GUILD_BANK_ITEMS_READY)
-	EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankError", EVENT_GUILD_BANK_TRANSFER_ERROR)
-	EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankSuccess", EVENT_GUILD_BANK_ITEM_ADDED)
-end
-
-function Roomba:InitialiseFrame()
-	self.control:SetDrawLayer(DL_OVERLAY)
-	self.speedRow = self.control:GetNamedChild("SpeedRow")
-    self.speedRow.name:SetText("                     0%")
-    self.icon = self.control:GetNamedChild("Icon")
-    self.text = self.control:GetNamedChild("Description")
-    self.text:SetText("...")
-    ZO_StatusBar_SetGradientColor(self.speedRow.bar, ZO_XP_BAR_GRADIENT_COLORS)
-    ZO_StatusBar_SmoothTransition(self.speedRow.bar, 0, 20, FORCE_VALUE)
-end
-
-function Roomba_Initialise(control)
-    ROOMBA = Roomba:New(control)
-end
-
-
+--[[
+-- Roomba
+ - (Thanks to BalkiTheWise for the name)
+ -
+ ]]
+
+Roomba = ZO_Object:Subclass()
+
+function Roomba:New(...)
+    local roomba = ZO_Object.New(self)
+    roomba:Initialise(...)
+    return roomba
+end
+
+local LAM = LibStub:GetLibrary("LibAddonMenu-1.0")
+local BACKPACK = ZO_PlayerInventoryBackpack.data
+local GUILDBANK = ZO_GuildBankBackpack.data
+local WM = WINDOW_MANAGER
+local DELAY = 100
+local settings = {}
+local format = "                     %3d"
+local containerHooks = { INVENTORY_BACKPACK, INVENTORY_BANK, INVENTORY_GUILD_BANK }
+local currentRun = {}
+
+local function GetItemID(link)
+	return tonumber(string.match(string.match(link, "%d+:"), "%d+"))
+end
+
+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
+
+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)
+	return {	name = GetGuildName(guildId),
+				lookUp = {},
+				duplicates = {},
+				index = {}
+			}
+end
+
+local 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(self)
+	for guildIndex = 1, GetNumGuilds()	do
+		local guildId = GetGuildId(guildIndex)
+		if DoesGuildHavePrivilege(guildId, GUILD_PRIVILEGE_BANK_DEPOSIT) then
+			self.guildInfo[guildId] = true
+		end
+	end
+end
+
+-- Okay, let's see.
+-- First we'll take current bag inventory.
+function Roomba:CheckWeHaveEnoughRoom()
+	return CheckInventorySpaceAndWarn(5)
+end
+
+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
+
+-- Bank is ready! Find those duplicates!
+function Roomba:RoombaReady()
+	if ZO_GuildBankBackpack:IsHidden() then return end
+	-- Are we in the process of checking the bank?
+	if not checkingBank then checkingBank = true else return end
+
+	local selectedBankId = GetSelectedGuildBankId()
+
+	if not self.guildInfo[selectedBankId] then return end
+
+	self.guildInfo[selectedBankId] = ClearGuildDetails(selectedBankId)
+	local bank = self.guildInfo[selectedBankId]
+
+	-- 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
+            local id = slot.data.itemInstanceId
+            local count, stack = GetSlotStackSize(slot.data.bagId, slot.data.slotIndex)
+            -- and B) slots with items that aren't full stacks or single unstackables
+            if count ~= stack then
+                if bank.lookUp[id] then -- If we've run across this item before
+                    if not bank.duplicates[id] then -- store the table reference as a duplicate
+                        bank.duplicates[id] = bank.lookUp[id]
+                    end
+                else
+                    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, texture = slot.data.iconFile, name = slot.data.name})
+            end
+        end
+    end
+    zo_callLater(function() checkingBank = nil end, 3000)
+    if KEYBIND_STRIP:HasKeybindButtonGroup(self.runDescriptor) then
+    	KEYBIND_STRIP:UpdateKeybindButtonGroup(self.runDescriptor)
+    end
+    currentRun = {}
+    self.control:SetHidden(true)
+end
+
+--[[
+Right, so this got complicated. Simply calling TransferFromGuildBank did not seem reliable, it would perhaps
+transfer one item in the loop, and disregard the rest.
+
+So instead we're going event based responses. This has the problem of breaking up the flow in a way that might
+be a little complicated to follow, but I'll try to make it simple, if for the basic reason that I have to read
+this crap afterwards.
+
+Let's hope this works.
+]]--
+
+local cInstanceId = nil
+local cDuplicateList = nil
+local cSlotIdx = nil
+local cSlot = nil
+local baseSlot = nil
+local inBagCollection = nil
+local transitBag = nil
+local currentReturnIndex = nil
+
+local function ResetAll()
+	cSlotIdx = nil
+	cSlot = nil
+	inBagCollection = {}
+	baseSlot = nil
+end
+
+function Roomba:SelectGuildBank(...)
+	local eventId, guildBankId = ...
+	self.currentBank = guildBankId
+	checkingBank = nil
+end
+
+function Roomba:ReturnItemsToBank(...)
+    local error = ...
+    local slot
+	-- Now that we've stacked it all lets move it back
+    currentReturnIndex, slot = next(inBagCollection)
+    if slot then
+        if error then
+            return zo_callLater(function(...) self:ReturnItemsToBank() end, 2000)
+        end
+        if FindSlot(BACKPACK, slot.bagSlot) then
+            self.text:SetText("Returning restacked " .. cSlot.name .. " to the Guild Bank")
+            return TransferToGuildBank(INVENTORY_BACKPACK, slot.bagSlot)
+        else
+            -- we have a space, move to next
+            table.remove(inBagCollection, currentReturnIndex)
+            return zo_callLater(function(...) self:ReturnItemsToBank(...) end, DELAY)
+        end
+    else
+        -- No more to move, we're complete
+        EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankError", EVENT_GUILD_BANK_TRANSFER_ERROR)
+        EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankSuccess", EVENT_GUILD_BANK_ITEM_ADDED)
+        -- Kick off the next transaction
+        ResetAll()
+        return zo_callLater(function() self:BeginProcess() end, DELAY)
+    end
+end
+
+function Roomba:BankItemsReceived(...)
+	local eventId, gslot = ...
+    local id = GetInstanceId(GUILDBANK, gslot)
+    if id ~= cInstanceId then return end
+    -- We've moved one back! Remove it from contention
+    local slot = table.remove(inBagCollection, currentReturnIndex)
+    currentReturnIndex = nil
+    return zo_callLater(function(...) self:ReturnItemsToBank() end, DELAY)
+end
+
+
+function Roomba:StartStacking()
+	baseSlot = nil
+    EVENT_MANAGER:UnregisterForEvent("RoombaInventoryAdded", EVENT_INVENTORY_SINGLE_SLOT_UPDATE)
+    self.text:SetText("Stacking " .. cSlot.name .. " in inventory")
+	for _,slot in pairs(inBagCollection) do
+		if not baseSlot then
+			-- We want to stack everything on this
+			baseSlot = slot
+		else
+            baseSlot.count, baseSlot.stack = GetSlotStackSize(INVENTORY_BACKPACK, slot.bagSlot)
+			-- Find out how much we can fit
+			-- If it's too much, move all we can and target this slot as the next to fill
+			if (baseSlot.stack - baseSlot.count) < slot.count then
+				result = CallSecureProtected("PickupInventoryItem", INVENTORY_BACKPACK, slot.bagSlot)
+				if (result) then
+					result = CallSecureProtected("PlaceInInventory", INVENTORY_BACKPACK, baseSlot.bagSlot)
+				end
+				baseSlot = slot
+			else -- Just move it all over
+				result = CallSecureProtected("PickupInventoryItem", INVENTORY_BACKPACK, slot.bagSlot, slot.count)
+				if (result) then result = CallSecureProtected("PlaceInInventory", INVENTORY_BACKPACK, baseSlot.bagSlot) end
+			end
+			ClearCursor()
+		end
+	end
+	baseSlot = nil
+    -- These events will loop the move back to the guild bank
+	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, DELAY)
+end
+
+
+-- Event called that item has arrived
+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(...) self:ReceiveItems(...) end, 1000)
+	end
+    if not GetInstanceId(BACKPACK, slotId) then return end -- are we empty
+	if GetInstanceId(BACKPACK, slotId) ~= cInstanceId then return end
+    cSlot.bagSlot = slotId
+	table.insert(inBagCollection, cSlot)
+	-- If we have another slot to move
+	if next(cDuplicateList, cSlotIdx) then
+		cSlotIdx, cSlot = next(cDuplicateList, cSlotIdx)
+		TransferFromGuildBank(cSlot.slot)
+	else -- No more slots to move, let's stack them
+		return zo_callLater(function() self:StartStacking() end, DELAY)
+	end
+end
+
+function Roomba:BeginProcess()
+	if ZO_GuildBankBackpack:IsHidden() then return end
+    local bank = self.guildInfo[self.currentBank]
+    if not bank then return end
+    if not self:CheckWeHaveEnoughRoom() then return end
+
+	ZO_MenuBar_SelectLastVisibleButton(ZO_PlayerInventoryTabs)
+
+    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
+
+        -- If it suddenly doesn't exist, try the next in the list
+        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, function(...) self:ReceiveItems(...) end)
+        self.text:SetText("Retrieving " .. cSlot.name .. " from Guild Bank")
+        TransferFromGuildBank(cSlot.slot)
+    else
+        -- Now rescan and show/hide roomba button
+        self.control:SetHidden(true)
+        self.text:SetText("Complete")
+        self:RoombaReady()
+        return false
+    end
+    return true
+end
+
+local function RoombaLoaded(eventCode, addOnName)
+
+	if(addOnName ~= "Roomba") then
+        return
+    end
+
+	ZO_CreateStringId("SI_BINDING_NAME_RUN_ROOMBA", "Run Roomba")
+	ZO_CreateStringId("SI_BINDING_NAME_RESCAN_ROOMBA", "Rescan Bank")
+end
+
+function Roomba:InitialiseSettings()
+
+	self.guildInfo = {}
+	self.currentBank = 1
+	self.CurrentState = CurrentState
+	GetGuildDetails(self)
+
+	self.runDescriptor = {
+		alignment = KEYBIND_STRIP_ALIGN_LEFT,
+		{
+		    name = "Run Roomba", -- or function that returns a name
+		    keybind = "RUN_ROOMBA",
+		    control = self,
+		    callback = function(descriptor) self:BeginProcess() end,
+		    visible = function(descriptor) return self:HaveStuffToStack() end,
+		    icon = [[Roomba\media\Roomba.dds]],
+		},
+		{
+		    name = "Scan Bank",
+		    keybind = "RESCAN_ROOMBA",
+		    control = self,
+		    callback = function(descriptor) self:RoombaReady() end,
+		    visible = function(descriptor) return ZO_GuildBankBackpackLoading:IsHidden() end,
+		    icon = [[Roomba\media\RoombaSearch.dds]],
+		},
+	}
+
+end
+
+function Roomba:Initialise(control)
+	self.control = control
+	self:InitialiseFrame()
+	self:InitialiseSettings()
+
+	local bGroup = self.runDescriptor
+
+	EVENT_MANAGER:RegisterForEvent("RoombaGuildBankOpen", EVENT_OPEN_GUILD_BANK, function()
+																	self:InitialiseEvents()
+																	if not KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then
+																		KEYBIND_STRIP:AddKeybindButtonGroup(bGroup)
+																	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)
+																	ResetAll()
+																	self:UninitialiseEvents()
+																	end)
+end
+
+function Roomba:InitialiseEvents()
+    -- 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(function() self:RoombaReady() end, 1000) end)
+	-- Clear the flag when swapping banks
+	EVENT_MANAGER:RegisterForEvent("RoombaSelected", EVENT_GUILD_BANK_SELECTED, function(...) self:SelectGuildBank(...) end)
+end
+
+function Roomba:UninitialiseEvents()
+	EVENT_MANAGER:UnregisterForEvent("RoombaInventoryAdded", EVENT_INVENTORY_SINGLE_SLOT_UPDATE)
+	EVENT_MANAGER:UnregisterForEvent("RoombaSelected", EVENT_GUILD_BANK_SELECTED)
+	EVENT_MANAGER:UnregisterForEvent("RoombaReady", EVENT_GUILD_BANK_ITEMS_READY)
+	EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankError", EVENT_GUILD_BANK_TRANSFER_ERROR)
+	EVENT_MANAGER:UnregisterForEvent("RoombaGuildBankSuccess", EVENT_GUILD_BANK_ITEM_ADDED)
+end
+
+function Roomba:InitialiseFrame()
+	self.control:SetDrawLayer(DL_OVERLAY)
+	self.speedRow = self.control:GetNamedChild("SpeedRow")
+    self.speedRow.name:SetText("                     0%")
+    self.icon = self.control:GetNamedChild("Icon")
+    self.text = self.control:GetNamedChild("Description")
+    self.text:SetText("...")
+    ZO_StatusBar_SetGradientColor(self.speedRow.bar, ZO_XP_BAR_GRADIENT_COLORS)
+    ZO_StatusBar_SmoothTransition(self.speedRow.bar, 0, 20, FORCE_VALUE)
+end
+
+function Roomba_Initialise(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 77c2b5b..1baa5fd 100644
--- a/Roomba.txt
+++ b/Roomba.txt
@@ -1,12 +1,12 @@
-## APIVersion: 100007
-## Title: |cFFFFB0Roomba|r by |c00C000Wobin & CrazyDutchGuy|r
-## Description: Your favorite guild bank cleaner ;)
-## Author: Wobin & CrazyDutchGuy
-## Version: @project-version@
-
-libs/LibStub/LibStub.lua
-libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
-
-Roomba.lua
-Roomba.xml
-bindings.xml
\ No newline at end of file
+## APIVersion: 100008
+## Title: |cFFFFB0Roomba|r by |c00C000Wobin & CrazyDutchGuy|r
+## Description: Your favorite guild bank cleaner ;)
+## Author: Wobin & CrazyDutchGuy
+## Version: @project-version@
+
+libs/LibStub/LibStub.lua
+libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
+
+Roomba.lua
+Roomba.xml
+bindings.xml
diff --git a/Roomba.xml b/Roomba.xml
index 053513e..3c0b915 100644
--- a/Roomba.xml
+++ b/Roomba.xml
@@ -1,29 +1,29 @@
-<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_Initialise(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>
-                <Label name="$(parent)Description" inherits="ZO_TooltipIfTruncatedLabel" font="ZoFontGameMedium" color="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_SECOND_CONTRAST" horizontalAlignment="CENTER">
-                    <Anchor point="TOPLEFT" relativeTo="$(parent)Icon" relativePoint="BOTTOM" offsetY="5" offsetX="-300"/>
-                    <Dimensions x="600" y="40" />
-                </Label>
-                <Control name="$(parent)SpeedRow" inherits="ZO_StableAttributeRow">
-                    <Anchor point="TOP" relativeTo="$(parent)Icon" relativePoint="BOTTOM" offsetY="30" offsetX="30"/>
-                </Control>
-            </Controls>
-        </TopLevelControl>
-    </Controls>
+<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_Initialise(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>
+                <Label name="$(parent)Description" inherits="ZO_TooltipIfTruncatedLabel" font="ZoFontGameMedium" color="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_SECOND_CONTRAST" horizontalAlignment="CENTER">
+                    <Anchor point="TOPLEFT" relativeTo="$(parent)Icon" relativePoint="BOTTOM" offsetY="5" offsetX="-300"/>
+                    <Dimensions x="600" y="40" />
+                </Label>
+                <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 8610eca..ffed6ea 100644
--- a/bindings.xml
+++ b/bindings.xml
@@ -1,12 +1,12 @@
-<Bindings>
-  <Layer name="General">
-    <Category name="Roomba">
-      <Action name="RUN_ROOMBA">
-        <Down>ROOMBA:BeginProcess()</Down>
-      </Action>
-      <Action name="RESCAN_ROOMBA">
-      	<Down>ROOMBA:RoombaReady()</Down>
-      </Action>
-    </Category>
-  </Layer>
+<Bindings>
+  <Layer name="General">
+    <Category name="Roomba">
+      <Action name="RUN_ROOMBA">
+        <Down>ROOMBA:BeginProcess()</Down>
+      </Action>
+      <Action name="RESCAN_ROOMBA">
+      	<Down>ROOMBA:RoombaReady()</Down>
+      </Action>
+    </Category>
+  </Layer>
 </Bindings>
\ No newline at end of file
diff --git a/libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua b/libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
index 7e382b1..d7a547c 100644
--- a/libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
+++ b/libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
@@ -1,373 +1,373 @@
-local MAJOR, MINOR = "LibAddonMenu-1.0", 6
-local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
-if not lam then return end	--the same or newer version of this lib is already loaded into memory
-
---UPVALUES--
-lam.lastAddedControl = {}
-local lastAddedControl = lam.lastAddedControl
-local wm = GetWindowManager()
-local strformat = string.format
-local tostring = tostring
-local round = zo_round
-local optionsWindow = ZO_OptionsWindowSettingsScrollChild
-
---maybe return the controls from the creation functions?
-
-function lam:CreateControlPanel(controlPanelID, controlPanelName)
-	local panelID
-
-	if _G[controlPanelID] then
-		panelID = _G[controlPanelID]
-		return panelID
-	end
-
-	ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelName)
-
-	--disables Defaults button because we don't need it, but keybind still works :/ ...
-	panelID = _G[controlPanelID]
-	ZO_PreHook("ZO_OptionsWindow_ChangePanels", function(panel)
-			local enable = (panel ~=  panelID)
-			ZO_OptionsWindowResetToDefaultButton:SetEnabled(enable)
-			ZO_OptionsWindowResetToDefaultButton:SetKeybindEnabled(enable)
-		end)
-
-	return panelID
-end
-
-function lam:AddHeader(panelID, controlName, text)
-	local header = wm:CreateControlFromVirtual(controlName, optionsWindow, lastAddedControl[panelID] and "ZO_Options_SectionTitle_WithDivider" or "ZO_Options_SectionTitle")
-	if lastAddedControl[panelID] then
-		header:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 15)
-	else
-		header:SetAnchor(TOPLEFT)
-	end
-	header.controlType = OPTIONS_SECTION_TITLE
-	header.panel = panelID
-	header.text = text
-
-	ZO_OptionsWindow_InitializeControl(header)
-
-	lastAddedControl[panelID] = header
-
-	return header
-end
-
-
---To-Do list:
---extra sub-options window out to the right?? (or maybe addon list?)
---find alternatives to handler hooks
-
-function lam:AddSlider(panelID, controlName, text, tooltip, minValue, maxValue, step, getFunc, setFunc, warning, warningText)
-	local slider = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Slider")
-	slider:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
-	slider.controlType = OPTIONS_SLIDER
-	slider.system = SETTING_TYPE_UI
-	slider.panel = panelID
-	slider.text = text
-	slider.tooltipText = tooltip
-	slider.showValue = true
-	slider.showValueMin = minValue
-	slider.showValueMax = maxValue
-	local range = maxValue - minValue
-	local slidercontrol = slider:GetNamedChild("Slider")
-	local slidervalue = slider:GetNamedChild("ValueLabel")
-	slidercontrol:SetValueStep(1/range * step)
-	slider:SetHandler("OnShow", function()
-			local curValue = getFunc()
-			slidercontrol:SetValue((curValue - minValue)/range)
-			slidervalue:SetText(tostring(curValue))
-		end)
-	slidercontrol:SetHandler("OnValueChanged", function (self, value)
-			self:SetValue(value)
-			value = round(value*range + minValue)
-			slidervalue:SetText(strformat("%d", value))
-		end)
-	slidercontrol:SetHandler("OnSliderReleased", function(self, value)
-			value = round(value*range + minValue)
-			setFunc(value)
-		end)
-
-	if warning then
-		slider.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", slider, "ZO_Options_WarningIcon")
-		slider.warning:SetAnchor(RIGHT, slidercontrol, LEFT, -5, 0)
-		slider.warning.tooltipText = warningText
-	end
-
-	ZO_OptionsWindow_InitializeControl(slider)
-
-	lastAddedControl[panelID] = slider
-
-	return slider
-end
-
-function lam:AddDropdown(panelID, controlName, text, tooltip, validChoices, getFunc, setFunc, warning, warningText)
-	local dropdown = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Dropdown")
-	dropdown:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
-	dropdown.controlType = OPTIONS_DROPDOWN
-	dropdown.system = SETTING_TYPE_UI
-	dropdown.panel = panelID
-	dropdown.text = text
-	dropdown.tooltipText = tooltip
-	dropdown.valid = validChoices
-	local dropmenu = ZO_ComboBox_ObjectFromContainer(GetControl(dropdown, "Dropdown"))
-	local setText = dropmenu.m_selectedItemText.SetText
-	local selectedName
-	ZO_PreHookHandler(dropmenu.m_selectedItemText, "OnTextChanged", function(self)
-			if dropmenu.m_selectedItemData then
-				selectedName = dropmenu.m_selectedItemData.name
-				setText(self, selectedName)
-				setFunc(selectedName)
-			end
-		end)
-	dropdown:SetHandler("OnShow", function()
-			dropmenu:SetSelectedItem(getFunc())
-		end)
-
-	if warning then
-		dropdown.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", dropdown, "ZO_Options_WarningIcon")
-		dropdown.warning:SetAnchor(RIGHT, dropdown:GetNamedChild("Dropdown"), LEFT, -5, 0)
-		dropdown.warning.tooltipText = warningText
-	end
-
-	ZO_OptionsWindow_InitializeControl(dropdown)
-
-	lastAddedControl[panelID] = dropdown
-
-	return dropdown
-end
-
-function lam:AddCheckbox(panelID, controlName, text, tooltip, getFunc, setFunc, warning, warningText)
-	local checkbox = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Checkbox")
-	checkbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
-	checkbox.controlType = OPTIONS_CHECKBOX
-	checkbox.system = SETTING_TYPE_UI
-	checkbox.settingId = _G[strformat("SETTING_%s", controlName)]
-	checkbox.panel = panelID
-	checkbox.text = text
-	checkbox.tooltipText = tooltip
-
-	local checkboxButton = checkbox:GetNamedChild("Checkbox")
-
-	ZO_PreHookHandler(checkbox, "OnShow", function()
-			checkboxButton:SetState(getFunc() and 1 or 0)
-			checkboxButton:toggleFunction(getFunc())
-		end)
-	ZO_PreHookHandler(checkboxButton, "OnClicked", function() setFunc(not getFunc()) end)
-
-	if warning then
-		checkbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", checkbox, "ZO_Options_WarningIcon")
-		checkbox.warning:SetAnchor(RIGHT, checkboxButton, LEFT, -5, 0)
-		checkbox.warning.tooltipText = warningText
-	end
-
-	ZO_OptionsWindow_InitializeControl(checkbox)
-
-	lastAddedControl[panelID] = checkbox
-
-	return checkbox
-end
-
-function lam:AddColorPicker(panelID, controlName, text, tooltip, getFunc, setFunc, warning, warningText)
-	local colorpicker = wm:CreateTopLevelWindow(controlName)
-	colorpicker:SetParent(optionsWindow)
-	colorpicker:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
-	colorpicker:SetResizeToFitDescendents(true)
-	colorpicker:SetWidth(510)
-	colorpicker:SetMouseEnabled(true)
-
-	colorpicker.label = wm:CreateControl(controlName.."Label", colorpicker, CT_LABEL)
-	local label = colorpicker.label
-	label:SetDimensions(300, 26)
-	label:SetAnchor(TOPLEFT)
-	label:SetFont("ZoFontWinH4")
-	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-	label:SetText(text)
-
-	colorpicker.color = wm:CreateControl(controlName.."Color", colorpicker, CT_CONTROL)
-	local color = colorpicker.color
-	color:SetDimensions(200,26)
-	color:SetAnchor(RIGHT)
-
-	color.thumb = wm:CreateControl(controlName.."ColorThumb", color, CT_TEXTURE)
-	local thumb = color.thumb
-	thumb:SetDimensions(36, 18)
-	thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
-	local r, g, b, a = getFunc()
-	thumb:SetColor(r, g, b, a or 1)
-
-	color.border = wm:CreateControl(controlName.."ColorBorder", color, CT_TEXTURE)
-	local border = color.border
-	border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds")
-	border:SetTextureCoords(0, .625, 0, .8125)
-	border:SetDimensions(40, 22)
-	border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
-
-	local ColorPickerCallback
-	if not ColorPickerCallback then
-		ColorPickerCallback = function(r, g, b, a)
-			thumb:SetColor(r, g, b, a or 1)
-			setFunc(r, g, b, a)
-		end
-	end
-
-	colorpicker.controlType = OPTIONS_CUSTOM
-	colorpicker.customSetupFunction = function(colorpicker)
-			colorpicker:SetHandler("OnMouseUp", function(self, btn, upInside)
-					if upInside then
-						local r, g, b, a = getFunc()
-						COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, text)
-					end
-				end)
-		end
-	colorpicker.panel = panelID
-	colorpicker.tooltipText = tooltip
-	colorpicker:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
-	colorpicker:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
-	if warning then
-		colorpicker.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", colorpicker, "ZO_Options_WarningIcon")
-		colorpicker.warning:SetAnchor(RIGHT, colorpicker:GetNamedChild("Color"), LEFT, -5, 0)
-		colorpicker.warning.tooltipText = warningText
-	end
-
-	ZO_OptionsWindow_InitializeControl(colorpicker)
-
-	lastAddedControl[panelID] = colorpicker
-
-	return colorpicker
-end
-
-function lam:AddEditBox(panelID, controlName, text, tooltip, isMultiLine, getFunc, setFunc, warning, warningText)
-	local editbox = wm:CreateTopLevelWindow(controlName)
-	editbox:SetParent(optionsWindow)
-	editbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
-	editbox:SetResizeToFitDescendents(true)
-	editbox:SetWidth(510)
-	editbox:SetMouseEnabled(true)
-
-	editbox.label = wm:CreateControl(controlName.."Label", editbox, CT_LABEL)
-	local label = editbox.label
-	label:SetDimensions(300, 26)
-	label:SetAnchor(TOPLEFT)
-	label:SetFont("ZoFontWinH4")
-	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-	label:SetText(text)
-
-	editbox.bg = wm:CreateControlFromVirtual(controlName.."BG", editbox, "ZO_EditBackdrop")
-	local bg = editbox.bg
-	bg:SetDimensions(200,isMultiLine and 100 or 24)
-	bg:SetAnchor(RIGHT)
-	editbox.edit = wm:CreateControlFromVirtual(controlName.."Edit", bg, isMultiLine and "ZO_DefaultEditMultiLineForBackdrop" or "ZO_DefaultEditForBackdrop")
-	editbox.edit:SetText(getFunc())
-	editbox.edit:SetHandler("OnFocusLost", function(self) setFunc(self:GetText()) end)
-
-
-	editbox.panel = panelID
-	editbox.tooltipText = tooltip
-	editbox:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
-	editbox:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
-	if warning then
-		editbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", editbox, "ZO_Options_WarningIcon")
-		editbox.warning:SetAnchor(TOPRIGHT, editbox:GetNamedChild("BG"), TOPLEFT, -5, 0)
-		editbox.warning.tooltipText = warningText
-	end
-
-	ZO_OptionsWindow_InitializeControl(editbox)
-
-	lastAddedControl[panelID] = editbox
-
-	return editbox
-end
-
-function lam:AddButton(panelID, controlName, text, tooltip, onClick, warning, warningText)
-	local button = wm:CreateTopLevelWindow(controlName)
-	button:SetParent(optionsWindow)
-	button:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
-	button:SetDimensions(510, 28)
-	button:SetMouseEnabled(true)
-
-	button.btn = wm:CreateControlFromVirtual(controlName.."Button", button, "ZO_DefaultButton")
-	local btn = button.btn
-	btn:SetAnchor(TOPRIGHT)
-	btn:SetWidth(200)
-	btn:SetText(text)
-	btn:SetHandler("OnClicked", onClick)
-
-	button.controlType = OPTIONS_CUSTOM
-	button.customSetupFunction = function() end	--move handlers into this function? (since I created a function...)
-	button.panel = panelID
-	btn.tooltipText = tooltip
-	btn:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
-	btn:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
-	if warning then
-		button.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", button, "ZO_Options_WarningIcon")
-		button.warning:SetAnchor(RIGHT, btn, LEFT, -5, 0)
-		button.warning.tooltipText = warningText
-	end
-
-	ZO_OptionsWindow_InitializeControl(button)
-
-	lastAddedControl[panelID] = button
-
-	return button
-end
-
-function lam:AddDescription(panelID, controlName, text, titleText)
-	local textBox = wm:CreateTopLevelWindow(controlName)
-	textBox:SetParent(optionsWindow)
-	textBox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
-	textBox:SetResizeToFitDescendents(true)
-	textBox:SetWidth(510)
-
-	if titleText then
-		textBox.title = wm:CreateControl(controlName.."Title", textBox, CT_LABEL)
-		local title = textBox.title
-		title:SetWidth(510)
-		title:SetAnchor(TOPLEFT, textBox, TOPLEFT)
-		title:SetFont("ZoFontWinH4")
-		title:SetText(titleText)
-	end
-
-	textBox.desc = wm:CreateControl(controlName.."Text", textBox, CT_LABEL)
-	local desc = textBox.desc
-	desc:SetWidth(510)
-	if titleText then
-		desc:SetAnchor(TOPLEFT, textBox.title, BOTTOMLEFT)
-	else
-		desc:SetAnchor(TOPLEFT)
-	end
-	desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
-	desc:SetFont("ZoFontGame")
-	desc:SetText(text)
-
-	textBox.controlType = OPTIONS_CUSTOM
-	textBox.panel = panelID
-
-	ZO_OptionsWindow_InitializeControl(textBox)
-
-	lastAddedControl[panelID] = textBox
-
-	return textBox
-end
-
-
---test controls & examples--
---[[local controlPanelID = lam:CreateControlPanel("ZAM_ADDON_OPTIONS", "ZAM Addons")
-lam:AddHeader(controlPanelID, "ZAM_Addons_TESTADDON", "TEST ADDON")
-lam:AddDescription(controlPanelID, "ZAM_Addons_TESTDESC", "This is a test description.", "Header")
-lam:AddSlider(controlPanelID, "ZAM_TESTSLIDER", "Test slider", "Adjust the slider.", 1, 10, 1, function() return 7 end, function(value) end, true, "needs UI reload")
-lam:AddDropdown(controlPanelID, "ZAM_TESTDROPDOWN", "Test Dropdown", "Pick something!", {"thing 1", "thing 2", "thing 3"}, function() return "thing 2" end, function(self,valueString) print(valueString) end)
-local checkbox1 = true
-lam:AddCheckbox(controlPanelID, "ZAM_TESTCHECKBOX", "Test Checkbox", "On or off?", function() return checkbox1 end, function(value) checkbox1 = not checkbox1 print(value, checkbox1) end)
-lam:AddColorPicker(controlPanelID, "ZAM_TESTCOLORPICKER", "Test color picker", "What's your favorite color?", function() return 1, 1, 0 end, function(r,g,b) print(r,g,b) end)
-lam:AddEditBox(controlPanelID, "ZAM_TESTEDITBOX", "Test Edit Box", "This is a tooltip!", false, function() return "hi" end, function(text) print(text) end)
-lam:AddHeader(controlPanelID, "ZAM_Addons_TESTADDON2", "TEST ADDON 2")
-local checkbox2 = false
-lam:AddCheckbox(controlPanelID, "ZAM_TESTCHECKBOX2", "Test Checkbox 2", "On or off?", function() return checkbox2 end, function(value) checkbox2 = not checkbox2 print(value, checkbox2) end)
-lam:AddButton(controlPanelID, "ZAM_TESTBUTTON", "Test Button", "Click me", function() print("hi") end, true, "oh noez!")
-lam:AddEditBox(controlPanelID, "ZAM_TESTEDITBOX2", "Test Edit Box 2", "This is a tooltip!", true, function() return "hi" end, function(text) print(text) end, true, "warning text")
-lam:AddSlider(controlPanelID, "ZAM_TESTSLIDER2", "Test slider 2", "Adjust the slider.", 50, 100, 10, function() return 80 end, function(value) end)
-lam:AddDropdown(controlPanelID, "ZAM_TESTDROPDOWN2", "Test Dropdown 2", "Pick something!", {"thing 4", "thing 5", "thing 6"}, function() return "thing 6" end, function(self,valueString) print(valueString) end)
+local MAJOR, MINOR = "LibAddonMenu-1.0", 6
+local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+if not lam then return end	--the same or newer version of this lib is already loaded into memory
+
+--UPVALUES--
+lam.lastAddedControl = {}
+local lastAddedControl = lam.lastAddedControl
+local wm = GetWindowManager()
+local strformat = string.format
+local tostring = tostring
+local round = zo_round
+local optionsWindow = ZO_OptionsWindowSettingsScrollChild
+
+--maybe return the controls from the creation functions?
+
+function lam:CreateControlPanel(controlPanelID, controlPanelName)
+	local panelID
+
+	if _G[controlPanelID] then
+		panelID = _G[controlPanelID]
+		return panelID
+	end
+
+	ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelName)
+
+	--disables Defaults button because we don't need it, but keybind still works :/ ...
+	panelID = _G[controlPanelID]
+	ZO_PreHook("ZO_OptionsWindow_ChangePanels", function(panel)
+			local enable = (panel ~=  panelID)
+			ZO_OptionsWindowResetToDefaultButton:SetEnabled(enable)
+			ZO_OptionsWindowResetToDefaultButton:SetKeybindEnabled(enable)
+		end)
+
+	return panelID
+end
+
+function lam:AddHeader(panelID, controlName, text)
+	local header = wm:CreateControlFromVirtual(controlName, optionsWindow, lastAddedControl[panelID] and "ZO_Options_SectionTitle_WithDivider" or "ZO_Options_SectionTitle")
+	if lastAddedControl[panelID] then
+		header:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 15)
+	else
+		header:SetAnchor(TOPLEFT)
+	end
+	header.controlType = OPTIONS_SECTION_TITLE
+	header.panel = panelID
+	header.text = text
+
+	ZO_OptionsWindow_InitializeControl(header)
+
+	lastAddedControl[panelID] = header
+
+	return header
+end
+
+
+--To-Do list:
+--extra sub-options window out to the right?? (or maybe addon list?)
+--find alternatives to handler hooks
+
+function lam:AddSlider(panelID, controlName, text, tooltip, minValue, maxValue, step, getFunc, setFunc, warning, warningText)
+	local slider = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Slider")
+	slider:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+	slider.controlType = OPTIONS_SLIDER
+	slider.system = SETTING_TYPE_UI
+	slider.panel = panelID
+	slider.text = text
+	slider.tooltipText = tooltip
+	slider.showValue = true
+	slider.showValueMin = minValue
+	slider.showValueMax = maxValue
+	local range = maxValue - minValue
+	local slidercontrol = slider:GetNamedChild("Slider")
+	local slidervalue = slider:GetNamedChild("ValueLabel")
+	slidercontrol:SetValueStep(1/range * step)
+	slider:SetHandler("OnShow", function()
+			local curValue = getFunc()
+			slidercontrol:SetValue((curValue - minValue)/range)
+			slidervalue:SetText(tostring(curValue))
+		end)
+	slidercontrol:SetHandler("OnValueChanged", function (self, value)
+			self:SetValue(value)
+			value = round(value*range + minValue)
+			slidervalue:SetText(strformat("%d", value))
+		end)
+	slidercontrol:SetHandler("OnSliderReleased", function(self, value)
+			value = round(value*range + minValue)
+			setFunc(value)
+		end)
+
+	if warning then
+		slider.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", slider, "ZO_Options_WarningIcon")
+		slider.warning:SetAnchor(RIGHT, slidercontrol, LEFT, -5, 0)
+		slider.warning.tooltipText = warningText
+	end
+
+	ZO_OptionsWindow_InitializeControl(slider)
+
+	lastAddedControl[panelID] = slider
+
+	return slider
+end
+
+function lam:AddDropdown(panelID, controlName, text, tooltip, validChoices, getFunc, setFunc, warning, warningText)
+	local dropdown = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Dropdown")
+	dropdown:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+	dropdown.controlType = OPTIONS_DROPDOWN
+	dropdown.system = SETTING_TYPE_UI
+	dropdown.panel = panelID
+	dropdown.text = text
+	dropdown.tooltipText = tooltip
+	dropdown.valid = validChoices
+	local dropmenu = ZO_ComboBox_ObjectFromContainer(GetControl(dropdown, "Dropdown"))
+	local setText = dropmenu.m_selectedItemText.SetText
+	local selectedName
+	ZO_PreHookHandler(dropmenu.m_selectedItemText, "OnTextChanged", function(self)
+			if dropmenu.m_selectedItemData then
+				selectedName = dropmenu.m_selectedItemData.name
+				setText(self, selectedName)
+				setFunc(selectedName)
+			end
+		end)
+	dropdown:SetHandler("OnShow", function()
+			dropmenu:SetSelectedItem(getFunc())
+		end)
+
+	if warning then
+		dropdown.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", dropdown, "ZO_Options_WarningIcon")
+		dropdown.warning:SetAnchor(RIGHT, dropdown:GetNamedChild("Dropdown"), LEFT, -5, 0)
+		dropdown.warning.tooltipText = warningText
+	end
+
+	ZO_OptionsWindow_InitializeControl(dropdown)
+
+	lastAddedControl[panelID] = dropdown
+
+	return dropdown
+end
+
+function lam:AddCheckbox(panelID, controlName, text, tooltip, getFunc, setFunc, warning, warningText)
+	local checkbox = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Checkbox")
+	checkbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+	checkbox.controlType = OPTIONS_CHECKBOX
+	checkbox.system = SETTING_TYPE_UI
+	checkbox.settingId = _G[strformat("SETTING_%s", controlName)]
+	checkbox.panel = panelID
+	checkbox.text = text
+	checkbox.tooltipText = tooltip
+
+	local checkboxButton = checkbox:GetNamedChild("Checkbox")
+
+	ZO_PreHookHandler(checkbox, "OnShow", function()
+			checkboxButton:SetState(getFunc() and 1 or 0)
+			checkboxButton:toggleFunction(getFunc())
+		end)
+	ZO_PreHookHandler(checkboxButton, "OnClicked", function() setFunc(not getFunc()) end)
+
+	if warning then
+		checkbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", checkbox, "ZO_Options_WarningIcon")
+		checkbox.warning:SetAnchor(RIGHT, checkboxButton, LEFT, -5, 0)
+		checkbox.warning.tooltipText = warningText
+	end
+
+	ZO_OptionsWindow_InitializeControl(checkbox)
+
+	lastAddedControl[panelID] = checkbox
+
+	return checkbox
+end
+
+function lam:AddColorPicker(panelID, controlName, text, tooltip, getFunc, setFunc, warning, warningText)
+	local colorpicker = wm:CreateTopLevelWindow(controlName)
+	colorpicker:SetParent(optionsWindow)
+	colorpicker:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
+	colorpicker:SetResizeToFitDescendents(true)
+	colorpicker:SetWidth(510)
+	colorpicker:SetMouseEnabled(true)
+
+	colorpicker.label = wm:CreateControl(controlName.."Label", colorpicker, CT_LABEL)
+	local label = colorpicker.label
+	label:SetDimensions(300, 26)
+	label:SetAnchor(TOPLEFT)
+	label:SetFont("ZoFontWinH4")
+	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+	label:SetText(text)
+
+	colorpicker.color = wm:CreateControl(controlName.."Color", colorpicker, CT_CONTROL)
+	local color = colorpicker.color
+	color:SetDimensions(200,26)
+	color:SetAnchor(RIGHT)
+
+	color.thumb = wm:CreateControl(controlName.."ColorThumb", color, CT_TEXTURE)
+	local thumb = color.thumb
+	thumb:SetDimensions(36, 18)
+	thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
+	local r, g, b, a = getFunc()
+	thumb:SetColor(r, g, b, a or 1)
+
+	color.border = wm:CreateControl(controlName.."ColorBorder", color, CT_TEXTURE)
+	local border = color.border
+	border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds")
+	border:SetTextureCoords(0, .625, 0, .8125)
+	border:SetDimensions(40, 22)
+	border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
+
+	local ColorPickerCallback
+	if not ColorPickerCallback then
+		ColorPickerCallback = function(r, g, b, a)
+			thumb:SetColor(r, g, b, a or 1)
+			setFunc(r, g, b, a)
+		end
+	end
+
+	colorpicker.controlType = OPTIONS_CUSTOM
+	colorpicker.customSetupFunction = function(colorpicker)
+			colorpicker:SetHandler("OnMouseUp", function(self, btn, upInside)
+					if upInside then
+						local r, g, b, a = getFunc()
+						COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, text)
+					end
+				end)
+		end
+	colorpicker.panel = panelID
+	colorpicker.tooltipText = tooltip
+	colorpicker:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+	colorpicker:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+
+	if warning then
+		colorpicker.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", colorpicker, "ZO_Options_WarningIcon")
+		colorpicker.warning:SetAnchor(RIGHT, colorpicker:GetNamedChild("Color"), LEFT, -5, 0)
+		colorpicker.warning.tooltipText = warningText
+	end
+
+	ZO_OptionsWindow_InitializeControl(colorpicker)
+
+	lastAddedControl[panelID] = colorpicker
+
+	return colorpicker
+end
+
+function lam:AddEditBox(panelID, controlName, text, tooltip, isMultiLine, getFunc, setFunc, warning, warningText)
+	local editbox = wm:CreateTopLevelWindow(controlName)
+	editbox:SetParent(optionsWindow)
+	editbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
+	editbox:SetResizeToFitDescendents(true)
+	editbox:SetWidth(510)
+	editbox:SetMouseEnabled(true)
+
+	editbox.label = wm:CreateControl(controlName.."Label", editbox, CT_LABEL)
+	local label = editbox.label
+	label:SetDimensions(300, 26)
+	label:SetAnchor(TOPLEFT)
+	label:SetFont("ZoFontWinH4")
+	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+	label:SetText(text)
+
+	editbox.bg = wm:CreateControlFromVirtual(controlName.."BG", editbox, "ZO_EditBackdrop")
+	local bg = editbox.bg
+	bg:SetDimensions(200,isMultiLine and 100 or 24)
+	bg:SetAnchor(RIGHT)
+	editbox.edit = wm:CreateControlFromVirtual(controlName.."Edit", bg, isMultiLine and "ZO_DefaultEditMultiLineForBackdrop" or "ZO_DefaultEditForBackdrop")
+	editbox.edit:SetText(getFunc())
+	editbox.edit:SetHandler("OnFocusLost", function(self) setFunc(self:GetText()) end)
+
+
+	editbox.panel = panelID
+	editbox.tooltipText = tooltip
+	editbox:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+	editbox:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+
+	if warning then
+		editbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", editbox, "ZO_Options_WarningIcon")
+		editbox.warning:SetAnchor(TOPRIGHT, editbox:GetNamedChild("BG"), TOPLEFT, -5, 0)
+		editbox.warning.tooltipText = warningText
+	end
+
+	ZO_OptionsWindow_InitializeControl(editbox)
+
+	lastAddedControl[panelID] = editbox
+
+	return editbox
+end
+
+function lam:AddButton(panelID, controlName, text, tooltip, onClick, warning, warningText)
+	local button = wm:CreateTopLevelWindow(controlName)
+	button:SetParent(optionsWindow)
+	button:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+	button:SetDimensions(510, 28)
+	button:SetMouseEnabled(true)
+
+	button.btn = wm:CreateControlFromVirtual(controlName.."Button", button, "ZO_DefaultButton")
+	local btn = button.btn
+	btn:SetAnchor(TOPRIGHT)
+	btn:SetWidth(200)
+	btn:SetText(text)
+	btn:SetHandler("OnClicked", onClick)
+
+	button.controlType = OPTIONS_CUSTOM
+	button.customSetupFunction = function() end	--move handlers into this function? (since I created a function...)
+	button.panel = panelID
+	btn.tooltipText = tooltip
+	btn:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+	btn:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+
+	if warning then
+		button.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", button, "ZO_Options_WarningIcon")
+		button.warning:SetAnchor(RIGHT, btn, LEFT, -5, 0)
+		button.warning.tooltipText = warningText
+	end
+
+	ZO_OptionsWindow_InitializeControl(button)
+
+	lastAddedControl[panelID] = button
+
+	return button
+end
+
+function lam:AddDescription(panelID, controlName, text, titleText)
+	local textBox = wm:CreateTopLevelWindow(controlName)
+	textBox:SetParent(optionsWindow)
+	textBox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
+	textBox:SetResizeToFitDescendents(true)
+	textBox:SetWidth(510)
+
+	if titleText then
+		textBox.title = wm:CreateControl(controlName.."Title", textBox, CT_LABEL)
+		local title = textBox.title
+		title:SetWidth(510)
+		title:SetAnchor(TOPLEFT, textBox, TOPLEFT)
+		title:SetFont("ZoFontWinH4")
+		title:SetText(titleText)
+	end
+
+	textBox.desc = wm:CreateControl(controlName.."Text", textBox, CT_LABEL)
+	local desc = textBox.desc
+	desc:SetWidth(510)
+	if titleText then
+		desc:SetAnchor(TOPLEFT, textBox.title, BOTTOMLEFT)
+	else
+		desc:SetAnchor(TOPLEFT)
+	end
+	desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
+	desc:SetFont("ZoFontGame")
+	desc:SetText(text)
+
+	textBox.controlType = OPTIONS_CUSTOM
+	textBox.panel = panelID
+
+	ZO_OptionsWindow_InitializeControl(textBox)
+
+	lastAddedControl[panelID] = textBox
+
+	return textBox
+end
+
+
+--test controls & examples--
+--[[local controlPanelID = lam:CreateControlPanel("ZAM_ADDON_OPTIONS", "ZAM Addons")
+lam:AddHeader(controlPanelID, "ZAM_Addons_TESTADDON", "TEST ADDON")
+lam:AddDescription(controlPanelID, "ZAM_Addons_TESTDESC", "This is a test description.", "Header")
+lam:AddSlider(controlPanelID, "ZAM_TESTSLIDER", "Test slider", "Adjust the slider.", 1, 10, 1, function() return 7 end, function(value) end, true, "needs UI reload")
+lam:AddDropdown(controlPanelID, "ZAM_TESTDROPDOWN", "Test Dropdown", "Pick something!", {"thing 1", "thing 2", "thing 3"}, function() return "thing 2" end, function(self,valueString) print(valueString) end)
+local checkbox1 = true
+lam:AddCheckbox(controlPanelID, "ZAM_TESTCHECKBOX", "Test Checkbox", "On or off?", function() return checkbox1 end, function(value) checkbox1 = not checkbox1 print(value, checkbox1) end)
+lam:AddColorPicker(controlPanelID, "ZAM_TESTCOLORPICKER", "Test color picker", "What's your favorite color?", function() return 1, 1, 0 end, function(r,g,b) print(r,g,b) end)
+lam:AddEditBox(controlPanelID, "ZAM_TESTEDITBOX", "Test Edit Box", "This is a tooltip!", false, function() return "hi" end, function(text) print(text) end)
+lam:AddHeader(controlPanelID, "ZAM_Addons_TESTADDON2", "TEST ADDON 2")
+local checkbox2 = false
+lam:AddCheckbox(controlPanelID, "ZAM_TESTCHECKBOX2", "Test Checkbox 2", "On or off?", function() return checkbox2 end, function(value) checkbox2 = not checkbox2 print(value, checkbox2) end)
+lam:AddButton(controlPanelID, "ZAM_TESTBUTTON", "Test Button", "Click me", function() print("hi") end, true, "oh noez!")
+lam:AddEditBox(controlPanelID, "ZAM_TESTEDITBOX2", "Test Edit Box 2", "This is a tooltip!", true, function() return "hi" end, function(text) print(text) end, true, "warning text")
+lam:AddSlider(controlPanelID, "ZAM_TESTSLIDER2", "Test slider 2", "Adjust the slider.", 50, 100, 10, function() return 80 end, function(value) end)
+lam:AddDropdown(controlPanelID, "ZAM_TESTDROPDOWN2", "Test Dropdown 2", "Pick something!", {"thing 4", "thing 5", "thing 6"}, function() return "thing 6" end, function(self,valueString) print(valueString) end)
 ]]--
\ No newline at end of file
diff --git a/libs/LibStub/LibStub.lua b/libs/LibStub/LibStub.lua
index bfd96df..4c509a5 100644
--- a/libs/LibStub/LibStub.lua
+++ b/libs/LibStub/LibStub.lua
@@ -1,34 +1,34 @@
--- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
--- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
--- LibStub developed for World of Warcraft by above members of the WowAce community.
--- Ported to Elder Scrolls Online by Seerah
-
-local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 1  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
-local LibStub = _G[LIBSTUB_MAJOR]
-
-local strformat = string.format
-if not LibStub or LibStub.minor < LIBSTUB_MINOR then
-	LibStub = LibStub or {libs = {}, minors = {} }
-	_G[LIBSTUB_MAJOR] = LibStub
-	LibStub.minor = LIBSTUB_MINOR
-
-	function LibStub:NewLibrary(major, minor)
-		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
-		minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
-
-		local oldminor = self.minors[major]
-		if oldminor and oldminor >= minor then return nil end
-		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
-		return self.libs[major], oldminor
-	end
-
-	function LibStub:GetLibrary(major, silent)
-		if not self.libs[major] and not silent then
-			error(("Cannot find a library instance of %q."):strformat(tostring(major)), 2)
-		end
-		return self.libs[major], self.minors[major]
-	end
-
-	function LibStub:IterateLibraries() return pairs(self.libs) end
-	setmetatable(LibStub, { __call = LibStub.GetLibrary })
-end
+-- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+-- LibStub developed for World of Warcraft by above members of the WowAce community.
+-- Ported to Elder Scrolls Online by Seerah
+
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 1  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+local strformat = string.format
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+	LibStub = LibStub or {libs = {}, minors = {} }
+	_G[LIBSTUB_MAJOR] = LibStub
+	LibStub.minor = LIBSTUB_MINOR
+
+	function LibStub:NewLibrary(major, minor)
+		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+		minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+		local oldminor = self.minors[major]
+		if oldminor and oldminor >= minor then return nil end
+		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+		return self.libs[major], oldminor
+	end
+
+	function LibStub:GetLibrary(major, silent)
+		if not self.libs[major] and not silent then
+			error(("Cannot find a library instance of %q."):strformat(tostring(major)), 2)
+		end
+		return self.libs[major], self.minors[major]
+	end
+
+	function LibStub:IterateLibraries() return pairs(self.libs) end
+	setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end