Merge pull request #21 from AssemblerManiac/master

manavortex [02-27-18 - 18:08]
Merge pull request #21 from AssemblerManiac/master

final version - I hope
Filename
IIfA/CharBagSpaceTooltip.lua
IIfA/IIfA.lua
IIfA/IIfA.txt
IIfA/IIfABackpack.lua
IIfA/IIfADataCollection.lua
IIfA/IIfAEvents.lua
IIfA/IIfASceneFuncs.lua
IIfA/IIfASettingsAdapter.lua
IIfA/IIfATooltip.lua
IIfA/IIfA_Preload.lua
IIfA/IIfA_xml_adapter.lua
diff --git a/IIfA/CharBagSpaceTooltip.lua b/IIfA/CharBagSpaceTooltip.lua
index 2e2f0ff..dcb3978 100644
--- a/IIfA/CharBagSpaceTooltip.lua
+++ b/IIfA/CharBagSpaceTooltip.lua
@@ -1,6 +1,7 @@
 local CharBagFrame = ZO_Object:Subclass()
 if IIfA == nil then IIfA = {} end
 IIfA.CharBagFrame = CharBagFrame
+CharBagFrame.EMPTY_STRING = ""

 --[[ not currently used
 local function HexToN(sHexVal)
@@ -49,7 +50,7 @@ end

 function CharBagFrame:ComputeColorAndText(spaceCurr, spaceMax)
 	local usedBagPercent = tonumber(spaceCurr) * 100 / tonumber(spaceMax)
-	local cs = ""
+	local cs = self.EMPTY_STRING
 	if spaceCurr == spaceMax then
 		cs = ColorStart(self.ColorFull)
 	else
@@ -125,7 +126,7 @@ function CharBagFrame:FillCharAndBank()
 				self:SetQty(tControl, "spaceUsed", self:ComputeColorAndText(tempUsed, GetBagSize(ctr)))
 				self:SetQty(tControl, "spaceMax", GetBagSize(ctr))
 				cName = GetCollectibleNickname(GetCollectibleForHouseBankBag(ctr))
-				if cName == "" then
+				if cName == self.EMPTY_STRING then
 					cName = GetCollectibleName(GetCollectibleForHouseBankBag(ctr))
 				end
 				tControl:GetNamedChild("charName"):SetText(cName)
diff --git a/IIfA/IIfA.lua b/IIfA/IIfA.lua
index 0dcda17..5f8e4b4 100644
--- a/IIfA/IIfA.lua
+++ b/IIfA/IIfA.lua
@@ -21,7 +21,7 @@ if IIfA == nil then IIfA = {} end
 --local IIfA = IIfA

 IIfA.name 				= "Inventory Insight"
-IIfA.version 			= "3.09b"
+IIfA.version 			= "3.10"
 IIfA.author 			= "AssemblerManiac & manavortex"
 IIfA.defaultAlertSound 	= nil
 IIfA.colorHandler 		= nil
@@ -31,6 +31,7 @@ IIfA.CurrSceneName 		= "hud"
 IIfA.bFilterOnSetName 	= false
 IIfA.searchFilter 		= ""
 IIfA.trackedHouses		= {}
+IIfA.EMPTY_STRING		= ""

 local LMP = LibStub("LibMediaProvider-1.0")
 local BACKPACK = ZO_PlayerInventoryBackpack
@@ -49,13 +50,16 @@ IIfA.task			= task
 -- --------------------------------------------------------------

 -- BAG_SUBSCRIBER_BANK handled special in the CollectAll function - do NOT add to this list
+-- has to be in this list because it's checked for in more than a few places as "do I track"

 IIfA.trackedBags = {
 	[BAG_WORN] 				= true,
 	[BAG_BACKPACK] 			= true,
 	[BAG_BANK] 				= true,
+	[BAG_SUBSCRIBER_BANK]	= true,
 	[BAG_GUILDBANK] 		= true,
 	[BAG_VIRTUAL] 			= true,
+	[BAG_HOUSE_BANK_ONE] 	= true,
 	[BAG_HOUSE_BANK_TWO] 	= true,
 	[BAG_HOUSE_BANK_THREE]	= true,
 	[BAG_HOUSE_BANK_FOUR] 	= true,
@@ -81,22 +85,10 @@ IIfA.dropdownBankNames = {
 	"All Houses",
 }

-function IIfA:GetItemID(itemLink)
-	local ret = nil
-	if (itemLink) then
-		local data = itemLink:match("|H.:item:(.-)|h.-|h")
-		local itemID = zo_strsplit(':', data)		-- just get the number
-
-		-- because other functions may be comparing string to string, we can't make this be a number or it won't compare properly
-		ret = itemID
-	end
-	return ret
-end
-
 -- 7-26-16 AM - global func, not part of IIfA class, used in IIfA_OnLoad
 function IIfA_SlashCommands(cmd)

-	if (cmd == "") then
+	if (cmd == IIfA.EMPTY_STRING) then
     	d("[IIfA]:Please find the majority of options in the addon settings section of the menu under Inventory Insight.")
     	d(" ")
     	d("[IIfA]:Usage - ")
@@ -413,7 +405,7 @@ function IIfA_onLoad(eventCode, addOnName)
 	if nil ~= IIfA.data.DBv2 then IIfA.data.DBv2 = nil end

 	-- keep EU and US items apart
-	local worldName = GetWorldName():gsub(" Megaserver", "")
+	local worldName = GetWorldName():gsub(" Megaserver", IIfA.EMPTY_STRING)
 	IIfA.data[worldName] = IIfA.data[worldName] or {}
 	if IIfA.data[worldName].DBv3 == nil then
 		 IIfA.data[worldName].DBv3 = IIfA.data.DBv3
@@ -421,7 +413,7 @@ function IIfA_onLoad(eventCode, addOnName)
 	IIfA.data.DBv3 = nil
 	IIfA.database = IIfA.data[worldName].DBv3

-	IIfA:ActionLayerInventoryUpdate()
+--	IIfA:ActionLayerInventoryUpdate()

 	if not ObjSettings.frameSettings.hud.hidden then
 		IIfA:ProcessSceneChange("hud", "showing", "shown")
@@ -432,7 +424,6 @@ function IIfA_onLoad(eventCode, addOnName)

 	IIfA.ignoredCharEquipment = IIfA.ignoredCharEquipment or {}
 	IIfA.ignoredCharInventories = IIfA.ignoredCharInventories or {}
-
 	IIfA.trackedBags[BAG_WORN] 		= not IIfA:IsCharacterEquipIgnored()
 	IIfA.trackedBags[BAG_BACKPACK] 	= not IIfA:IsCharacterInventoryIgnored()

@@ -455,8 +446,9 @@ end
 function IIfA:MakeBSI()
 	local bs = {}
 	local idx
-	local itemLink, DBItem, locname, data
-	for itemLink, DBItem in pairs(IIfA.database) do
+	local itemKey, DBItem, locname, data
+	local bagSlot, qty
+	for itemKey, DBItem in pairs(IIfA.database) do
 		if DBItem.locations then
 			for locname, data in pairs(DBItem.locations) do
 				if ((data.bagID == BAG_BACKPACK or data.bagID == BAG_WORN) and locname == IIfA.currentCharacterId) or	-- only index items ON this character if they're in backpack
@@ -469,7 +461,15 @@ function IIfA:MakeBSI()
 						bs[idx] = {}
 					end
 					if nil ~= idx and nil ~= data.bagSlot then
-						bs[idx][data.bagSlot] = itemLink
+						for bagSlot, qty in pairs(data.bagSlot) do
+							bs[idx][bagSlot] = itemKey
+						end
+					end
+					if data.bagSlot ~= nil and type(data.bagSlot) ~= "table" then
+						bagSlot = data.bagSlot
+						data.bagSlot = {}
+						data.bagSlot[bagSlot] = data.itemCount
+						data.itemCount = nil
 					end
 				end
 			end
@@ -479,8 +479,6 @@ function IIfA:MakeBSI()
 	return bs	-- return only used in IIfA:SaveBagSlotIndex when IIfA.BagSlotInfo is nil
 end

-
-
 --[[
 for reference

diff --git a/IIfA/IIfA.txt b/IIfA/IIfA.txt
index 39804a7..a451f0f 100644
--- a/IIfA/IIfA.txt
+++ b/IIfA/IIfA.txt
@@ -1,6 +1,6 @@
 ## Title: Inventory Insight
 ## Author: manavortex, AssemblerManiac
-## Version: 3.09b
+## Version: 3.10
 ## APIVersion: 100022
 ## SavedVariables: IIfA_Settings IIfA_Data
 ## OptionalDependsOn: libFilters pChat
diff --git a/IIfA/IIfABackpack.lua b/IIfA/IIfABackpack.lua
index ad7ffc0..6102ee7 100644
--- a/IIfA/IIfABackpack.lua
+++ b/IIfA/IIfABackpack.lua
@@ -77,7 +77,7 @@ end

 function IIfA:GUIDoubleClick(control, button)
 	if button == MOUSE_BUTTON_INDEX_LEFT and control.itemLink then
-		if control.itemLink ~= "" then
+		if control.itemLink ~= IIfA.EMPTY_STRING then
 			ZO_ChatWindowTextEntryEditBox:SetText(ZO_ChatWindowTextEntryEditBox:GetText() .. zo_strformat(SI_TOOLTIP_ITEM_NAME, control.itemLink))
 		end
 	end
@@ -91,45 +91,44 @@ local function getHouseIds()
 	return ret
 end

+local function isHouse()
+	return IIfA:GetTrackingWithHouseNames()[locationName]
+end
+
+function IIfA:IsOneOf(value, comp1, comp2, comp3, comp4, comp5, comp6)
+	return nil ~= value and (value == comp6) or (value == comp5) or (value == comp4) or (value == comp3) or (value == comp2) or value == comp1
+end

 local function DoesInventoryMatchList(locationName, location)
 	local bagId 	= location.bagID
 	local filter 	= IIfA.InventoryListFilter

-	local function isHouse()
-		return IIfA:GetTrackingWithHouseNames()[locationName]
-	end
-
-	local function isOneOf(value, comp1, comp2, comp3, comp4, comp5, comp6)
-		return nil ~= value and (value == comp6) or (value == comp5) or (value == comp4) or (value == comp3) or (value == comp2) or value == comp1
-	end
-
 --	if locationName == "attributes" then return false end
 	if (filter == "All") then
 		return true

 	elseif (filter == "All Banks") then
-		return isOneOf(bagId, BAG_SUBSCRIBER_BANK, BAG_GUILDBANK) and IIfA.trackedBags[bagId]
+		return IIfA:IsOneOf(bagId, BAG_SUBSCRIBER_BANK, BAG_GUILDBANK) and IIfA.trackedBags[bagId]

 	elseif (filter == "All Guild Banks") then
-		return isOneOf(bagId, BAG_GUILDBANK)
+		return IIfA:IsOneOf(bagId, BAG_GUILDBANK)

 	elseif (filter == "All Characters") then
-		return isOneOf(bagId, BAG_BACKPACK, BAG_WORN)
+		return IIfA:IsOneOf(bagId, BAG_BACKPACK, BAG_WORN)

 	elseif (filter == "Bank and Characters") then
-		return isOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK, BAG_BACKPACK, BAG_WORN)
+		return IIfA:IsOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK, BAG_BACKPACK, BAG_WORN)

 	elseif(filter == "Bank and Current Character") then
-		return isOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK, BAG_BACKPACK, BAG_WORN)
+		return IIfA:IsOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK, BAG_BACKPACK, BAG_WORN)
 			and locationName == IIfA.currentCharacterId

 	elseif(filter == "Bank and other characters") then
-		return isOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK, BAG_BACKPACK, BAG_WORN)
+		return IIfA:IsOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK, BAG_BACKPACK, BAG_WORN)
 			and locationName ~= IIfA.currentCharacterId

 	elseif(filter == "Bank Only") then
