Quantcast

add energy mana regen ticker

rawoil [12-06-21 - 08:04]
add energy mana regen ticker
Filename
oUF/elements/happinessindicator.lua
oUF/elements/masterlooterindicator.lua
oUF_Simple/core/functions.lua
oUF_Simple/core/style.lua
oUF_Simple/modules/oUF_EnergyManaRegen.lua
oUF_Simple/oUF_Simple.toc
oUF_SimpleConfig/player.lua
diff --git a/oUF/elements/happinessindicator.lua b/oUF/elements/happinessindicator.lua
new file mode 100644
index 0000000..b6f56c2
--- /dev/null
+++ b/oUF/elements/happinessindicator.lua
@@ -0,0 +1,116 @@
+--[[
+# Element: HappinessIndicator
+
+Handles the visibility and updating of player pet happiness.
+
+## Widget
+
+HappinessIndicator - A `Texture` used to display the current happiness level.
+The element works by changing the texture's vertex color.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+    -- Position and size
+    local HappinessIndicator = self:CreateTexture(nil, 'OVERLAY')
+    HappinessIndicator:SetSize(16, 16)
+    HappinessIndicator:SetPoint('TOPRIGHT', self)
+
+    -- Register it with oUF
+    self.HappinessIndicator = HappinessIndicator
+--]]
+
+local _, ns = ...
+local oUF = ns.oUF
+
+local GetPetHappiness = GetPetHappiness
+local HasPetUI = HasPetUI
+
+local function Update(self, event, unit)
+	if(not unit or self.unit ~= unit) then return end
+
+	local element = self.HappinessIndicator
+
+	--[[ Callback: HappinessIndicator:PreUpdate()
+	Called before the element has been updated.
+
+	* self - the ComboPoints element
+	--]]
+	if(element.PreUpdate) then
+		element:PreUpdate()
+	end
+
+	local _, hunterPet = HasPetUI()
+	local happiness, damagePercentage = GetPetHappiness()
+
+	if(hunterPet and happiness) then
+		if(happiness == 1) then
+			element:SetTexCoord(0.375, 0.5625, 0, 0.359375)
+		elseif(happiness == 2) then
+			element:SetTexCoord(0.1875, 0.375, 0, 0.359375)
+		elseif(happiness == 3) then
+			element:SetTexCoord(0, 0.1875, 0, 0.359375)
+		end
+
+		element:Show()
+	else
+		return element:Hide()
+	end
+
+	--[[ Callback: HappinessIndicator:PostUpdate(role)
+	Called after the element has been updated.
+
+	* self      - the ComboPoints element
+	* unit      - the unit for which the update has been triggered (string)
+	* happiness        - the numerical happiness value of the pet (1 = unhappy, 2 = content, 3 = happy) (number)
+	* damagePercentage - damage modifier, happiness affects this (unhappy = 75%, content = 100%, happy = 125%) (number)
+	--]]
+	if(element.PostUpdate) then
+		return element:PostUpdate(unit, happiness, damagePercentage)
+	end
+end
+
+local function Path(self, ...)
+	--[[ Override: HappinessIndicator.Override(self, event, ...)
+	Used to completely override the internal update function.
+
+	* self  - the parent object
+	* event - the event triggering the update (string)
+	* ...   - the arguments accompanying the event
+	--]]
+	return (self.HappinessIndicator.Override or Update) (self, ...)
+end
+
+local function ForceUpdate(element)
+	return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function Enable(self)
+	local element = self.HappinessIndicator
+	if(element) then
+		element.__owner = self
+		element.ForceUpdate = ForceUpdate
+
+		self:RegisterEvent('UNIT_HAPPINESS', Path)
+
+		if(element:IsObjectType('Texture') and not element:GetTexture()) then
+			element:SetTexture([[Interface\PetPaperDollFrame\UI-PetHappiness]])
+		end
+
+		return true
+	end
+end
+
+local function Disable(self)
+	local element = self.HappinessIndicator
+	if(element) then
+		element:Hide()
+
+		self:UnregisterEvent('UNIT_HAPPINESS', Path)
+	end
+end
+
+oUF:AddElement('HappinessIndicator', Path, Enable, Disable)
diff --git a/oUF/elements/masterlooterindicator.lua b/oUF/elements/masterlooterindicator.lua
new file mode 100644
index 0000000..ad49362
--- /dev/null
+++ b/oUF/elements/masterlooterindicator.lua
@@ -0,0 +1,124 @@
+--[[
+# Element: Master Looter Indicator
+
+Toggles the visibility of an indicator based on the unit's master looter status.
+
+## Widget
+
+MasterLooterIndicator - Any UI widget.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+    -- Position and size
+    local MasterLooterIndicator = self:CreateTexture(nil, 'OVERLAY')
+    MasterLooterIndicator:SetSize(16, 16)
+    MasterLooterIndicator:SetPoint('TOPRIGHT', self)
+
+    -- Register it with oUF
+    self.MasterLooterIndicator = MasterLooterIndicator
+--]]
+
+local _, ns = ...
+local oUF = ns.oUF
+
+local GetLootMethod = GetLootMethod
+local UnitInParty = UnitInParty
+local UnitInRaid = UnitInRaid
+local UnitIsUnit = UnitIsUnit
+
+local function Update(self, event)
+	local unit = self.unit
+	local element = self.MasterLooterIndicator
+
+	--[[ Callback: MasterLooterIndicator:PreUpdate()
+	Called before the element has been updated.
+
+	* self - the MasterLooterIndicator element
+	--]]
+	if(element.PreUpdate) then
+		element:PreUpdate()
+	end
+
+	local isShown = false
+	if(UnitInParty(unit) or UnitInRaid(unit)) then
+		local method, partyIndex, raidIndex = GetLootMethod()
+		if(method == 'master') then
+			local mlUnit
+			if(partyIndex) then
+				if(partyIndex == 0) then
+					mlUnit = 'player'
+				else
+					mlUnit = 'party' .. partyIndex
+				end
+			elseif(raidIndex) then
+				mlUnit = 'raid' .. raidIndex
+			end
+
+			isShown = mlUnit and UnitIsUnit(unit, mlUnit)
+		end
+	end
+
+	if isShown then
+		element:Show()
+	else
+		element:Hide()
+	end
+
+	--[[ Callback: MasterLooterIndicator:PostUpdate(isShown)
+	Called after the element has been updated.
+
+	* self    - the MasterLooterIndicator element
+	* isShown - indicates whether the element is shown (boolean)
+	--]]
+	if(element.PostUpdate) then
+		return element:PostUpdate(isShown)
+	end
+end
+
+local function Path(self, ...)
+	--[[ Override: MasterLooterIndicator.Override(self, event, ...)
+	Used to completely override the internal update function.
+
+	* self  - the parent object
+	* event - the event triggering the update (string)
+	* ...   - the arguments accompanying the event
+	--]]
+	return (self.MasterLooterIndicator.Override or Update) (self, ...)
+end
+
+local function ForceUpdate(element)
+	return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self, unit)
+	local element = self.MasterLooterIndicator
+	if(element) then
+		element.__owner = self
+		element.ForceUpdate = ForceUpdate
+
+		self:RegisterEvent('PARTY_LOOT_METHOD_CHANGED', Path, true)
+		self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
+
+		if(element:IsObjectType('Texture') and not element:GetTexture()) then
+			element:SetTexture([[Interface\GroupFrame\UI-Group-MasterLooter]])
+		end
+
+		return true
+	end
+end
+
+local function Disable(self)
+	local element = self.MasterLooterIndicator
+	if(element) then
+		element:Hide()
+
+		self:UnregisterEvent('PARTY_LOOT_METHOD_CHANGED', Path)
+		self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path)
+	end
+end
+
+oUF:AddElement('MasterLooterIndicator', Path, Enable, Disable)
diff --git a/oUF_Simple/core/functions.lua b/oUF_Simple/core/functions.lua
index 82a1f8f..7fd4540 100644
--- a/oUF_Simple/core/functions.lua
+++ b/oUF_Simple/core/functions.lua
@@ -680,4 +680,17 @@ local function CreateTrinket(self)

   return s
 end
