Quantcast

- Retail version to 10.2.7

urnati [06-13-24 - 16:01]
- Retail version to 10.2.7
- Repair and Bag : fix Beta errors
- XP : move to 30 sec timer versus OnUpdate
- Location : Classic versions only, add Tom and Bottom to prevent coords overlap on map
- AutoHide : Fix error in tooltip
- Loot & Volume : Small cleanup
Filename
Titan/Titan.code-workspace
Titan/TitanAutoHide.lua
Titan/TitanHistory.lua
Titan/TitanUtils.lua
Titan/TitanVariables.lua
Titan/Titan_Mainline.toc
Titan/_ATitanDoc.lua
Titan/_TitanIDE.lua
TitanBag/TitanBag.lua
TitanBag/TitanBag_Mainline.toc
TitanClock/TitanClock_Mainline.toc
TitanGold/TitanGold_Mainline.toc
TitanLocation/TitanLocation.lua
TitanLocation/TitanLocation_Mainline.toc
TitanLootType/TitanClassicLootType.lua
TitanPerformance/TitanPerformance_Mainline.toc
TitanRepair/TitanRepair.lua
TitanRepair/TitanRepair_Mainline.toc
TitanVolume/TitanVolume.lua
TitanVolume/TitanVolume_Mainline.toc
TitanXP/TitanXP.lua
TitanXP/TitanXP_Mainline.toc
diff --git a/Titan/Titan.code-workspace b/Titan/Titan.code-workspace
index 84d2af7..e9213b3 100644
--- a/Titan/Titan.code-workspace
+++ b/Titan/Titan.code-workspace
@@ -369,6 +369,14 @@
 			"GetNumSubgroupMembers",
 			"GetNumGroupMembers",
 			"UnitExists"
-		]
-	}
+		],
+		"Lua.misc.parameters": [
+			"--develop=true",
+			"--dbgport=11428"
+		],
+	},
+	"launch": {
+		"version": "0.2.0",
+		"configurations": []
+	},
 }
\ No newline at end of file
diff --git a/Titan/TitanAutoHide.lua b/Titan/TitanAutoHide.lua
index afdb9b5..a02241b 100644
--- a/Titan/TitanAutoHide.lua
+++ b/Titan/TitanAutoHide.lua
@@ -54,6 +54,7 @@ function Titan_AutoHide_OnLoad(self)
 		version = TITAN_VERSION,
 		menuText = "AutoHide_"..bar,
 		tooltipTitle = L["TITAN_PANEL_AUTOHIDE_TOOLTIP"],
+		tooltipTextFunction = "TitanPanelClockButton_GetTooltipText",
 		savedVariables = {
 			DisplayOnRightSide = 1,
 			ForceBar = bar,
@@ -61,6 +62,21 @@ function Titan_AutoHide_OnLoad(self)
 	};
 end

+function TitanPanelClockButton_GetTooltipText(self)
+	local returnstring = ""
+--[[
+	local bar = self.bar_name
+	local frame_str  = TitanVariables_GetFrameName(bar)
+
+	if TitanBarDataVars[frame_str].auto_hide then
+		returnstring = L["TITAN_PANEL_MENU_DISABLED"]
+	else
+		returnstring = L["TITAN_PANEL_MENU_ENABLED"]
+	end
+--]]
+	return returnstring
+end
+
 --[[
 NAME: Titan_AutoHide_OnShow
 DESC: Show the plugin on the given bar.
diff --git a/Titan/TitanHistory.lua b/Titan/TitanHistory.lua
index 1aa32e9..54ce662 100644
--- a/Titan/TitanHistory.lua
+++ b/Titan/TitanHistory.lua
@@ -15,12 +15,42 @@ Green - 'header' - Titan or plugin
 Highlight - notes. tips. and details
 --]]
 Titan_Global.recent_changes = ""
-.. TitanUtils_GetGoldText("8.0.12 : 2024/04/14\n")
-.. TitanUtils_GetGreenText("Ammo : \n")
+.. TitanUtils_GetGoldText("8.0.13 : 2024/05/xx\n")
+.. TitanUtils_GetGreenText("Titan : \n")
 .. TitanUtils_GetHighlightText(""
-.. "- Fix to remove plugin error text when wand (non-ammo) weapon is equipped in Classic (Wrath or Era) .\n"
-)
+.. "- Update Retail version to 10.2.7.\n")
+.. TitanUtils_GetGreenText("Repair : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Change to not error in Beta (The War Within).\n")
+.. TitanUtils_GetGreenText("Bag : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Bag taint appears to be fixed (10.2.7). Removed nag message and reverted code.\n"
+.. "- Change to not error in Beta (The War Within).\n")
+.. TitanUtils_GetGreenText("XP : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Improve performance. Now on a 30 sec timer rather than OnUpdate. Still event driven.\n")
+.. TitanUtils_GetGreenText("Location : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Classic versions Only : Add option to put coords on Top or Bottom to prevent Cata overlap.\n")
+.. TitanUtils_GetGreenText("AutoHide : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Fix error in tooltip.\n")
+.. TitanUtils_GetGreenText("Loot : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Small cleanup.\n")
+.. TitanUtils_GetGreenText("Volume : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Small cleanup.\n")
+.. "\n\n"
+.. TitanUtils_GetGoldText("8.0.12 : 2024/05/01\n")
+.. TitanUtils_GetGreenText("Titan : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- TOC update for Cataclysm.\n")
+.. "\n\n"
 .. TitanUtils_GetGoldText("8.0.11 : 2024/04/10\n")
+.. TitanUtils_GetGreenText("Ammo : \n")
+.. TitanUtils_GetHighlightText(""
+.. "- Fix to remove plugin error text when wand (non-ammo) weapon is equipped in Classic (Wrath or Era) .\n")
 .. TitanUtils_GetGreenText("Volume : \n")
 .. TitanUtils_GetHighlightText(""
 .. "- Double click (left) will mute / unmute. Note: tooltip will flash, not sure how to prevent that.\n"
@@ -50,19 +80,6 @@ Titan_Global.recent_changes = ""
         .. "- TOC update only : Classic Era to 1.15.2.\n"
     )
     .. "\n\n"