-		return isOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK)
+		return IIfA:IsOneOf(bagId, BAG_BANK, BAG_SUBSCRIBER_BANK)

 	elseif(filter == "Craft Bag") then
 		return (bagId == BAG_VIRTUAL)
@@ -144,7 +143,7 @@ local function DoesInventoryMatchList(locationName, location)
 		return (bagId == IIfA:GetHouseIdFromName(filter))

 	else --Not a preset, must be a specific guildbank or character
-		if isOneOf(bagId, BAG_BACKPACK, BAG_WORN) then
+		if IIfA:IsOneOf(bagId, BAG_BACKPACK, BAG_WORN) then
 			-- it's a character name, convert to Id, check that against location Name in the dbv3 table
 			if locationName == IIfA.CharNameToId[filter] then return true end
 		else
@@ -196,7 +195,7 @@ local function matchFilter(itemName, itemLink)
 	local searchFilter = IIfA.searchFilter
 	-- 17-7-30 AM - moved lowercasing to when it's created, one less call to lowercase for every item

-    local name = string.lower(itemName) or ""
+    local name = string.lower(itemName) or IIfA.EMPTY_STRING

 	-- text filter takes precedence
 	-- 3-6-17 AM - you're either filtering on a set name, or not - much less confusing (hopefully)
@@ -320,7 +319,7 @@ local function IIfA_FilterCompareUp(a, b)

 	local sort1 = (IIfA.bSortQuality and a.quality) or a.name
 	local sort2 = (IIfA.bSortQuality and b.quality) or b.name
-	return (sort1 or "") < (sort2 or "")
+	return (sort1 or IIfA.EMPTY_STRING) < (sort2 or IIfA.EMPTY_STRING)
 end
 local function IIfA_FilterCompareDown(a, b)
 	return IIfA_FilterCompareUp(b, a)
@@ -336,6 +335,16 @@ local function sort(dataLines)
 	end
 end

+local function itemSum(location)
+	if type(location.bagSlot) ~= "table" then return 0 end
+	local totQty = 0
+	local bagSlot, itemCount
+	for bagSlot, itemCount in pairs(location.bagSlot) do
+		totQty = totQty + itemCount
+	end
+	return totQty
+end
+
 -- fill the shown item list with items that match current filter(s)
 function IIfA:UpdateScrollDataLinesData()

@@ -360,7 +369,7 @@ function IIfA:UpdateScrollDataLinesData()
 				itemLink = itemKey
 			end

-			if (itemKey ~= "") then
+			if (itemKey ~= IIfA.EMPTY_STRING) then

 				itemTypeFilter = 0
 				if (dbItem.filterType) then
@@ -373,7 +382,7 @@ function IIfA:UpdateScrollDataLinesData()

 				local locationName, locData
 				for locationName, locData in pairs(dbItem.locations) do
-					itemCount = itemCount + (locData.itemCount or 0)
+					itemCount = itemCount + itemSum(locData)
 					if DoesInventoryMatchList(locationName, locData) then
 						match = true
 					end
@@ -412,11 +421,11 @@ end
 local function fillLine(curLine, curItem)
 	local color
 	if curItem == nil then
-		curLine.itemLink = ""
+		curLine.itemLink = IIfA.EMPTY_STRING
 		curLine.icon:SetTexture(nil)
 		curLine.icon:SetAlpha(0)
-		curLine.text:SetText("")
-		curLine.qty:SetText("")
+		curLine.text:SetText(IIfA.EMPTY_STRING)
+		curLine.qty:SetText(IIfA.EMPTY_STRING)
 		curLine.worn:SetHidden(true)
 		curLine.stolen:SetHidden(true)
 	else
@@ -613,7 +622,6 @@ function IIfA:QueryAccountInventory(itemLink)
 		itemLink = string.gsub(itemLink, '|H0', '|H1')
 	end

