added movable experience bar in gamepad mode

Kith [02-19-16 - 04:19]
added movable experience bar in gamepad mode

added new feature, Bag Watcher for monitoring bag contents

fixed bug with non-standard fonts being used on overlays not loading if
the addon that provided that font was loaded after Azurah

deleted unused files (forgot to remove LAM-fontblock in last commit)
Filename
ActionBar.lua
Azurah.lua
Azurah.txt
Azurah.xml
BagWatcher.lua
Bossbar.lua
Core.lua
Defaults.lua
ExperienceBar.lua
Lib/LAM-fontblock.lua
Locales/Local_en.lua
Locales/Local_fr.lua
Player.lua
Settings.lua
Target.lua
Unlock.lua
diff --git a/ActionBar.lua b/ActionBar.lua
index 2d9cf68..03d70a2 100644
--- a/ActionBar.lua
+++ b/ActionBar.lua
@@ -112,6 +112,5 @@ function Azurah:InitializeActionBar()
 	-- Fix for scaling issue
 	ActionButton8Decoration:SetAnchor(CENTER, ActionButton8, CENTER, 0, 0)

-	self:ConfigureUltimateOverlays()
 	self:ConfigureActionBarElements()
 end
diff --git a/Azurah.lua b/Azurah.lua
deleted file mode 100644
index eb94fe1..0000000
--- a/Azurah.lua
+++ /dev/null
@@ -1,245 +0,0 @@
---[[----------------------------------------------------------
-	Azurah - Interface Enhanced
-	----------------------------------------------------------
-	* An addon designed to allow for user customization of the
-	* stock interface with optional components to provide
-	* additional information while maintaining the stock feel.
-	*
-	* Version 2.11d
-	* Kithayri
-	*
-	* (updated by Garkin, Phinix, Sounomi)
-]]--
-local Azurah = _G['Azurah'] -- grab addon table from global
-local L = Azurah:GetLocale()
-
-Azurah.name			= 'Azurah'
-Azurah.slash		= '/azurah'
-Azurah.version		= '2.11d'
-Azurah.versionDB	= 2
-Azurah.loaded		= false
-
-Azurah.movers		= {}
-Azurah.snapToGrid	= true
-Azurah.uiUnlocked	= false
-
-local defaults = {
-	uiData						= {},
-	compassPinScale				= 1.0,
-	compassHidePinLabel			= false,
-
-	attributes = {
-		fadeMinAlpha			= 0,	-- when full
-		fadeMaxAlpha			= 1,	-- when not full
-		combatBars				= true,
-		lockSize				= false,
-		-- overlays
-		healthOverlay			= 2,
-		healthOverlayFancy		= false,
-		healthFontFace			= 'Univers 67',
-		healthFontColour		= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		healthFontOutline		= 'soft-shadow-thick',
-		healthFontSize			= 16,
-		magickaOverlay			= 2,
-		magickaOverlayFancy		= false,
-		magickaFontFace			= 'Univers 67',
-		magickaFontColour		= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		magickaFontOutline		= 'soft-shadow-thick',
-		magickaFontSize			= 16,
-		staminaOverlay			= 2,
-		staminaOverlayFancy		= false,
-		staminaFontFace			= 'Univers 67',
-		staminaFontColour		= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		staminaFontOutline		= 'soft-shadow-thick',
-		staminaFontSize			= 16,
-	},
-	target = {
-		lockSize				= false,
-		colourByBar				= 2,
-		colourByName			= 1,
-		colourByLevel			= true,
-		classShow				= false,
-		classByName				= true,
-		allianceShow			= false,
-		allianceByName			= false,
-		-- overlay
-		overlay					= 2,
-		overlayFancy			= false,
-		fontFace				= 'Univers 67',
-		fontColour				= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		fontOutline				= 'soft-shadow-thick',
-		fontSize				= 16,
-	},
-	bossbar = {
-		overlay					= 2,
-		overlayFancy			= false,
-		fontFace				= 'Univers 67',
-		fontColour				= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		fontOutline				= 'soft-shadow-thick',
-		fontSize				= 16,
-	},
-	actionBar = {
-		hideBindBG				= false,
-		hideBindText			= false,
-		hideWeaponSwap			= false,
-		-- overlays
-		ultValueShow			= true,
-		ultValueFontFace		= 'Univers 67',
-		ultValueFontColour		= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		ultValueFontOutline		= 'soft-shadow-thick',
-		ultValueFontSize		= 16,
-		ultPercentShow			= true,
-		ultPercentFontFace		= 'Univers 67',
-		ultPercentFontColour	= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		ultPercentFontOutline	= 'soft-shadow-thick',
-		ultPercentFontSize		= 16,
-		ultPercentRelative		= false,
-	},
-	experienceBar = {
-		displayStyle			= 1,
-		-- overlay
-		overlay					= 2,
-		overlayFancy			= true,
-		fontFace				= 'Univers 67',
-		fontColour				= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
-		fontOutline				= 'soft-shadow-thick',
-		fontSize				= 18,
-	},
-}
-
-function Azurah.OnStateChanged(eventCode, eventBool)
-	local self = Azurah
-	self:ConfigureAttributeFade()
-end
-
-function Azurah.OnPreferedModeChanged(code, gamepadPrefered)
-	local self = Azurah
-
-	if self.uiUnlocked then
-		self:LockUI()
-	end
-
-	self:InitializeUnlock()
-	self:ConfigureTargetIcons()
-    self:ConfigureExperienceBarOverlay()
-end
-
-function Azurah.OnPlayerActivated()
-	EVENT_MANAGER:UnregisterForEvent(Azurah.name, EVENT_PLAYER_ACTIVATED)
-
-	Azurah:InitializeUnlock()
-end
-
-function Azurah.OnInitialize(code, addon)
-	if (addon ~= Azurah.name) then return end
-
-	local self = Azurah
-
-	EVENT_MANAGER:UnregisterForEvent(self.name, EVENT_ADD_ON_LOADED)
-	SLASH_COMMANDS[self.slash] = self.SlashCommand
-
-	self.db = ZO_SavedVars:New('AzurahDB', self.versionDB, nil, defaults)
-
-	self:InitializePlayer()
-	self:InitializeTarget()
-	self:InitializeBossbar()
-	self:InitializeActionBar()
-	self:InitializeExperienceBar()
-
-	self:InitializeSettings()
-end
-
-function Azurah.SlashCommand(text)
-	if (text == 'lock') then
-		Azurah:LockUI()
-	elseif (text == 'unlock') then
-		Azurah:UnlockUI()
-	else
-		CHAT_SYSTEM:AddMessage(Azurah:GetLocale().Usage)
-	end
-end
-
-EVENT_MANAGER:RegisterForEvent(Azurah.name, EVENT_ADD_ON_LOADED, Azurah.OnInitialize)
-EVENT_MANAGER:RegisterForEvent(Azurah.name, EVENT_PLAYER_ACTIVATED, Azurah.OnPlayerActivated)
-EVENT_MANAGER:RegisterForEvent(Azurah.name, EVENT_GAMEPAD_PREFERRED_MODE_CHANGED, Azurah.OnPreferedModeChanged)
-EVENT_MANAGER:RegisterForEvent(Azurah.name, EVENT_PLAYER_COMBAT_STATE, Azurah.OnStateChanged)
-EVENT_MANAGER:RegisterForEvent(Azurah.name, EVENT_MOUNTED_STATE_CHANGED, Azurah.OnStateChanged)
-EVENT_MANAGER:RegisterForEvent(Azurah.name, EVENT_WEREWOLF_STATE_CHANGED, Azurah.OnStateChanged)
-
--- ----------------------------
--- OVERLAY BASE ---------------
--- ----------------------------
-
-local strformat		= string.format
-local strgsub		= string.gsub
-local captureStr	= '%1' .. L.ThousandsSeperator .. '%2'
-
-local k
-local function comma_value(amount)
-	while (true) do
-		amount, k = strgsub(amount, '^(-?%d+)(%d%d%d)', captureStr)
-
-		if (k == 0) then
-			break
-		end
-	end
-
-	return amount
-end
-
-Azurah.overlayFuncs = {
-	[1] = function(current, max, effMax)
-		return '' -- dummy, returns an empty string
-	end,
-	-- standard overlays
-	[2] = function(current, max, effMax)
-		effMax = effMax > 0 and effMax or 1 -- ensure we don't do a divide by 0
-		return strformat('%d / %d (%d%%)', current, effMax, (current / effMax) * 100)
-	end,
-	[3] = function(current, max, effMax)
-		return strformat('%d / %d', current, effMax)
-	end,
-	[4] = function(current, max, effMax)
-		effMax = effMax > 0 and effMax or 1 -- ensure we don't do a divide by 0
-		return strformat('%d (%d%%)', current, (current / effMax) * 100)
-	end,
-	[5] = function(current, max, effMax)
-		return strformat('%d', current)
-	end,
-	[6] = function(current, max, effMax)
-		effMax = effMax > 0 and effMax or 1 -- ensure we don't do a divide by 0
-		return strformat('%d%%', (current / effMax) * 100)
-	end,
-	-- comma-seperated overlays
-	[12] = function(current, max, effMax)
-		effMax = effMax > 0 and effMax or 1 -- ensure we don't do a divide by 0
-		return strformat('%s / %s (%d%%)', comma_value(current), comma_value(effMax), (current / effMax) * 100)
-	end,
-	[13] = function(current, max, effMax)
-		return strformat('%s / %s', comma_value(current), comma_value(effMax))
-	end,
-	[14] = function(current, max, effMax)
-		effMax = effMax > 0 and effMax or 1 -- ensure we don't do a divide by 0
-		return strformat('%s (%d%%)', comma_value(current), (current / effMax) * 100)
-	end,
-	[15] = function(current, max, effMax)
-		return strformat('%s', comma_value(current))
-	end,
-	[16] = function(current, max, effMax)
-		effMax = effMax > 0 and effMax or 1 -- ensure we don't do a divide by 0
-		return strformat('%d%%', (current / effMax) * 100)
-	end
-}
-
-function Azurah:CreateOverlay(parent, rel, relPoint, x, y, width, height, vAlign, hAlign)
-	local o = WINDOW_MANAGER:CreateControl(nil, parent, CT_LABEL)
-	o:SetResizeToFitDescendents(true)
-	o:SetInheritScale(false)
-	o:SetDrawTier(DT_HIGH)
-	o:SetDrawLayer(DL_OVERLAY)
-	o:SetAnchor(rel, parent, relPoint, x, y)
-	o:SetHorizontalAlignment(hAlign or TEXT_ALIGN_CENTER)
-	o:SetVerticalAlignment(vAlign or TEXT_ALIGN_CENTER)
-
-	return o
-end
diff --git a/Azurah.txt b/Azurah.txt
index ed38f8b..36d0bbb 100644
--- a/Azurah.txt
+++ b/Azurah.txt
@@ -40,6 +40,7 @@ Target.lua
 ActionBar.lua
 ExperienceBar.lua
 Bossbar.lua
