Quantcast

- Fixing some more TOC changes in the repository.

HonorGoG [07-03-25 - 06:59]
- Fixing some more TOC changes in the repository.
Filename
Titan/TitanGame.lua
Titan/TitanHistory.lua
Titan/_ATitanDoc.lua
TitanBag/TitanBag.toc
TitanBag/TitanBag_Mainline.toc
TitanBag/TitanBag_Vanilla.toc
TitanClock/TitanClock.toc
TitanClock/TitanClock_Mainline.toc
TitanClock/TitanClock_Vanilla.toc
TitanGold/TitanGold.toc
TitanGold/TitanGold_Mainline.toc
TitanGold/TitanGold_Vanilla.toc
TitanLDB/Artwork/Bag_Blue.blp
TitanLDB/Artwork/Bag_Red.blp
TitanLDB/Artwork/Starter.tga
TitanLDB/DevReadMe.lua
TitanLDB/StarterLDB.lua
TitanLDB/TitanLDB.toc
TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
TitanLDB/libs/LibDataBroker-1.1.lua
TitanLocation/TitanLocation.toc
TitanLocation/TitanLocation_Mainline.toc
TitanLocation/TitanLocation_Vanilla.toc
TitanLootType/TitanLootType.toc
TitanLootType/TitanLootType_Classic.toc
TitanLootType/TitanLootType_Mainline.toc
TitanPerformance/TitanPerformance.toc
TitanPerformance/TitanPerformance_Mainline.toc
TitanPerformance/TitanPerformance_Vanilla.toc
TitanPlugin/Artwork/TitanStarter.tga
TitanPlugin/DevReadMe.lua
TitanPlugin/TitanPlugin.toc
TitanPlugin/TitanStarter.lua
TitanRepair/TitanRepair.toc
TitanRepair/TitanRepair_Mainline.toc
TitanRepair/TitanRepair_Vanilla.toc
TitanVolume/TitanVolume.toc
TitanVolume/TitanVolume_Mainline.toc
TitanVolume/TitanVolume_Vanilla.toc
TitanXP/TitanXP.toc
TitanXP/TitanXP_Mainline.toc
TitanXP/TitanXP_Vanilla.toc
diff --git a/Titan/TitanGame.lua b/Titan/TitanGame.lua
index 923007c..2d4d3be 100644
--- a/Titan/TitanGame.lua
+++ b/Titan/TitanGame.lua
@@ -1,8 +1,8 @@
 --[===[ File
 NAME: TitanGame.lua
-DESC: This file contains the 'game version' Titan or Titan. Used to set up libs, locale, ...
+DESC: This file contains the 'game version' Titan or TitanClassic. Used to set up libs, locale, ...
 Different folders are required because Titan used Titan as a name (& folder) for the Classic WoW versions.
-The saved variables for Classic WoW are in Titan.lua - not Titan.lua.
+The saved variables for Classic WoW are in TitanClassic.lua - not Titan.lua.
 :DESC
 --]===]

diff --git a/Titan/TitanHistory.lua b/Titan/TitanHistory.lua
index 6106877..b3245fc 100644
--- a/Titan/TitanHistory.lua
+++ b/Titan/TitanHistory.lua
@@ -15,7 +15,7 @@ Green - 'header' - Titan or plugin
 Highlight - notes. tips. and details
 --]]
 Titan_Global.recent_changes = ""