-
 	local queryItem = {
 		link = itemLink,
 		locations = {},
@@ -622,19 +630,15 @@ function IIfA:QueryAccountInventory(itemLink)
 	local queryItemsFound = 0
 	local AlreadySavedLoc = false
 	local newLocation = {}
+	local itemCount = 0

-	local itemType = GetItemLinkItemType(itemLink)
-	if CanItemLinkBeVirtual(itemLink) or
-		itemType == ITEMTYPE_LOCKPICK or
-		itemType == ITEMTYPE_RECIPE or
-		itemType == ITEMTYPE_RACIAL_STYLE_MOTIF then
-		itemLink = IIfA:GetItemID(itemLink)
-	end
+	itemLink = IIfA:GetItemKey(itemLink)

 	local item = IIfA.database[itemLink]

 	if ((queryItem.link ~= nil) and (item ~= nil)) then
 		for locationName, location in pairs(item.locations) do
+			itemCount = itemSum(location)
 			AlreadySavedLoc = false
 			if location.bagID == BAG_WORN or location.bagID == BAG_BACKPACK then
 				locationName = IIfA.CharIdToName[locationName]
@@ -642,24 +646,24 @@ function IIfA:QueryAccountInventory(itemLink)
 			if locationName ~= nil then
 				for x, QILocation in pairs(queryItem.locations) do
 					if (QILocation.name == locationName)then
-						QILocation.itemsFound = QILocation.itemsFound + location.itemCount
+						QILocation.itemsFound = QILocation.itemsFound + itemCount
 						AlreadySavedLoc = true
 					end
 				end

-				if location.itemCount ~= nil and location.itemCount > 0 then
-					if (not AlreadySavedLoc) and (location.itemCount > 0) then
+				if itemCount ~= nil and itemCount > 0 then
+					if (not AlreadySavedLoc) and (itemCount > 0) then
 						newLocation = {}
 						newLocation.name = locationName

 						if location.bagID >= BAG_HOUSE_BANK_ONE and location.bagID <= BAG_HOUSE_BANK_TEN then -- location is a housing chest
 							newLocation.name = GetCollectibleNickname(locationName)
-							if newLocation.name == "" then newLocation.name = GetCollectibleName(locationName) end
+							if newLocation.name == IIfA.EMPTY_STRING then newLocation.name = GetCollectibleName(locationName) end
 						elseif location.bagID == locationName then	-- location is a house
 							newLocation.name = GetCollectibleName(locationName)
 						end

-						newLocation.itemsFound = location.itemCount
+						newLocation.itemsFound = itemCount
 						newLocation.worn = location.bagID == BAG_WORN

 						table.insert(queryItem.locations, newLocation)
@@ -771,7 +775,7 @@ function IIfA:ProcessRightClick(control)

 	-- it's an IIFA list item, lets see if it has data, and allow menu if it does

-	if control.itemLink ~= "" then
+	if control.itemLink ~= IIfA.EMPTY_STRING then
 		zo_callLater(function()
 			AddCustomMenuItem(GetString(SI_ITEM_ACTION_LINK_TO_CHAT), function() IIfA:GUIDoubleClick(control, MOUSE_BUTTON_INDEX_LEFT) end, MENU_ADD_OPTION_LABEL)
 			AddCustomMenuItem("Missing Motifs to text", function() IIfA:FMC(control, "Private") end, MENU_ADD_OPTION_LABEL)
@@ -868,7 +872,7 @@ function IIfA:FMC(control, WhoSeesIt)
 	langChapNames["DE"] = {"Äxte", "Gürtel", "Stiefel", "Bogen", "Torsi", "Dolche", "Handschuhe", "Helme", "Beine", "Keulen", "Schilde", "Schultern", "Stäbe", "Schwerter" }
 	local chapnames = langChapNames[GetCVar("language.2")] or langChapNames["EN"]

-	if control.itemLink == nil or control.itemLink == "" then
+	if control.itemLink == nil or control.itemLink == IIfA.EMPTY_STRING then
 		d("Invalid item. Right-Click ignored.")
 		return
 	end
@@ -900,10 +904,10 @@ function IIfA:FMC(control, WhoSeesIt)
 		end
 	end

-	local s = ""
+	local s = IIfA.EMPTY_STRING
 	for i, val in pairs(chapnames) do
 		if val ~= nil then
-			if s == "" then
+			if s == IIfA.EMPTY_STRING then
 				s = val
 			else
 				s = string.format("%s, %s", s, val)
@@ -911,7 +915,7 @@ function IIfA:FMC(control, WhoSeesIt)
 		end
 	end

-	if s == "" then
+	if s == IIfA.EMPTY_STRING then
 		d("No motif chapters missing")
 	else
 		-- incomplete motif achieve
diff --git a/IIfA/IIfADataCollection.lua b/IIfA/IIfADataCollection.lua
index eedda07..626af64 100644
--- a/IIfA/IIfADataCollection.lua
+++ b/IIfA/IIfADataCollection.lua
@@ -1,12 +1,23 @@
-local IIfA 			= IIfA
-local EMPTY_STRING 	= ""
+local IIfA 			= IIfA or {}
 local _
-
 local task 			= IIfA.task or LibStub("LibAsync"):Create("IIfA_DataCollection")
 IIfA.task			= task

 local function p(...) IIfA:DebugOut(...) end

+local function IIfA_GetItemID(itemLink)
+	local ret = nil
+	if itemLink then
+		if GetItemLinkItemId then
+	   		ret = tostring(GetItemLinkItemId(itemLink))
+		else
+			local data = itemLink:match("|H.:item:(.-)|h.-|h")
+			ret = zo_strsplit(':', data)		-- just get the number
+		end
+	end
+	return ret
+end
+
 local function grabBagContent(bagId, override)
 	if bagId >= BAG_HOUSE_BANK_ONE and bagId <= BAG_HOUSE_BANK_TEN and not IsOwnerOfCurrentHouse() then return end

@@ -172,12 +183,9 @@ function IIfA:OnFirstInventoryOpen()
 	if IIfA.BagsScanned then return end
 	IIfA.BagsScanned = true

-	-- call with libAsync to avoid lags
-	task:Call(function()
-		IIfA:ScanBank()
-	end):Then(function()
-		IIfA:ScanCurrentCharacter()
-	end)
+	-- do not async this, each scan function does that itself
+	IIfA:ScanBank()
+	IIfA:ScanCurrentCharacter()
 end

 function IIfA:CheckForAgedGuildBankData( days )
@@ -188,7 +196,7 @@ function IIfA:CheckForAgedGuildBankData( days )
 		for guildName, guildData in pairs(IIfA.data.guildBanks)do
 			local today = GetDate()
 			local lastCollected = guildData.lastCollected:match('(........)')
-			if(lastCollected and lastCollected ~= EMPTY_STRING)then
+			if(lastCollected and lastCollected ~= IIfA.EMPTY_STRING)then
 				if(today - lastCollected >= days)then
 					d("[IIfA]:Warning - " .. guildName .. " Guild Bank data not collected in " .. days .. " or more days!")
 					results = true
@@ -207,7 +215,7 @@ function IIfA:UpdateGuildBankData()
 	if IIfA.data.bCollectGuildBankData then
 		local tempGuildBankBag = {
 			items = 0;
-			lastCollected = EMPTY_STRING;
+			lastCollected = IIfA.EMPTY_STRING;
 		}
 		for index=1, GetNumGuilds() do
 			local guildName = GetGuildName(index)
@@ -220,9 +228,9 @@ function IIfA:UpdateGuildBankData()
 end

 function IIfA:CleanEmptyGuildBug()
-	local emptyGuild = IIfA.data.guildBanks[EMPTY_STRING]
+	local emptyGuild = IIfA.data.guildBanks[IIfA.EMPTY_STRING]
 	if(emptyGuild)then
-		IIfA.data.guildBanks[EMPTY_STRING] = nil
+		IIfA.data.guildBanks[IIfA.EMPTY_STRING] = nil
 	end
 end

@@ -263,17 +271,20 @@ function IIfA:GuildBankAddRemove(eventID, slotId)
 		if eventID == EVENT_GUILD_BANK_ITEM_ADDED then
 			IIfA:DebugOut("GB Add - Slot <<1>>", slotId)
 			dbItem, itemKey = IIfA:EvalBagItem(BAG_GUILDBANK, slotId, true)
-			IIfA:ValidateItemCounts(BAG_GUILDBANK, slotId, dbItem, itemKey)
+--			IIfA:ValidateItemCounts(BAG_GUILDBANK, slotId, dbItem, itemKey)
+			if not IIfA.BagSlotInfo[guildName] then
+				IIfA.BagSlotInfo[guildName] = {}
+			end
 			IIfA.BagSlotInfo[guildName][slotId] = itemKey
 		else
-			if IIfA.BagSlotInfo[guildName] ~= nil and IIfA.BagSlotInfo[guildName][slotId] then
-				itemLink = IIfA.BagSlotInfo[guildName][slotId]
+			if IIfA.BagSlotInfo[guildName] and IIfA.BagSlotInfo[guildName][slotId] then
+				local itemLink = IIfA.BagSlotInfo[guildName][slotId]
 				if #itemLink < 10 then
 					itemLink = IIfA.database[itemLink].itemLink
 				end
-				IIfA:DebugOut("GB Remove - Slot <<1>>, Link <<2>>, ", slotId)
-				dbItem, itemKey = IIfA:EvalBagItem(BAG_GUILDBANK, slotId, false, 0, itemLink)
-				IIfA:ValidateItemCounts(BAG_GUILDBANK, slotId, dbItem, itemKey)
+				IIfA:DebugOut("GB Remove - Slot <<1>>, Link <<2>>, ", slotId, itemLink)
+				dbItem, itemKey = IIfA:EvalBagItem(BAG_GUILDBANK, slotId, false, nil, itemLink)
+--				IIfA:ValidateItemCounts(BAG_GUILDBANK, slotId, dbItem, itemKey)
 				IIfA.BagSlotInfo[guildName][slotId] = nil
 			else
 				IIfA:DebugOut("GB Remove - Slot <<1>> - no BSI found", slotId)
@@ -282,9 +293,10 @@ function IIfA:GuildBankAddRemove(eventID, slotId)
 	end)
 end

-function IIfA:ActionLayerInventoryUpdate()
+
+--function IIfA:ActionLayerInventoryUpdate()
 	-- IIfA:CollectAll()
-end
+--end


 --[[
@@ -334,8 +346,7 @@ function IIfA:RescanHouse(houseCollectibleId)
 		for itemLink, itemCount in pairs(getAllPlacedFurniture()) do
 			-- (bagId, slotId, fromXfer, itemCount, itemLink, itemName, locationID)
 			IIfA:DebugOut("furniture item <<1>> x<<2>>", itemLink, itemCount)
-			IIfA:EvalBagItem(houseCollectibleId, tonumber(IIfA:GetItemID(itemLink)), false, itemCount, itemLink, GetItemLinkName(itemLink), houseCollectibleId)
-
+			IIfA:EvalBagItem(houseCollectibleId, tonumber(IIfA_GetItemID(itemLink)), false, itemCount, itemLink, GetItemLinkName(itemLink), houseCollectibleId)
 		end
 	end)

@@ -344,28 +355,23 @@ end
 -- try to read item name from bag/slot - if that's empty, we read it from item link
 local function getItemName(bagId, slotId, itemLink)
 	local itemName = GetItemName(bagId, slotId)
-	if "" ~= itemName then return itemName end
+	if IIfA.EMPTY_STRING ~= itemName then return itemName end
 	if nil == itemLink then return end
 	return GetItemLinkName(itemLink)
 end

 -- returns the item's db key, we only save under the item link if we need to save level information etc, else we use the ID
-function IIfA:GetItemKey(itemLink, usedInCraftingType, itemType)
-
-	if CanItemLinkBeVirtual(itemLink) then	-- anything that goes in the craft bag
-		return IIfA:GetItemID(itemLink)
-	elseif usedInCraftingType ~= CRAFTING_TYPE_INVALID and		-- crafting materials get saved by ID - think about removing this
-   		itemType ~= ITEMTYPE_GLYPH_ARMOR and
-   		itemType ~= ITEMTYPE_GLYPH_JEWELRY and
-   		itemType ~= ITEMTYPE_GLYPH_WEAPON then
-   		return IIfA:GetItemID(itemLink)
+function IIfA:GetItemKey(itemLink)
+
+	if CanItemLinkBeVirtual(itemLink) then	-- anything that goes in the craft bag - must be a crafting material
+		return IIfA_GetItemID(itemLink)
 	else
 		-- other oddball items that might have level info in them
-		itemType = itemType or GetItemLinkItemType(itemLink)
+		local itemType = GetItemLinkItemType(itemLink)
 		if	itemType == ITEMTYPE_LOCKPICK or
 			itemType == ITEMTYPE_RACIAL_STYLE_MOTIF or		-- 9-12-16 AM - added because motifs now appear to have level info in them
 			itemType == ITEMTYPE_RECIPE then
-			return IIfA:GetItemID(itemLink)
+			return IIfA_GetItemID(itemLink)
 		end
 	end
 	return itemLink
@@ -373,24 +379,25 @@ end

 local function getItemCount(bagId, slotId, itemLink)
 	local stackCountBackpack, stackCountBank, stackCountCraftBag, itemCount
-	if bagId > BAG_MAX_VALUE then return 0 end
-
-	-- first try to read item count from bag/slot
-	_, itemCount =  GetItemInfo(bagId, slotId)
-	if 0 < itemCount then return itemCount end
+	if bagId > BAG_MAX_VALUE then return 1 end		-- it's furniture because of the out of range id, always count of 1

 	-- try to find it by item link - only works for bag_backpack / bank / virtual
 	stackCountBackpack, stackCountBank, stackCountCraftBag = GetItemLinkStacks(itemLink)
 	if 		bagId == BAG_BACKPACK 	and 0 < stackCountBackpack 	then return stackCountBackpack
 	elseif 	bagId == BAG_BANK 		and 0 < stackCountBank 		then return stackCountBank
 	elseif 	bagId == BAG_VIRTUAL 	and 0 < stackCountCraftBag 	then return stackCountCraftBag
-	elseif  bagId == BAG_WORN then return 1 end
+	elseif  bagId == BAG_WORN then return 1
+	else
+		-- try to read item count from bag/slot
+		_, itemCount =  GetItemInfo(bagId, slotId)
+		if 0 < itemCount then return itemCount end
+	end

 	-- return 0 if no item count was found, possibly an out of date index to a house container that no longer exists
 	return 0
 end

-local function getLocation(location, bagId)
+local function getLocation(bagId)
 	if(bagId == BAG_BACKPACK or bagId == BAG_WORN) then
 		return IIfA.currentCharacterId
 	elseif(bagId == BAG_BANK or bagId == BAG_SUBSCRIBER_BANK) then
@@ -404,20 +411,31 @@ local function getLocation(location, bagId)
 	end
 end

+--[[
 function IIfA:SaveBagSlotIndex(bagId, slotId, itemLink)
 	if not bagId or not slotId then return end
 	IIfA.BagSlotInfo = IIfA.BagSlotInfo or IIfA:MakeBSI()
 	IIfA.BagSlotInfo[bagId] = IIfA.BagSlotInfo[bagId] or {}
 	IIfA.BagSlotInfo[bagId][slotId] = IIfA.BagSlotInfo[bagId][slotId] or itemLink
 end
+ --]]

 function IIfA:AddOrRemoveFurnitureItem(itemLink, itemCount, houseCollectibleId, fromInitialize)
 	-- d(zo_strformat("trying to add/remove <<1>> x <<2>> from houseCollectibleId <<3>>", itemLink, itemCount, houseCollectibleId))
 	local location = houseCollectibleId
-	IIfA:EvalBagItem(houseCollectibleId, IIfA:GetItemID(itemLink), false, itemCount, itemLink, GetItemLinkName(itemLink), houseCollectibleId)
+	IIfA:EvalBagItem(houseCollectibleId, IIfA_GetItemID(itemLink), false, itemCount, itemLink, GetItemLinkName(itemLink), houseCollectibleId)
 end

-function IIfA:EvalBagItem(bagId, slotId, fromXfer, itemCount, itemLink, itemName, locationID)
+function IIfA:TableCount(tbl)
+	local slotId, itemCount, cnt
+	cnt = 0
+	for slotId, itemCount in pairs(tbl) do
+		cnt = cnt + 1
+	end
+	return cnt
+end
+
+function IIfA:EvalBagItem(bagId, slotId, fromXfer, qty, itemLink, itemName, locationID)

 	if not IIfA.trackedBags[bagId] then return end

@@ -441,56 +459,59 @@ function IIfA:EvalBagItem(bagId, slotId, fromXfer, itemCount, itemLink, itemName
 	itemName = itemName or getItemName(bagId, slotId, itemLink)

 	-- item count is either passed or we have to get it from bag/slot ID or item link
-	itemCount = itemCount or getItemCount(bagId, slotId, itemLink)
+	itemCount = qty or getItemCount(bagId, slotId, itemLink)

 	--IIfA:DebugOut("trying to save <<1>> x<<2>>", itemLink, itemCount)

-	-- get item key from crafting type
-	local usedInCraftingType, itemType
-	local itemQuality
-
-	if bagId <= BAG_MAX_VALUE then
-		usedInCraftingType, _ = GetItemCraftingInfo(bagId, slotId)
-		_, itemCount, _, _, _, _, _, itemQuality = GetItemInfo(bagId, slotId)
-	else	-- these are furniture items in a house
-		usedInCraftingType = GetItemLinkCraftingSkillType(itemLink)
-		itemQuality = GetItemLinkQuality(itemLink)
-	end
+	local itemQuality = GetItemLinkQuality(itemLink)

 	local itemType = GetItemLinkItemType(itemLink)

-	-- IIfA:DebugOut("CraftingType, ItemType <<1>>, <<2>>", usedInCraftingType, itemType)
-
-	itemQuality			= GetItemLinkQuality(itemLink)
-	usedInCraftingType 	= GetItemLinkCraftingSkillType(itemLink)
-	itemType 			= GetItemLinkItemType(itemLink)
-
 	local itemKey
 	if bagId == BAG_VIRTUAL then
 		itemKey = tostring(slotId)
 	else
-		itemKey = IIfA:GetItemKey(itemLink, usedInCraftingType, itemType) or itemLink
+		itemKey = IIfA:GetItemKey(itemLink) or itemLink
 	end

 	if nil == itemKey then return end

 	local itemFilterType = GetItemFilterTypeInfo(bagId, slotId) or 0
 	local DBitem = DBv3[itemKey]
-	local location = locationID or getLocation(location, bagId) or EMPTY_STRING
+	local location = locationID or getLocation(bagId) or IIfA.EMPTY_STRING

 	if(DBitem) then
 		if itemCount == 0 then
-			DBitem.locations[location] = nil
+			DBitem.locations[location].bagSlot[slotId] = nil
+			if bagId == BAG_GUILDBANK then
+				IIfA.BagSlotInfo[location][slotId] = nil
+			else
+				IIfA.BagSlotInfo[bagId][slotId] = nil
+			end
 		else
-			local DBitemlocation = DBitem.locations[location]
-			if DBitemlocation then
-				DBitemlocation.itemCount = itemCount 		-- DBitemlocation.itemCount + itemCount
-				DBitemlocation.bagSlot = DBitemlocation.bagSlot or slotId
+IIfA:DebugOut(DBitem.locations[location])
+			if DBitem.locations[location] then
+				if DBitem.locations[location].bagSlot[slotId] then
+IIfA:DebugOut("Adding to slot " .. slotId)
+					DBitem.locations[location].bagSlot[slotId] = DBitem.locations[location].bagSlot[slotId] + itemCount
+					if DBitem.locations[location].bagSlot[slotId] == 0 then
+						DBitem.locations[location].bagSlot[slotId] = nil
+						if bagId == BAG_GUILDBANK then
+							IIfA.BagSlotInfo[location][slotId] = nil
+						else
+							IIfA.BagSlotInfo[bagId][slotId] = nil
+						end
+					end
+				else
+IIfA:DebugOut("Overwriting slot " .. slotId)
+					DBitem.locations[location].bagSlot[slotId] = itemCount
+				end
 			else
+IIfA:DebugOut("Adding loc=<<1>>, slot <<2>>, count=<<3>>", location, slotId, itemCount)
 				DBitem.locations[location] = {}
 				DBitem.locations[location].bagID = bagId
-				DBitem.locations[location].bagSlot = slotId
-				DBitem.locations[location].itemCount = itemCount
+				DBitem.locations[location].bagSlot = {}
+				DBitem.locations[location].bagSlot[slotId] = itemCount
 			end
 		end
 	else
@@ -501,16 +522,22 @@ function IIfA:EvalBagItem(bagId, slotId, fromXfer, itemCount, itemLink, itemName
 		DBv3[itemKey].locations = {}
 		DBv3[itemKey].locations[location] = {}
 		DBv3[itemKey].locations[location].bagID = bagId
-		DBv3[itemKey].locations[location].bagSlot = slotId
-		DBv3[itemKey].locations[location].itemCount = itemCount
+		DBv3[itemKey].locations[location].bagSlot = {}
+		DBv3[itemKey].locations[location].bagSlot[slotId] = itemCount
+		DBitem = DBv3[itemKey]
+	end
+
+	if IIfA:TableCount(DBitem.locations[location].bagSlot) == 0 then
+IIfA:DebugOut("Zapping location=<<1>>, bag=<<2>>, slot=<<3>>", location, bagId, slotId)
+		DBitem.locations[location] = nil
 	end

 	if zo_strlen(itemKey) < 10 then
 		DBv3[itemKey].itemLink = itemLink
 	end
-	if (IIfA.trackedBags[bagId]) and fromXfer then
-		IIfA:ValidateItemCounts(bagId, slotId, DBv3[itemKey], itemKey, itemLink, true)
-	end
+--	if (IIfA.trackedBags[bagId]) and fromXfer then
+--		IIfA:ValidateItemCounts(bagId, slotId, DBv3[itemKey], itemKey, itemLink, true)
+--	end

 	IIfA:DebugOut("saved bag/slot=<<1>>/<<2>> <<3>> x<<4>> -> <<5>>, loc=<<6>>", bagId, slotId, itemLink, itemCount, itemKey, location)

@@ -518,6 +545,7 @@ function IIfA:EvalBagItem(bagId, slotId, fromXfer, itemCount, itemLink, itemName

 end

+--[[
 function IIfA:ValidateItemCounts(bagID, slotId, dbItem, itemKey, itemLinkOverride, override)

 	local itemCount
@@ -545,7 +573,7 @@ function IIfA:ValidateItemCounts(bagID, slotId, dbItem, itemKey, itemLinkOverrid

 			itemLinkCheck = GetItemLink(data.bagID, data.bagSlot, LINK_STYLE_BRACKETS)
 			if itemLinkCheck == nil then
-				itemLinkCheck = (override and itemLinkOverride) or EMPTY_STRING
+				itemLinkCheck = (override and itemLinkOverride) or IIfA.EMPTY_STRING
 			end
 			if itemLinkCheck ~= itemLink then
 				if bagID ~= data.bagID and slotId ~= data.bagSlot then
@@ -560,17 +588,17 @@ function IIfA:ValidateItemCounts(bagID, slotId, dbItem, itemKey, itemLinkOverrid
 		end
 	end
 end
-
+ --]]

 function IIfA:CollectAll(bagId, tracked)		-- the args aren't used, but by making them args to function, they're avail to the task
 	local bagItems = nil
 	local itemLink, dbItem = nil
 	local itemKey
-	local location = EMPTY_STRING
+	local location = IIfA.EMPTY_STRING
 	local BagList = IIfA:GetTrackedBags() -- 20.1. mana: Iterating over a list now

 	for bagId, tracked in pairs(BagList) do		-- do NOT use ipairs, it's non-linear list (holes in the # sequence)
-		if bagId <= BAG_MAX_VALUE then
+		if bagId <= BAG_MAX_VALUE and bagId ~= BAG_SUBSCRIBER_BANK then -- ignore subscriber bank, it's handled along with the regular bank
 			-- call with libAsync to avoid lags
 			task:Call(function()
 				bagItems = GetBagSize(bagId)
@@ -682,6 +710,7 @@ end

 -- rewrite item links with proper level value in them, instead of random value based on who knows what
 -- written by SirInsidiator
+--[[
 local function RewriteItemLink(itemLink)
     local requiredLevel = select(6, ZO_LinkHandler_ParseLink(itemLink))
     requiredLevel = tonumber(requiredLevel)
@@ -718,7 +747,7 @@ local function GetItemIdentifier(itemLink)
         return itemId
     end
 end
-
+--]]
 function IIfA:RenameItems()
 	local DBv3 = IIfA.database
 	local item = nil
diff --git a/IIfA/IIfAEvents.lua b/IIfA/IIfAEvents.lua
index e46b348..2062e3b 100644
--- a/IIfA/IIfAEvents.lua
+++ b/IIfA/IIfAEvents.lua
@@ -14,34 +14,43 @@ end


 -- used by an event function
-function IIfA:InventorySlotUpdate(eventCode, bagId, slotId, isNewItem, itemSoundCategory, inventoryUpdateReason, qty)
+function IIfA:InventorySlotUpdate(eventCode, bagId, slotId, bNewItem, itemSoundCategory, inventoryUpdateReason, qty)

+	local sNewItem
 	if nil == bagId or nil == slotId then return end
-	if isNewItem then
-		isNewItem = "True"
+	if bNewItem then
+		sNewItem = "True"
 	else
-		isNewItem = "False"
+		sNewItem = "False"
 	end

-	local itemLink = GetItemLink(bagId, slotId, LINK_STYLE_BRACKETS) or ""
-	local itemKey = IIfA:GetItemKey(itemLink, nil, nil)		-- yes, the nil's can be left off, but this way we know it's supposed to take 3 args)
-	if nil ~= itemLink and #itemLink == 0 and IIfA.BagSlotInfo[bagId] ~= nil and IIfA.BagSlotInfo[bagId][slotId] then
+	local itemLink = GetItemLink(bagId, slotId, LINK_STYLE_BRACKETS)
+	if not itemLink then itemLink = IIfA.EMPTY_STRING end
+	local itemKey = IIfA:GetItemKey(itemLink, nil)		-- yes, the nil can be left off, but this way we know it's supposed to take a 2nd arg)
+	if not itemKey then itemKey = IIfA.EMPTY_STRING end
+	if #itemLink == 0 and IIfA.BagSlotInfo[bagId] ~= nil and IIfA.BagSlotInfo[bagId][slotId] then
 		itemKey = IIfA.BagSlotInfo[bagId][slotId]
-		if nil ~= itemKey and nil ~= itemLink and nil ~= IIfA.database and #itemLink < 10 then
+		if #itemKey < 10 and IIfA.database[itemKey] then
 			itemLink = IIfA.database[itemKey].itemLink
+		elseif #itemKey >= 10 then
+			itemLink = itemKey
 		end
-	elseif nil ~= itemLink and #itemLink > 0 and IIfA.BagSlotInfo[bagId] == nil then
+--IIfA:DebugOut("no itemlink, lookup found key=<<1>>, link=<<2>>", itemKey, itemLink)
+	elseif #itemLink > 0 and IIfA.BagSlotInfo[bagId] == nil then
 		IIfA.BagSlotInfo[bagId] = {}
 		IIfA.BagSlotInfo[bagId][slotId] = itemKey
-	elseif nil ~= itemLink and #itemLink > 0 and IIfA.BagSlotInfo[bagId][slotId] == nil then
+--IIfA:DebugOut("New bag, new slot, bag=<<1>, slot=<<2>, key=<<3>>, link=<<4>>", bagId, slotId, itemKey, itemLink)
+	elseif #itemLink > 0 and IIfA.BagSlotInfo[bagId][slotId] == nil then
 		IIfA.BagSlotInfo[bagId][slotId] = itemKey
+--IIfA:DebugOut("Existing bag, new slot=<<1>>, key=<<2>>, link=<<3>>", slotId, itemKey, itemLink)
 	end

 	IIfA:DebugOut("Inv Slot Upd <<1>> - bag/slot <<2>>/<<3>> x<<4>>, new: <<6>>",
-		itemLink, bagId, slotId, qty, inventoryUpdateReason, isNewItem)
+		itemLink, bagId, slotId, qty, inventoryUpdateReason, sNewItem)

 	-- (bagId, slotNum, fromXfer, itemCount, itemLink, itemName, locationID)
-	local dbItem, itemKey = self:EvalBagItem(bagId, slotId, not isNewItem, qty, itemLink)
+	local dbItem, itemKey = self:EvalBagItem(bagId, slotId, not bNewItem, qty, itemLink)
+

 	-- once a bunch of items comes in, this will be created for each, but only the last one stays alive
 	-- so once all the items are finished coming in, it'll only need to update the shown list one time
@@ -62,7 +71,6 @@ function IIfA:InventorySlotUpdate(eventCode, bagId, slotId, isNewItem, itemSound
     	EVENT_MANAGER:RegisterForUpdate(callbackName, 250, Update)
 	end
 end
--- |H1:item:16424:4:1:0:0:0:0:0:0:0:0:0:0:0:0:7:0:0:0:0:0|h|h

 local function IIfA_InventorySlotUpdate(...)
 	IIfA:InventorySlotUpdate(...)
@@ -96,7 +104,7 @@ end
 local function IIfA_EventDump(...)
 	--d(...)
 	local l = {...}
-	local s = ""
+	local s = IIfA.EMPTY_STRING
 	for name, data in pairs(l) do
 		if type(data) ~= "table" then
 			s = s .. name .. " = " .. tostring(data) .. "\r\n"
@@ -128,11 +136,11 @@ local function finv3(...)
 	IIfA_EventDump(...)
 end
 local function fgb1(...)
-	d("gb open error")
+	d("gb item add")
 	IIfA_EventDump(...)
 end
 local function fgb2(...)
-	d("gb updated qty")
+	d("gb item remove")
 	IIfA_EventDump(...)
 end
 local function fgb3(...)
@@ -170,7 +178,7 @@ function IIfA:RegisterForEvents()


 	-- Events for data collection
-	em:RegisterForEvent("IIFA_ALPUSH", 		EVENT_ACTION_LAYER_PUSHED, 	function() IIfA:ActionLayerInventoryUpdate() end)
+--	em:RegisterForEvent("IIFA_ALPUSH", 		EVENT_ACTION_LAYER_PUSHED, 	function() IIfA:ActionLayerInventoryUpdate() end)
 	em:RegisterForEvent("IIFA_BANK_OPEN",	EVENT_OPEN_BANK, 			function() IIfA:ScanBank() end)

 	-- on opening guild bank:
diff --git a/IIfA/IIfASceneFuncs.lua b/IIfA/IIfASceneFuncs.lua
index 3fcec53..54e8560 100644
--- a/IIfA/IIfASceneFuncs.lua
+++ b/IIfA/IIfASceneFuncs.lua
@@ -2,7 +2,7 @@


 function IIfA:GetCurrentSceneName()
-	local ret = ""
+	local ret = IIfA.EMPTY_STRING

 	-- [16:20] scene name: 65553, hidden: false
 	if not SCENE_MANAGER or not SCENE_MANAGER:GetCurrentScene() then
diff --git a/IIfA/IIfASettingsAdapter.lua b/IIfA/IIfASettingsAdapter.lua
index 20d525c..bdd59e9 100644
--- a/IIfA/IIfASettingsAdapter.lua
+++ b/IIfA/IIfASettingsAdapter.lua
@@ -88,7 +88,7 @@ end


 function IIfA:SetInventoryListFilter(value)
-	if not value or value == "" then value = "All" end
+	if not value or value == IIfA.EMPTY_STRING then value = "All" end
 	IIfA.InventoryListFilter = value

 	IIfA.searchFilter = IIFA_GUI_SearchBox:GetText()
diff --git a/IIfA/IIfATooltip.lua b/IIfA/IIfATooltip.lua
index a9c4552..03db0e9 100644
--- a/IIfA/IIfATooltip.lua
+++ b/IIfA/IIfATooltip.lua
@@ -27,7 +27,7 @@ function IIfA:CreateTooltips()
 end

 function IIfA:SetTooltipFont(font)
-	if not font or font == "" then font = "ZoFontGameMedium" end
+	if not font or font == IIfA.EMPTY_STRING then font = "ZoFontGameMedium" end
 --	d("SetTooltipFont called with " .. tostring(font))
 	IIfA:GetSettings().in2TooltipsFont = font
 --	IIFA_ITEM_TOOLTIP:GetNamedChild("_Label"):SetFont(font)
@@ -39,7 +39,7 @@ local function getTex(name)
 end

 IIfA.racialTextures = {
-	[0]		= { styleName = "", styleTexture = ""},
+	[0]		= { styleName = IIfA.EMPTY_STRING, styleTexture = IIfA.EMPTY_STRING},
 	[1]		= { styleName = zo_strformat("<<1>>", GetItemStyleName(1)), styleTexture = getTex("breton")}, 				-- Breton
 	[2]		= { styleName = zo_strformat("<<1>>", GetItemStyleName(2)), styleTexture = getTex("redguard")}, 			-- Redguard
 	[3]		= { styleName = zo_strformat("<<1>>", GetItemStyleName(3)), styleTexture = getTex("orsimer")}, 				-- Orc
@@ -102,23 +102,23 @@ IIfA.racialTextures = {
 	[60] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(60)), styleTexture = getTex("clockwork")}, 			-- Clockwork
 	[61] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(61)), styleTexture = getTex("bloodforge")}, 			-- Bloodforge
 	[62] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(62)), styleTexture = getTex("dreadhorn")}, 			-- Dreadhorn / Falkreath
-	[63] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(63)), styleTexture = getTex("")}, 					-- Unused
-	[64] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(64)), styleTexture = getTex("")},					-- Unused
+	[63] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(63)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[64] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(64)), styleTexture = getTex(IIfA.EMPTY_STRING)},					-- Unused
 	[65] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(65)), styleTexture = getTex("apostle")},				-- Apostle
 	[66] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(66)), styleTexture = getTex("ebonshadow")},			-- Ebonshadow