+BagWatcher.lua

 Settings.lua

diff --git a/Azurah.xml b/Azurah.xml
index 972189c..95e3106 100644
--- a/Azurah.xml
+++ b/Azurah.xml
@@ -2,5 +2,9 @@
 	<Controls>
 		<TopLevelControl name="Azurah" />
 		<TopLevelControl name="Azurah_Mover" virtual="true" />
+		<TopLevelControl name="Azurah_BagWatcher" clampedToScreen="true" hidden="true">
+			<Dimensions x="375" y="56" />
+			<Anchor point="TOPRIGHT" relativeTo="GuiRoot" relativePoint="TOPRIGHT" offsetX="-15" offsetY="10" />
+		</TopLevelControl>
 	</Controls>
 </GuiXml>
diff --git a/BagWatcher.lua b/BagWatcher.lua
new file mode 100644
index 0000000..3f1da94
--- /dev/null
+++ b/BagWatcher.lua
@@ -0,0 +1,246 @@
+local Azurah		= _G['Azurah']				-- grab addon table from global
+local Watcher		= _G['Azurah_BagWatcher']	-- grab bag watcher control
+local WatcherScene	= ZO_HUDFadeSceneFragment:New(Watcher, 0, 0)
+local LMP			= LibStub('LibMediaProvider-1.0')
+
+-- UPVALUES --
+local BAG_BACKPACK			= BAG_BACKPACK
+local SmoothTransition		= ZO_StatusBar_SmoothTransition
+local GetNumBagUsedSlots	= GetNumBagUsedSlots
+local GetBagSize			= GetBagSize
+
+local VISIBLE_TIME_HOLD		= 2500
+local VISIBLE_TIME_FADE_OUT	= 400
+local BAR_WIDTH				= 315
+
+local FormatOverlay
+local db
+local bagMax, bagCurrent, bagNew = 0, 0, 0
+local firstLoad				= true
+
+
+local function ShowWatcher()
+	Watcher:SetAlpha(1) -- make sure watcher is fully visible
+
+	if (db.lowSpaceLock and (bagMax - bagCurrent) <= db.lowSpaceTrigger) then -- low space triggered, we should stay visible
+		if (Watcher.fader:IsPlaying()) then
+			Watcher.fader:Stop() -- stop fader anim if playing
+		end
+	else -- not in low space or not locking on low space, start (or restart) fader
+		Watcher.fader:PlayFromStart()
+	end
+end
+
+
+-- ------------------------
+-- EVENT HANDLERS
+-- ------------------------
+local function OnBagSizeChanged(code, prevSize, currentSize)
+	if (prevSize == currentSize) then return end -- just make sure they aren't the same
+
+	bagMax		= currentSize -- set new backpack size
+	bagCurrent	= GetNumBagUsedSlots(BAG_BACKPACK)
+
+	Watcher.bar:SetMinMax(0, bagMax)
+	Watcher.bar.gloss:SetMinMax(0, bagMax)
+
+	ShowWatcher()
+
+	SmoothTransition(Watcher.bar, bagCurrent, bagMax, false, false, 0.05)
+	Watcher.overlay:SetText(FormatOverlay(bagCurrent, nil, bagMax))
+end
+
+local function OnBagUpdate(code, bagID)
+	if (bagID ~= BAG_BACKPACK) then return end -- we only care about the backpack
+
+	bagNew = GetNumBagUsedSlots(BAG_BACKPACK)
+
+	if (bagNew == bagCurrent) then return end -- available slots didn't actually change
+
+	bagCurrent = bagNew -- available slots have changed, proceed
+
+	ShowWatcher()
+
+	SmoothTransition(Watcher.bar, bagCurrent, bagMax, false, false, 0.05)
+	Watcher.overlay:SetText(FormatOverlay(bagCurrent, nil, bagMax))
+end
+
+local function SceneOnShown()
+	if (Watcher.fader:IsPlaying()) then
+		Watcher.fader:Stop() -- stop fader anim if playing
+	end
+
+	if (db.lowSpaceLock and (bagMax - bagCurrent) <= db.lowSpaceTrigger) then -- low space triggered, we should stay visible
+		Watcher:SetAlpha(1) -- make sure we're fully visible
+	else -- shouldnt' be visible right now
+		Watcher:SetAlpha(0)
+	end
+
+end
+
+
+-- ------------------------
+-- CONSTRUCTION
+-- ------------------------
+local function AddControl(parent, cType, level)
+	local c = WINDOW_MANAGER:CreateControl(nil, parent, cType)
+	c:SetDrawLayer(DL_CONTROLS)
+	c:SetDrawLevel(level)
+	return c, c
+end
+
+local function BuildWatcher()
+	local ctrl
+	-- ICON
+	Watcher.icon, ctrl = AddControl(Watcher, CT_TEXTURE, 3)
+	ctrl:SetDimensions(56, 56)
+	ctrl:SetAnchor(CENTER)
+	ctrl:SetTexture([[esoui/art/mainmenu/menuBar_inventory_up.dds]])
+	ctrl:SetTextureCoords(0.0625, 0.9375, 0.0625, 0.9375)
+	-- BAR
+	Watcher.bar, ctrl = AddControl(Watcher, CT_STATUSBAR, 2)
+	ctrl:SetDimensions(BAR_WIDTH, 20)
+	ctrl:SetTexture([[/esoui/art/miscellaneous/progressbar_genericfill.dds]])
+	ctrl:SetTextureCoords(0, 1, 0, 0.625)
+	ZO_StatusBar_SetGradientColor(ctrl, ZO_XP_BAR_GRADIENT_COLORS)
+	ctrl:SetLeadingEdge([[/esoui/art/miscellaneous/progressbar_genericfill_leadingedge.dds]], 8, 32)
+	ctrl:SetLeadingEdgeTextureCoords(0, 1, 0, 0.625)
+	ctrl:EnableLeadingEdge(true)
+	ctrl:SetMinMax(0, 1)
+	ctrl:SetHandler('OnValueChanged', function(bar, value) bar.gloss:SetValue(value) end) -- change gloss value as main bar changes
+	-- BAR GLOSS
+	Watcher.bar.gloss, ctrl = AddControl(Watcher.bar, CT_STATUSBAR, 3)
+	ctrl:SetDimensions(BAR_WIDTH, 20)
+	ctrl:SetAnchor(TOPLEFT)
+	ctrl:SetTexture([[/esoui/art/miscellaneous/progressbar_genericfill_gloss.dds]])
+	ctrl:SetTextureCoords(0, 1, 0, 0.625)
+	ctrl:SetLeadingEdge([[/esoui/art/miscellaneous/progressbar_genericfill_leadingedge_gloss.dds]], 8, 32)
+	ctrl:SetLeadingEdgeTextureCoords(0, 1, 0, 0.625)
+	ctrl:EnableLeadingEdge(true)
+	ctrl:SetMinMax(0, 1)
+	-- BAR FRAME
+	Watcher.bar.borderL, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 4)
+	ctrl:SetDimensions(10, 20)
+	ctrl:SetAnchor(TOPLEFT)
+	ctrl:SetTexture([[/esoui/art/miscellaneous/progressbar_frame.dds]])
+	Watcher.bar.borderR, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 4)
+	ctrl:SetDimensions(10, 20)
+	ctrl:SetAnchor(TOPRIGHT)
+	ctrl:SetTexture([[/esoui/art/miscellaneous/progressbar_frame.dds]])
+	Watcher.bar.borderM, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 4)
+	ctrl:SetDimensions(BAR_WIDTH - 20, 20)
+	ctrl:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, 10, 0)
+	ctrl:SetTexture([[/esoui/art/miscellaneous/progressbar_frame.dds]])
+	ctrl:SetTextureCoords(0.019500000402331, 0.58980000019073, 0, 0.625)
+	-- BAR BACKDROP
+	Watcher.bar.backdropEnd, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 1)
+	ctrl:SetDimensions(10, 20)
+	ctrl:SetTexture([[/esoui/art/miscellaneous/progressbar_genericfill_leadingedge.dds]])
+	ctrl:SetColor(0,0,0,0.4)
+	Watcher.bar.backdrop, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 1)
+	ctrl:SetDimensions(BAR_WIDTH - 10, 20)
+	ctrl:SetTexture('')
+	ctrl:SetColor(0,0,0,0.4)
+	-- OVERLAY
+	Watcher.overlay = Azurah:CreateOverlay(Watcher, CENTER, CENTER, 0, 0, nil, nil, nil, TEXT_ALIGN_LEFT) -- will be reanchored later by configure
+	-- ANIMATION TIMELINE
+	ctrl = ANIMATION_MANAGER:CreateTimeline()
+	ctrl:SetPlaybackType(ANIMATION_PLAYBACK_ONE_SHOT)
+	Watcher.fader = ctrl
+	ctrl = Watcher.fader:InsertAnimation(ANIMATION_ALPHA, Watcher, VISIBLE_TIME_HOLD)
+	ctrl:SetDuration(VISIBLE_TIME_FADE_OUT)
+	ctrl:SetEasingFunction(ZO_LinearEase)
+	ctrl:SetAlphaValues(1, 0)
+
+	HUD_SCENE:AddFragment(WatcherScene)
+	HUD_UI_SCENE:AddFragment(WatcherScene)
+	LOOT_SCENE:AddFragment(WatcherScene)
+
+	WatcherScene:SetConditional(function() return Azurah.db.bagWatcher.enabled end)
+	WatcherScene.OnShown = SceneOnShown
+end
+
+
+-- ------------------------
+-- CONFIGURATION
+-- ------------------------
+function Azurah:ConfigureBagWatcher(onLoad)
+	if (not db.enabled) then -- not using bag watcher
+		-- unregister watcher events
+		EVENT_MANAGER:UnregisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_SINGLE_SLOT_UPDATE)
+		EVENT_MANAGER:UnregisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_BAG_CAPACITY_CHANGED)
+	else -- using bag watcher
+		if (not Watcher.bar) then -- need to build the watcher gui
+			BuildWatcher()
+		end
+
+		-- configure bag watcher appearance
+		Watcher.overlay:SetFont(string.format('%s|%d|%s', LMP:Fetch('font', db.fontFace), db.fontSize, db.fontOutline))
+		Watcher.overlay:SetColor(db.fontColour.r, db.fontColour.g, db.fontColour.b, db.fontColour.a)
+		Watcher.overlay:ClearAnchors()
+
+		Watcher.bar:ClearAnchors()
+		Watcher.bar.backdrop:ClearAnchors()
+		Watcher.bar.backdropEnd:ClearAnchors()
+		Watcher.icon:ClearAnchors()
+
+		if (db.reverseAlignment) then
+			Watcher.bar.backdrop:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 0, 0)
+			Watcher.bar.backdropEnd:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, 0, 0)
+			Watcher.bar:SetBarAlignment(BAR_ALIGNMENT_REVERSE)
+			Watcher.bar.gloss:SetBarAlignment(BAR_ALIGNMENT_REVERSE)
+			Watcher.bar.borderL:SetTextureCoords(0.6133000254631, 0.59380000829697, 0, 0.625)
+			Watcher.bar.borderR:SetTextureCoords(0.019500000402331, 0, 0, 0.625)
+			Watcher.bar.backdropEnd:SetTextureCoords(1, 0, 0, 0.625)
+
+			Watcher.icon:SetAnchor(TOPRIGHT, Watcher, TOPRIGHT, 10, 7)
+			Watcher.bar:SetAnchor(BOTTOMRIGHT, Watcher.icon, BOTTOMLEFT, 7, -8)
+			Watcher.overlay:SetAnchor(BOTTOMRIGHT, Watcher.bar, TOPRIGHT, -4, -2)
+		else
+			Watcher.bar.backdrop:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, 0, 0)
+			Watcher.bar.backdropEnd:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 0, 0)
+			Watcher.bar:SetBarAlignment(BAR_ALIGNMENT_NORMAL)
+			Watcher.bar.gloss:SetBarAlignment(BAR_ALIGNMENT_NORMAL)
+			Watcher.bar.borderL:SetTextureCoords(0, 0.019500000402331, 0, 0.625)
+			Watcher.bar.borderR:SetTextureCoords(0.59380000829697, 0.6133000254631, 0, 0.625)
+			Watcher.bar.backdropEnd:SetTextureCoords(0, 1, 0, 0.625)
+
+			Watcher.icon:SetAnchor(TOPLEFT, Watcher, TOPLEFT, -10, 7)
+			Watcher.bar:SetAnchor(BOTTOMLEFT, Watcher.icon, BOTTOMRIGHT, -7, -8)
+			Watcher.overlay:SetAnchor(BOTTOMLEFT, Watcher.bar, TOPLEFT, 4, -2)
+		end
+
+		bagMax		= GetBagSize(BAG_BACKPACK)
+		bagCurrent	= GetNumBagUsedSlots(BAG_BACKPACK)
+
+		FormatOverlay = self.overlayFuncs[db.overlay]
+
+		Watcher.bar:SetMinMax(0, bagMax)
+		Watcher.bar.gloss:SetMinMax(0, bagMax)
+
+		EVENT_MANAGER:RegisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_SINGLE_SLOT_UPDATE,	OnBagUpdate)
+		EVENT_MANAGER:RegisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_BAG_CAPACITY_CHANGED,	OnBagSizeChanged)
+
+		if (firstLoad) then -- first load, fillup bar to current level nicely
+			firstLoad = false
+
+			Watcher.bar:SetValue(0)
+
+			ShowWatcher()
+
+			SmoothTransition(Watcher.bar, bagCurrent, bagMax, false, false, 0.05)
+		else
+			Watcher.bar:SetValue(bagCurrent)
+		end
+
+		Watcher.overlay:SetText(FormatOverlay(bagCurrent, nil, bagMax))
+	end
+end
+
+
+-- ------------------------
+-- INITIALIZATION
+-- ------------------------
+function Azurah:InitializeBagWatcher()
+	db = self.db.bagWatcher		-- local db reference
+end
diff --git a/Bossbar.lua b/Bossbar.lua
index 9f38d0d..c3cefbb 100644
--- a/Bossbar.lua
+++ b/Bossbar.lua
@@ -66,11 +66,11 @@ function Azurah:ConfigureBossbarOverlay()
 	if (not IsInGamepadPreferredMode() and db.overlay > 1) then -- showing overlay, enabled tracking
 		EVENT_MANAGER:RegisterForEvent(self.name .. 'Bossbar', EVENT_POWER_UPDATE,		OnPowerUpdate)
 		EVENT_MANAGER:RegisterForEvent(self.name .. 'Bossbar', EVENT_BOSSES_CHANGED,	RefreshAllBosses)