-.. TitanUtils_GetGoldText("8.3.0 : 2025/07/15\n")
+.. TitanUtils_GetGoldText("8.3.0 : 2025/07/2\n")
 .. TitanUtils_GetGreenText("Titan : \n")
 .. TitanUtils_GetHighlightText(""
 .. "-  Major change : \n"
diff --git a/Titan/_ATitanDoc.lua b/Titan/_ATitanDoc.lua
index d19e186..68d4c7f 100644
--- a/Titan/_ATitanDoc.lua
+++ b/Titan/_ATitanDoc.lua
@@ -38,7 +38,7 @@ These are routines Titan will keep stable.
 Changes to these varaibles and routines will be broadcast to developers via Discord at a minimum.

 Dev :
-These are global routines Tian uses. These may change at any time per Titan needs and design.
+These are global routines Titan uses. These may change at any time per Titan needs and design.

 File :
 Each file has a terse description of its contents.
diff --git a/TitanBag/TitanBag.toc b/TitanBag/TitanBag.toc
new file mode 100644
index 0000000..2c413f6
--- /dev/null
+++ b/TitanBag/TitanBag.toc
@@ -0,0 +1,9 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fBag|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\AddOns\TitanBag\TitanBag
+## Notes: Adds bag and free slot information to Titan Panel
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## Dependencies: Titan
+TitanBag.lua
diff --git a/TitanBag/TitanBag_Mainline.toc b/TitanBag/TitanBag_Mainline.toc
deleted file mode 100644
index dbf89cf..0000000
--- a/TitanBag/TitanBag_Mainline.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fBag|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\AddOns\TitanBag\TitanBag
-## Notes: Adds bag and free slot information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## Dependencies: Titan
-TitanBag.lua
diff --git a/TitanBag/TitanBag_Vanilla.toc b/TitanBag/TitanBag_Vanilla.toc
deleted file mode 100644
index 8ebc4ee..0000000
--- a/TitanBag/TitanBag_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fBag|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Adds bag and free slot information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanBag.lua
diff --git a/TitanClock/TitanClock.toc b/TitanClock/TitanClock.toc
new file mode 100644
index 0000000..e4b816a
--- /dev/null
+++ b/TitanClock/TitanClock.toc
@@ -0,0 +1,10 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fClock|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\Icons\Spell_Nature_TimeStop
+## Notes: Adds a clock to Titan Panel
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## OptionalDeps:
+## Dependencies: Titan
+TitanClock.lua
diff --git a/TitanClock/TitanClock_Mainline.toc b/TitanClock/TitanClock_Mainline.toc
deleted file mode 100644
index 710ed98..0000000
--- a/TitanClock/TitanClock_Mainline.toc
+++ /dev/null
@@ -1,10 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fClock|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\Icons\Spell_Nature_TimeStop
-## Notes: Adds a clock to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanClock.lua
diff --git a/TitanClock/TitanClock_Vanilla.toc b/TitanClock/TitanClock_Vanilla.toc
deleted file mode 100644
index fcdb12b..0000000
--- a/TitanClock/TitanClock_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fClock|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Adds a clock to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanClock.lua
diff --git a/TitanGold/TitanGold.toc b/TitanGold/TitanGold.toc
new file mode 100644
index 0000000..5bf41d9
--- /dev/null
+++ b/TitanGold/TitanGold.toc
@@ -0,0 +1,10 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fGold|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\AddOns\TitanGold\Artwork\TitanGold
+## Notes: Keeps track of all gold held by a player's toons on a per server/faction basis.
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables: GoldSave
+## OptionalDeps:
+## Dependencies: Titan
+TitanGold.lua
diff --git a/TitanGold/TitanGold_Mainline.toc b/TitanGold/TitanGold_Mainline.toc
deleted file mode 100644
index d8d594f..0000000
--- a/TitanGold/TitanGold_Mainline.toc
+++ /dev/null
@@ -1,10 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fGold|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\AddOns\TitanGold\Artwork\TitanGold
-## Notes: Keeps track of all gold held by a player's toons on a per server/faction basis.
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables: GoldSave
-## OptionalDeps:
-## Dependencies: Titan
-TitanGold.lua
diff --git a/TitanGold/TitanGold_Vanilla.toc b/TitanGold/TitanGold_Vanilla.toc
deleted file mode 100644
index c3788b1..0000000
--- a/TitanGold/TitanGold_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fGold|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Keeps track of all gold held by a player's toons on a per server/faction basis.
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables: GoldSave
-## OptionalDeps:
-## Dependencies: Titan
-TitanGold.lua
diff --git a/TitanLDB/Artwork/Bag_Blue.blp b/TitanLDB/Artwork/Bag_Blue.blp
new file mode 100644
index 0000000..5e7bde1
Binary files /dev/null and b/TitanLDB/Artwork/Bag_Blue.blp differ
diff --git a/TitanLDB/Artwork/Bag_Red.blp b/TitanLDB/Artwork/Bag_Red.blp
new file mode 100644
index 0000000..31579e7
Binary files /dev/null and b/TitanLDB/Artwork/Bag_Red.blp differ
diff --git a/TitanLDB/Artwork/Starter.tga b/TitanLDB/Artwork/Starter.tga
new file mode 100644
index 0000000..6a7ddda
Binary files /dev/null and b/TitanLDB/Artwork/Starter.tga differ
diff --git a/TitanLDB/DevReadMe.lua b/TitanLDB/DevReadMe.lua
new file mode 100644
index 0000000..8ec059d
--- /dev/null
+++ b/TitanLDB/DevReadMe.lua
@@ -0,0 +1,156 @@
+--[[ Example
+This example is intended to introduce LDB (LibDataBroker) essentials by using an example loosely based on Titan Bag.
+A display addon is needed to show this addon. Titan is recommended :).
+
+This example is intended to be small and light for easy understanding and editting.
+
+Important notes are denoted with ***:
+*** The 'official' LDB spec is here : https://github.com/tekkub/libdatabroker-1-1 .
+*** This example is provided as is and without restrictions.
+*** Timers are outside the scope of this example.
+- Titan built-in addons use timers (AceTimer).
+*** Localized strings are outside the scope of this example.
+- Titan and built-in plugins use localized strings (AceLocale).
+
+There are sites that have deeper explanations about addon development such as wowhead or wow wiki (warcraft.wiki.gg).
+Please use these or other sites for more detailed addon information.
+--]]
+
+--[[ Folder Structure
+This addon folder must be added to the Addon folder to be considered for loading into WoW.
+Inside this folder you will notice :
+- Artwork folder : icon(s) used by the addon
+- libs folder
+- .toc files
+- one .lua file : for your great idea
+- This read me file
+
+=== .toc
+The folder and the .toc files MUST have the same name!
+Sort of... the name prior to the underscore(_) must be the same as the folder name.
+The name after that (postfix) has meaning to the WoW addon loader.
+https://warcraft.wiki.gg/wiki/TOC_format : Contains the full list and A LOT more detail about .toc files
+
+If your addon is only for Classic Era leave <addon>_Vanilla. Delete (or rename) the other .toc files.
+
+*** The ## Interface value should match the current interface value of the corresponding WoW version.
+If the interface value is higher or lower, WoW will complain that you are running 'out of date' addons.
+In the BattleNet app this typically shown below the 'Play' button.
+- DragonFlight 10.2.7 is represented without dots - 100207 - in the .toc file.
+- Cataclysm 4.4.0 is represented without dots - 40401 - in the .toc file.
+
+=== Artwork folder: icons and artwork
+Anyone can extract the Blizzard UI code and art from WoW. This can be handy to get code examples.
+My understanding is any WoW icon can be used within an addon without violating the ToS (Terms of Service).
+Wowhead has a searchable list of WoW icons : https://www.wowhead.com/icons
+
+WoW icons tend to be .blp files. These files are NOT easy to look at or manipulate!!
+BLPView (Windows only) from wowinterface is light and easy to view blp files as thumbnails in File Explorer.
+You will need to research third party tools to manipulate .blp files. My advice is convert .blp to another format.
+
+=== libs folder
+*** The libraries required for a LDB addon are in the LDB/libs folder.
+- WoW does not guarentee the load order of addons.
+- If the LDB addon were loaded before the display addon, the loader would throw errors if the libs were not found.
+- If the LDB addon requires additional libraries, please include them in libs folder and update the .toc appropriately.
+
+--]]
+
+--[[ LDB attributes
+The list of required attributes depend on the type of LDB being created.
+
+Attributes used in this addon:
+.type : Required : data source | launcher
+.icon : Path to the icon to be used. Place the icon in the addon folder, even if copied from WoW folder.
+.label : The label for the addon text
+.text : The addon text to display
+.OnTooltipShow : The function to use for the tool tip, if any
+.OnClick : The function to to handle mouse clicks, if any
+
+
+Available Titan extensions:
+.category : The general grouping this addon is in.
+- Titan attempts to grab X-Category from the addon TOC first.
+- The complete category list is in
+- TITAN_PANEL_BUTTONS_PLUGIN_CATEGORY (TitanGlobal.lua) "Built-ins" is reserved for addons that Titan releases!
+.version : Addon version shown in Titan menus and config.
+- Titan attempts to grab Version from the addon TOC first.
+.OnDoubleClick : Implemented by orig dev, not sure this is used by any addon.
+
+The three data elements are:
+- icon
+- label
+- text
+
+When any of these are changed, the LDB lib initiates a callback to the display addon.
+The display addon registers for these callbacks and creates any frame(s) it needs to display the LDB addon data.
+--]]
+
+--[[ Editing
+Before you start changing this example it is HIGHLY recommended to install the following addons:
+- BugGrabber : Grabs errors and stores them
+- BugSack : The visual part of BugGrabber
+- WowLua : Allows you to try Lua code directly in WoW.
+
+It is recommended you make small changes then check your coding.
+When testing just start or /reload WoW. All versions now check and load new files on reload.
+
+Routines:
+GetBagSlotInfo will be replaced by your code.
+
+Button_OnEvent will be changed to react to any events your addon needs.
+- All events registered for should be handled here.
+- The display addon is not directly involved in any event handling of this addon.
+--]]
+
+--[[ Code flow within WoW
+First step: ==== Starting WoW
+Wow will load addons in the Addons folder.
+Order is not guaranteed, however dependencies (## Dependencies) are honored.
+
+When this addon is loaded any code outside the Lua functions will be run.
+Examples:
+- local VERSION = GetAddOnMetadata(add_on, "Version")   will set VERSION
+- ...
+- Create_Frames is called
+
+Create_Frames will create the addon frame StarterLDBExample.
+- All created frames will be in the global namespace.
+- All created frames are forever – they are not touched by the Lua garbage collection.
+
+Then Create_frames sets the frame OnEvent script handler. This is the only handler required in this addon.
+
+Then local LDB_Init will initialize the required LDB object.
+This routine should be small :
+- Set the LDB object
+- Set required local variables
+- Register for PLAYER_ENTERING_WORLD
+- *** DO NOT rely on any saved variables (## SavedVariables) being ready here
+
+Next: ==== Waiting for WoW
+WoW fires a bunch of events as addons are loaded.
+
+Eventually the game and all addons are loaded and addons receive the PLAYER_ENTERING_WORLD event via the frame script OnEvent.
+When processing PLAYER_ENTERING_WORLD, register for additional events your addon requires.
+Any saved variables should be ready.
+
+Next: ==== Still waiting for WoW
+The display addon (such as Titan) shows the user requested bars with the user requested addons.
+
+The addon is now ready for the user.
+
+Next: ==== Ready to play WoW! Yeah!
+The addon is 'idle' until one of the following occur:
+- Any registered event is received - OnEvent
+- User clicks on this addon - OnClick via display addon
+- User mouses over addon - OnTooltipShow via display addon
+- User mouse leaves addon - OnLeave via display addon
+
+Next: ====
+The above steps continues until:
+- The user logs out the character or exits WoW or reloads UI - Onhide
+
+On logout or exit any saved variables are saved to the local system.
+No additional actions are required.
+
+--]]
diff --git a/TitanLDB/StarterLDB.lua b/TitanLDB/StarterLDB.lua
new file mode 100644
index 0000000..c0ceadb
--- /dev/null
+++ b/TitanLDB/StarterLDB.lua
@@ -0,0 +1,253 @@
+--[[ StarterLDB.lua
+By: The Titan Panel Development Team
+--]]
+
+
+-- Intended for Intellisense if an IDE supports and is used
+-- Lines starting with triple dash are usually Intellisense
+---@class Frame WoW frame to get events
+---@field obj table For LDB object
+
+-- ******************************** Constants *******************************
+local ADDON_NAME = ...
+-- Set the name we want in the global name space. Ensure the name is unique across all addons.
+StarterLDB = {}
+
+-- NOTE: The 'id' and the 'addon' name are different!
+-- Typically they are the same to reduce user confusion but they do not need to be the same.
+local id = "LDBStarter"; -- Name the user dhould see in the display addon
+local addon = ADDON_NAME -- addon name / folder name / toc name
+
+-- Localized strings are outside the scope of this example.
+
+--[[
+The artwork path must start with Interface\\AddOns
+Then the name of the plugin
+Then any additional folder(s) to your artwork / icons.
+Double backslash will for for Windows; forward slash works fine.
+--]]
+local artwork_path = "Interface/AddOns/TitanLDB/Artwork/"
+---@diagnostic disable-next-line: deprecated, undefined-global
+local GetAddOnMetadata = C_AddOns.GetAddOnMetadata or GetAddOnMetadata
+
+--  Get data from the TOC file.
+local version = tostring(GetAddOnMetadata(addon, "Version")) or "Unknown"
+local author = GetAddOnMetadata(addon, "Author") or "Unknown"
+-- NOTE: GetAddOnMetadata expects the addon name :
+--       The addon folder name or .toc name needs to be the same.
+
+-- ******************************** Variables *******************************
+local trace = false -- toggle to show / hide debug statements in this addon
+
+-- ******************************** Functions *******************************
+
+---Output a debug statement to Chat with timestamp.
+---@param debug_message string
+---@param debug_type string
+local function Debug(debug_message, debug_type)
+	if trace then
+		local dtype = ""
+		local time_stamp = ""
+		local msg = ""
+		if debug_type == "error" then
+			dtype = "Error: "
+		elseif debug_type == "warning" then
+			dtype = "Warning: "
+		end
+		time_stamp = date("%H:%M:%S") .. ": "
+
+		msg =
+			tostring(addon) .. ": "
+			.. time_stamp
+			.. dtype
+			.. debug_message
+
+		_G["DEFAULT_CHAT_FRAME"]:AddMessage(msg)
+	else
+		-- not requested
+	end
+	--date("%m/%d/%y %H:%M:%S")
+end
+
+--- Calculate bag space then return text and icon to display
+---@return string bagText display text
+---@return string icon path to
+local function GetBagSlotInfo()
+	local totalSlots, usedSlots, availableSlots, icon
+	totalSlots = 0;
+	usedSlots = 0;
+	for bag = 0, 4 do
+		local size = C_Container.GetContainerNumSlots(bag);
+		if (size and size > 0) then
+			totalSlots = totalSlots + size;
+			local free = C_Container.GetContainerNumFreeSlots(bag)
+			local used = size - free
+			usedSlots = usedSlots + used;
+		end
+	end
+	availableSlots = totalSlots - usedSlots;
+
+	local i, r = math.modf(availableSlots / 2)
+	-- Simple example of changing the icon : even blue - odd red
+	-- wowhead.com/icons was searched and these selected
+	-- The art was extracted : ../_retail_/BliizardInterfaceArt
+	-- These were found in /Interface/ICONS of the extracted folder by the name used on wowhead
+	-- Copied into /Artwork in case Blizz ever renames or removes these icons.
+	if (r == 0) then
+		icon = artwork_path .. "Bag_Blue.blp"
+	else
+		icon = artwork_path .. "Bag_Red.blp"
+	end
+
+	local bagText
+	bagText = format("%d/%d", availableSlots, totalSlots);
+
+	bagText = HIGHLIGHT_FONT_COLOR_CODE .. bagText .. FONT_COLOR_CODE_CLOSE
+
+	return bagText, icon
+end
+
+--- Create the tooltip
+---@param tooltip GameTooltip From display addon
+local function LDB_OnTooltipShow(tooltip)
+	tooltip = tooltip or GameTooltip  -- for safety
+	local tt_str = ""
+
+	tt_str =
+		GREEN_FONT_COLOR_CODE
+		.. id .. " Info"
+		.. FONT_COLOR_CODE_CLOSE
+	tooltip:AddLine(tt_str)
+
+	local text, icon = GetBagSlotInfo()
+	tt_str = "Available bag slots"
+		.. " " .. text .. "\n"
+		.. "\n" .. "Hint: Left-click to open all bags."
+
+	tooltip:AddLine(tt_str)
+end
+
+--- Initialize the LDB obj and initial set up
+---@param LDB_frame Frame Addon frame
+local function LDB_Init(LDB_frame)
+	Debug(id .. " Init ...", "normal");
+	--[[
+	Initialize the Data Broker 'button'.
+	This is the heart of a LDB plugin. It determines how the display addon is to treat this addon.
+
+	Setting the type is required so the LDB lib and display addon know what to do. See the LDB spec.
+
+	id will be the name Titan uses for the plugin. You can find it in the Titan Config or Titan right click menu.
+	--]]
+
+	LDB_frame.obj =
+		LibStub("LibDataBroker-1.1"):NewDataObject(id, -- Name used within Titan
+		{
+			type          = "data source", -- required
+			-- LDB spec: The two options are:
+			--      "data source" - Expected to show some type of info
+			--      "launcher" - Expected to open another window or perform some action
+			icon          = artwork_path .. "Starter.tga", -- The icon to display on the display addon
+			label         = id,        -- label for the text
+			text          = "nyl",     -- will be updated as needed by this plugin
+			OnTooltipShow = function(tooltip)
+				LDB_OnTooltipShow(tooltip)
+			end,
+			OnClick       = function(self, button)
+				if (button == "LeftButton") then
+					-- Just a simple action to illustrate an LDB addon.
+					ToggleAllBags();
+				elseif (button == "RightButton") then
+					-- There is no action to take in this example.
+					--[[ Add code here if your addon needs to do something on right click.
+						Typically an options menu which is outside the scope of this example.
+					--]]
+				end
+			end,
+			-- Titan specific!!
+			category = "Information", -- Otherwise defaults to General : TITAN_PANEL_BUTTONS_PLUGIN_CATEGORY
+		})
+
+	-- After player entering world it is safe
+	-- - to look at any saved variables
+	-- - register for more events; registering here may cause errors if data is not ready
+	LDB_frame:RegisterEvent("PLAYER_ENTERING_WORLD");
+
+	Debug(id .. " Init fini.", "normal");
+end
+
+--- Update the Bags Data Broker 'button'
+---@param LDB_frame Frame
+local function LDB_Update(LDB_frame)
+	local text, icon = GetBagSlotInfo()
+	LDB_frame.obj.text = text
+	LDB_frame.obj.icon = icon
+end
+
+--- Parse events registered events and act on them
+---@param self Button
+---@param event string
+---@param ... any
+local function Button_OnEvent(self, event, ...)
+	-- https://warcraft.wiki.gg/wiki/UIHANDLER_OnEvent
+
+	Debug("OnEvent"
+		.. " " .. tostring(event) .. ""
+	, "normal")
+	if (event == "PLAYER_ENTERING_WORLD") then
+		-- Do any additional set up needed
+		--
+		-- Now that events have settled, register the one(s) we really want.
+		-- Registering here may reduce churn and possible timing issues wrt data being ready
+		self:RegisterEvent("BAG_UPDATE");
+
+		-- Unregister events no longer needed.
+		-- Good practice to avoid init again - this is fired on /reload
+		self:UnregisterEvent("PLAYER_ENTERING_WORLD");
+
+		-- Update the text (bag numbers)
+		LDB_Update(self)
+
+	end
+	if event == "BAG_UPDATE" then
+		LDB_Update(self)
+	end
+end
+
+--- Create needed frames
+local function Create_Frames()
+	-- general container frame to get events from WoW.
+	-- The display addon will create frame(s) needed to display data set by this addon.
+	local window = CreateFrame("Frame", "StarterLDBExample", UIParent)
+	--	window:Hide()
+
+	-- Set strata as desired
+	window:SetFrameStrata("FULLSCREEN")
+	-- https://warcraft.wiki.gg/wiki/Frame_Strata
+
+	window:SetScript("OnEvent", function(self, event, ...)
+		Button_OnEvent(self, event, ...)
+	end)
+	-- https://warcraft.wiki.gg/wiki/API_ScriptObject_SetScript
+
+	-- Using SetScript("OnLoad",   does not work
+	LDB_Init(window)
+
+	-- shamelessly print a load message to chat window
+	DEFAULT_CHAT_FRAME:AddMessage(
+		GREEN_FONT_COLOR_CODE
+		.. addon .. id .. " " .. version
+		.. " by "
+		.. FONT_COLOR_CODE_CLOSE
+		.. "|cFFFFFF00" .. author .. FONT_COLOR_CODE_CLOSE);
+end
+
+Create_Frames() -- Create WoW frames to get events
+
+--[[
+print(""
+	.." "..tostring(id)..""
+	.." "..tostring(version)..""
+	.." by "..tostring(author)..""
+	)
+--]]
diff --git a/TitanLDB/TitanLDB.toc b/TitanLDB/TitanLDB.toc
new file mode 100644
index 0000000..94e79e1
--- /dev/null
+++ b/TitanLDB/TitanLDB.toc
@@ -0,0 +1,13 @@
+## Interface: 110000
+## Title: StarterLDB
+## Notes: LDB example
+## Author: Titan Dev Team
+## DefaultState: Enabled
+## SavedVariables:
+## OptionalDeps:
+## Dependencies:
+## Version: 1.1
+## X-Child-Of:
+libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
+libs/LibDataBroker-1.1.lua
+StarterLDB.lua
diff --git a/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
new file mode 100644
index 0000000..01287bd
--- /dev/null
+++ b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
@@ -0,0 +1,202 @@
+--[[ $Id: CallbackHandler-1.0.lua 1298 2022-12-12 15:10:10Z nevcairiel $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 8
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+-- Lua APIs
+local securecallfunction, error = securecallfunction, error
+local setmetatable, rawget = setmetatable, rawget
+local next, select, pairs, type, tostring = next, select, pairs, type, tostring
+
+
+local function Dispatch(handlers, ...)
+	local index, method = next(handlers)
+	if not method then return end
+	repeat
+		securecallfunction(method, ...)
+		index, method = next(handlers, index)
+	until not method
+end
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+--   target            - target object to embed public APIs in
+--   RegisterName      - name of the callback registration API, default "RegisterCallback"
+--   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
+--   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler.New(_self, target, RegisterName, UnregisterName, UnregisterAllName)
+
+	RegisterName = RegisterName or "RegisterCallback"
+	UnregisterName = UnregisterName or "UnregisterCallback"
+	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
+		UnregisterAllName = "UnregisterAllCallbacks"
+	end
+
+	-- we declare all objects and exported APIs inside this closure to quickly gain access
+	-- to e.g. function names, the "target" parameter, etc
+
+
+	-- Create the registry object
+	local events = setmetatable({}, meta)
+	local registry = { recurse=0, events=events }
+
+	-- registry:Fire() - fires the given event/message into the registry
+	function registry:Fire(eventname, ...)
+		if not rawget(events, eventname) or not next(events[eventname]) then return end
+		local oldrecurse = registry.recurse
+		registry.recurse = oldrecurse + 1
+
+		Dispatch(events[eventname], eventname, ...)
+
+		registry.recurse = oldrecurse
+
+		if registry.insertQueue and oldrecurse==0 then
+			-- Something in one of our callbacks wanted to register more callbacks; they got queued
+			for event,callbacks in pairs(registry.insertQueue) do
+				local first = not rawget(events, event) or not next(events[event])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+				for object,func in pairs(callbacks) do
+					events[event][object] = func
+					-- fire OnUsed callback?
+					if first and registry.OnUsed then
+						registry.OnUsed(registry, target, event)
+						first = nil
+					end
+				end
+			end
+			registry.insertQueue = nil
+		end
+	end
+
+	-- Registration of a callback, handles:
+	--   self["method"], leads to self["method"](self, ...)
+	--   self with function ref, leads to functionref(...)
+	--   "addonId" (instead of self) with function ref, leads to functionref(...)
+	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+		if type(eventname) ~= "string" then
+			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+		end
+
+		method = method or eventname
+
+		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+
+		if type(method) ~= "string" and type(method) ~= "function" then
+			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+		end
+
+		local regfunc
+
+		if type(method) == "string" then
+			-- self["method"] calling style
+			if type(self) ~= "table" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+			elseif self==target then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+			elseif type(self[method]) ~= "function" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) self[method](self,arg,...) end
+			else
+				regfunc = function(...) self[method](self,...) end
+			end
+		else
+			-- function ref with self=object or self="addonId" or self=thread
+			if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
+				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) method(arg,...) end
+			else
+				regfunc = method
+			end
+		end
+
+
+		if events[eventname][self] or registry.recurse<1 then
+		-- if registry.recurse<1 then
+			-- we're overwriting an existing entry, or not currently recursing. just set it.
+			events[eventname][self] = regfunc
+			-- fire OnUsed callback?
+			if registry.OnUsed and first then
+				registry.OnUsed(registry, target, eventname)
+			end
+		else
+			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
+			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+			registry.insertQueue[eventname][self] = regfunc
+		end
+	end
+
+	-- Unregister a callback
+	target[UnregisterName] = function(self, eventname)
+		if not self or self==target then
+			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+		end
+		if type(eventname) ~= "string" then
+			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+		end
+		if rawget(events, eventname) and events[eventname][self] then
+			events[eventname][self] = nil
+			-- Fire OnUnused callback?
+			if registry.OnUnused and not next(events[eventname]) then
+				registry.OnUnused(registry, target, eventname)
+			end
+		end
+		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+			registry.insertQueue[eventname][self] = nil
+		end
+	end
+
+	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+	if UnregisterAllName then
+		target[UnregisterAllName] = function(...)
+			if select("#",...)<1 then
+				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+			end
+			if select("#",...)==1 and ...==target then
+				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+			end
+
+
+			for i=1,select("#",...) do
+				local self = select(i,...)
+				if registry.insertQueue then
+					for eventname, callbacks in pairs(registry.insertQueue) do
+						if callbacks[self] then
+							callbacks[self] = nil
+						end
+					end
+				end
+				for eventname, callbacks in pairs(events) do
+					if callbacks[self] then
+						callbacks[self] = nil
+						-- Fire OnUnused callback?
+						if registry.OnUnused and not next(callbacks) then
+							registry.OnUnused(registry, target, eventname)
+						end
+					end
+				end
+			end
+		end
+	end
+
+	return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
diff --git a/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
new file mode 100644
index 0000000..a5b22a7
--- /dev/null
+++ b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
@@ -0,0 +1,4 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+	<Script file="CallbackHandler-1.0.lua"/>
+</Ui>
diff --git a/TitanLDB/libs/LibDataBroker-1.1.lua b/TitanLDB/libs/LibDataBroker-1.1.lua
new file mode 100644
index 0000000..4182f2e
--- /dev/null
+++ b/TitanLDB/libs/LibDataBroker-1.1.lua
@@ -0,0 +1,90 @@
+
+assert(LibStub, "LibDataBroker-1.1 requires LibStub")
+assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
+
+local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
+if not lib then return end
+oldminor = oldminor or 0
+
+
+lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
+lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
+local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
+
+if oldminor < 2 then
+	lib.domt = {
+		__metatable = "access denied",
+		__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
+	}
+end
+
+if oldminor < 3 then
+	lib.domt.__newindex = function(self, key, value)
+		if not attributestorage[self] then attributestorage[self] = {} end
+		if attributestorage[self][key] == value then return end
+		attributestorage[self][key] = value
+		local name = namestorage[self]
+		if not name then return end
+		callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
+	end
+end
+
+if oldminor < 2 then
+	function lib:NewDataObject(name, dataobj)
+		if self.proxystorage[name] then return end
+
+		if dataobj then
+			assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
+			self.attributestorage[dataobj] = {}
+			for i,v in pairs(dataobj) do
+				self.attributestorage[dataobj][i] = v
+				dataobj[i] = nil
+			end
+		end
+		dataobj = setmetatable(dataobj or {}, self.domt)
+		self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
+		self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
+		return dataobj
+	end
+end
+
+if oldminor < 1 then
+	function lib:DataObjectIterator()
+		return pairs(self.proxystorage)
+	end
+
+	function lib:GetDataObjectByName(dataobjectname)
+		return self.proxystorage[dataobjectname]
+	end
+
+	function lib:GetNameByDataObject(dataobject)
+		return self.namestorage[dataobject]
+	end
+end
+
+if oldminor < 4 then
+	local next = pairs(attributestorage)
+	function lib:pairs(dataobject_or_name)
+		local t = type(dataobject_or_name)
+		assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
+
+		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+		assert(attributestorage[dataobj], "Data object not found")
+
+		return next, attributestorage[dataobj], nil
+	end
+
+	local ipairs_iter = ipairs(attributestorage)
+	function lib:ipairs(dataobject_or_name)
+		local t = type(dataobject_or_name)
+		assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
+
+		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+		assert(attributestorage[dataobj], "Data object not found")
+
+		return ipairs_iter, attributestorage[dataobj], 0
+	end
+end
diff --git a/TitanLocation/TitanLocation.toc b/TitanLocation/TitanLocation.toc
new file mode 100644
index 0000000..f4afce2
--- /dev/null
+++ b/TitanLocation/TitanLocation.toc
@@ -0,0 +1,10 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fLocation|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\AddOns\TitanLocation\TitanLocation
+## Notes: Adds coordinates and location information to Titan Panel
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## OptionalDeps:
+## Dependencies: Titan
+TitanLocation.lua
diff --git a/TitanLocation/TitanLocation_Mainline.toc b/TitanLocation/TitanLocation_Mainline.toc
deleted file mode 100644
index 0f24b24..0000000
--- a/TitanLocation/TitanLocation_Mainline.toc
+++ /dev/null
@@ -1,10 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fLocation|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\AddOns\TitanLocation\TitanLocation
-## Notes: Adds coordinates and location information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanLocation.lua
diff --git a/TitanLocation/TitanLocation_Vanilla.toc b/TitanLocation/TitanLocation_Vanilla.toc
deleted file mode 100644
index 24545fd..0000000
--- a/TitanLocation/TitanLocation_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fLocation|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Adds coordinates and location information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanLocation.lua
diff --git a/TitanLootType/TitanLootType.toc b/TitanLootType/TitanLootType.toc
new file mode 100644
index 0000000..2b61c9f
--- /dev/null
+++ b/TitanLootType/TitanLootType.toc
@@ -0,0 +1,10 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\AddOns\TitanLootType\TitanLootType
+## Notes: Adds group loot and instance difficulty information to Titan Panel
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## OptionalDeps:
+## Dependencies: Titan
+TitanLootType.lua
diff --git a/TitanLootType/TitanLootType_Classic.toc b/TitanLootType/TitanLootType_Classic.toc
index 3f0d33c..a07b439 100644
--- a/TitanLootType/TitanLootType_Classic.toc
+++ b/TitanLootType/TitanLootType_Classic.toc
@@ -1,9 +1,9 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Adds group loot and instance difficulty information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables: TitanClassicLootTypeSaved
-## OptionalDeps:
-## Dependencies: Titan
-TitanClassicLootType.xml
+## Interface: 11507, 40401
+## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## Notes: Adds group loot and instance difficulty information to Titan Panel
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables: TitanClassicLootTypeSaved
+## OptionalDeps:
+## Dependencies: Titan
+TitanClassicLootType.xml
diff --git a/TitanLootType/TitanLootType_Mainline.toc b/TitanLootType/TitanLootType_Mainline.toc
deleted file mode 100644
index 4ceb153..0000000
--- a/TitanLootType/TitanLootType_Mainline.toc
+++ /dev/null
@@ -1,10 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\AddOns\TitanLootType\TitanLootType
-## Notes: Adds group loot and instance difficulty information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanLootType.lua
diff --git a/TitanPerformance/TitanPerformance.toc b/TitanPerformance/TitanPerformance.toc
new file mode 100644
index 0000000..b44c307
--- /dev/null
+++ b/TitanPerformance/TitanPerformance.toc
@@ -0,0 +1,10 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fPerformance|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\AddOns\TitanPerformance\TitanPerformance
+## Notes: Adds FPS and Garbage collection information to Titan Panel
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## OptionalDeps:
+## Dependencies: Titan
+TitanPerformance.lua
diff --git a/TitanPerformance/TitanPerformance_Mainline.toc b/TitanPerformance/TitanPerformance_Mainline.toc
deleted file mode 100644
index 64ffe84..0000000
--- a/TitanPerformance/TitanPerformance_Mainline.toc
+++ /dev/null
@@ -1,10 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fPerformance|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\AddOns\TitanPerformance\TitanPerformance
-## Notes: Adds FPS and Garbage collection information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanPerformance.lua
diff --git a/TitanPerformance/TitanPerformance_Vanilla.toc b/TitanPerformance/TitanPerformance_Vanilla.toc
deleted file mode 100644
index b0e1efe..0000000
--- a/TitanPerformance/TitanPerformance_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fPerformance|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Adds FPS and Garbage collection information to Titan Panel
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanPerformance.lua
diff --git a/TitanPlugin/Artwork/TitanStarter.tga b/TitanPlugin/Artwork/TitanStarter.tga
new file mode 100644
index 0000000..6a7ddda
Binary files /dev/null and b/TitanPlugin/Artwork/TitanStarter.tga differ
diff --git a/TitanPlugin/DevReadMe.lua b/TitanPlugin/DevReadMe.lua
new file mode 100644
index 0000000..c0a438d
--- /dev/null
+++ b/TitanPlugin/DevReadMe.lua
@@ -0,0 +1,539 @@
+--[[ Titan Example with Explanation
+
+This example will introduce Titan plugin essentials using a Titan plugin loosely based on Titan Bag.
+The intent is to clarify what may appear to be a daunting experience.
+
+We suggest you grab your favorite beverage, read this doc, and relax!
+Many of Titan mysteries will be explained. Helping you create a tool your audience will enjoy. 🙂
+
+The Titan team and its users are available to answer questions.
+The two most used ways are :
+- The Titan Discord community - https://discord.gg/e93sxuSPwC
+- Curse comments under Titan Panel addon
+
+Using a text editor with code folding features will make this file easier to read and find information.
+Notepad++ is a popular Windows code editor.
+Visual Studio Code with a couple extensions can be used to develop WoW addons.
+--]]
+
+--[[ Titan Panel Notes:
+- Use the current version of Titan to ensure no errors.
+- You may freely use this example for addon development and publish it on WoW addon sites like Curseforge. If published, please add the Titan tag for users.
+- The terms addon and plugin are essentially the same. Within this document, plugin is used when the addon is displayed by Titan.
+- Titan includes several libraries under the Titan/libs folder. You are free to use these.
+If you require additional libraries, please include them within your addon.
+
+=== Out of Scope Notes:
+- A discussion on Lua syntax. A basic understanding of Lua is assumed.
+- Timers are outside the scope of this example. See other Titan built-in plugins that use timers (AceTimer) such as TitanClock.
+- Localization of strings presented to the user. Titan uses AceLocale; other addons use different schemes.
+- Ace library information. Titan includes the Ace libraries it uses - not the entire library. (https://www.wowace.com)
+- The API for LDB (LibDataBroker) : (https://github.com/tekkub/libdatabroker-1-1)
+- WoW images : Some image type info (https://warcraft.wiki.gg/wiki/API_TextureBase_SetTexture)
+--]]
+
+--[[ “Best Practices” When Creating Your Addon/Plugin
+=== Naming Convention
+When publishing your addon/plugin please use this naming convention :
+
+Titan Panel [Name]
+
+Using this naming format, most Titan users will understand this plugin is intended for Titan Panel.
+They should know to contact you first instead of the Titan Panel team.
+The Titan team does receive comments and errors from time to time. We usually tell them to contact the plugin developer.
+
+=== Additional Help For You
+A good Lua resource is https://www.lua.org/docs.html
+NOTE: WoW uses Lua version 5.1 as its base.
+NOTE: WoW does restrict, add, or even remove some Lua features. For example the file routines and many OS routines are not available to an addon.
+
+There are sites that have deeper explanations about addon development, such as
+- Wowhead.com
+- Warcraft wiki (Warcraft.Wiki.gg).
+Please use these or other sites for more detailed addon and API information. The API information changes over time for several reasons.
+--]]
+
+--[[ Running right now!
+The folder and .toc file prefix MUST be the same to be considered for loading into WoW!
+See the .toc section under Example Folder Structure.
+
+=== Steps needed to run this example:
+- Unzip this example to your WoW installation: ../World of Warcraft/_retail_/Interface/AddOns
+- Ensure the folder name is TitanPlugin
+- Start or reload WoW
+
+That is it!
+You should see another Titan Bag icon in any version of WoW you are running.
+You are now ready to start changing code.
+--]]
+
+--[[ Example Folder Structure
+Inside this folder you will notice :
+- Artwork folder : with one .tga file - the icon used by the plugin
+- libs : empty, ready for any library routines you may need
+- three .toc files
+- one .lua file – for your great idea
+- a ReadMe file - This file
+
+=== .toc
+
+The folder and the .toc files MUST have the same name!
+Sort of... the name prior to the underscore(_) must be the same as the folder name.
+The part after (postfix) has meaning to the WoW addon loader.
+https://warcraft.wiki.gg/wiki/TOC_format : Contains the full list and A LOT more detail about .toc files
+
+If your addon is only for Classic Era leave <addon>_Vanilla. Delete (or rename) the other .toc files.
+Titan uses this TOC method. Notice TitanAmmo and TitanRegen.
+This allows Titan to load differently so plugins (built-in or 3rd party) intended for Classic versions can run without change.
+
+=== .toc internals
+NOTE: The ## Interface value should match the current interface value of the corresponding WoW version.
+In BattleNet this is typically shown below the 'Play' button.
+DragonFlight 10.02.05 is represented without dots - 100207 - in the .toc.
+
+If the interface value is higher or lower, WoW will complain that you are running 'out of date' addons.
+
+== .lua
+
+This is the code for the plugin.
+
+Titan specific details will be noted and explained within the Lua file.
+The comments will specify where names are important.
+
+The plugin starts with local constants used throughout.
+Then local variables; then functions.
+
+Suggestion is start with Create_Frames routine at the bottom of the file. It is where the magic starts.
+
+NOTES:
+- Titan locale strings (using AceLocale) were left in the code so the example will run as is. Please use your own strings - localized or not.
+- Feel free to look at Titan code for Lua examples.
+- Any routine marked with ---API can be used by a plugin.
+Titan API routines will be maintained and the functionality expected to remain stable.
+Any parameter or functionality changes to API will be 'broadcast' on delivery sites and our sites (Discord, our web page).
+
+=== .tga
+
+This file is the icon used by the plugin.
+This file is also specified in the .registry of the Lua file – detailed later in this doc.
+--]]
+
+--[[ Start editing
+
+Before you start changing this example, it is HIGHLY recommended to install the following WoW addons:
+- BugGrabber : Grabs errors and stores them
+- BugSack : The visual part of BugGrabber
+- WowLua : This allows you to try Lua code directly in WoW.
+
+Install a code / text editor. Notepad++ is a very popular editor.
+
+Small changes are recommended; then test your coding.
+When testing, just start or /reload WoW. All versions now check and load new files on reload.
+
+First Routines to change:
+- GetBagData will be replaced by your code. It uses the local function IsProfessionBagID.
+- ToggleBags is called from OnClick. This will be replaced by your code that handles mouse clicks.
+- CreateMenu will be changed to implement your right click menu, if one is needed.
+
+Other routines may be modified to implement your idea.
+
+--]]
+
+--[[ Addon code flow
+
+First step: ==== Starting WoW
+Wow will load this addon after Titan is loaded.
+
+NOTE: The .toc states Titan is required [## Dependencies: Titan].
+WoW will load Titan BEFORE this addon.
+
+Any code outside the Lua functions will be run.
+Examples:
+- local VERSION = GetAddOnMetadata(add_on, "Version") will run GetAddOnMetadata
+- bag_info will be populated
+- ...
+- Create_Frames is called
+
+Create_Frames will create the addon frame and name it the string in TITAN_BUTTON.
+All created frames will be in the global namespace.
+All created frames are forever – they are not touched by the Lua garbage collection.
+
+Then local OnLoad is called when WoW loads the frame into memory.
+
+OnLoad does two important things
+1) Sets the .registry of the addon - See the .registry comment block
+2) Registers for event PLAYER_ENTERING_WORLD
+
+NOTE: OnLoad should :
+- Be small
+- NOT assume plugin saved variable data are ready / loaded yet
+
+Then Create_frames sets the frame scripts for the addon. See Frame Scripts block.
+
+Next: ==== Waiting for WoW
+WoW fires a bunch of events as this and other addons are loaded.
+
+Eventually the game and all addons are loaded and this plugin receives the PLAYER_ENTERING_WORLD event via the frame script OnEvent.
+When processing PLAYER_ENTERING_WORLD, only register for events and access local data this plugin needs.
+Do NOT assume saved variables from the registry or any server data are ready.
+
+Titan also receives the PLAYER_ENTERING_WORLD event.
+It is best to assume there is NO guarantee this plugin receives the event before or after Titan!
+
+Titan then processes its own data, creates Titan bars, registers Titan plugins and LDB addons, and syncs plugin saved variables.
+Titan will process any saved variables specified in the .registry of this plugin!
+
+Next: ==== Still waiting for WoW
+Titan shows the user requested bars with the user requested plugins.
+OnShow is called by Titan only if the user has requested the plugin to be shown.
+It is best to assume any saved variables in .registry are NOT ready until OnShow!
+
+OnShow now does the processing to set up this plugin and its data properly.
+Lastly OnShow needs to call TitanPanelButton_UpdateButton to update the plugin text.
+The plugin is now ready for the user.
+
+Next: ==== Ready to play WoW, Yeah!
+The plugin will be 'idle' until one of the following occur:
+- Titan needs to (re)display this plugin -  TitanPanelButton_UpdateButton
+- User selects to show this plugin via Titan Config or menu -  TitanPanelButton_UpdateButton
+- User changes a plugin option using the Titan plugin menu :  TitanPanelButton_UpdateButton
+- User clicks on this plugin - Right click .menuTextFunction; any other OnClick
+- Any registered event is received - OnEvent
+- User mouses over plugin - OnEnter
+- User mouse leaves plugin - OnLeave
+- A timer or callback calls a plugin routine – AceTimer
+
+Next: ====
+The above steps continue until:
+- User hides the plugin - OnHide
+- The user logs out the character or exits WoW or reloads UI - Onhide
+
+On logout or exit the saved variables are saved to the local system - .registry.savedVariables .
+No additional actions are required.
+
+==== Using OnShow to set up this addon is good practice :
+It should:
+- Register any events the plugin will react to
+- Process any saved variable data such as user options
+- Create any timers
+- Set the initial plugin - icon, label, text
+
+This ensures:
+- All saved variable data is set and ready
+- Less processing if the user never selects the plugin
+
+==== Using OnHide to clean up is good practice :
+It should:
+- Unregister any events the plugin registered for
+- Cancel any timers
+- Cleanup any plugin specific data or objects
+
+This ensures:
+- Less processing after the user clicks Hide
+
+==== TitanPanelButton_UpdateButton(TITAN_PLUGIN) should be called by this plugin whenever the plugin text could change :
+- On processing an event registered for
+- On user left click – some action taken
+- On user right click – plugin menu
+
+NOTE: TitanPanelButton_UpdateButton expects label - value pairs (up to 4).
+TitanPerformance uses and shows multiple label - value pairs, based on user selection.
+
+Titan uses ShowLabelText to control showing the label or not. This plugin only returns the expected label(s).
+
+==== OnEnter and OnLeave
+NOTE: The Titan template handles OnEnter and OnLeave to show or hide the tooltip.
+Titan calls the specified routine to show the tooltip – .registry.tooltipTextFunction.
+Titan expects a formatted string as the return from the function.
+
+==== Additional saved variables specific to this addon must be handled by this addon and are outside the scope of this example.
+Titan Gold is a Titan plugin that has its own saved variables.
+--]]
+
+--[[ Frame Scripts
+
+The frame scripts are how WoW and Titan interact with this addon.
+NOTE: The creation of the frame also creates scripts handlers. This is a bit hidden by the 'inherits' "TitanPanelComboTemplate" below.
+	local window = CreateFrame("Button", TITAN_BUTTON, f, "TitanPanelComboTemplate")
+TitanTemplate.xml defines TitanPanelButtonTemplate as the base for each of its plugin types - Combo / Text / Icon.
+TitanPanelButtonTemplate sets OnLoad / OnShow / OnClick / OnEnter / OnLeave where each calls TitanPanelButton_On*.
+If the script is overriden in the plugin, it should call the appropriate TitanPanelButton_On* routine as shown below.
+In a few cases, the default is not called because the plugin replaces what Titan would do.
+TitanPerformance, for example overrides OnClick to create a custom right click menu.
+
+==== OnShow script :
+This is triggered when this plugin (frame) is shown.
+Technically :
+- WoW calls the now registered plugin frame - TITAN_BUTTON:OnShow() as set in Create_Frames
+- Which calls the local OnShow to init the plugin
+- Then calls TitanPanelButton_OnShow to update the plugin button text
+
+==== OnClick script :
+This is triggered when this plugin (frame) has been clicked by the mouse.
+Technically :
+- WoW calls the now registered plugin frame - TITAN_BUTTON:OnClick() as set in Create_Frames
+- Which calls the local OnClick to handle left click (or any click / mod-click other than right click)
+- Then calls TitanPanelButton_OnClick to handle right click (plugin menu) – see ‘Right Click’ below
+
+== Right click:
+TitanPanelButton_OnClick is called to handle right click generically because it will
+- Close any open control frame
+- Close any tooltip
+- Position the menu relative to the plugin on whatever Titan bar it is on
+- Call the plugin routine to create the actual menu content
+
+The plugin routine here is local CreateMenu.
+
+The plugin can inform Titan of the routine in one of two ways:
+1) Specify in .registry.menuTextFunction - preferred
+2) Named routine in the global namespace with the expected name of - TitanPanelRightClickMenu_Prepare<id>Menu
+- For this plugin the name would be TitanPanelRightClickMenu_PrepareStarterMenu
+Titan will use the registry over the created routine. It will not use both.
+
+==== OnEnter script :
+OnEnter is handled by the Titan template to show the tooltip next to the plugin wherever it may be.
+It calls the routine specified in .registry.tooltipTextFunction.
+This routine is expected to return a formatted string to be shown inthe tooltip.
+
+==== OnLeave script :
+OnLeave is handled by the Titan template to hide the tooltip.
+
+==== OnHide script :
+This is triggered when this plugin (frame) has been hidden by the user :
+- via the plugin menu
+- via Titan config
+- On exit or logout or /reload
+Technically :
+- WoW calls the now registered plugin frame - TITAN_BUTTON:OnHide() as set in Create_Frames
+- Which calls the local OnHide
+The local OnHide should :
+- Do any cleanup your plugin needs
+- Stop any timers
+- Unregister any events
+These steps keep processing to a minimum and reduce the chance of errors to the user.
+
+==== OnEvent script :
+This is triggered when any event this plugin (frame) has registered for is fired.
+Technically :
+- WoW calls the now registered plugin frame - TITAN_BUTTON:OnEvent() as set in Create_Frames
+- Which calls the local OnEvent to handle all registered events
+
+Titan Bag uses PLAYER_ENTERING_WORLD to handle a difference between Retail and Classic versions when opening bags via the addon.
+
+BAG_UPDATE just updates the text (count) whenever this event is fired.
+NOTE: The event also fires when moving items within the bag...
+--]]
+
+--[[ .registry attributes
+This is the GUTS of a Titan plugin. The .registry table on the frame contains all the information to register the plugin for display.
+
+Every plugin registry with an id should appear in Titan > Configuration > Attempts.
+Information about the plugin is shown there along with pass / fail.
+If the plugin failed to register, the error is shown there.
+
+NOTE: Titan looks for 3 routines. See .registry Routines.
+
+Attributes:
+.id : Required : must be unique across Titan plugins. If there are duplicates, the first one 'wins'.
+.category : The general grouping this plugin is in.
+	The complete category list is in 	TITAN_PANEL_BUTTONS_PLUGIN_CATEGORY (TitanGlobal.lua)
+	"Built-ins" is reserved for plugins that Titan releases.
+.version : plugin version shown in menus and config.
+.menuText : Used as the title for the right click menu.
+.menuTextFunction : See .registry Routines.
+.buttonTextFunction : See .registry Routines.
+.tooltipTitle : Used as the title for the tool tip
+.tooltipTextFunction : See .registry Routines.
+.icon : Allowed path to the icon to be used.
+	It is recommended to store the icon in the plugin folder, even if exists within WoW.
+.iconWidth : Best left at 16...
+.notes : This is shown in Titan > Config > Plugins when this plugin is selected.
+.controlVariables : This list is controls whether the variable is shown. See below.
+.savedVariables : These are the variables stored in Titan saved variables.
+	The initial values are used only if that particular entry is 'new' to
+	that character (new Titan install, new character, character new to Titan).
+	If a value is removed then it is removed from the saved variables as Titan is run for each character.
+
+== .controlVariables
+These are used to show or hide 'controls' in the Titan config or Titan right click menu.
+- ShowIcon
+- ShowLabelText
+- ShowColoredText
+- DisplayOnRightSide
+- ShowRegularText (LDB only)
+If true, the control is shown to the user.
+If false, the control is not shown to the user.
+--]]
+
+--[[ .registry Saved Variables
+
+All saved variables for this plugin are listed within savedVariables
+- ShowUsedSlots = 1,
+- ShowDetailedInfo = false,
+- CountProfBagSlots = false,
+- ShowIcon = 1,
+- ShowLabelText = 1,
+- ShowColoredText = 1,
+- DisplayOnRightSide = false,
+- OpenBags = false,
+- OpenBagsClassic = "new_install",
+
+Plugin variables :
+- ShowUsedSlots : Show used versus available slots
+- ShowDetailedInfo : Show bag details in the tooltip
+- CountProfBagSlots : Whether to include, or not, profession bags in the counts
+- OpenBags : Whether to open bags on left click or not. Included due to a taint issue introduced by WoW
+- OpenBagsClassic : Used to determine a new install / new character (to Titan or just created)
+
+Titan uses the below to control display of the plugin :
+- ShowIcon : Whether the icon,if specified is shown
+- ShowLabelText : Whether the labels returned by buttonTextFunction are shown
+- ShowColoredText : Whether the text is 'colored' or not
+- DisplayOnRightSide : Put this plugin in the right side of the Titan bar
+
+ShowColoredText is plugin specific. Generally used to indicate a range such as your bags are empty (green) to nearly full (red).
+If the plugin does not need this then please set controlVariables > ShowColoredText to false to prevent the user from seeing
+the option and potentially getting confused.
+
+NOTE: Titan routines have used 1 as true since inception so be careful on 'true checks'.
+"if ShowUsedSlots then " *should* work fine if ShowUsedSlots is true or 1
+
+=== Where are these saved variables?????
+The saved variables are specified in the Titan toc :
+## SavedVariables: TitanAll, TitanSettings, TitanSkins, ServerTimeOffsets, ServerHourFormat
+
+TitanSettings contains all the plugin saved variables.
+Titan uses the single table structure to store the saved variables across a user account.
+This makes the setup code rather cumbersome and not straight forward - just warning...
+
+The saved variables can be found here: .../World of Warcraft/_retail_/WTF/Account/(account name>/SavedVariables/Titan.lua
+There is a Titan.lua.bak which is the prior save (logout / exit / reload).
+
+It is HIGHLY recommended opening the saved variables file in an editor with code folding features!
+This file could be quite large with many lines.
+I have 20+ characters on one server. Even though I do not use many addons, I do test with addons on some characters.
+A plugin such as Titan Panel [Reputation] can create 100+ plugins. My file is nearly 90,000 lines long!
+
+Say we want to find a character named Embic on Staghelm being used for testing to examine the saved variables.
+This would under
+TitanSettings = {
+	["Players"] = {
+		["Embic@Staghelm"] = {
+			["Panel"] = {
+				-- Holds all the Titan settings for this character
+				}
+			["BarVars"] = {
+				-- Holds all the Titan bar settings for this character
+				}
+			["Plugins"] = {
+				-- Each registered plugin will be here
+					["Starter"] = {
+						["notes"] = "Adds bag and free slot information to Titan Panel.\n",
+						["menuTextFunction"] = nil,
+						["id"] = "Starter",
+						["menuText"] = "Bag",
+						["iconWidth"] = 16,
+						["savedVariables"] = {
+							["ShowColoredText"] = 1,
+							["CustomLabel3Text"] = "",
+							["ShowIcon"] = 1,
+							["OpenBags"] = false,
+							["CustomLabel3TextShow"] = false,
+							["CustomLabelTextShow"] = false,
+							["CustomLabel4Text"] = "",
+							["CustomLabel2Text"] = "",
+							["OpenBagsClassic"] = "new_install",
+							["ShowLabelText"] = 1,
+							["CustomLabel4TextShow"] = false,
+							["CountProfBagSlots"] = false,
+							["ShowUsedSlots"] = 1,
+							["DisplayOnRightSide"] = false,
+							["ShowDetailedInfo"] = false,
+							["CustomLabel2TextShow"] = false,
+							["CustomLabelText"] = "",
+						},
+						["controlVariables"] = {
+							["DisplayOnRightSide"] = true,
+							["ShowColoredText"] = true,
+							["ShowIcon"] = true,
+							["ShowLabelText"] = true,
+						},
+						["version"] = "1.0.0",
+						["category"] = "Information",
+						["buttonTextFunction"] = nil ,
+						["tooltipTextFunction"] = nil ,
+						["icon"] = "Interface\\AddOns\\TitanPlugin\\Artwork\\TitanStarter",
+						["tooltipTitle"] = "Bags Info",
+					},
+				}
+			["Adjust"] = {
+				-- Holds offsets for frames the user may adjust - Retail and Classic have different list of frames
+				}
+			["Register"] = {
+				-- Holds data as each plugin and LDB is attempted to be registered.
+				-- There may be helpful debug data here under your plugin name if the plugin is not shown as expected.
+				-- Titan > Configuration > Attempts shows some of this data, including errors.
+				}
+
+NOTES:
+- "Starter" index under Plugins is also .registry.id !!
+- This lists the last saved contents of .registry - NOT what is in memory!
+- This file contains all the tables specified in the Titan .toc file.
+
+--]]
+--[[ .registry Routines
+
+Titan looks for 3 routines specified in the .registry :
+- .buttonTextFunction : Routine that updates the plugin text.
+- .tooltipTextFunction : Routine that generates the tool tip text.
+- .menuTextFunction : Routine that creates the options for the menu (right click) OR "TitanPanelRightClickMenu_Prepare"<id>"Menu"
+
+.menuTextFunction : This is the routine called by Titan on right click so the plugin can create its menu.
+	1) This is the newer, preferred method which makes the options menu routine explicit (changed 2024 Feb).
+	If found, this will be used over the older method - both will not be used.
+	NOTE: Routine can be specified :
+	--- As a string, it MUST be in the global namespace. Strings were the only method for a long time.
+	--- As a function, it may be in the global namespace but could be local. This example uses a local routine which is preferred.
+
+	2) The older method is still supported!
+	Titan builds the expected routine name as "TitanPanelRightClickMenu_Prepare"<id>"Menu".
+	In this example it would be : TitanPanelRightClickMenu_PrepareStarterMenu
+
+.buttonTextFunction : This is called whenever the button is to be updated.
+	This is called from within the plugin and from Titan by calling TitanPanelButton_UpdateButton(TITAN_PLUGIN) .
+	Titan will usually return "<?>" if the routine dies.
+	If you need to see the error, search for this attribute in the Titan folder and uncomment the print of the error message.
+	This may generate a LOT of messages!
+.tooltipTextFunction : This is called when the mouse enters the plugin frame is triggered.
+	The Titan templates set the OnEnter script for the plugin frame.
+	On a tooltip error, Titan will usually show part of the error in the tool tip.
+	If you need to see the full error, search for this attribute in the Titan folder and uncomment the print of the error message.
+
+NOTE: The .registry routines are called securely using pcall to protect Titan.
+These routines are expected to have NO parameters. Handling parameters was not implemented in any version of Titan.
+--]]
+--[[ Special Icons and Artwork
+
+Anyone can extract the Blizzard UI code and art from WoW. This can be handy to get code examples.
+And to grab icons to use for a plugin. My understanding is any icon can be used within WoW without violating the ToS.
+WoW icons tend to be .blp files. These files are NOT easy to look at or manipulate!!
+You will need to research third party tools to manipulate .blp files.
+BLPView (Windows only) from wowinterface is light and easy to view blp files as thumbnail pics in File Explorer.
+
+==== Extracting art and code
+Add the switch -console when starting WoW.
+In BattleNet click the Settings (next to Play) then Game Settintgs. Add as an additional command line argument.
+
+Start WoW but stay on the character screen.
+Hit the ~ (tilde) key to open a text console which will appear from the top of the screen.
+Type exportInterfaceFiles (can tab to auto fill) with parameter code or art
+exportInterfaceFiles code
+exportInterfaceFiles art
+
+These must be run separately. Code should take a second or so; art may take some time and appear to hang the game.
+
+For retail, the result will be here :
+.../World of Warcraft/_retail_/BlizzardInterfaceCode
+.../World of Warcraft/_retail_/BlizzardInterfaceArt
+--]]
+
diff --git a/TitanPlugin/TitanPlugin.toc b/TitanPlugin/TitanPlugin.toc
new file mode 100644
index 0000000..7b177cd
--- /dev/null
+++ b/TitanPlugin/TitanPlugin.toc
@@ -0,0 +1,9 @@
+## Interface: 110000
+## Title: Titan Starter
+## Version: 1.0.0
+## Notes: Adds bag and free slot information to Titan Panel
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## Dependencies: Titan
+## DefaultState: Enabled
+TitanStarter.lua
diff --git a/TitanPlugin/TitanStarter.lua b/TitanPlugin/TitanStarter.lua
new file mode 100644
index 0000000..c8edc4b
--- /dev/null
+++ b/TitanPlugin/TitanStarter.lua
@@ -0,0 +1,569 @@
+---@diagnostic disable: duplicate-set-field
+--[[
+-- **************************************************************************
+-- * TitanStarter.lua
+-- *
+-- * By: The Titan Panel Development Team
+-- **************************************************************************
+--]]
+-- ******************************** Constants *******************************
+local add_on = ...
+local _G = _G --getfenv(0);
+local artwork_path = "Interface\\AddOns\\TitanPlugin\\Artwork\\"
+-- NOTE: The plugin id needs be unique across Titan plugins
+-- It does not need to match the addon id.
+local TITAN_PLUGIN = "Starter"
+-- NOTE: The convention is TitanPanel<id>Button
+local TITAN_BUTTON = "TitanPanel" .. TITAN_PLUGIN .. "Button"
+local VERSION = C_AddOns.GetAddOnMetadata(add_on, "Version")
+
+local TITAN_BAG_THRESHOLD_TABLE = {
+	Values = { 0.5, 0.75, 0.9 },
+	Colors = { HIGHLIGHT_FONT_COLOR, NORMAL_FONT_COLOR, ORANGE_FONT_COLOR, RED_FONT_COLOR },
+}
+
+-- ******************************** Variables *******************************
+local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true)
+
+local bag_info = {                   -- itemType : warcraft.wiki.gg/wiki/itemType
+	[1] =                            -- Soul bag
+	{ color = { r = 0.96, g = 0.55, b = 0.73 } }, -- PINK
+	[2] =                            -- HERBALISM =
+	{ color = { r = 0, g = 1, b = 0 } }, -- GREEN
+	[3] =                            -- ENCHANTING =
+	{ color = { r = 0, g = 0, b = 1 } }, -- BLUE
+	[4] =                            -- ENGINEERING =
+	{ color = { r = 1, g = 0.49, b = 0.04 } }, -- ORANGE
+	[5] =                            -- JEWELCRAFTING =
+	{ color = { r = 1, g = 0, b = 0 } }, -- RED
+	[6] =                            -- MINING =
+	{ color = { r = 1, g = 1, b = 1 } }, -- WHITE
+	[7] =                            -- LEATHERWORKING =
+	{ color = { r = 0.78, g = 0.61, b = 0.43 } }, -- TAN
+	[8] =                            -- INSCRIPTION =
+	{ color = { r = 0.58, g = 0.51, b = 0.79 } }, -- PURPLE
+	[9] =                            -- FISHING =
+	{ color = { r = 0.41, g = 0.8, b = 0.94 } }, -- LIGHT_BLUE
+	[10] =                           -- COOKING =
+	{ color = { r = 0.96, g = 0.55, b = 0.73 } }, -- PINK
+	-- These are Classic arrow or bullet bags
+	[22] =                           -- Classic arrow
+	{ color = { r = 1, g = .4, b = 0 } }, -- copper
+	[23] =                           -- Classic bullet
+	{ color = { r = 0.8, g = 0.8, b = 0.8 } }, -- silver
+}
+
+local trace = false -- true / false    Make true when debug output is needed.
+
+local MIN_BAGS = 0
+local MAX_BAGS = Constants.InventoryConstants.NumBagSlots
+local bag_data = {} -- to hold the user bag data
+
+-- ******************************** Functions *******************************
+---@diagnostic disable-next-line: deprecated
+local GetInstant = C_Item.GetItemInfoInstant or GetItemInfoInstant
+
+local function IsProfessionBagID(slot)
+	-- The info needed is available using GetItemInfoInstant; only the bag / item id is required
+	-- itemType : warcraft.wiki.gg/wiki/itemType
+	local res = false
+	local style = 0
+	local info, itemId, itemType, itemSubType, itemEquipLoc, itemTexture, classID, subclassID
+	local inv_id = C_Container.ContainerIDToInventoryID(slot)
+
+	if inv_id == nil then
+		-- Only works on bag and bank bags NOT backpack!
+	else
+		info = GetInventoryItemLink("player", inv_id)
+		itemId, itemType, itemSubType, itemEquipLoc, itemTexture, classID, subclassID = GetInstant(info)
+		style = subclassID
+
+		if classID == 1 then -- is a container / bag
+			if subclassID >= 1 then
+				-- profession bag of some type [2 - 10] Jan 2024 (DragonFlight / Wrath / Classic Era)
+				-- OR soul bag [1]
+				res = true
+			else
+				-- is a arrow or bullet; only two options
+			end
+		elseif classID == 6 then -- is a 'projectile' holder
+			res = true
+			-- is a ammo bag or quiver; only two options
+		elseif classID == 11 then -- is a 'quiver'; Wrath and CE
+			res = true
+			-- is a ammo pouch or quiver; only two options
+			style = subclassID + 20 -- change to get local color for name
+		else
+			-- not a bag
+		end
+	end
+
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "T isP:"
+			.. " " .. tostring(res) .. ""
+			.. " " .. tostring(style) .. ""
+			.. " " .. tostring(itemId) .. ""
+			.. " " .. tostring(classID) .. ""
+			.. " " .. tostring(subclassID) .. ""
+			.. " " .. tostring(inv_id) .. ""
+		)
+	end
+
+	return res, style
+end
+
+local function ToggleBags()
+	if TitanGetVar(TITAN_PLUGIN, "OpenBags") then
+		ToggleAllBags()
+	else
+	end
+end
+
+--[[
+Where the magic happens!
+It is good practice - and good memory - to document the 'why' the code does what it does.
+And give details that are not obvious to the reader who did not write the code.
+--]]
+local function GetBagData(id)
+	--[[
+	The bag name is not always available when player entering world
+	Grabbing the total slots is available though to determine if a bag exists.
+	The user may see bag name as UNKNOWN until an event triggers a bag check AND the name is available.
+	--]]
+
+	local total_slots = 0
+	local total_free = 0
+	local total_used = 0
+
+	local count_prof = TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots")
+
+	for bag_slot = MIN_BAGS, MAX_BAGS do -- assuming 0 (Backpack) will not be a profession bag
+		local slots = C_Container.GetContainerNumSlots(bag_slot)
+
+		-- Ensure a blank structure exists
+		bag_data[bag_slot] = {
+			has_bag = false,
+			name = "",
+			maxi_slots = 0,
+			free_slots = 0,
+			used_slots = 0,
+			style = "",
+			color = "",
+		}
+
+		if slots > 0 then
+			bag_data[bag_slot].has_bag = true
+
+			local bag_name = (C_Container.GetBagName(bag_slot) or UNKNOWN)
+			bag_data[bag_slot].name = bag_name
+			bag_data[bag_slot].maxi_slots = slots
+
+			local free = C_Container.GetContainerNumFreeSlots(bag_slot)
+			local used = slots - free
+			bag_data[bag_slot].free_slots = free
+			bag_data[bag_slot].used_slots = used
+
+			-- some info is not known until the name is available...
+			-- The API requires name to get the bag ID.
+			local bag_type = "none"
+			local color = { r = 0, g = 0, b = 0 } -- black (should never be used...)
+
+			-- Jan 2024 : Moved away from named based to an id based. Allows name to come later from server
+			local is_prof_bag, style = IsProfessionBagID(bag_slot)
+
+			if is_prof_bag then
+				color = bag_info[style].color
+				bag_type = "profession"
+			else
+				bag_type = "normal"
+			end
+			bag_data[bag_slot].style = bag_type
+			bag_data[bag_slot].color = color
+
+			-- add to total
+			if bag_data[bag_slot].style == "profession" then
+				if count_prof then
+					total_slots = total_slots + slots
+					total_free = total_free + free
+					total_used = total_used + used
+				else
+					-- ignore in totals
+				end
+			else
+				total_slots = total_slots + slots
+				total_free = total_free + free
+				total_used = total_used + used
+			end
+		else
+			bag_data[bag_slot].has_bag = false
+		end
+
+		if trace then
+			TitanPluginDebug(TITAN_PLUGIN, "T info"
+				.. " " .. tostring(bag_slot) .. ""
+				.. " ?:" .. tostring(bag_data[bag_slot].has_bag) .. ""
+				.. " max: " .. tostring(bag_data[bag_slot].maxi_slots) .. ""
+				.. " used: " .. tostring(bag_data[bag_slot].used_slots) .. ""
+				.. " free: " .. tostring(bag_data[bag_slot].free_slots) .. ""
+				.. " type: " .. tostring(bag_data[bag_slot].style) .. ""
+				.. " count: " .. tostring(count_prof) .. ""
+				.. " '" .. tostring(bag_data[bag_slot].name) .. "'"
+			)
+		end
+	end
+
+	bag_data.total_slots = total_slots
+	bag_data.total_free = total_free
+	bag_data.total_used = total_used
+
+	local bagText = ""
+	if (TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots")) then
+		bagText = format(L["TITAN_BAG_FORMAT"], total_used, total_slots);
+	else
+		bagText = format(L["TITAN_BAG_FORMAT"], total_free, total_slots);
+	end
+
+	local bagRichText = ""
+	if (TitanGetVar(TITAN_PLUGIN, "ShowColoredText")) then
+		local color = ""
+		color = TitanUtils_GetThresholdColor(TITAN_BAG_THRESHOLD_TABLE, total_used / total_slots);
+		bagRichText = TitanUtils_GetColoredText(bagText, color);
+	else
+		bagRichText = TitanUtils_GetHighlightText(bagText);
+	end
+
+	bagRichText =
+	bagRichText            --..bagRichTextProf[1]..bagRichTextProf[2]..bagRichTextProf[3]..bagRichTextProf[4]..bagRichTextProf[5];
+
+	return L["TITAN_BAG_BUTTON_LABEL"], bagRichText
+end
+
+-- Create the right click menu for this plugin
+local function CreateMenu()
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS event"
+			.. " " .. tostring(TitanPanelRightClickMenu_GetDropdownLevel()) .. ""
+			.. " '" .. tostring(TitanPanelRightClickMenu_GetDropdMenuValue()) .. "'"
+		)
+	end
+	local info = {}
+	-- level 2
+	if TitanPanelRightClickMenu_GetDropdownLevel() == 2 then
+		if TitanPanelRightClickMenu_GetDropdMenuValue() == "Options" then
+			TitanPanelRightClickMenu_AddTitle(L["TITAN_PANEL_OPTIONS"], TitanPanelRightClickMenu_GetDropdownLevel())
+			info = {};
+			info.text = L["TITAN_BAG_MENU_SHOW_USED_SLOTS"];
+			info.func = function()
+				TitanSetVar(TITAN_PLUGIN, "ShowUsedSlots", 1);
+				TitanPanelButton_UpdateButton(TITAN_PLUGIN);
+			end
+			info.checked = TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots");
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+			info = {};
+			info.text = L["TITAN_BAG_MENU_SHOW_AVAILABLE_SLOTS"];
+			info.func = function()
+				TitanSetVar(TITAN_PLUGIN, "ShowUsedSlots", nil);
+				TitanPanelButton_UpdateButton(TITAN_PLUGIN);
+			end
+			info.checked = TitanUtils_Toggle(TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots"));
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+			info = {};
+			info.text = L["TITAN_BAG_MENU_SHOW_DETAILED"];
+			info.func = function()
+				TitanToggleVar(TITAN_PLUGIN, "ShowDetailedInfo");
+			end
+			info.checked = TitanGetVar(TITAN_PLUGIN, "ShowDetailedInfo");
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+			info = {};
+			info.text = L["TITAN_BAG_MENU_OPEN_BAGS"]
+			info.func = function()
+				TitanToggleVar(TITAN_PLUGIN, "OpenBags")
+			end
+			info.checked = TitanGetVar(TITAN_PLUGIN, "OpenBags");
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+		end
+		return
+	end
+
+	-- level 1
+	TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_PLUGIN].menuText);
+
+	info = {};
+	info.notCheckable = true
+	info.text = L["TITAN_PANEL_OPTIONS"];
+	info.value = "Options"
+	info.hasArrow = 1;
+	TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+	TitanPanelRightClickMenu_AddSpacer();
+	info = {};
+	info.text = L["TITAN_BAG_MENU_IGNORE_PROF_BAGS_SLOTS"];
+	info.func = function()
+		TitanToggleVar(TITAN_PLUGIN, "CountProfBagSlots");
+		TitanPanelButton_UpdateButton(TITAN_PLUGIN);
+	end
+	info.checked = not TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots")
+	TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+	TitanPanelRightClickMenu_AddControlVars(TITAN_PLUGIN)
+end
+
+-- Grab the button text to display
+local function GetButtonText(id)
+	local strA, strB = GetBagData(id)
+	return strA, strB
+end
+
+-- Create the tooltip string
+local function GetTooltipText()
+	local returnstring = "";
+
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS tool tip"
+			.. " detail " .. tostring(TitanGetVar(TITAN_PLUGIN, "ShowDetailedInfo")) .. ""
+			.. " used " .. tostring(TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots")) .. ""
+			.. " prof " .. tostring(TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots")) .. ""
+			.. " color " .. tostring(TitanGetVar(TITAN_PLUGIN, "ShowColoredText")) .. ""
+			.. " open " .. tostring(TitanGetVar(TITAN_PLUGIN, "OpenBags")) .. ""
+		)
+	end
+
+	if TitanGetVar(TITAN_PLUGIN, "ShowDetailedInfo") then
+		returnstring = "\n";
+		if TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots") then
+			returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_MENU_TEXT"])
+				.. ":\t" .. TitanUtils_GetNormalText(L["TITAN_BAG_USED_SLOTS"]) .. ":\n";
+		else
+			returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_MENU_TEXT"])
+				.. ":\t" .. TitanUtils_GetNormalText(L["TITAN_BAG_FREE_SLOTS"]) .. ":\n";
+		end
+
+		for bag = MIN_BAGS, MAX_BAGS do
+			local bagText, bagRichText, color;
+
+			if bag_data[bag] and bag_data[bag].has_bag then
+				if (TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots")) then
+					bagText = format(L["TITAN_BAG_FORMAT"], bag_data[bag].used_slots, bag_data[bag].maxi_slots);
+				else
+					bagText = format(L["TITAN_BAG_FORMAT"], bag_data[bag].free_slots, bag_data[bag].maxi_slots);
+				end
+
+				if bag_data[bag].style == "profession"
+					and not TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots")
+				then
+					bagRichText = "|cffa0a0a0" .. bagText .. "|r" -- show as gray
+				elseif (TitanGetVar(TITAN_PLUGIN, "ShowColoredText")) then
+					if bag_data[bag].maxi_slots == 0 then
+						color = TitanUtils_GetThresholdColor(TITAN_BAG_THRESHOLD_TABLE, 1);
+					else
+						color = TitanUtils_GetThresholdColor(TITAN_BAG_THRESHOLD_TABLE,
+							bag_data[bag].used_slots / bag_data[bag].maxi_slots);
+					end
+					bagRichText = TitanUtils_GetColoredText(bagText, color);
+				else
+					-- use without color
+					bagRichText = TitanUtils_GetHighlightText(bagText);
+				end
+
+				local name_text = bag_data[bag].name
+				if bag_data[bag].style == "profession"
+				then
+					name_text = TitanUtils_GetColoredText(name_text, bag_data[bag].color)
+				else
+					-- use without color
+				end
+				returnstring = returnstring .. name_text .. "\t" .. bagRichText .. "\n";
+			else
+				returnstring = returnstring .. NONE .. "\n";
+			end
+		end
+		returnstring = returnstring .. "\n";
+	end
+
+	if TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots") then
+		local xofy = "" .. tostring(bag_data.total_used)
+			.. "/" .. tostring(bag_data.total_slots) .. "\n"
+		returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_USED_SLOTS"])
+			.. ":\t" .. xofy
+	else
+		local xofy = "" .. tostring(bag_data.total_free)
+			.. "/" .. tostring(bag_data.total_slots) .. "\n"
+		returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_USED_SLOTS"])
+			.. ":\t" .. xofy
+	end
+
+	-- Add Hint
+	if TitanGetVar(TITAN_PLUGIN, "OpenBags") then
+		returnstring = returnstring .. TitanUtils_GetGreenText(L["TITAN_BAG_TOOLTIP_HINTS"])
+	else
+		-- nop
+	end
+	return returnstring
+end
+
+-- Create the .registry for Titan so it can register and place the plugin
+local function OnLoad(self)
+	local notes = ""
+		.. "Adds bag and free slot information to Titan Panel.\n"
+	--		.."- xxx.\n"
+	self.registry = {
+		id = TITAN_PLUGIN,
+		category = "Information",
+		version = VERSION,
+		menuText = L["TITAN_BAG_MENU_TEXT"],
+		menuTextFunction = CreateMenu,
+		buttonTextFunction = GetButtonText,
+		tooltipTitle = L["TITAN_BAG_TOOLTIP"],
+		tooltipTextFunction = GetTooltipText,
+		icon = artwork_path .. "TitanStarter",
+		iconWidth = 16,
+		notes = notes,
+		controlVariables = {
+			ShowIcon = true,
+			ShowLabelText = true,
+			ShowColoredText = true,
+			DisplayOnRightSide = true,
+		},
+		savedVariables = {
+			ShowUsedSlots = 1,
+			ShowDetailedInfo = false,
+			CountProfBagSlots = false,
+			ShowIcon = 1,
+			ShowLabelText = 1,
+			ShowColoredText = 1,
+			DisplayOnRightSide = false,
+			OpenBags = false,
+			OpenBagsClassic = "new_install",
+		}
+	};
+
+	self:RegisterEvent("PLAYER_ENTERING_WORLD");
+
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS OnLoad"
+			.. " complete"
+		)
+	end
+end
+
+-- Parse and react to registered events
+local function OnEvent(self, event, a1, a2, ...)
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS event"
+			.. " " .. tostring(event) .. ""
+			.. " " .. tostring(a1) .. ""
+		)
+	end
+
+	if event == "PLAYER_ENTERING_WORLD" then
+	end
+
+	if event == "BAG_UPDATE" then
+		-- update the plugin text
+		TitanPanelButton_UpdateButton(TITAN_PLUGIN);
+	end
+end
+
+-- Handle mouse clicks; here L click opens all bags
+local function OnClick(self, button)
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS click"
+			.. " " .. tostring(button) .. ""
+		)
+	end
+
+	if (button == "LeftButton") then
+		ToggleBags();
+	end
+end
+
+local function OnShow(self)
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS OnShow"
+			.. " register"
+		)
+	end
+	-- Register for bag updates and update the plugin text
+	self:RegisterEvent("BAG_UPDATE")
+	TitanPanelButton_UpdateButton(TITAN_PLUGIN);
+end
+
+local function OnHide(self)
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS OnShow"
+			.. " unregister"
+		)
+	end
+	self:UnregisterEvent("BAG_UPDATE")
+end
+
+-- ====== Create needed frames
+local function Create_Frames()
+	if _G[TITAN_BUTTON] then
+		return -- if already created
+	end
+
+	if trace then
+		TitanPluginDebug(TITAN_PLUGIN, "TS frames"
+			.. " '" .. tostring(TITAN_BUTTON) .. "'"
+		)
+	end
+
+	-- general container frame
+	local f = CreateFrame("Frame", nil, UIParent)
+	--	f:Hide()
+
+	-- Titan plugin button
+	--[[
+	The plugin frame is created here. The typical plugin is a 'combo' which includes
+	- an icon (can be shown or hidden)
+	- label - value pair where the label can be turned off
+	There can be multiple label - value pairs; TitanPerformance uses this scheme.
+
+	The frame is 'forever' as are most of WoW game frames.
+	--]]
+	local window = CreateFrame("Button", TITAN_BUTTON, f, "TitanPanelComboTemplate")
+	window:SetFrameStrata("FULLSCREEN")
+	-- Using SetScript to set "OnLoad" does not work
+	--
+	-- This routine sets the guts of the plugin - the .registry
+	OnLoad(window);
+
+	--[[
+	Below are the frame 'events' that need to be processed.
+	A couple have Titan routines that ensure the plugin is properly on / off a Titan bar.
+
+	The combined Titan changed design to register for events when the user places the plugin
+	on the bar (OnShow)	and unregister events when the user hids the plugin (OnHide).
+	This reduces cycles the plugin uses when the user does not want the plugin.
+
+	NOTE: If a Titan bar is hidden, the plugins on it will still run.
+	NOTE: Titan plugins are NOT child frames!! Meaning plugins are not automatically hidden when the
+	bar they are on is hidden!
+	--]]
+	window:SetScript("OnShow", function(self)
+		OnShow(self)
+		-- This routine ensures the plugin is put where the user requested it.
+		-- Titan saves the bar the plugin was on. It does not save the relative order.
+		TitanPanelButton_OnShow(self);
+	end)
+	window:SetScript("OnHide", function(self)
+		OnHide(self)
+		-- We use the Blizzard frame hide to visually remove the frame
+	end)
+	window:SetScript("OnEvent", function(self, event, ...)
+		-- Handle any events the plugin is interested in
+		OnEvent(self, event, ...)
+	end)
+	window:SetScript("OnClick", function(self, button)
+		-- Typically this routine handles actions on left click
+		OnClick(self, button);
+		-- Typically this routine handles the menu creation on right click
+		TitanPanelButton_OnClick(self, button);
+	end)
+end
+
+Create_Frames() -- do the work
diff --git a/TitanRepair/TitanRepair.toc b/TitanRepair/TitanRepair.toc
new file mode 100644
index 0000000..4dfeb9c
--- /dev/null
+++ b/TitanRepair/TitanRepair.toc
@@ -0,0 +1,10 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fRepair|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\AddOns\TitanRepair\TitanRepair
+## Notes: Provides a configurable durability display. Also adds the ability to auto repair items and inventory at vendors. Adds selling of grey items.
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## OptionalDeps:
+## Dependencies: Titan
+TitanRepair.lua
diff --git a/TitanRepair/TitanRepair_Mainline.toc b/TitanRepair/TitanRepair_Mainline.toc
deleted file mode 100644
index de2d4dd..0000000
--- a/TitanRepair/TitanRepair_Mainline.toc
+++ /dev/null
@@ -1,10 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fRepair|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\AddOns\TitanRepair\TitanRepair
-## Notes: Provides a configurable durability display. Also adds the ability to auto repair items and inventory at vendors. Adds selling of grey items.
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanRepair.lua
diff --git a/TitanRepair/TitanRepair_Vanilla.toc b/TitanRepair/TitanRepair_Vanilla.toc
deleted file mode 100644
index 05aff95..0000000
--- a/TitanRepair/TitanRepair_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fRepair|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Provides a configurable durability display. Also adds the ability to auto repair items and inventory at vendors. Adds selling of grey items.
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanRepair.lua
diff --git a/TitanVolume/TitanVolume.toc b/TitanVolume/TitanVolume.toc
new file mode 100644
index 0000000..2134129
--- /dev/null
+++ b/TitanVolume/TitanVolume.toc
@@ -0,0 +1,11 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fVolume|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\AddOns\TitanVolume\Artwork\TitanVolumeHigh
+## Notes: Adds a volume control icon on your Titan Bar
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## OptionalDeps:
+## OptionalDeps:
+## Dependencies: Titan
+TitanVolume.lua
diff --git a/TitanVolume/TitanVolume_Mainline.toc b/TitanVolume/TitanVolume_Mainline.toc
deleted file mode 100644
index 63d99ac..0000000
--- a/TitanVolume/TitanVolume_Mainline.toc
+++ /dev/null
@@ -1,11 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fVolume|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\AddOns\TitanVolume\Artwork\TitanVolumeHigh
-## Notes: Adds a volume control icon on your Titan Bar
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## OptionalDeps:
-## Dependencies: Titan
-TitanVolume.lua
diff --git a/TitanVolume/TitanVolume_Vanilla.toc b/TitanVolume/TitanVolume_Vanilla.toc
deleted file mode 100644
index fba8739..0000000
--- a/TitanVolume/TitanVolume_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fVolume|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Adds a volume control icon on your Titan Bar
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanVolume.lua
diff --git a/TitanXP/TitanXP.toc b/TitanXP/TitanXP.toc
new file mode 100644
index 0000000..5089fe0
--- /dev/null
+++ b/TitanXP/TitanXP.toc
@@ -0,0 +1,10 @@
+## Interface: 110105, 40402, 11507
+## Title: Titan Panel [|cffeda55fXP|r] |cff00aa008.3.0|r
+## Version: 8.3.0
+## IconTexture: Interface\Icons\xp_icon
+## Notes: Adds information to Titan Panel about XP earned and time to level
+## Author: Titan Panel Development Team (http://www.titanpanel.org)
+## SavedVariables:
+## OptionalDeps:
+## Dependencies: Titan
+TitanXP.lua
diff --git a/TitanXP/TitanXP_Mainline.toc b/TitanXP/TitanXP_Mainline.toc
deleted file mode 100644
index 2cc2572..0000000
--- a/TitanXP/TitanXP_Mainline.toc
+++ /dev/null
@@ -1,10 +0,0 @@
-## Interface: 110107
-## Title: Titan Panel [|cffeda55fXP|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## IconTexture: Interface\Icons\xp_icon
-## Notes: Adds information to Titan Panel about XP earned and time to level
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanXP.lua
diff --git a/TitanXP/TitanXP_Vanilla.toc b/TitanXP/TitanXP_Vanilla.toc
deleted file mode 100644
index b41ba9e..0000000
--- a/TitanXP/TitanXP_Vanilla.toc
+++ /dev/null
@@ -1,9 +0,0 @@
-## Interface: 11507, 50500
-## Title: Titan Panel [|cffeda55fXP|r] |cff00aa008.3.0|r
-## Version: 8.3.0
-## Notes: Adds information to Titan Panel about XP earned and time to level
-## Author: Titan Panel Development Team (http://www.titanpanel.org)
-## SavedVariables:
-## OptionalDeps:
-## Dependencies: Titan
-TitanXP.lua