-L.F.CreateTrinket = CreateTrinket
\ No newline at end of file
+L.F.CreateTrinket = CreateTrinket
+
+--CreateEneryTicker
+local function CreateEneryTicker(self)
+	if not self.cfg.emr then return end
+
+	local s = CreateFrame("StatusBar", nil, self.Power)
+	s:SetFrameLevel(self.Power:GetFrameLevel() + 3)
+	s:SetAllPoints()
+	s.Spark = s:CreateTexture(nil, "OVERLAY")
+
+	return s
+end
+L.F.CreateEneryTicker = CreateEneryTicker
\ No newline at end of file
diff --git a/oUF_Simple/core/style.lua b/oUF_Simple/core/style.lua
index a1e6d80..7483279 100644
--- a/oUF_Simple/core/style.lua
+++ b/oUF_Simple/core/style.lua
@@ -50,5 +50,6 @@ local function CreateStyle(self)
   self.RaidRoleIndicator = L.F.CreateRaidRoleIndicator(self)
   self.Range = L.F.CreateRange(self)
   self.Trinket = L.F.CreateTrinket(self)
+  self.EnergyManaRegen = L.F.CreateEneryTicker(self)
 end
 L.F.CreateStyle = CreateStyle
\ No newline at end of file
diff --git a/oUF_Simple/modules/oUF_EnergyManaRegen.lua b/oUF_Simple/modules/oUF_EnergyManaRegen.lua
new file mode 100644
index 0000000..bc7d60f
--- /dev/null
+++ b/oUF_Simple/modules/oUF_EnergyManaRegen.lua
@@ -0,0 +1,174 @@
+local A, L = ...
+local oUF = L.oUF or oUF
+if not oUF then return end
+
+local _G = _G
+local GetTime = GetTime
+local UnitPower = UnitPower
+local UnitClass = UnitClass
+local tonumber = tonumber
+local UnitPowerType = UnitPowerType
+local UnitPowerMax = UnitPowerMax
+local GetSpellPowerCost = GetSpellPowerCost
+
+local LastTickTime = GetTime()
+local TickDelay = 2.025 -- Average tick time is slightly over 2 seconds
+local CurrentValue = UnitPower('player')
+local LastValue = CurrentValue
+local myClass = select(2, UnitClass('player'))
+local Mp5Delay = 5
+local Mp5DelayWillEnd = nil
+local Mp5IgnoredSpells = {
+	[18182] = true, -- Improved Life Tap 1
+	[18183] = true, -- Improved Life Tap 2
+	[1454] = true, -- Life Tap 1
+	[1455] = true, -- Life Tap 2
+	[1456] = true, -- Life Tap 3
+	[11687] = true, -- Life Tap 4
+	[11688] = true, -- Life Tap 5
+	[11689] = true, -- Life Tap 6
+}
+
+-- Sets tick time to the last possible time based on the last tick
+local UpdateTickTime = function(now)
+	LastTickTime = now - ((now - LastTickTime) % TickDelay)
+end
+
+local Update = function(self, elapsed)
+	local element = self.EnergyManaRegen
+	element.sinceLastUpdate = (element.sinceLastUpdate or 0) + (tonumber(elapsed) or 0)
+
+	if element.sinceLastUpdate > 0.01 then
+		local powerType = UnitPowerType('player')
+		if powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.Mana then
+			element.Spark:Hide()
+			return
+		end
+
+		CurrentValue = UnitPower('player', powerType)
+		local MaxPower = UnitPowerMax('player', powerType)
+		local Now = GetTime()
+
+		if powerType == Enum.PowerType.Mana then
+			if CurrentValue >= MaxPower then
+				element:SetValue(0)
+				element.Spark:Hide()
+				return
+			end
+
+			-- Sync last tick time after 5 seconds are over
+			if Mp5DelayWillEnd and Mp5DelayWillEnd < Now then
+				Mp5DelayWillEnd = nil
+				UpdateTickTime(Now)
+			end
+		elseif powerType == Enum.PowerType.Energy then
+			-- If energy is not full we just wait for the next tick
+			if Now >= LastTickTime + TickDelay and CurrentValue >= MaxPower then
+				UpdateTickTime(Now)
+			end
+		end
+
+		if Mp5DelayWillEnd and powerType == Enum.PowerType.Mana then
+			-- Show 5 second indicator
+			element.Spark:Show()
+			element:SetMinMaxValues(0, Mp5Delay)
+			element.Spark:SetVertexColor(1, 1, 0, 1)
+			element:SetValue(Mp5DelayWillEnd - Now)
+		else
+			-- Show tick indicator
+			element.Spark:Show()
+			element:SetMinMaxValues(0, TickDelay)
+			element.Spark:SetVertexColor(1, 1, 1, 1)
+			element:SetValue(Now - LastTickTime)
+		end
+
+		element.sinceLastUpdate = 0
+	end
+end
+
+local OnUnitPowerUpdate = function()
+	local powerType = UnitPowerType('player')
+	if powerType ~= Enum.PowerType.Mana and powerType ~= Enum.PowerType.Energy then
+		return
+	end
+
+	-- We also register ticks from mp5 gear within the 5-second-rule to get a more accurate sync later.
+	-- Unfortunately this registers a tick when a mana pot or life tab is used.
+	local CurrentValue = UnitPower('player', powerType)
+	if CurrentValue > LastValue then
+		LastTickTime = GetTime()
+	end
+	LastValue = CurrentValue
+end
+
+local OnUnitSpellcastSucceeded = function(_, _, _, _, spellID)
+	local powerType = UnitPowerType('player')
+	if powerType ~= Enum.PowerType.Mana then
+		return
+	end
+
+	local spellCost = false
+	local costTable = GetSpellPowerCost(spellID)
+	for _, costInfo in next, costTable do
+		if costInfo.cost then
+			spellCost = true
+		end
+	end
+
+	if not spellCost or Mp5IgnoredSpells[spellID] then
+		return
+	end
+
+	Mp5DelayWillEnd = GetTime() + 5
+end
+
+local Path = function(self, ...)
+	return (self.EnergyManaRegen.Override or Update) (self, ...)
+end
+
+local Enable = function(self, unit)
+	local element = self.EnergyManaRegen
+	local Power = self.Power
+
+	if (unit == 'player') and element and Power and myClass ~= 'WARRIOR' then
+		element.__owner = self
+
+		if(element:IsObjectType('StatusBar')) then
+			element:SetStatusBarTexture([[Interface\Buttons\WHITE8X8]])
+			element:GetStatusBarTexture():SetAlpha(0)
+			element:SetMinMaxValues(0, 2)
+		end
+
+		local spark = element.Spark
+		if(spark and spark:IsObjectType('Texture')) then
+			spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
+			spark:SetSize(5, 5)
+			spark:SetBlendMode('ADD')
+			spark:SetPoint('CENTER', element:GetStatusBarTexture(), 'RIGHT')
+		end
+
+		self:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED', OnUnitSpellcastSucceeded)
+		self:RegisterEvent('UNIT_POWER_UPDATE', OnUnitPowerUpdate)
+
+		element:SetScript('OnUpdate', function(_, elapsed) Path(self, elapsed) end)
+
+		return true
+	end
+end
+
+local Disable = function(self)
+	local element = self.EnergyManaRegen
+	local Power = self.Power
+
+	if (Power) and (element) then
+		self:UnregisterEvent('UNIT_SPELLCAST_SUCCEEDED', OnUnitSpellcastSucceeded)
+		self:UnregisterEvent('UNIT_POWER_UPDATE', OnUnitPowerUpdate)
+
+		element.Spark:Hide()
+		element:SetScript('OnUpdate', nil)
+
+		return false
+	end
+end
+
+oUF:AddElement('EnergyManaRegen', Path, Enable, Disable)
\ No newline at end of file
diff --git a/oUF_Simple/oUF_Simple.toc b/oUF_Simple/oUF_Simple.toc
index e2f4812..8f2cc4c 100644
--- a/oUF_Simple/oUF_Simple.toc
+++ b/oUF_Simple/oUF_Simple.toc
@@ -10,6 +10,7 @@ modules\oUF_DebuffHighlight.lua
 modules\oUF_Swing.lua
 modules\oUF_RaidDebuffs.lua
 modules\oUF_Trinkets.lua
+modules\oUF_EnergyManaRegen.lua

 core\init.lua
 core\functions.lua
diff --git a/oUF_SimpleConfig/player.lua b/oUF_SimpleConfig/player.lua
index e5fb980..cb09511 100644
--- a/oUF_SimpleConfig/player.lua
+++ b/oUF_SimpleConfig/player.lua
@@ -134,4 +134,6 @@ L.C.player = {
     orientation = "VERTICAL",
     colorPower = true,
   },
+  --energymanaregen
+  emr = true,
 }