-		EVENT_MANAGER:RegisterForEvent(self.name .. 'Bossbar', EVENT_PLAYER_ACTIVATED,	RefreshAllBosses)
+--		EVENT_MANAGER:RegisterForEvent(self.name .. 'Bossbar', EVENT_PLAYER_ACTIVATED,	RefreshAllBosses)
 	else -- no overlay being shown, disable tracking
 		EVENT_MANAGER:UnregisterForEvent(self.name .. 'Bossbar', EVENT_POWER_UPDATE)
 		EVENT_MANAGER:UnregisterForEvent(self.name .. 'Bossbar', EVENT_BOSSES_CHANGED)
-		EVENT_MANAGER:UnregisterForEvent(self.name .. 'Bossbar', EVENT_PLAYER_ACTIVATED)
+--		EVENT_MANAGER:UnregisterForEvent(self.name .. 'Bossbar', EVENT_PLAYER_ACTIVATED)
 	end

 	local fontStr, value, max, maxEff
@@ -106,6 +106,4 @@ function Azurah:InitializeBossbar()
 	for i = 1, MAX_BOSSES do
 		bossUnitTags["boss"..i] = true
 	end
-
-	self:ConfigureBossbarOverlay()
 end
diff --git a/Core.lua b/Core.lua
index 093c175..24e3f06 100644
--- a/Core.lua
+++ b/Core.lua
@@ -36,11 +36,12 @@ function Azurah.OnInitialize(code, addon)

 	self.db = ZO_SavedVars:New('AzurahDB', self.versionDB, nil, self:GetDefaults())