-    .. TitanUtils_GetGoldText("8.0.09 : 2024/03/20\n")
-    .. TitanUtils_GetGreenText("Titan : \n")
-    .. TitanUtils_GetHighlightText(""
-        .. "- TOC update only : Retail to 10.2.6; Classic Era to 1.15.1.\n"
-    )
-    .. "\n\n"
-    .. TitanUtils_GetGoldText("8.0.8 : 2024/03/08\n")
-    .. TitanUtils_GetGreenText("Location : \n")
-    .. TitanUtils_GetHighlightText(""
-        ..
-        "- Reverted change to TITAN_PANEL_MENU_CATEGORIES. Removal of this table broke a couple Titan plugins.  Sorry about that.\n"
-    )
-    .. "\n\n"

 --[[ Var Notes
 Use for important notes in the Titan Config About
@@ -76,5 +93,5 @@ Titan_Global.config_notes = ""
     .. "\n"
     .. TitanUtils_GetGoldText("Known Issues:\n")
     .. TitanUtils_GetHighlightText(""
-        .. "- Titan Bag : Opening bags is still an option until taint issue is resolved.\n"
-    )
+    .. "- Cata : Titan right-click menu may stay visible even if click elsewhere. Hit Esc twice. Investigating...\n"
+)
diff --git a/Titan/TitanUtils.lua b/Titan/TitanUtils.lua
index 0984858..850f313 100644
--- a/Titan/TitanUtils.lua
+++ b/Titan/TitanUtils.lua
@@ -32,8 +32,8 @@ Blizzard hard-codes the value...
 The Titan routines abstract the menu creation built into WoW.

 Whenever there is a change to the menu routines, the abstractions :
-- Insulate 3rd party Titan plugin authors from Blizz or lib changes.
-- Allow better maintainance by updating Utils rather than updating Titan using search & replace.
+: Insulate 3rd party Titan plugin authors from Blizz or lib changes.
+: Allow better maintainance by updating Utils rather than updating Titan using search & replace.

 Titan uses TITAN_ID to determine which version of the abstracted routines to use!

diff --git a/Titan/TitanVariables.lua b/Titan/TitanVariables.lua
index 44009b7..f45e0b9 100644
--- a/Titan/TitanVariables.lua
+++ b/Titan/TitanVariables.lua
@@ -53,12 +53,12 @@ DESC:
 --[===[ Var
 TitanBarData table.
 The table holds:
-- the name of each Titan bar (as the index)
-- the short name of the bar
-- whether the bar is relative - top or bottom or short (user placed)
-- the order they should be considered
-- SetPoint values for show / hide
-- short bar specific values
+: the name of each Titan bar (as the index)
+: the short name of the bar
+: whether the bar is relative - top or bottom or short (user placed)
+: the order they should be considered
+: SetPoint values for show / hide
+: short bar specific values

 The short name is used to build names of the various saved variables, frames,
  and buttons used by Titan.
diff --git a/Titan/Titan_Mainline.toc b/Titan/Titan_Mainline.toc
index 2963887..01fe78a 100644
--- a/Titan/Titan_Mainline.toc
+++ b/Titan/Titan_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55f_Core_|r] |cff00aa008.0.13|r
 ## Author: Titan Panel Dev Team
 ## Version: 8.0.13
diff --git a/Titan/_ATitanDoc.lua b/Titan/_ATitanDoc.lua
index be34202..9c8221f 100644
--- a/Titan/_ATitanDoc.lua
+++ b/Titan/_ATitanDoc.lua
@@ -114,7 +114,7 @@ Titan has no dependencies but Titan plugins need to list Titan or TitanClassic.
 === .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 - 100206 - in the .toc.
+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.

diff --git a/Titan/_TitanIDE.lua b/Titan/_TitanIDE.lua
index e6606a6..0bd7768 100644
--- a/Titan/_TitanIDE.lua
+++ b/Titan/_TitanIDE.lua
@@ -1,6 +1,6 @@
 --[===[ File
     This file is NOT to be included in the TOC file!
-    This is intended to be used for IDE Intellisense.
+    This is intended for IDE Intellisense.
 --]===]

 --[[ IDE
@@ -135,6 +135,8 @@ VideoOptionsFrameOkay_OnClick = {}
 ---@field bar_name string Used by auto hide built-in
 ---@field registry table Any Titan plugin (built-in; third party; or LDB)

+---@class UIParent WoW frame
+---@field GetScale function WoW region routine

 ---@class Button Plugin frame
 ---@field RequestTimePlayed table Override default - XP
diff --git a/TitanBag/TitanBag.lua b/TitanBag/TitanBag.lua
index 970ca0b..dd99751 100644
--- a/TitanBag/TitanBag.lua
+++ b/TitanBag/TitanBag.lua
@@ -13,11 +13,11 @@ 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 },
 }
-local updateTable = {TITAN_BAG_ID, TITAN_PANEL_UPDATE_BUTTON};
+--local updateTable = {TITAN_BAG_ID, TITAN_PANEL_UPDATE_BUTTON};
 -- ******************************** Variables *******************************
-local AceTimer = LibStub("AceTimer-3.0")
+--local AceTimer = LibStub("AceTimer-3.0")
 local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true)
-local BagTimer
+--local BagTimer

 local bag_info = { -- itemType : warcraft.wiki.gg/wiki/itemType
 	[1] = -- Soul bag
@@ -53,6 +53,9 @@ local MAX_BAGS = Constants.InventoryConstants.NumBagSlots
 local bag_data = {} -- to hold the user bag data

 -- ******************************** Functions *******************************
+
+local GetItemNow = 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
@@ -65,20 +68,8 @@ local function IsProfessionBagID(slot)
 		-- Only works on bag and bank bags NOT backpack!
 	else
 		info = GetInventoryItemLink("player", inv_id)
-		itemId, itemType, itemSubType, itemEquipLoc, itemTexture, classID, subclassID	= GetItemInfoInstant(info)
+		itemId, itemType, itemSubType, itemEquipLoc, itemTexture, classID, subclassID = GetItemNow(info)
 		style = subclassID
---[[
-TitanDebug("T isP 0:"
-	.." "..tostring(slot)..""
-	.." "..tostring(itemId)..""
-	.." '"..tostring(itemType).."'"
-	.." '"..tostring(itemSubType).."'"
-	.." "..tostring(itemEquipLoc)..""
-	.." '"..tostring(itemTexture).."'"
-	.." "..tostring(classID)..""
-	.." "..tostring(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)
@@ -117,6 +108,7 @@ local function ToggleBags()
 	if TitanGetVar(TITAN_BAG_ID, "OpenBags") then
 		ToggleAllBags()
 	else
+		-- User has not enabled open on click
 	end
 end

@@ -265,6 +257,7 @@ end
 function TitanPanelBagButton_OnLoad(self)
 	local notes = ""
 		.."Adds bag and free slot information to Titan Panel.\n"
+		.."- Open bags should work... Retail taint fixed Apr 2024 (10.2.7).\n"
 --		.."- xxx.\n"
 	self.registry = {
 		id = TITAN_BAG_ID,
@@ -291,17 +284,11 @@ function TitanPanelBagButton_OnLoad(self)
 			ShowLabelText = 1,
 			ShowColoredText = 1,
 			DisplayOnRightSide = false,
-			OpenBags = false,
-			OpenBagsClassic = "new_install",
+			OpenBags = true,
 		}
 	};
-	if TITAN_ID == "Titan" then -- 10.* / Retail
-		-- for taint issue
-		self.registry.savedVariables.OpenBags = false
-	else
-		-- does not taint so default to open bags on click
-		self.registry.savedVariables.OpenBags = true
-	end
+
+	-- As of Apr 2024 (10.2.7) the taint on opening bags in Retail is fixed.

 	self:RegisterEvent("PLAYER_ENTERING_WORLD");
 end
@@ -314,52 +301,7 @@ end
 --]]
 function TitanPanelBagButton_OnEvent(self, event, a1, a2, ...)
 	if event == "PLAYER_ENTERING_WORLD" then
---[===[
-local inv_id = C_Container.ContainerIDToInventoryID(1)
-local info = GetInventoryItemLink("player", inv_id)
-local name, _, Color, Ltype, Id, Enchant, Gem1, Gem2, Gem3, Gem4, Suffix, Unique, LinkLvl, reforging, Name = string.find(info, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?")
-
-local itemName, itemLink, itemQuality, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount,
-itemEquipLoc, itemTexture, sellPrice, classID, subclassID, bindType, expacID, setID, isCraftingReagent
-= GetItemInfo(Id)
-
-local iitemId, iitemType, iitemSubType,
-iitemEquipLoc, iitemTexture, iclassID, isubclassID
-= GetItemInfoInstant(info)
-
-print("======")
-print("bag"
-   .." "..tostring(inv_id)..""
-)
-print("inv"
-   .." "..tostring(name)..""
-   .." "..tostring(Id)..""
-   .." "..tostring(classID)..""
-   .." "..tostring(subclassID)..""
-)
-print("iinv"
-   .." "..tostring(iitemId)..""
-   .." "..tostring(Id)..""
-   .." "..tostring(iclassID)..""
-   .." "..tostring(isubclassID)..""
-)
-print("======")
---]===]
-
-		if a1 == true and TITAN_ID == "Titan" then -- 10.* / Retail
-			-- initial login
-
-			TitanPrint(L["TITAN_BAG_TAINT_TEXT"], "warning")
-		else -- either Classic version
-			local open = TitanGetVar(TITAN_BAG_ID, "OpenBagsClassic")
-			if open == "new_install" then --
-				-- set to default behavior of opening bag on left click
-				TitanSetVar(TITAN_BAG_ID, "OpenBags", true)
-				TitanSetVar(TITAN_BAG_ID, "OpenBagsClassic", "processed") -- don't do again
-			else
-				-- already processed...
-			end
-		end
+		-- Leave in case future code is needed...
 	end

 	if event == "BAG_UPDATE" then
@@ -627,3 +569,16 @@ end


 Create_Frames() -- do the work
+
+--[[
+TitanDebug("T isP 0:"
+	.." "..tostring(slot)..""
+	.." "..tostring(itemId)..""
+	.." '"..tostring(itemType).."'"
+	.." '"..tostring(itemSubType).."'"
+	.." "..tostring(itemEquipLoc)..""
+	.." '"..tostring(itemTexture).."'"
+	.." "..tostring(classID)..""
+	.." "..tostring(subclassID)..""
+	)
+--]]
diff --git a/TitanBag/TitanBag_Mainline.toc b/TitanBag/TitanBag_Mainline.toc
index 72b970a..aff3363 100644
--- a/TitanBag/TitanBag_Mainline.toc
+++ b/TitanBag/TitanBag_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fBag|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\AddOns\TitanBag\TitanBag
diff --git a/TitanClock/TitanClock_Mainline.toc b/TitanClock/TitanClock_Mainline.toc
index 2f3dbef..1c8293e 100644
--- a/TitanClock/TitanClock_Mainline.toc
+++ b/TitanClock/TitanClock_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fClock|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\Icons\Spell_Nature_TimeStop
diff --git a/TitanGold/TitanGold_Mainline.toc b/TitanGold/TitanGold_Mainline.toc
index 992aae9..f78a87a 100644
--- a/TitanGold/TitanGold_Mainline.toc
+++ b/TitanGold/TitanGold_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fGold|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\AddOns\TitanGold\Artwork\TitanGold
diff --git a/TitanLocation/TitanLocation.lua b/TitanLocation/TitanLocation.lua
index be1e848..916ea16 100755
--- a/TitanLocation/TitanLocation.lua
+++ b/TitanLocation/TitanLocation.lua
@@ -135,13 +135,6 @@ local function CheckForPositionUpdate()
 end

 local function ZoneUpdate(self)
-
---[==[
-print("TLoc ZoneUpdate"
-.." c "..tostring(self).." "
-.." p "..tostring(self:GetName()).." "
-)
---]==]
 	local _ = nil
 	self.zoneText = GetZoneText();
 	self.subZoneText = GetSubZoneText();
@@ -151,36 +144,51 @@ print("TLoc ZoneUpdate"
 end

 local function SetCoordText(player, cursor)
-	local playerLocationText = player or ""
-	local cursorLocationText = cursor or ""
-
-	TitanMapPlayerLocation:SetText(cursorLocationText);
-	TitanMapCursorLocation:SetText(playerLocationText);
+	local player_frame = TitanMapPlayerLocation
+	local cursor_frame = TitanMapCursorLocation
+	local world_frame = WorldMapFrame
+
+	player_frame:SetText(player or "");
+	cursor_frame:SetText(cursor or "");

---		local mloc = TitanGetVar(TITAN_LOCATION_ID, "MapLocation") or "TOPRIGHT"
 	if TITAN_ID == "TitanClassic" then
 		-- Determine where to show the text
-		TitanMapPlayerLocation:ClearAllPoints()
-		TitanMapCursorLocation:ClearAllPoints()
+		player_frame:ClearAllPoints()
+		cursor_frame:ClearAllPoints()

-		TitanMapPlayerLocation:SetPoint("BOTTOMLEFT", WorldMapFrame, "BOTTOM", 0, 10)
-		TitanMapCursorLocation:SetPoint("BOTTOMRIGHT", WorldMapFrame, "BOTTOM", -10, 10)
+		local mloc = TitanGetVar(TITAN_LOCATION_ID, "CoordsLoc")
+		if mloc == "Top" then
+			if WorldMapFrame:IsMaximized() then
+				TitanMapPlayerLocation:SetPoint("TOPLEFT", WorldMapFrame.BorderFrame, "TOPLEFT", 10, -5)
+			else
+				TitanMapPlayerLocation:SetPoint("TOPLEFT", WorldMapFrame.MiniBorderFrame, "TOPLEFT", 20, -33)
+			end
+			TitanMapCursorLocation:SetPoint("RIGHT", WorldMapFrame.MaximizeMinimizeFrame, "LEFT", 0, 0)
+		elseif mloc == "Bottom" then
+			player_frame:SetPoint("BOTTOMRIGHT", world_frame, "BOTTOM", -10, 10)
+			cursor_frame:SetPoint("BOTTOMLEFT", world_frame, "BOTTOM", 0, 10)
+		else
+			-- Correct to the default of bottom
+			TitanSetVar(TITAN_LOCATION_ID, "CoordsLoc", "Bottom")
+			player_frame:SetPoint("BOTTOMRIGHT", world_frame, "BOTTOM", -10, 10)
+			cursor_frame:SetPoint("BOTTOMLEFT", world_frame, "BOTTOM", 0, 10)
+		end
 	else -- current retail
 		-- Position the text
-		local anchor = WorldMapFrame.BorderFrame.MaximizeMinimizeFrame
-		if WorldMapFrame:IsMaximized() then
+		local anchor = world_frame.BorderFrame.MaximizeMinimizeFrame
+		if world_frame:IsMaximized() then
 			-- map should be 'full' screen
-			TitanMapPlayerLocation:ClearAllPoints();
-			TitanMapCursorLocation:ClearAllPoints();
-			TitanMapPlayerLocation:SetPoint("RIGHT", anchor, "LEFT", 0, 0)
-			TitanMapCursorLocation:SetPoint("TOP", TitanMapPlayerLocation, "BOTTOM", 0, -5)
-			WorldMapFrame.TitanSize = "large"
+			player_frame:ClearAllPoints();
+			cursor_frame:ClearAllPoints();
+			player_frame:SetPoint("RIGHT", anchor, "LEFT", 0, 0)
+			cursor_frame:SetPoint("TOP", player_frame, "BOTTOM", 0, -5)
+			world_frame.TitanSize = "large"
 		else
-			TitanMapPlayerLocation:ClearAllPoints();
-			TitanMapCursorLocation:ClearAllPoints();
-			TitanMapPlayerLocation:SetPoint("RIGHT", anchor, "LEFT", 0, 0)
-			TitanMapCursorLocation:SetPoint("LEFT", WorldMapFrame.BorderFrame.Tutorial, "RIGHT", 0, 0)
-			WorldMapFrame.TitanSize = "small"
+			player_frame:ClearAllPoints();
+			cursor_frame:ClearAllPoints();
+			player_frame:SetPoint("RIGHT", anchor, "LEFT", 0, 0)
+			cursor_frame:SetPoint("LEFT", world_frame.BorderFrame.Tutorial, "RIGHT", 0, 0)
+			world_frame.TitanSize = "small"
 		end
 	end
 end
@@ -195,7 +203,6 @@ local function LocOnMiniMap(reason)
 	if TitanGetVar(TITAN_LOCATION_ID, "ShowLocOnMiniMap") then
 		MinimapBorderTop:Show()
 		MinimapZoneTextButton:Show()
---		MiniMapWorldMapButton:Show()
 	else
 		MinimapBorderTop:Hide()
 		MinimapZoneTextButton:Hide()
@@ -229,6 +236,17 @@ local function TitanMapFrame_OnUpdate(self, elapsed)
 		-- use default
 	end

+	local player_format = ""
+	local cursor_format = ""
+	local label = TitanGetVar(TITAN_LOCATION_ID, "CoordsLabel")
+	if label then
+		player_format = L["TITAN_LOCATION_MAP_PLAYER_COORDS_TEXT"]
+		cursor_format = L["TITAN_LOCATION_MAP_CURSOR_COORDS_TEXT"]
+	else
+		player_format = "%s"
+		cursor_format = "%s"
+	end
+
 	if (TitanGetVar(TITAN_LOCATION_ID, "ShowCoordsOnMap")) then
 		self.px, self.py = GetPlayerMapPosition();
 		if self.px == nil then self.px = 0 end
@@ -238,7 +256,7 @@ local function TitanMapFrame_OnUpdate(self, elapsed)
 		else
 			playerLocationText = format(TitanGetVar(TITAN_LOCATION_ID, "CoordsFormat"), 100 * self.px, 100 * self.py);
 		end
-		playerLocationText = (format(L["TITAN_LOCATION_MAP_PLAYER_COORDS_TEXT"], TitanUtils_GetHighlightText(playerLocationText)));
+		playerLocationText = (format(player_format, TitanUtils_GetHighlightText(playerLocationText)));

 		-- Determine the text to show for cursor coords
 		local cx, cy = GetCursorPosition();
@@ -254,19 +272,12 @@ local function TitanMapFrame_OnUpdate(self, elapsed)

 		-- per the user requested format
 		cursorLocationText = format(TitanGetVar(TITAN_LOCATION_ID, "CoordsFormat"), 100 * cx, 100 * cy)
-		cursorLocationText = (format(L["TITAN_LOCATION_MAP_CURSOR_COORDS_TEXT"],
-			TitanUtils_GetHighlightText(cursorLocationText)))
+		cursorLocationText = (format(cursor_format, TitanUtils_GetHighlightText(cursorLocationText)))
 	else
 		-- use defaults, saving a few cpu cycles
 	end
---[==[
-print("TLoc"
-.." c "..tostring(cursorLocationText).." "
-.." p "..tostring(playerLocationText).." "
-)
---]==]
-	SetCoordText(playerLocationText, cursorLocationText)

+	SetCoordText(playerLocationText, cursorLocationText)
 end

 --[[
@@ -521,6 +532,7 @@ local function GetTooltipText()
 		..sub_zone.."\n"
 		..TitanUtils_GetHighlightText(L["TITAN_LOCATION_TOOLTIP_HOMELOCATION"]).."\n"
 		..L["TITAN_LOCATION_TOOLTIP_INN"].."\t"..bind_loc.."\n"
+		..pvpInfoRichText.."\n\n"
 		..TitanUtils_GetGreenText(L["TITAN_LOCATION_TOOLTIP_HINTS_1"]).."\n"
 		..TitanUtils_GetGreenText(L["TITAN_LOCATION_TOOLTIP_HINTS_2"])
 end
@@ -589,8 +601,35 @@ end
 local function CreateMenu()
 	local info

+	-- level 1
+	if TitanPanelRightClickMenu_GetDropdownLevel() == 1 then
+		-- level 1
+		TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_LOCATION_ID].menuText);
+
+		info = {};
+		info.notCheckable = true
+		info.text = L["TITAN_PANEL_OPTIONS"];
+		info.value = "Options"
+		info.hasArrow = 1;
+		TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+		info = {};
+		info.notCheckable = true
+		info.text = L["TITAN_LOCATION_FORMAT_COORD_LABEL"];
+		info.value = "CoordFormat"
+		info.hasArrow = 1;
+		TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+		info = {};
+		info.notCheckable = true
+		info.text = "WorldMap"
+		info.value = "WorldMap"
+		info.hasArrow = 1;
+		TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+		TitanPanelRightClickMenu_AddControlVars(TITAN_LOCATION_ID)
 	-- level 2
-	if TitanPanelRightClickMenu_GetDropdownLevel() == 2 then
+	elseif TitanPanelRightClickMenu_GetDropdownLevel() == 2 then
 		if TitanPanelRightClickMenu_GetDropdMenuValue() == "Options" then
 			TitanPanelRightClickMenu_AddTitle(L["TITAN_PANEL_OPTIONS"], TitanPanelRightClickMenu_GetDropdownLevel());
 			info = {};
@@ -690,27 +729,66 @@ local function CreateMenu()
 			info.checked = (TitanGetVar(TITAN_LOCATION_ID, "CoordsFormat") == L["TITAN_LOCATION_FORMAT3"])
 			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
 		end
-		return
-	end

-	-- level 1
-	TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_LOCATION_ID].menuText);
-
-	info = {};
-	info.notCheckable = true
-	info.text = L["TITAN_PANEL_OPTIONS"];
-	info.value = "Options"
-	info.hasArrow = 1;
-	TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
-
-	info = {};
-	info.notCheckable = true
-	info.text = L["TITAN_LOCATION_FORMAT_COORD_LABEL"];
-	info.value = "CoordFormat"
-	info.hasArrow = 1;
-	TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
-
-	TitanPanelRightClickMenu_AddControlVars(TITAN_LOCATION_ID)
+		if TitanPanelRightClickMenu_GetDropdMenuValue() == "WorldMap" then
+			TitanPanelRightClickMenu_AddTitle(L["TITAN_LOCATION_MENU_TEXT"], TitanPanelRightClickMenu_GetDropdownLevel());
+			info = {};
+			info.text = L["TITAN_LOCATION_MENU_SHOW_COORDS_ON_MAP_TEXT"];
+			info.func = function()
+				TitanToggleVar(TITAN_LOCATION_ID, "ShowCoordsOnMap");
+				if (TitanGetVar(TITAN_LOCATION_ID, "ShowCoordsOnMap")) then
+					CoordFrames("start")
+				else
+					CoordFrames("stop")
+				end
+			end
+			info.checked = TitanGetVar(TITAN_LOCATION_ID, "ShowCoordsOnMap");
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+			info = {};
+			info.text = L["TITAN_LOCATION_MENU_UPDATE_WORLD_MAP"];
+			info.func = function()
+				TitanToggleVar(TITAN_LOCATION_ID, "UpdateWorldmap");
+			end
+			info.checked = TitanGetVar(TITAN_LOCATION_ID, "UpdateWorldmap");
+			info.disabled = InCombatLockdown()
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+			if TITAN_ID == "TitanClassic" then
+				info = {};
+				info.notCheckable = true
+				info.text = L["TITAN_LOCATION_MENU_TEXT"];
+				info.value = "CoordsLoc"
+				info.hasArrow = 1;
+				TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+			else
+				-- no work needed
+			end
+		end
+
+	-- level 3
+	elseif TitanPanelRightClickMenu_GetDropdownLevel() == 3 then
+		if TitanPanelRightClickMenu_GetDropdMenuValue() == "CoordsLoc" then
+
+			info = {};
+			info.text = L["TITAN_PANEL_MENU_BOTTOM"];
+			info.func = function()
+				TitanSetVar(TITAN_LOCATION_ID, "CoordsLoc", "Bottom");
+--				TitanPanelButton_UpdateButton(TITAN_LOCATION_ID);
+			end
+			info.checked = (TitanGetVar(TITAN_LOCATION_ID, "CoordsLoc") == "Bottom")
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+
+			info = {};
+			info.text = L["TITAN_PANEL_MENU_TOP"];
+			info.func = function()
+				TitanSetVar(TITAN_LOCATION_ID, "CoordsLoc", "Top");
+--				TitanPanelButton_UpdateButton(TITAN_LOCATION_ID);
+			end
+			info.checked = (TitanGetVar(TITAN_LOCATION_ID, "CoordsLoc") == "Top")
+			TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());
+		end
+	end
 end

 --[[
@@ -753,8 +831,9 @@ local function OnLoad(self)
 			ShowLabelText = 1,
 			ShowColoredText = 1,
 			CoordsFormat = L["TITAN_LOCATION_FORMAT"],
+			CoordsLoc = "Bottom",
+			CoordsLabel = true,
 			UpdateWorldmap = false,
-			MapLocation = "TOPRIGHT",
 			DisplayOnRightSide = false,
 		}
 	};
diff --git a/TitanLocation/TitanLocation_Mainline.toc b/TitanLocation/TitanLocation_Mainline.toc
index e7f117e..336cd17 100644
--- a/TitanLocation/TitanLocation_Mainline.toc
+++ b/TitanLocation/TitanLocation_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fLocation|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\AddOns\TitanLocation\TitanLocation
diff --git a/TitanLootType/TitanClassicLootType.lua b/TitanLootType/TitanClassicLootType.lua
index d8b423d..cb3e1f2 100644
--- a/TitanLootType/TitanClassicLootType.lua
+++ b/TitanLootType/TitanClassicLootType.lua
@@ -113,7 +113,7 @@ local function LootDebug(msg, mtype)
 	end

 	if show then
-		TitanPluginDebug(tostring(msg))
+		TitanPluginDebug(TITAN_LOOTTYPE_ID, tostring(msg))
 	end
 end

@@ -508,7 +508,7 @@ OUT: retName	- table of player names pointing into ret
 local function OutPlayer(player)
 	if LT.Debug.on then --
 		if player then
-			TitanPluginDebug("GetPlayerList:"
+			TitanPluginDebug(TITAN_LOOTTYPE_ID, "GetPlayerList:"
 				.. " p'" .. (player.name or "nyl") .. "'"
 				.. " r'" .. (player.rank or "nyl") .. "'"
 				.. " c'" .. (player.class or "nyl") .. "'"
@@ -1119,7 +1119,7 @@ function Track.UpdateRollList()
 		if ctxt ~= "" then ctxt = ctxt .. "\n" .. L["TxtLine"] .. "\n" end
 	end
 	if LT.Debug.on then --
-		TitanPluginDebug("UpdateRollList"
+		TitanPluginDebug(TITAN_LOOTTYPE_ID, "UpdateRollList"
 			.. " '" .. (rollText or "nyl") .. "'"
 			.. " '" .. (ctxt or "nyl") .. "'"
 			.. " '" .. (gtxt or "nyl") .. "'"
diff --git a/TitanPerformance/TitanPerformance_Mainline.toc b/TitanPerformance/TitanPerformance_Mainline.toc
index 5874f7b..587cad4 100644
--- a/TitanPerformance/TitanPerformance_Mainline.toc
+++ b/TitanPerformance/TitanPerformance_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fPerformance|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\AddOns\TitanPerformance\TitanPerformance
diff --git a/TitanRepair/TitanRepair.lua b/TitanRepair/TitanRepair.lua
index 58e09ae..56f31f3 100644
--- a/TitanRepair/TitanRepair.lua
+++ b/TitanRepair/TitanRepair.lua
@@ -179,7 +179,7 @@ local function GetRepairCostEquip(slotName, slot)
 	if C_TooltipInfo then
 		local data = C_TooltipInfo.GetInventoryItem("player", slot)
 		if data then
-			TooltipUtil.SurfaceArgs(data) -- readable format
+--			TooltipUtil.SurfaceArgs(data) -- readable format
 			res = (data.repairCost or 0)
 			equipped = true
 		end
@@ -233,7 +233,7 @@ local function GetRepairCostBag(bag, slot)
 	if C_TooltipInfo then
 		local data = C_TooltipInfo.GetBagItem(bag, slot)
 		if data then
-			TooltipUtil.SurfaceArgs(data) -- readable format
+--			TooltipUtil.SurfaceArgs(data) -- readable format
 			res = (data.repairCost or 0)
 		end
 	else
@@ -1492,7 +1492,6 @@ local function OnLoad(self)
 		.."- Shift + Left - Click forces a scan.\n"
 		.."- Left - Click now sells ALL gray items - use with CAUTION!\n"
 		.."- Option to auto sell ALL gray items - use with CAUTION!\n"
-		.."May 2023 : New option to display cost in gold only.\n"
 	self.registry = {
 		id = TITAN_REPAIR_ID,
 		category = "Built-ins",
diff --git a/TitanRepair/TitanRepair_Mainline.toc b/TitanRepair/TitanRepair_Mainline.toc
index 131018b..78e895d 100644
--- a/TitanRepair/TitanRepair_Mainline.toc
+++ b/TitanRepair/TitanRepair_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fRepair|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\AddOns\TitanRepair\TitanRepair
diff --git a/TitanVolume/TitanVolume.lua b/TitanVolume/TitanVolume.lua
index b0e4c63..091c192 100644
--- a/TitanVolume/TitanVolume.lua
+++ b/TitanVolume/TitanVolume.lua
@@ -17,13 +17,14 @@ local TITAN_VOLUME_ARTWORK_PATH = "Interface\\AddOns\\TitanVolume\\Artwork\\";
 local _G = getfenv(0);
 local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true)

+local ALL_SOUND = "Sound_EnableAllSound"
 local function GetVolumeText(volume)
 	return tostring(floor(100 * volume + 0.5)) .. "%";
 end

 local function IsMuted()
 	local mute = false
-	local setting = "Sound_EnableAllSound"
+	local setting = ALL_SOUND
 	local value = C_CVar.GetCVar(setting)
 	if value == nil then
 		-- value is invalid - Blizz change??
@@ -38,34 +39,19 @@ local function IsMuted()
 end

 local function SetVolumeIcon()
---[[
-	local icon = _G["TitanPanelVolumeButtonIcon"];
+	local plugin = TitanUtils_GetPlugin(TITAN_VOLUME_ID)
+
 	local masterVolume = tonumber(GetCVar("Sound_MasterVolume"));
-	if (masterVolume <= 0) then
-		icon:SetTexture(TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeMute");
+	if (masterVolume <= 0)
+	or IsMuted()
+	then
+		plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeMute"
 	elseif (masterVolume < 0.33) then
-		icon:SetTexture(TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeLow");
+		plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeLow"
 	elseif (masterVolume < 0.66) then
-		icon:SetTexture(TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeMedium");
+		plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeMedium"
 	else
-		icon:SetTexture(TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeHigh");
-	end
---]]
-	local plugin = TitanUtils_GetPlugin(TITAN_VOLUME_ID)
-
-	if IsMuted() then
-		plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeMute"
-	else
-		local masterVolume = tonumber(GetCVar("Sound_MasterVolume"));
-		if (masterVolume <= 0) then
-			plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeMute"
-		elseif (masterVolume < 0.33) then
-			plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeLow"
-		elseif (masterVolume < 0.66) then
-			plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeMedium"
-		else
-			plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeHigh"
-		end
+		plugin.icon = TITAN_VOLUME_ARTWORK_PATH .. "TitanVolumeHigh"
 	end
 end

@@ -119,6 +105,14 @@ end
 local function MasterSlider_OnLeave(self)
 	self.tooltipText = nil;
 	GameTooltip:Hide();
+
+	local masterVolume = tonumber(GetCVar("Sound_MasterVolume"));
+	if (masterVolume <= 0) then
+		C_CVar.SetCVar(ALL_SOUND, "0")
+	else
+		C_CVar.SetCVar(ALL_SOUND, "1")
+	end
+
 	TitanUtils_StartFrameCounting(self:GetParent(), TITAN_VOLUME_FRAME_SHOW_TIME);
 end

@@ -133,12 +127,14 @@ local function MasterSlider_OnShow(self)
 end

 local function MasterSlider_OnValueChanged(self, a1)
-	_G[self:GetName() .. "Text"]:SetText(GetVolumeText(1 - self:GetValue()));
+	local vol = 1 - self:GetValue()
+	_G[self:GetName() .. "Text"]:SetText(GetVolumeText(vol));

-	SetCVar("Sound_MasterVolume", 1 - self:GetValue());
-	TitanSetVar(TITAN_VOLUME_ID, "VolumeMaster", 1 - self:GetValue())
+	SetCVar("Sound_MasterVolume", vol);
+	TitanSetVar(TITAN_VOLUME_ID, "VolumeMaster", vol)

 	SetVolumeIcon();
+	TitanPanelButton_UpdateButton(TITAN_VOLUME_ID);

 	-- Update GameTooltip
 	if (self.tooltipText) then
@@ -159,7 +155,6 @@ local function OnMouseWheel(self, a1)
 	end
 end

-
 -- 'Music'
 local function MusicSlider_OnEnter(self)
 	--	self.tooltipText = TitanOptionSlider_TooltipText(OPTION_TOOLTIP_MUSIC_VOLUME, GetVolumeText(GetCVar("Sound_MusicVolume")));
@@ -393,9 +388,9 @@ local function OnDoubleClick(self, button)
 	if button == "LeftButton" then
 		-- Toggle mute value
 		if IsMuted() then
-			SetCVar("Sound_EnableAllSound","1")
+			SetCVar(ALL_SOUND,"1")
 		else
-			SetCVar("Sound_EnableAllSound","0")
+			SetCVar(ALL_SOUND,"0")
 		end
 		SetVolumeIcon()
 		_G[cname]:Hide()
diff --git a/TitanVolume/TitanVolume_Mainline.toc b/TitanVolume/TitanVolume_Mainline.toc
index 0835064..c96742a 100644
--- a/TitanVolume/TitanVolume_Mainline.toc
+++ b/TitanVolume/TitanVolume_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fVolume|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\AddOns\TitanVolume\Artwork\TitanVolumeHigh
diff --git a/TitanXP/TitanXP.lua b/TitanXP/TitanXP.lua
index 8fdeba7..3fca72c 100644
--- a/TitanXP/TitanXP.lua
+++ b/TitanXP/TitanXP.lua
@@ -8,20 +8,30 @@
 --]]

 -- ******************************** Constants *******************************
+
 local TITAN_XP_ID = "XP";
 local TITAN_XP_BUTTON = "TitanPanel" .. TITAN_XP_ID .. "Button"
 local _G = getfenv(0);
 local TITAN_XP_FREQUENCY = 1;
 local updateTable = { TITAN_XP_ID, TITAN_PANEL_UPDATE_ALL };
+
 -- ******************************** Variables *******************************
+
 local lastMobXP, lastXP, XPGain = 0, 0, 0
 local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true)

+local AceTimer = LibStub("AceTimer-3.0")
+local XPTimer = {}
+---@diagnostic disable-next-line: missing-fields
+XPTimer.timer = nil -- set & cancelled as needed
+XPTimer.delay = 30 -- seconds
+XPTimer.running = false
+XPTimer.last = 0
+
 local trace = false
 local trace_update = false

 --****** overload the 'time played' text to Chat - if XP requested the API call
-
 local requesting
 local xp_frame = {}

@@ -37,6 +47,7 @@ ChatFrame_DisplayTimePlayed = function(...)
 		orig_ChatFrame_DisplayTimePlayed(...)
 	end
 end
+--****** overload

 -- ******************************** Functions *******************************
 --[[
@@ -80,6 +91,46 @@ end

 --[[
 -- **************************************************************************
+-- NAME : ResetSession()
+-- DESC : Reset session and accumulated variables
+-- **************************************************************************
+--]]
+local function ResetSession(self)
+	self.initXP = UnitXP("player")
+	self.accumXP = 0
+	self.sessionXP = 0
+	self.startSessionTime = time() -- clock time
+	lastXP = self.initXP;
+end
+
+-- Wrapper for menu to use
+local function ResetThisSession()
+	ResetSession(_G[TITAN_XP_BUTTON])
+end
+
+--[[ 2024 Apr
+Change to a repeating timer instead of OnUpdate to reduce cycles
+The timer, started OnShow, will update session time here
+The prior scheme used OnUpdate which is related to FPS.
+XP does not need that level of precision.
+--]]
+local function XPTimeUpdate(plugin)
+	local elapsed = GetTime() - XPTimer.last
+	XPTimer.last = GetTime()
+	plugin.totalTime = plugin.totalTime + elapsed
+	plugin.levelTime = plugin.levelTime + elapsed
+
+	TitanPanelButton_UpdateButton(TITAN_XP_ID)
+
+	if trace then
+		local txt = "XP Text"
+			.. " " .. tostring(format("%0.2f", elapsed)) .. ""
+			TitanPluginDebug(TITAN_XP_ID, txt)
+	end
+end
+
+--[[
+-- **************************************************************************
 -- NAME : RefreshPlayed()
 -- DESC : Get total time played
 -- Do not send RequestTimePlayed output to Chat if XP requested the info.
@@ -100,16 +151,17 @@ end
 local function OnShow(self)
 	local txt = ""

-	if (not self.sessionTime) then -- initial login / PEW
+	if self.sessionTime then
+		-- No action
+	else
+		-- initial login / PEW
 		self.sessionTime = time();
 		txt = txt .. "Sess reset"
 	end
-	if (not self.initXP) then -- initial login / PEW
-		self.initXP = UnitXP("player");
-		self.accumXP = 0;
-		self.sessionXP = 0;
-		self.startSessionTime = time();
-		lastXP = self.initXP;
+	if self.initXP then
+		-- No action
+	else -- initial login / PEW
+		ResetSession(self)
 		txt = txt .. " | Init"
 	end
 	self:RegisterEvent("TIME_PLAYED_MSG");
@@ -122,6 +174,14 @@ local function OnShow(self)
 	SetIcon();
 	txt = txt .. " | Events"

+	if XPTimer.running then
+		-- Do not create a new one
+	else
+		XPTimer.timer = AceTimer:ScheduleRepeatingTimer(XPTimeUpdate, XPTimer.delay, self)
+		XPTimer.running = true
+		XPTimer.last = GetTime() -- No need for millisecond precision
+	end
+
 	if trace then
 		local dbg = "XP _OnShow"
 			.. " " .. tostring(txt) .. ""
@@ -134,13 +194,17 @@ local function OnHide(self)
 	self:UnregisterEvent("PLAYER_XP_UPDATE");
 	self:UnregisterEvent("PLAYER_LEVEL_UP");
 	self:UnregisterEvent("CHAT_MSG_COMBAT_XP_GAIN");
+
+	AceTimer:CancelTimer(XPTimer.timer)
+	XPTimer.running = false
+	XPTimer.timer = nil
 end

 --[[
 -- **************************************************************************
--- NAME : OnEvent(arg1, arg2)
--- DESC : Parse events registered to addon and act on them
--- VARS : arg1 = <research> , arg2 = <research>
+-- NAME : OnEvent(self, event, a1, a2, ...)
+-- DESC : Parse events registered to addon and act on them.
+-- VARS : https://warcraft.wiki.gg/wiki/UIHANDLER_OnEvent
 -- **************************************************************************
 --]]
 local function OnEvent(self, event, a1, a2, ...)
@@ -154,25 +218,32 @@ local function OnEvent(self, event, a1, a2, ...)
 	end

 	if (event == "PLAYER_ENTERING_WORLD") then
-		-- Do nothing
+		if a1 == true then
+			-- Initial login so start session
+			ResetSession(self)
+		end
 	elseif (event == "TIME_PLAYED_MSG") then
 		-- Remember play time
 		self.totalTime = a1;
 		self.levelTime = a2;
+
+		TitanPanelButton_UpdateButton(TITAN_XP_ID)
 	elseif (event == "PLAYER_XP_UPDATE") then
 		if self.initXP then
 			-- has been initialized
 		else
-			self.initXP = UnitXP("player");
-			self.accumXP = 0;
-			self.sessionXP = 0;
-			self.startSessionTime = time();
+			ResetSession(self)
 		end

 		XPGain = UnitXP("player") - lastXP;
 		lastXP = UnitXP("player");
-		if XPGain < 0 then XPGain = 0 end
+		if XPGain < 0 then
+			XPGain = 0
+		else
+			-- Assume it is valid
+		end
 		self.sessionXP = UnitXP("player") - self.initXP + self.accumXP;
+		TitanPanelButton_UpdateButton(TITAN_XP_ID)
 		if trace then
 			txt = "XP Ev "
 				.. " unit " .. tostring(format("%0.1f", UnitXP("player"))) .. ""
@@ -184,10 +255,18 @@ local function OnEvent(self, event, a1, a2, ...)
 		self.levelTime = 0;
 		self.accumXP = self.accumXP + UnitXPMax("player") - self.initXP;
 		self.initXP = 0;
+		TitanPanelButton_UpdateButton(TITAN_XP_ID)
 	elseif (event == "CHAT_MSG_COMBAT_XP_GAIN") then
 		local _, _, _, killXP = string.find(a1, "^" .. L["TITAN_XP_GAIN_PATTERN"])
-		if killXP then lastMobXP = tonumber(killXP) end
-		if lastMobXP < 0 then lastMobXP = 0 end
+		if killXP then
+			lastMobXP = tonumber(killXP)
+			if lastMobXP < 0 then -- sanity check
+				lastMobXP = 0
+			else
+				-- Assume valid
+			end
+			TitanPanelButton_UpdateButton(TITAN_XP_ID)
+		end
 	end
 end

@@ -198,6 +277,7 @@ end
 -- VARS : elapsed = <research>
 -- **************************************************************************
 --]]
+--[[
 local function OnUpdate(self, elapsed)
 	TITAN_XP_FREQUENCY = TITAN_XP_FREQUENCY - elapsed;
 	if (TITAN_XP_FREQUENCY <= 0) then
@@ -209,6 +289,7 @@ local function OnUpdate(self, elapsed)
 		self.levelTime = self.levelTime + elapsed;
 	end
 end
+--]]

 --[[
 -- **************************************************************************
@@ -236,35 +317,47 @@ end
 --]]
 local function GetButtonText(id)
 	local txt = ""
-	if (TitanPanelXPButton.startSessionTime == nil) then
+	local button, id = TitanUtils_GetButton(id) -- sanity check, also get plugin frame
+	if button and (TitanPanelXPButton.startSessionTime == nil) then
 		if trace then
 			txt = "XP "
 				.. " " .. tostring("start not set - too early") .. ""
 			TitanPluginDebug(TITAN_XP_ID, txt)
 		end
-		return
-	else
-		local button, id = TitanUtils_GetButton(id);
+		return "XP", ""
+	elseif button then
 		local totalXP = UnitXPMax("player");
 		local currentXP = UnitXP("player");
 		local toLevelXP = totalXP - currentXP;
 		local sessionXP = button and button.sessionXP;
 		local xpPerHour, xpPerHourText, timeToLevel, timeToLevelText;
-		local sessionTime = time() - TitanPanelXPButton.startSessionTime;
-		local levelTime = TitanPanelXPButton.levelTime;
+		local sessionTime = time() - button.startSessionTime;
+		local levelTime = button.levelTime;
 		local numofkills, numofgains;
-		if lastMobXP ~= 0 then numofkills = math.ceil(toLevelXP / lastMobXP) else numofkills = _G["UNKNOWN"] end
-		if XPGain ~= 0 then numofgains = math.ceil(toLevelXP / XPGain) else numofgains = _G["UNKNOWN"] end
+		if lastMobXP ~= 0 then
+			numofkills = math.ceil(toLevelXP / lastMobXP)
+		else
+			numofkills = _G["UNKNOWN"]
+		end
+		if XPGain ~= 0 then
+			numofgains = math.ceil(toLevelXP / XPGain)
+		else
+			numofgains = _G["UNKNOWN"]
+		end
 		if trace_update then
 			txt = "XP / Hr"
 				.. " sxp" .. tostring(format("%0.1f", sessionXP)) .. ""
-				.. " st" .. tostring(format("%0.1f", TitanPanelXPButton.startSessionTime)) .. ""
+				.. " st" .. tostring(format("%0.1f", button.startSessionTime)) .. ""
 			TitanPluginDebug(TITAN_XP_ID, txt)
 		end

 		if (levelTime) then
 			if (TitanGetVar(TITAN_XP_ID, "DisplayType") == "ShowXPPerHourSession") then
-				xpPerHour = sessionXP / sessionTime * 3600;
+				if sessionXP <= 0 then
+					xpPerHour = 0
+				else
+					xpPerHour = sessionXP / sessionTime * 3600
+				end
 				--			timeToLevel = TitanUtils_Ternary((sessionXP == 0), -1, toLevelXP / sessionXP * sessionTime);
 				timeToLevel = (sessionXP == 0) and -1 or toLevelXP / sessionXP * sessionTime;

@@ -304,7 +397,7 @@ local function GetButtonText(id)
 				local percent = floor(10000 * (currentXP / totalXP) + 0.5) / 100;
 				if TitanGetVar(TITAN_XP_ID, "ShowSimpleToLevel") then
 					toLevelXPText = TitanUtils_GetColoredText(
-					format(L["TITAN_XP_FORMAT"], comma_value(math.floor(toLevelXP + 0.5))), _G["GREEN_FONT_COLOR"]);
+						format(L["TITAN_XP_FORMAT"], comma_value(math.floor(toLevelXP + 0.5))), _G["GREEN_FONT_COLOR"]);
 					labeltolevel = L["TITAN_XP_XPTOLEVELUP"];
 				end
 				if TitanGetVar(TITAN_XP_ID, "ShowSimpleRested") then
@@ -326,11 +419,15 @@ local function GetButtonText(id)
 				end

 				if TitanGetVar(TITAN_XP_ID, "ShowSimpleNumOfGains") then
-					return L["TITAN_XP_LEVEL_COMPLETE"], TitanUtils_GetHighlightText(percent .. "%"), labelrested, rest,
-						labeltolevel, toLevelXPText, labelnumofgains, numofgains
+					return L["TITAN_XP_LEVEL_COMPLETE"], TitanUtils_GetHighlightText(percent .. "%"),
+						labelrested, rest,
+						labeltolevel, toLevelXPText,
+						labelnumofgains, numofgains
 				else
-					return L["TITAN_XP_LEVEL_COMPLETE"], TitanUtils_GetHighlightText(percent .. "%"), labelrested, rest,
-						labeltolevel, toLevelXPText, labelnumofkills, numofkills
+					return L["TITAN_XP_LEVEL_COMPLETE"], TitanUtils_GetHighlightText(percent .. "%"),
+						labelrested, rest,
+						labeltolevel, toLevelXPText,
+						labelnumofkills, numofkills
 				end
 			end
 		else
@@ -339,6 +436,8 @@ local function GetButtonText(id)
 			end
 			return "(" .. L["TITAN_XP_UPDATE_PENDING"] .. ")";
 		end
+	else
+		-- Invalid button - frame not created?
 	end
 end

@@ -349,65 +448,85 @@ end
 -- **************************************************************************
 --]]
 local function GetTooltipText()
-	local totalTime = TitanPanelXPButton.totalTime;
-	local sessionTime = time() - TitanPanelXPButton.startSessionTime;
-	local levelTime = TitanPanelXPButton.levelTime;
-	-- failsafe to ensure that an error wont be returned
-	if not levelTime then return end
-	local totalXP = UnitXPMax("player");
-	local currentXP = UnitXP("player");
-	local toLevelXP = totalXP - currentXP;
-	local currentXPPercent = currentXP / totalXP * 100;
-	local toLevelXPPercent = toLevelXP / totalXP * 100;
-	local xpPerHourThisLevel = currentXP / levelTime * 3600;
-	local xpPerHourThisSession = TitanPanelXPButton.sessionXP / sessionTime * 3600;
-	local estTimeToLevelThisLevel = TitanUtils_Ternary((currentXP == 0), -1, toLevelXP / (max(currentXP, 1)) * levelTime);
-	local estTimeToLevelThisSession = 0;
-	if TitanPanelXPButton.sessionXP > 0 then
-		estTimeToLevelThisSession = TitanUtils_Ternary((TitanPanelXPButton.sessionXP == 0), -1,
-			toLevelXP / TitanPanelXPButton.sessionXP * sessionTime);
+	local res = ""
+	local button, id = TitanUtils_GetButton(TITAN_XP_ID) -- sanity check, also get plugin frame
+
+	if button then
+		local totalTime = button.totalTime;
+		local sessionTime = time() - button.startSessionTime;
+		local levelTime = button.levelTime;
+		-- failsafe to ensure that an error wont be returned
+		if levelTime then
+			local totalXP = UnitXPMax("player");
+			local currentXP = UnitXP("player");
+			local toLevelXP = totalXP - currentXP;
+			local currentXPPercent = currentXP / totalXP * 100;
+			local toLevelXPPercent = toLevelXP / totalXP * 100;
+			local xpPerHourThisLevel = currentXP / levelTime * 3600;
+			local xpPerHourThisSession = button.sessionXP / sessionTime * 3600;
+			local estTimeToLevelThisLevel = TitanUtils_Ternary((currentXP == 0), -1,
+				toLevelXP / (max(currentXP, 1)) * levelTime);
+			local estTimeToLevelThisSession = 0;
+			if button.sessionXP > 0 then
+				estTimeToLevelThisSession = TitanUtils_Ternary((button.sessionXP == 0), -1,
+					toLevelXP / button.sessionXP * sessionTime);
+			end
+			local numofkills, numofgains;
+			if lastMobXP ~= 0 then
+				numofkills = math.ceil(toLevelXP / lastMobXP)
+			else
+				numofkills = _G["UNKNOWN"]
+			end
+			if XPGain ~= 0 then
+				numofgains = math.ceil(toLevelXP / XPGain)
+			else
+				numofgains = _G["UNKNOWN"]
+			end
+			res = "" ..
+				L["TITAN_XP_TOOLTIP_TOTAL_TIME"] ..
+				"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(totalTime)) .. "\n" ..
+				L["TITAN_XP_TOOLTIP_LEVEL_TIME"] ..
+				"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(levelTime)) .. "\n" ..
+				L["TITAN_XP_TOOLTIP_SESSION_TIME"] ..
+				"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(sessionTime)) .. "\n" ..
+				"\n" ..
+				L["TITAN_XP_TOOLTIP_TOTAL_XP"] .. "\t" .. TitanUtils_GetHighlightText(comma_value(totalXP)) .. "\n" ..
+				L["TITAN_XP_TOTAL_RESTED"] ..
+				"\t" ..
+				TitanUtils_GetHighlightText(comma_value(GetXPExhaustion() == nil and "0" or GetXPExhaustion())) .. "\n" ..
+				L["TITAN_XP_TOOLTIP_LEVEL_XP"] ..
+				"\t" ..
+				TitanUtils_GetHighlightText(comma_value(currentXP) .. " " ..
+					format(L["TITAN_XP_PERCENT_FORMAT"], currentXPPercent)) .. "\n" ..
+				L["TITAN_XP_TOOLTIP_TOLEVEL_XP"] ..
+				"\t" ..
+				TitanUtils_GetHighlightText(comma_value(toLevelXP) .. " " ..
+					format(L["TITAN_XP_PERCENT_FORMAT"], toLevelXPPercent)) .. "\n" ..
+				L["TITAN_XP_TOOLTIP_SESSION_XP"] ..
+				"\t" .. TitanUtils_GetHighlightText(comma_value(button.sessionXP)) .. "\n" ..
+				format(L["TITAN_XP_KILLS_LABEL"], comma_value(lastMobXP)) ..
+				"\t" .. TitanUtils_GetHighlightText(comma_value(numofkills)) .. "\n" ..
+				format(L["TITAN_XP_XPGAINS_LABEL"], comma_value(XPGain)) ..
+				"\t" .. TitanUtils_GetHighlightText(comma_value(numofgains)) .. "\n" ..
+				"\n" ..
+				L["TITAN_XP_TOOLTIP_XPHR_LEVEL"] ..
+				"\t" ..
+				TitanUtils_GetHighlightText(format(L["TITAN_XP_FORMAT"], comma_value(math.floor(xpPerHourThisLevel + 0.5)))) ..
+				"\n" ..
+				L["TITAN_XP_TOOLTIP_XPHR_SESSION"] ..
+				"\t" ..
+				TitanUtils_GetHighlightText(format(L["TITAN_XP_FORMAT"], comma_value(math.floor(xpPerHourThisSession + 0.5)))) ..
+				"\n" ..
+				L["TITAN_XP_TOOLTIP_TOLEVEL_LEVEL"] ..
+				"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(estTimeToLevelThisLevel)) .. "\n" ..
+				L["TITAN_XP_TOOLTIP_TOLEVEL_SESSION"] ..
+				"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(estTimeToLevelThisSession));
+		else
+		end
+	else
+		-- No button - not created?
 	end
-	local numofkills, numofgains;
-	if lastMobXP ~= 0 then numofkills = math.ceil(toLevelXP / lastMobXP) else numofkills = _G["UNKNOWN"] end
-	if XPGain ~= 0 then numofgains = math.ceil(toLevelXP / XPGain) else numofgains = _G["UNKNOWN"] end
-	return "" ..
-		L["TITAN_XP_TOOLTIP_TOTAL_TIME"] ..
-		"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(totalTime)) .. "\n" ..
-		L["TITAN_XP_TOOLTIP_LEVEL_TIME"] ..
-		"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(levelTime)) .. "\n" ..
-		L["TITAN_XP_TOOLTIP_SESSION_TIME"] ..
-		"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(sessionTime)) .. "\n" ..
-		"\n" ..
-		L["TITAN_XP_TOOLTIP_TOTAL_XP"] .. "\t" .. TitanUtils_GetHighlightText(comma_value(totalXP)) .. "\n" ..
-		L["TITAN_XP_TOTAL_RESTED"] ..
-		"\t" .. TitanUtils_GetHighlightText(comma_value(GetXPExhaustion() == nil and "0" or GetXPExhaustion())) .. "\n" ..
-		L["TITAN_XP_TOOLTIP_LEVEL_XP"] ..
-		"\t" ..
-		TitanUtils_GetHighlightText(comma_value(currentXP) .. " " ..
-		format(L["TITAN_XP_PERCENT_FORMAT"], currentXPPercent)) .. "\n" ..
-		L["TITAN_XP_TOOLTIP_TOLEVEL_XP"] ..
-		"\t" ..
-		TitanUtils_GetHighlightText(comma_value(toLevelXP) .. " " ..
-		format(L["TITAN_XP_PERCENT_FORMAT"], toLevelXPPercent)) .. "\n" ..
-		L["TITAN_XP_TOOLTIP_SESSION_XP"] ..
-		"\t" .. TitanUtils_GetHighlightText(comma_value(TitanPanelXPButton.sessionXP)) .. "\n" ..
-		format(L["TITAN_XP_KILLS_LABEL"], comma_value(lastMobXP)) ..
-		"\t" .. TitanUtils_GetHighlightText(comma_value(numofkills)) .. "\n" ..
-		format(L["TITAN_XP_XPGAINS_LABEL"], comma_value(XPGain)) ..
-		"\t" .. TitanUtils_GetHighlightText(comma_value(numofgains)) .. "\n" ..
-		"\n" ..
-		L["TITAN_XP_TOOLTIP_XPHR_LEVEL"] ..
-		"\t" ..
-		TitanUtils_GetHighlightText(format(L["TITAN_XP_FORMAT"], comma_value(math.floor(xpPerHourThisLevel + 0.5)))) ..
-		"\n" ..
-		L["TITAN_XP_TOOLTIP_XPHR_SESSION"] ..
-		"\t" ..
-		TitanUtils_GetHighlightText(format(L["TITAN_XP_FORMAT"], comma_value(math.floor(xpPerHourThisSession + 0.5)))) ..
-		"\n" ..
-		L["TITAN_XP_TOOLTIP_TOLEVEL_LEVEL"] ..
-		"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(estTimeToLevelThisLevel)) .. "\n" ..
-		L["TITAN_XP_TOOLTIP_TOLEVEL_SESSION"] ..
-		"\t" .. TitanUtils_GetHighlightText(TitanUtils_GetAbbrTimeText(estTimeToLevelThisSession));
+	return res
 end

 local function Seperator(chosen)
@@ -465,20 +584,6 @@ end

 --[[
 -- **************************************************************************
--- NAME : ResetSession()
--- DESC : Reset session and accumulated variables
--- **************************************************************************
---]]
-local function ResetSession()
-	TitanPanelXPButton.initXP = UnitXP("player");
-	TitanPanelXPButton.accumXP = 0;
-	TitanPanelXPButton.sessionXP = 0;
-	TitanPanelXPButton.startSessionTime = time();
-	lastXP = TitanPanelXPButton.initXP;
-end
-
---[[
--- **************************************************************************
 -- NAME : TitanPanelRightClickMenu_PrepareXPMenu()
 -- DESC : Display rightclick menu options
 -- **************************************************************************
@@ -548,7 +653,7 @@ local function CreateMenu()
 		TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel());

 		TitanPanelRightClickMenu_AddSpacer();
-		TitanPanelRightClickMenu_AddCommand(L["TITAN_XP_MENU_RESET_SESSION"], TITAN_XP_ID, ResetSession);
+		TitanPanelRightClickMenu_AddCommand(L["TITAN_XP_MENU_RESET_SESSION"], TITAN_XP_ID, ResetThisSession);
 		TitanPanelRightClickMenu_AddCommand(L["TITAN_XP_MENU_REFRESH_PLAYED"], TITAN_XP_ID, RefreshPlayed);
 	end

@@ -582,7 +687,7 @@ end
 local function OnLoad(self)
 	local notes = ""
 		.. "Adds information to Titan Panel about XP earned and time to level.\n"
-	--		.."- xxx.\n"
+		.."- Updates XP per hour statistics every "..XPTimer.delay.." sec.\n"
 	self.registry = {
 		id = TITAN_XP_ID,
 		category = "Built-ins",
@@ -613,7 +718,7 @@ local function OnLoad(self)
 			DisplayOnRightSide = false,
 		}
 	};
-	--	self:RegisterEvent("PLAYER_ENTERING_WORLD");
+	self:RegisterEvent("PLAYER_ENTERING_WORLD");
 end

 -- ====== Create needed frames
@@ -643,9 +748,9 @@ local function Create_Frames()
 		window:SetScript("OnEvent", function(self, event, ...)
 			OnEvent(self, event, ...)
 		end)
-		window:SetScript("OnUpdate", function(self, elapsed)
-			OnUpdate(self, elapsed)
-		end)
+		--		window:SetScript("OnUpdate", function(self, elapsed)
+		--			OnUpdate(self, elapsed)
+		--		end)

 		-- Do not output Chat messages when using RequestTimePlayed
 		function window:RequestTimePlayed()
diff --git a/TitanXP/TitanXP_Mainline.toc b/TitanXP/TitanXP_Mainline.toc
index 8028034..de1d03d 100644
--- a/TitanXP/TitanXP_Mainline.toc
+++ b/TitanXP/TitanXP_Mainline.toc
@@ -1,4 +1,4 @@
-## Interface: 100206
+## Interface: 100207
 ## Title: Titan Panel [|cffeda55fXP|r] |cff00aa008.0.13|r
 ## Version: 8.0.13
 ## IconTexture: Interface\Icons\xp_icon