-	[67] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(67)), styleTexture = getTex("")}, 					-- Unused
-	[68] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(68)), styleTexture = getTex("")}, 					-- Unused
-	[69] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(69)), styleTexture = getTex("")}, 					-- Unused
-	[70] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(70)), styleTexture = getTex("")}, 					-- Unused
-	[71] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(71)), styleTexture = getTex("")}, 					-- Unused
-	[72] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(72)), styleTexture = getTex("")}, 					-- Unused
-	[73] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(73)), styleTexture = getTex("")}, 					-- Unused
-	[74] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(74)), styleTexture = getTex("")}, 					-- Unused
-	[75] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(75)), styleTexture = getTex("")}, 					-- Unused
-	[76] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(76)), styleTexture = getTex("")}, 					-- Unused
-	[77] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(77)), styleTexture = getTex("")}, 					-- Unused
-	[78] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(78)), styleTexture = getTex("")}, 					-- Unused
-	[79] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(79)), styleTexture = getTex("")}, 					-- Unused
+	[67] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(67)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[68] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(68)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[69] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(69)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[70] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(70)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[71] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(71)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[72] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(72)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[73] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(73)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[74] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(74)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[75] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(75)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[76] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(76)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[77] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(77)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[78] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(78)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
+	[79] 	= { styleName = zo_strformat("<<1>>", GetItemStyleName(79)), styleTexture = getTex(IIfA.EMPTY_STRING)}, 					-- Unused
 }

 -- check on icons Hlaalu, Redoran and Morag Tong not loading properly