-	self:InitializePlayer()
-	self:InitializeTarget()
-	self:InitializeBossbar()
-	self:InitializeActionBar()
-	self:InitializeExperienceBar()
+	self:InitializePlayer()					-- Player.lua
+	self:InitializeTarget()					-- Target.lua
+	self:InitializeBossbar()				-- Bossbar.lua
+	self:InitializeActionBar()				-- ActionBar.lua
+	self:InitializeExperienceBar()			-- ExperienceBar.lua
+	self:InitializeBagWatcher()				-- BagWatcher.lua

 	self:InitializeSettings()

@@ -55,6 +56,14 @@ function Azurah.OnPlayerActivated()
 	EVENT_MANAGER:UnregisterForEvent(Azurah.name, EVENT_PLAYER_ACTIVATED)

 	Azurah:InitializeUnlock()
+
+	-- done later in load to make sure fonts from other addons are available (if being used)
+	Azurah:ConfigureAttributeOverlays()		-- Player.lua
+	Azurah:ConfigureTargetOverlay()			-- Target.lua
+	Azurah:ConfigureBossbarOverlay()		-- Bossbar.lua
+	Azurah:ConfigureUltimateOverlays()		-- ActionBar.lua
+	Azurah:ConfigureExperienceBarOverlay()	-- ExperienceBar.lua
+	Azurah:ConfigureBagWatcher()			-- BagWatcher.lua
 end

 function Azurah.OnStateChanged()
diff --git a/Defaults.lua b/Defaults.lua
index 65fd7e5..683cd19 100644
--- a/Defaults.lua
+++ b/Defaults.lua
@@ -82,6 +82,18 @@ local defaults = {
 		fontOutline				= 'soft-shadow-thick',
 		fontSize				= 18,
 	},
+	bagWatcher = {
+		enabled 				= false,
+		reverseAlignment		= true,
+		lowSpaceLock			= true,
+		lowSpaceTrigger			= 10,
+		-- overlay
+		overlay					= 2,
+		fontFace				= 'Univers 67',
+		fontColour				= {r = 0.9, g = 0.9, b = 0.9, a = 1.0},
+		fontOutline				= 'soft-shadow-thick',
+		fontSize				= 18,
+	},
 }

 function Azurah:GetDefaults()
diff --git a/ExperienceBar.lua b/ExperienceBar.lua
index b542b14..6a6c37e 100644
--- a/ExperienceBar.lua
+++ b/ExperienceBar.lua
@@ -175,6 +175,5 @@ function Azurah:InitializeExperienceBar()
 	-- set 'dummy' display function
 	FormatExp = self.overlayFuncs[1]

-	self:ConfigureExperienceBarOverlay()
 	self:ConfigureExperienceBarDisplay()
 end
\ No newline at end of file
diff --git a/Lib/LAM-fontblock.lua b/Lib/LAM-fontblock.lua
deleted file mode 100644
index b74b157..0000000
--- a/Lib/LAM-fontblock.lua
+++ /dev/null
@@ -1,268 +0,0 @@
---[[widgetData = {
-	type = "fontblock",
-	name = "My Control",
-	tooltip = "Control's tooltip",
-	getFace = function() return face end,
-	getSize = function() return size end,
-	getOutline = function() return outline end,
-	getColor = function() return r, g, b, a end,
-	setFace = function(face) end,
-	setSize = function(size) end,
-	setOutline = function(outline) end,
-	setColor = function(r, g, b, a) end,
-	width = "full", --or "half" (optional)
-	disabled = function() return boolean end, --(optional) boolean or function which returns boolean
-	warning = "Some warning text", --(optional)
-	default = { --(optional)
-		face = "Univers 67",
-		size = "22",
-		outline = "soft-shadow-thin",
-		color = { r = val1, g = val2, b = val3, a = val4 }, -- table (or ZO_ColorDef object) with default color values
-	},
-	reference = "MyControlReference", --(optional) unique global reference
-}
-]]
-
-local widgetVersion = 4
-local LAM = LibStub("LibAddonMenu-2.0", true)
-local LMP = LibStub("LibMediaProvider-1.0", true)
-if (not LAM or not LMP) then return end -- need both libs to function
-if not LAM:RegisterWidget("fontblock", widgetVersion) then return end
-
---UPVALUES--
-local wm = GetWindowManager()
-local cm = CALLBACK_MANAGER
-local tinsert = table.insert
-local strformat = string.format
-local tostring = tostring
-local round = zo_round
-
-local fontOutlineChoices = {"none", "outline", "thin-outline", "thick-outline", "shadow", "soft-shadow-thin", "soft-shadow-thick"}
-local fontSizeChoices = {}
-
-for x = 1, 25 do
-	fontSizeChoices[x] = tostring(x + 7)
-end
-
-local function UpdateDisabled(control)
-	local disable
-	if type(control.data.disabled) == "function" then
-		disable = control.data.disabled()
-	else
-		disable = control.data.disabled
-	end
-
-	if disable then
-		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-	else
-		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-	end
-
-	control.isDisabled = disable
-end
-
-local function UpdateValue(control, forceDefault, face, size, outline, colorR, colorG, colorB, colorA)
-	local data = control.data
-	local isUpdated = false
-
-	if forceDefault then
-		face = data.default.face
-		size = data.default.size
-		outline = data.default.outline
-		colorR = data.default.color.r
-		colorG = data.default.color.g
-		colorB = data.default.color.b
-		colorA = data.default.color.a
-	end
-
-	if face then
-		data.setFace(face)
-		isUpdated = true
-	else
-		face = data.getFace()
-	end
-
-	if size then
-		data.setSize(size)
-		isUpdated = true
-	else
-		size = data.getSize()
-	end
-
-	if outline then
-		data.setOutline(outline)
-		isUpdated = true
-	else
-		outline = data.getOutline()
-	end
-
-	if colorR and colorG and colorB then
-		data.setColor(colorR, colorG, colorB, colorA or 1)
-		isUpdated = true
-	else
-		colorR, colorG, colorB, colorA = data.getColor()
-	end
-
-	if isUpdated then
-		if control.panel.data.registerForRefresh then
-			cm:FireCallbacks("LAM-RefreshPanel", control)
-		end
-	end
-
-	control.size.dropdown:SetSelectedItem(size)
-	control.face.dropdown:SetSelectedItem(face)
-	control.outline.dropdown:SetSelectedItem(outline)
-	control.color.thumb:SetColor(colorR, colorG, colorB, colorA or 1)
-end
-
-function LAMCreateControl.fontblock(parent, widgetData, controlName)
-	local panel = parent.panel or parent
-	if not panel.fbCounter then
-		panel.fbCounter = 0
-	end
-	panel.fbCounter = panel.fbCounter + 1
-	controlName = controlName or widgetData.reference or (panel:GetName() .. "Fontblock" .. tostring(panel.fbCounter))
-	local fb = wm:CreateControl(controlName, parent.scroll or parent, CT_CONTROL)
-	fb:SetMouseEnabled(true)
-	fb:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
-	fb:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
-	fb.label = wm:CreateControl(nil, fb, CT_LABEL)
-	fb.label:SetAnchor(TOPLEFT)
-	fb.label:SetFont("ZoFontWinH4")
-	fb.label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-	fb.label:SetText(widgetData.name)
-
-	-- font face
-	local face = wm:CreateControlFromVirtual(controlName .. "Face", fb, "ZO_ComboBox")
-	fb.face = face
-	face:SetDimensions(164, 26)
-	face:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(fb) end)
-	face:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(fb) end)
-
-	face.dropdown = ZO_ComboBox_ObjectFromContainer(face)
-	face.dropdown:ClearItems()
-
-	local fontFaceChoices = LMP:List("font")
-
-	local function FaceDropdownCallback(self, choiceText, choice)
-		fb:UpdateValue(false, choiceText)
-	end
-
-	for i = 1, #fontFaceChoices do
-		local entry = face.dropdown:CreateItemEntry(fontFaceChoices[i], FaceDropdownCallback)
-		face.dropdown:AddItem(entry, ZO_COMBOBOX_SUPRESS_UPDATE)
-	end
-
-	-- color picker
-	local color = wm:CreateControl(nil, fb, CT_CONTROL)
-	fb.color = color
-	color:SetDimensions(28, 25)
-	color:SetMouseEnabled(true)
-	color:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(fb) end)
-	color:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(fb) end)
-
-	local thumb = wm:CreateControl(nil, color, CT_TEXTURE)
-	fb.color.thumb = thumb
-	thumb:SetDimensions(24, 20)
-	thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
-	local border = wm:CreateControl(nil, color, CT_TEXTURE)
-	border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
-	border:SetDimensions(28, 25)
-	border:SetTexture("EsoUI/Art/ChatWindow/chatOptions_bgColSwatch_frame.dds")
-	border:SetTextureCoords(0, .625, 0, .8125)
-
-	local function ColorPickerCallback(r, g, b, a)
-		fb:UpdateValue(false, nil, nil, nil, r, g, b, a)
-	end
-
-	fb.color:SetHandler("OnMouseUp", function(self, btn, upInside)
-		if (upInside) then
-			local r, g, b, a = widgetData.getColor()
-			COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, widgetData.name)
-		end
-	end)
-
-	-- outline
-	local outline = wm:CreateControlFromVirtual(controlName .. "Outline", fb, "ZO_ComboBox")
-	fb.outline = outline
-	outline:SetDimensions(138, 26)
-	outline:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(fb) end)
-	outline:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(fb) end)
-
-	outline.dropdown = ZO_ComboBox_ObjectFromContainer(outline)
-	outline.dropdown:ClearItems()
-
-	local function OutlineDropdownCallback(self, choiceText, choice)
-		fb:UpdateValue(false, nil, nil, choiceText)
-	end
-
-	for i = 1, #fontOutlineChoices do
-		local entry = outline.dropdown:CreateItemEntry(fontOutlineChoices[i], OutlineDropdownCallback)
-		outline.dropdown:AddItem(entry, ZO_COMBOBOX_SUPRESS_UPDATE)
-	end
-
-	--size
-	local size = wm:CreateControlFromVirtual(controlName .. "Size", fb, "ZO_ComboBox")
-	fb.size = size
-	size:SetDimensions(54, 26)
-	size:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(fb) end)
-	size:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(fb) end)
-
-	size.dropdown = ZO_ComboBox_ObjectFromContainer(size)
-	size.dropdown:ClearItems()
-
-	local function SizeDropdownCallback(self, choiceText, choice)
-		fb:UpdateValue(false, nil, choiceText)
-	end
-
-	for i = 1, #fontSizeChoices do
-		local entry = size.dropdown:CreateItemEntry(fontSizeChoices[i], SizeDropdownCallback)
-		size.dropdown:AddItem(entry, ZO_COMBOBOX_SUPRESS_UPDATE)
-	end
-
-
-	local isHalfWidth = widgetData.width == "half"
-	local widgetWidth = panel:GetWidth() - 60
-	if isHalfWidth then
-		widgetWidth = widgetWidth / 2
-		fb:SetDimensions(widgetWidth, 80)
-		fb.label:SetDimensions(widgetWidth, 26)
-		face:SetAnchor(TOPLEFT, fb, TOPLEFT, widgetWidth - 195, 26)
-		color:SetAnchor(TOPLEFT, fb, TOPLEFT, widgetWidth - 30, 26)
-		outline:SetAnchor(BOTTOMLEFT, fb, BOTTOMLEFT, widgetWidth - 195, 0)
-		size:SetAnchor(BOTTOMLEFT, fb, BOTTOMLEFT, widgetWidth - 54, 0)
-	else
-		fb:SetDimensions(widgetWidth, 54)
-		fb.label:SetDimensions(widgetWidth - 210, 26)
-		face:SetAnchor(TOPLEFT, fb, TOPLEFT, widgetWidth - 195, 0)
-		color:SetAnchor(TOPLEFT, fb, TOPLEFT, widgetWidth - 30, 0)
-		outline:SetAnchor(BOTTOMLEFT, fb, BOTTOMLEFT, widgetWidth - 195, 0)
-		size:SetAnchor(BOTTOMLEFT, fb, BOTTOMLEFT, widgetWidth - 54, 0)
-	end
-
-
-	if (widgetData.warning) then
-		fb.warning = wm:CreateControlFromVirtual(nil, fb, "ZO_Options_WarningIcon")
-		fb.warning:SetAnchor(RIGHT, face, LEFT, -5, 0)
-		fb.warning.data = { tooltipText = widgetData.warning }
-	end
-
-	fb.panel = parent.panel or parent	 --if this is in a submenu, panel is its parent
-	fb.data = widgetData
-	fb.data.tooltipText = widgetData.tooltip
-
-	if widgetData.disabled then
-		fb.UpdateDisabled = UpdateDisabled
-		fb:UpdateDisabled()
-	end
-
-	fb.UpdateValue = UpdateValue
-	fb:UpdateValue()
-
-	if fb.panel.data.registerForRefresh or fb.panel.data.registerForDefaults then	 --if our parent window wants to refresh controls, then add this to the list
-		tinsert(fb.panel.controlsToRefresh, fb)
-	end
-
-	return fb
-end
\ No newline at end of file
diff --git a/Locales/Local_en.lua b/Locales/Local_en.lua
index 2fe41c6..ea5690f 100644
--- a/Locales/Local_en.lua
+++ b/Locales/Local_en.lua
@@ -35,6 +35,7 @@ L.TelVarMeter			= 'Tel Var Display'
 L.ActiveCombatTips		= 'Active Combat Tips'
 L.Tutorial				= 'Tutorials'
 L.CaptureMeter			= 'AvA Capture Meter'