@@ -130,7 +130,7 @@ IIfA.itemEquipTypeTextures = {
 	[EQUIP_TYPE_FEET]  =   "/esoui/art/inventory/inventory_tabicon_armor_up.dds",
 	[EQUIP_TYPE_HAND]  =   "/esoui/art/inventory/inventory_tabicon_armor_up.dds",
 	[EQUIP_TYPE_HEAD]  =   "/esoui/art/inventory/inventory_tabicon_armor_up.dds",
-	[EQUIP_TYPE_INVALID]  =   "",
+	[EQUIP_TYPE_INVALID]  =   IIfA.EMPTY_STRING,
 	[EQUIP_TYPE_LEGS]  =   "/esoui/art/inventory/inventory_tabicon_armor_up.dds",
 	[EQUIP_TYPE_MAIN_HAND]  =   "/esoui/art/inventory/inventory_tabicon_weapons_up.dds",
 	[EQUIP_TYPE_NECK]  =   "/esoui/art/inventory/inventory_tabicon_armor_up.dds",
@@ -254,7 +254,7 @@ end

 function IIfA:GetEquippedItemLink(mouseOverControl)
 	local fullSlotName = mouseOverControl:GetName()
-	local slotName = string.gsub(fullSlotName, "ZO_CharacterEquipmentSlots", "")
+	local slotName = string.gsub(fullSlotName, "ZO_CharacterEquipmentSlots", IIfA.EMPTY_STRING)
 	local index = 0

 	if 		(slotName == "Head")		then index = 0
@@ -420,15 +420,15 @@ function IIfA:UpdateTooltip(tooltip)
 	local queryResults = IIfA:QueryAccountInventory(itemLink)
 	local itemStyleTexArray = getStyleIntel(itemLink)

-	if not itemStyleTexArray then itemStyleTexArray = {["styleTexture"] = "", ["styleName"] = ""} end
-	if itemStyleTexArray.styleName == nil then itemStyleTexArray = {["styleTexture"] = "", ["styleName"] = ""} end
+	if not itemStyleTexArray then itemStyleTexArray = {["styleTexture"] = IIfA.EMPTY_STRING, ["styleName"] = IIfA.EMPTY_STRING} end
+	if itemStyleTexArray.styleName == nil then itemStyleTexArray = {["styleTexture"] = IIfA.EMPTY_STRING, ["styleName"] = IIfA.EMPTY_STRING} end

 	if IIfA:GetSettings().bInSeparateFrame then
 		local parentTooltip = nil
 		if tooltip == IIFA_POPUP_TOOLTIP then parentTooltip = PopupTooltip end
 		if tooltip == IIFA_ITEM_TOOLTIP then parentTooltip = ItemTooltip end

-		if (not itemLink) or ((#queryResults.locations == 0) and (itemStyleTexArray.styleName == "")) then
+		if (not itemLink) or ((#queryResults.locations == 0) and (itemStyleTexArray.styleName == IIfA.EMPTY_STRING)) then
 			tooltip:SetHidden(true)
 			return
 		end
@@ -439,14 +439,14 @@ function IIfA:UpdateTooltip(tooltip)

 		tooltip:SetWidth(parentTooltip:GetWidth())

-		if itemStyleTexArray.styleName ~= "" then
+		if itemStyleTexArray.styleName ~= IIfA.EMPTY_STRING then
 			tooltip:AddLine(" ");
 		end

 		if(queryResults) then
 			if #queryResults.locations > 0 then
 				IIfA:DebugOut(queryResults)
-				if itemStyleTexArray.styleName ~= "" then
+				if itemStyleTexArray.styleName ~= IIfA.EMPTY_STRING then
 					ZO_Tooltip_AddDivider(tooltip)
 				end
 				for x, location in pairs(queryResults.locations) do
@@ -475,17 +475,17 @@ function IIfA:UpdateTooltip(tooltip)
 		styleIcon:SetTexture(itemStyleTexArray.styleTexture)
 		styleLabel:SetText(itemStyleTexArray.styleName)

-		styleLabel:SetHidden(itemStyleTexArray.styleName == "")
-		styleIcon:SetHidden(itemStyleTexArray.styleName == "")
+		styleLabel:SetHidden(itemStyleTexArray.styleName == IIfA.EMPTY_STRING)
+		styleIcon:SetHidden(itemStyleTexArray.styleName == IIfA.EMPTY_STRING)
 		IIfA:AnchorFrame(tooltip, parentTooltip)
 	else
-		if (not itemLink) or ((#queryResults.locations == 0) and (itemStyleTexArray.styleName == "")) then
+		if (not itemLink) or ((#queryResults.locations == 0) and (itemStyleTexArray.styleName == IIfA.EMPTY_STRING)) then
 			IIfA_HideTooltip(tooltip)
 			return
 		end

 		local bHasStyle
-		bHasStyle = not (itemStyleTexArray.styleName == nil or itemStyleTexArray.styleName == "")
+		bHasStyle = not (itemStyleTexArray.styleName == nil or itemStyleTexArray.styleName == IIfA.EMPTY_STRING)

 		-- only add/show the style info if it's got style
 		if bHasStyle then
diff --git a/IIfA/IIfA_Preload.lua b/IIfA/IIfA_Preload.lua
index 6d5d980..c10faec 100644
--- a/IIfA/IIfA_Preload.lua
+++ b/IIfA/IIfA_Preload.lua
@@ -1,7 +1,4 @@
- --this creates a menu for the addon.
-
--- IIfA doesn't exist at the point when this module is loaded, so this is useless
--- local IIfA = IIfA
+ --this creates static strings

 local strings = {
 	IIFA_BAG_BAGPACK 	= "Inventory",
@@ -9,7 +6,6 @@ local strings = {
 	IIFA_BAG_CRAFTBAG 	= "CraftBag",
 }

-
 for stringId, stringValue in pairs(strings) do
 	ZO_CreateStringId(stringId, stringValue)
 	SafeAddVersion(stringId, 1)
diff --git a/IIfA/IIfA_xml_adapter.lua b/IIfA/IIfA_xml_adapter.lua
index e76d28a..7c0f2f8 100644
--- a/IIfA/IIfA_xml_adapter.lua
+++ b/IIfA/IIfA_xml_adapter.lua
@@ -180,7 +180,7 @@ function IIfA:GuiOnFilterButton(control, mouseButton, filterGroup, filterTypes,
 			return IIfA:GuiOnFilterButton(IIFA_GUI_Header_Filter:GetChild(1), MOUSE_BUTTON_INDEX_LEFT, "All", nil)
 		else
 			IIfA.LastSubFilterControl = control
-			local parentIdx = control:GetParent():GetName():gsub("IIFA_GUI_Header_Subfilter_", "")
+			local parentIdx = control:GetParent():GetName():gsub("IIFA_GUI_Header_Subfilter_", IIfA.EMPTY_STRING)
 			local parentControl = IIFA_GUI_Header_Filter:GetChild(parentIdx+1)
 			return IIfA:GuiOnFilterButton(parentControl, MOUSE_BUTTON_INDEX_LEFT, parentControl.filterText)
 		end
@@ -197,7 +197,7 @@ function IIfA:GuiOnFilterButton(control, mouseButton, filterGroup, filterTypes,
 		   IIfA.LastSubFilterControl:GetParent():SetHidden(true)
 		end
 		if filterGroup ~= "All" then
-			IIfA.LastSubFilterControl = IIFA_GUI_Header:GetNamedChild(control:GetName():gsub("IIFA_GUI_Header", ""):gsub("Filter_Button", "Subfilter_") .. "_Button0")
+			IIfA.LastSubFilterControl = IIFA_GUI_Header:GetNamedChild(control:GetName():gsub("IIFA_GUI_Header", IIfA.EMPTY_STRING):gsub("Filter_Button", "Subfilter_") .. "_Button0")
 			IIfA.LastSubFilterControl:SetState(BSTATE_PRESSED)
 		else
 			IIfA.LastSubFilterControl = nil
@@ -265,7 +265,7 @@ function IIfA:GuiOnFilterButton(control, mouseButton, filterGroup, filterTypes,
 		IIFA_GUI_Header_SortBar_Subfilter_Dropdown:SetHidden(true)
 	end

-
+
 	IIfA:GuiResizeScroll()

 	IIfA:RefreshInventoryScroll()
@@ -275,30 +275,30 @@ end
 -- IIFA_GUI_SearchBoxText is the "Filter by text search" text msg
 function IIfA:GuiOnSearchboxText(control)
 	local text = control:GetText()
-	IIFA_GUI_SearchBoxText:SetHidden(text ~= nil and text > "")
+	IIFA_GUI_SearchBoxText:SetHidden(text ~= nil and text > IIfA.EMPTY_STRING)
 	IIfA.searchFilter = zo_strlower(text)
     IIfA:RefreshInventoryScroll()
 end

 function IIfA:GuiOnSearchBoxClear(control)
-	IIFA_GUI_SearchBox:SetText("")
+	IIFA_GUI_SearchBox:SetText(IIfA.EMPTY_STRING)
 	IIFA_GUI_SearchBoxText:SetHidden(false)
-	IIfA.searchFilter = ""
+	IIfA.searchFilter = IIfA.EMPTY_STRING
     IIfA:RefreshInventoryScroll()
 end



-	-- We're inverting search order if same header is clicked twice.
+	-- We're inverting search order if same header is clicked twice.
 IIfA.bSortQuality = false
 -- IIFA_GUI_ListHolder sort
-function IIfA:GuiOnSort(sortQuality)
-
+function IIfA:GuiOnSort(sortQuality)
+
 	if (IIfA.bSortQuality == sortQuality) then
 		IIfA.ScrollSortUp = not IIfA.ScrollSortUp
 	end
 	IIfA.bSortQuality = sortQuality
-
+
 	local icon = IIFA_GUI_Header_SortBar.Icon

 	if (IIfA.ScrollSortUp) then
@@ -343,7 +343,7 @@ end
 function IIfA:GuiLineOnMouseEnter(lineControl)
 	if not lineControl then return end

-	if( lineControl.itemLink ~= nil and lineControl.itemLink ~= "") then
+	if( lineControl.itemLink ~= nil and lineControl.itemLink ~= IIfA.EMPTY_STRING) then
 		IIfA.TooltipLink = lineControl.itemLink
 		InitializeTooltip(ItemTooltip, lineControl, LEFT, 0, 0, 0)
 		ItemTooltip:SetLink(lineControl.itemLink)
@@ -414,8 +414,8 @@ function IIfA:GuiReloadDimensions(settings, sceneName)
 end

 function IIfA:GuiResizeLines()
-	local lines
-
+	local lines
+
 	if not IIFA_GUI_ListHolder.lines then
 		lines = IIfA:CreateInventoryScroll()
 	end