+L.BagWatcher			= 'Bag Watcher'

 -- --------------------------------------------
 -- SETTINGS -----------------------------------
@@ -59,13 +60,17 @@ L.TabButton2			= 'Attributes'
 L.TabButton3			= 'Target'
 L.TabButton4			= 'Action Bar'
 L.TabButton5			= 'Experience'
-L.TabButton6			= 'Profiles'
+L.TabButton6			= 'Bag Watcher'
+L.TabButton7			= 'Thievery'
+L.TabButton8			= 'Profiles'
 L.TabHeader1			= 'General Settings'
 L.TabHeader2			= 'Player Attribute Settings'
 L.TabHeader3			= 'Target Window Settings'
 L.TabHeader4			= 'Action Bar Settings'
 L.TabHeader5			= 'Experience Bar Settings'
-L.TabHeader6			= 'Profile Settings'
+L.TabHeader6			= 'Bag Watcher Settings'
+L.TabHeader7			= 'Thievery Settings'
+L.TabHeader8			= 'Profile Settings'
 -- unlock window
 L.UnlockHeader			= 'UI Unlocked'
 L.UnlockGridEnable		= 'Enable Snap to Grid'
@@ -149,7 +154,17 @@ L.ExperienceDisplayStyle = 'Display Style'
 L.ExperienceDisplayStyleTip = 'Set how to display the experience bar.\n\nNote: Even when Always Shown, the bar will be hidden while crafting and when the World Map is open so as not to overlap other windows.'
 L.ExperienceOverlayFormatTip = 'Set how to display the overlay text for the experience bar.\n\nThe default UI setting is No Overlay.'

--- settings: profiles tab (6)
+-- serttings: bag watcher tab (6)
+L.Bag_Desc					= 'The bag watcher creates a bar (similar to the experience bar in appearance) that shows how full your backpack is. It will show up briefly whenever your bag contents change, and can optionally be set to always show if your bag is almost full.'
+L.Bag_Enable				= 'Enable Bag Watcher'
+L.Bag_ReverseAlignment		= 'Reverse Bar Alignment'
+L.Bag_ReverseAlignmentTip	= 'Set whether to reverse the direction of the bar by making it increase towards the right. This will also place the icon on the opposite side of the bar.'
+L.Bag_LowSpaceLock			= 'Always Show When Low On Space'
+L.Bag_LowSpaceLockTip		= 'Set whether the bag watcher should always be shown when your backpack is nearly full.'
+L.Bag_LowSpaceTrigger		= 'Low On Space Trigger Level'
+L.Bag_LowSpaceTriggerTip	= 'Set how many slots should remain free before considering your backpack to be low on space.'
+
+-- settings: profiles tab (8)
 L.ProfileHeader = 'Profiles'
 L.ProfileCharacterList = 'Existing Settings'
 L.ProfileCharacterListTip = 'List of characters that currently have Azurah settings.'
diff --git a/Locales/Local_fr.lua b/Locales/Local_fr.lua
index aa1e18f..b2438b2 100644
--- a/Locales/Local_fr.lua
+++ b/Locales/Local_fr.lua
@@ -1,10 +1,9 @@
--- French (fr) - Translations provided by Ykses (http://www.esoui.com/forums/member.php?u=1521)
-local Azurah = _G['Azurah'] -- grab addon table from global
+local Azurah = _G['Azurah'] -- grab addon table from global [French (fr) - Translations provided by Ykses (http://www.esoui.com/forums/member.php?u=1521)]

 local L = {}

-L.Azurah = '|c67b1e9A|c4779cezurah|r'
-L.Usage = '|c67b1e9A|c4779cezurah|r - Utilisation : taper \"/azurah lock\" ou \"unlock\" pour verrouiller ou déverrouiller la possibilité de déplacer les éléments de l\'interface.'
+L.Azurah				= '|c67b1e9A|c4779cezurah|r'
+L.Usage					= '|c67b1e9A|c4779cezurah|r - Utilisation : taper \"/azurah lock\" ou \"unlock\" pour verrouiller ou déverrouiller la possibilité de déplacer les éléments de l\'interface.'

 -- L.ThousandsSeperator	= ',' -- used to seperator large numbers in overlays

@@ -37,6 +36,7 @@ L.ActiveCombatTips		= 'Aide au combat'
 L.Tutorial				= 'Didacticiels'
 L.CaptureMeter			= 'AvA capture compteur'

+
 -- --------------------------------------------
 -- SETTINGS -----------------------------------
 -- --------------------------------------------
@@ -60,13 +60,17 @@ L.TabButton2			= 'Caractéristiques'
 L.TabButton3			= 'Cible'
 L.TabButton4			= 'Barre d\'actions'
 L.TabButton5			= 'Expérience'
-L.TabButton6			= 'Profils'
+
+
+L.TabButton8			= 'Profils'
 L.TabHeader1			= 'Réglages généraux'
 L.TabHeader2			= 'Réglages des caractéristiques'
 L.TabHeader3			= 'Réglages de la cible'
 L.TabHeader4			= 'Réglages de la barre d\'actions'
 L.TabHeader5			= 'Réglages de la barre d\'XP'
-L.TabHeader6			= 'Réglage du profil'
+
+
+L.TabHeader8			= 'Réglage du profil'
 -- unlock window
 L.UnlockHeader			= 'Interface déverrouillée'
 L.UnlockGridEnable		= 'Activer l\'alignement'
@@ -147,7 +151,7 @@ L.ExperienceDisplayStyle = 'Style de l\'affichage'
 L.ExperienceDisplayStyleTip = 'Permet de définir la façon dont la barre d\'expérience s\'affiche.\n\nNote : Même avec l\'option \"Toujours affichée\", la barre sera masquée lors de l\'artisanat ou quand la carte du monde est ouverte, afin de ne pas se superposer à l\'affichage d\'autres informations.'
 L.ExperienceOverlayFormatTip = 'Permet de définir la façon dont le texte est affiché sur la barre d\'expérience.\n\nLe réglage par défaut est \"Ne rien afficher\".'

--- settings: profiles tab (6)
+-- settings: profiles tab (8)
 L.ProfileHeader = 'Profils'
 L.ProfileCharacterList = 'Réglages existants'
 L.ProfileCharacterListTip = 'Liste des personnages utilisant Azurah.'
@@ -156,6 +160,7 @@ L.ProfileCopyFromTip = 'Permet de copier les réglages du personnage séléction
 L.ProfileCopyFromWarn = 'Cliquer sur ce bouton rechargera l\'interface, en remplaçant les réglages d\'Azurah avec ceux du personnage séléctionné.\n\nVous ne pourrez pas revenir sur cette action, les nouveaux réglages écraseront les réglages actuels.'


+
 if (GetCVar('language.2') == 'fr') then -- overwrite GetLocale for new language
 	for k, v in pairs(Azurah:GetLocale()) do
 		if (not L[k]) then -- no translation for this string, use default
diff --git a/Player.lua b/Player.lua
index 27de1e8..f3717da 100644
--- a/Player.lua
+++ b/Player.lua
@@ -168,7 +168,6 @@ function Azurah:InitializePlayer()
 	FormatMagicka	= self.overlayFuncs[1]
 	FormatStamina	= self.overlayFuncs[1]

-	self:ConfigureAttributeOverlays()
 	self:ConfigureAttributeFade()
 	self:ConfigureAttributeSizeLock()
 end
diff --git a/Settings.lua b/Settings.lua
index 3bbefaf..5f83bbe 100644
--- a/Settings.lua
+++ b/Settings.lua
@@ -142,7 +142,7 @@ local function TabButtonOnClick(self)
 		CreateTabPanel(self.panelID) -- call to create appropriate panel if not created yet
 	end

-	for x = 1, 6 do
+	for x = 1, 8 do
 		tabButtons[x].button:SetState(0) -- unset selected state for all buttons
 	end

@@ -165,7 +165,7 @@ local function CompleteInitialization(panel)

 	local btn

-	for x = 1, 6 do
+	for x = 1, 8 do
 		btn = LAMCreateControl.button(tabButtonsPanel, { -- create our tab buttons
 			type = 'button',
 			name = L['TabButton' .. x],
@@ -174,9 +174,9 @@ local function CompleteInitialization(panel)
 		btn.button.buttonID	= x -- reference lookup to refer to buttons
 		btn.button.panelID	= x -- reference lookup to refer to panels

-		btn:SetWidth((controlPanelWidth / 3) - 2)
-		btn.button:SetWidth((controlPanelWidth / 3) - 2)
-		btn:SetAnchor(TOPLEFT, tabButtonsPanel, TOPLEFT, (controlPanelWidth / 3) * ((x - 1) % 3), (x <= 3) and 0 or 34)
+		btn:SetWidth((controlPanelWidth / 4) - 2)
+		btn.button:SetWidth((controlPanelWidth / 4) - 2)
+		btn:SetAnchor(TOPLEFT, tabButtonsPanel, TOPLEFT, (controlPanelWidth / 4) * ((x - 1) % 4), (x <= 4) and 0 or 34)

 		tabButtons[x] = btn
 	end
@@ -1074,11 +1074,136 @@ tabPanelData = {
 			end,
 		},
 	},
+
 	-- ----------------------------
-	-- PROFILES PANEL
+	-- BAG WATCHER PANEL
 	-- ----------------------------
 	[6] = {
 		{
+			type = 'description',
+			text = L.Bag_Desc,
+		},
+		{
+			type = 'checkbox',
+			name = L.Bag_Enable,
+			getFunc = function()
+				return Azurah.db.bagWatcher.enabled
+			end,
+			setFunc = function(v)
+				Azurah.db.bagWatcher.enabled = v
+				Azurah:ConfigureBagWatcher()
+			end,
+		},
+		{
+			type = 'checkbox',
+			name = L.Bag_ReverseAlignment,
+			tooltip = L.Bag_ReverseAlignmentTip,
+			getFunc = function()
+				return Azurah.db.bagWatcher.reverseAlignment
+			end,
+			setFunc = function(v)
+				Azurah.db.bagWatcher.reverseAlignment = v
+				Azurah:ConfigureBagWatcher()
+			end
+		},
+		{
+			type = 'checkbox',
+			name = L.Bag_LowSpaceLock,
+			tooltip = L.Bag_LowSpaceLockTip,
+			getFunc = function()
+				return Azurah.db.bagWatcher.lowSpaceLock
+			end,
+			setFunc = function(v)
+				Azurah.db.bagWatcher.lowSpaceLock = v
+			end
+		},
+		{
+			type = 'slider',
+			name = L.Bag_LowSpaceTrigger,
+			tooltip = L.Bag_LowSpaceTriggerTip,
+			min = 1,
+			max = GetBagSize(BAG_BACKPACK),
+			getFunc = function()
+				return Azurah.db.bagWatcher.lowSpaceTrigger
+			end,
+			setFunc = function(v)
+				Azurah.db.bagWatcher.lowSpaceTrigger = v
+			end
+		},
+		{
+			type = "dropdown",
+			name = L.SettingOverlayFormat,
+			tooltip = L.ExperienceOverlayFormatTip,
+			choices = dropOverlay,
+			getFunc = function() return dropOverlay[Azurah.db.bagWatcher.overlay] end,
+			setFunc = function(arg)
+					Azurah.db.bagWatcher.overlay = dropOverlayRef[arg]
+					Azurah:ConfigureBagWatcher()
+				end,
+		},
+		{
+			type = 'dropdown',
+			name = L.SettingOverlayFont,
+			choices = LMP:List('font'),
+			getFunc = function()
+				return Azurah.db.bagWatcher.fontFace
+			end,
+			setFunc = function(v)
+				Azurah.db.bagWatcher.fontFace = v
+				Azurah:ConfigureBagWatcher()
+			end,
+		},
+		{
+			type = 'dropdown',
+			name = L.SettingOverlayStyle,
+			choices = dropFontStyle,
+			getFunc = function()
+				return Azurah.db.bagWatcher.fontOutline
+			end,
+			setFunc = function(v)
+				Azurah.db.bagWatcher.fontOutline = v
+				Azurah:ConfigureBagWatcher()
+			end,
+		},
+		{
+			type = 'colorpicker',
+			getFunc = function()
+				return Azurah.db.bagWatcher.fontColour.r, Azurah.db.bagWatcher.fontColour.g, Azurah.db.bagWatcher.fontColour.b, Azurah.db.bagWatcher.fontColour.a
+			end,
+			setFunc = function(r, g, b, a)
+				Azurah.db.bagWatcher.fontColour.r = r
+				Azurah.db.bagWatcher.fontColour.g = g
+				Azurah.db.bagWatcher.fontColour.b = b
+				Azurah.db.bagWatcher.fontColour.a = a
+				Azurah:ConfigureBagWatcher()
+			end,
+			isFontColour = true,
+		},
+		{
+			type = 'slider',
+			name = L.SettingOverlaySize,
+			min = 8,
+			max = 32,
+			getFunc = function()
+				return Azurah.db.bagWatcher.fontSize
+			end,
+			setFunc = function(v)
+				Azurah.db.bagWatcher.fontSize = v
+				Azurah:ConfigureBagWatcher()
+			end,
+		},
+	},
+	-- ----------------------------
+	-- THIEVERY PANEL
+	-- ----------------------------
+	[7] = {
+
+	},
+	-- ----------------------------
+	-- PROFILES PANEL
+	-- ----------------------------
+	[8] = {
+		{
 			type = "dropdown",
 			name = L.ProfileCharacterList,
 			tooltip = L.ProfileCharacterListTip,
diff --git a/Target.lua b/Target.lua
index 495b965..81663e3 100644
--- a/Target.lua
+++ b/Target.lua
@@ -237,7 +237,6 @@ function Azurah:InitializeTarget()
 	targetAlliance = WINDOW_MANAGER:CreateControl(nil, ZO_TargetUnitFramereticleover, CT_TEXTURE)
 	targetAlliance:SetHidden(true)

-	self:ConfigureTargetOverlay()
 	self:ConfigureTargetColouring()
 	self:ConfigureTargetIcons()
 	self:ConfigureTargetSizeLock()
diff --git a/Unlock.lua b/Unlock.lua
index aebc9dc..034f97a 100644
--- a/Unlock.lua
+++ b/Unlock.lua
@@ -33,6 +33,7 @@ local uiFrames = {
 		['ZO_ActiveCombatTipsTip']								= {1, L.ActiveCombatTips, 250, 20},
 		['ZO_TutorialHudInfoTipKeyboard']						= {1, L.Tutorial},
 		['ZO_ObjectiveCaptureMeter']							= {1, L.CaptureMeter, 128, 128},
+		['Azurah_BagWatcher']									= {1, L.BagWatcher},
 	},
 	gamepad = {
 		['ZO_PlayerAttributeHealth']							= {1, L.Health},
@@ -41,6 +42,7 @@ local uiFrames = {
 		['ZO_PlayerAttributeWerewolf']							= {2, L.Werewolf},
 		['ZO_PlayerAttributeStamina']							= {1, L.Stamina},
 		['ZO_PlayerAttributeMountStamina']						= {2, L.StaminaMount},
+		['ZO_PlayerProgress']									= {1, L.Experience},
 		['ZO_SynergyTopLevelContainer']							= {1, L.Synergy},
 		['ZO_CompassFrame']										= {1, L.Compass},
 		['ZO_TargetUnitFramereticleover']						= {1, L.ReticleOver},
@@ -55,6 +57,7 @@ local uiFrames = {
 		['ZO_ActiveCombatTipsTip']								= {1, L.ActiveCombatTips, 250, 20},
 		['ZO_TutorialHudInfoTipGamepad']						= {1, L.Tutorial},
 		['ZO_ObjectiveCaptureMeter']							= {1, L.CaptureMeter, 128, 128},
+		['Azurah_BagWatcher']									= {1, L.BagWatcher},
 	}
 }

@@ -369,7 +372,7 @@ function Azurah:LockUI()
 		uiPanel:SetHidden(true)
 		uiPanel = nil

-		if not IsInGamepadPreferredMode() then
+		if (not IsInGamepadPreferredMode()) then
 			framesList = uiFrames.keyboard
 		else
 			framesList = uiFrames.gamepad
@@ -387,12 +390,12 @@ function Azurah:UnlockUI()

 		local mover, userData, framesList

-		if not IsInGamepadPreferredMode() then
-			userData = self.db.uiData.keyboard
-			framesList = uiFrames.keyboard
+		if (not IsInGamepadPreferredMode()) then
+			userData	= self.db.uiData.keyboard
+			framesList	= uiFrames.keyboard
 		else
-			userData = self.db.uiData.gamepad
-			framesList = uiFrames.gamepad
+			userData	= self.db.uiData.gamepad
+			framesList	= uiFrames.gamepad
 		end

 		for frame, data in pairs(framesList) do