initial commit
This commit is contained in:
300
Libraries/oUF/elements/healthprediction.lua
Normal file
300
Libraries/oUF/elements/healthprediction.lua
Normal file
@@ -0,0 +1,300 @@
|
||||
--[[
|
||||
# Element: Health Prediction Bars
|
||||
|
||||
Handles the visibility and updating of incoming heals and heal/damage absorbs.
|
||||
|
||||
## Widget
|
||||
|
||||
HealthPrediction - A `table` containing references to sub-widgets and options.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
myBar - A `StatusBar` used to represent incoming heals from the player.
|
||||
otherBar - A `StatusBar` used to represent incoming heals from others.
|
||||
absorbBar - A `StatusBar` used to represent damage absorbs.
|
||||
healAbsorbBar - A `StatusBar` used to represent heal absorbs.
|
||||
overAbsorb - A `Texture` used to signify that the amount of damage absorb is greater than the unit's missing health.
|
||||
overHealAbsorb - A `Texture` used to signify that the amount of heal absorb is greater than the unit's current health.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied to the StatusBar widgets if they don't have a texture set.
|
||||
A default texture will be applied to the Texture widgets if they don't have a texture or a color set.
|
||||
|
||||
## Options
|
||||
|
||||
.maxOverflow - The maximum amount of overflow past the end of the health bar. Set this to 1 to disable the overflow.
|
||||
Defaults to 1.05 (number)
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local myBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
myBar:SetPoint('TOP')
|
||||
myBar:SetPoint('BOTTOM')
|
||||
myBar:SetPoint('LEFT', self.Health:GetStatusBarTexture(), 'RIGHT')
|
||||
myBar:SetWidth(200)
|
||||
|
||||
local otherBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
otherBar:SetPoint('TOP')
|
||||
otherBar:SetPoint('BOTTOM')
|
||||
otherBar:SetPoint('LEFT', myBar:GetStatusBarTexture(), 'RIGHT')
|
||||
otherBar:SetWidth(200)
|
||||
|
||||
local absorbBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
absorbBar:SetPoint('TOP')
|
||||
absorbBar:SetPoint('BOTTOM')
|
||||
absorbBar:SetPoint('LEFT', otherBar:GetStatusBarTexture(), 'RIGHT')
|
||||
absorbBar:SetWidth(200)
|
||||
|
||||
local healAbsorbBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
healAbsorbBar:SetPoint('TOP')
|
||||
healAbsorbBar:SetPoint('BOTTOM')
|
||||
healAbsorbBar:SetPoint('RIGHT', self.Health:GetStatusBarTexture())
|
||||
healAbsorbBar:SetWidth(200)
|
||||
healAbsorbBar:SetReverseFill(true)
|
||||
|
||||
local overAbsorb = self.Health:CreateTexture(nil, "OVERLAY")
|
||||
overAbsorb:SetPoint('TOP')
|
||||
overAbsorb:SetPoint('BOTTOM')
|
||||
overAbsorb:SetPoint('LEFT', self.Health, 'RIGHT')
|
||||
overAbsorb:SetWidth(10)
|
||||
|
||||
local overHealAbsorb = self.Health:CreateTexture(nil, "OVERLAY")
|
||||
overHealAbsorb:SetPoint('TOP')
|
||||
overHealAbsorb:SetPoint('BOTTOM')
|
||||
overHealAbsorb:SetPoint('RIGHT', self.Health, 'LEFT')
|
||||
overHealAbsorb:SetWidth(10)
|
||||
|
||||
-- Register with oUF
|
||||
self.HealthPrediction = {
|
||||
myBar = myBar,
|
||||
otherBar = otherBar,
|
||||
absorbBar = absorbBar,
|
||||
healAbsorbBar = healAbsorbBar,
|
||||
overAbsorb = overAbsorb,
|
||||
overHealAbsorb = overHealAbsorb,
|
||||
maxOverflow = 1.05,
|
||||
}
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.HealthPrediction
|
||||
|
||||
--[[ Callback: HealthPrediction:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the HealthPrediction element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local myIncomingHeal = UnitGetIncomingHeals(unit, 'player') or 0
|
||||
local allIncomingHeal = UnitGetIncomingHeals(unit) or 0
|
||||
local absorb = UnitGetTotalAbsorbs(unit) or 0
|
||||
local healAbsorb = UnitGetTotalHealAbsorbs(unit) or 0
|
||||
local health, maxHealth = UnitHealth(unit), UnitHealthMax(unit)
|
||||
local otherIncomingHeal = 0
|
||||
local hasOverHealAbsorb = false
|
||||
|
||||
if(healAbsorb > allIncomingHeal) then
|
||||
healAbsorb = healAbsorb - allIncomingHeal
|
||||
allIncomingHeal = 0
|
||||
myIncomingHeal = 0
|
||||
|
||||
if(health < healAbsorb) then
|
||||
hasOverHealAbsorb = true
|
||||
end
|
||||
else
|
||||
allIncomingHeal = allIncomingHeal - healAbsorb
|
||||
healAbsorb = 0
|
||||
|
||||
if(health + allIncomingHeal > maxHealth * element.maxOverflow) then
|
||||
allIncomingHeal = maxHealth * element.maxOverflow - health
|
||||
end
|
||||
|
||||
if(allIncomingHeal < myIncomingHeal) then
|
||||
myIncomingHeal = allIncomingHeal
|
||||
else
|
||||
otherIncomingHeal = allIncomingHeal - myIncomingHeal
|
||||
end
|
||||
end
|
||||
|
||||
local hasOverAbsorb = false
|
||||
if(health + allIncomingHeal + absorb >= maxHealth) and (absorb > 0) then
|
||||
hasOverAbsorb = true
|
||||
end
|
||||
|
||||
if(element.myBar) then
|
||||
element.myBar:SetMinMaxValues(0, maxHealth)
|
||||
element.myBar:SetValue(myIncomingHeal)
|
||||
element.myBar:Show()
|
||||
end
|
||||
|
||||
if(element.otherBar) then
|
||||
element.otherBar:SetMinMaxValues(0, maxHealth)
|
||||
element.otherBar:SetValue(otherIncomingHeal)
|
||||
element.otherBar:Show()
|
||||
end
|
||||
|
||||
if(element.absorbBar) then
|
||||
element.absorbBar:SetMinMaxValues(0, maxHealth)
|
||||
element.absorbBar:SetValue(absorb)
|
||||
element.absorbBar:Show()
|
||||
end
|
||||
|
||||
if(element.healAbsorbBar) then
|
||||
element.healAbsorbBar:SetMinMaxValues(0, maxHealth)
|
||||
element.healAbsorbBar:SetValue(healAbsorb)
|
||||
element.healAbsorbBar:Show()
|
||||
end
|
||||
|
||||
if(element.overAbsorb) then
|
||||
if(hasOverAbsorb) then
|
||||
element.overAbsorb:Show()
|
||||
else
|
||||
element.overAbsorb:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if(element.overHealAbsorb) then
|
||||
if(hasOverHealAbsorb) then
|
||||
element.overHealAbsorb:Show()
|
||||
else
|
||||
element.overHealAbsorb:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: HealthPrediction:PostUpdate(unit, myIncomingHeal, otherIncomingHeal, absorb, healAbsorb, hasOverAbsorb, hasOverHealAbsorb)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the HealthPrediction element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* myIncomingHeal - the amount of incoming healing done by the player (number)
|
||||
* otherIncomingHeal - the amount of incoming healing done by others (number)
|
||||
* absorb - the amount of damage the unit can absorb without losing health (number)
|
||||
* healAbsorb - the amount of healing the unit can absorb without gaining health (number)
|
||||
* hasOverAbsorb - indicates if the amount of damage absorb is higher than the unit's missing health (boolean)
|
||||
* hasOverHealAbsorb - indicates if the amount of heal absorb is higher than the unit's current health (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, myIncomingHeal, otherIncomingHeal, absorb, healAbsorb, hasOverAbsorb, hasOverHealAbsorb, health, maxHealth)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: HealthPrediction.Override(self, event, unit)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event
|
||||
--]]
|
||||
return (self.HealthPrediction.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.HealthPrediction
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_HEALTH', Path)
|
||||
self:RegisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:RegisterEvent('UNIT_HEAL_PREDICTION', Path)
|
||||
self:RegisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
|
||||
self:RegisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
|
||||
|
||||
if(not element.maxOverflow) then
|
||||
element.maxOverflow = 1.05
|
||||
end
|
||||
|
||||
if(element.myBar) then
|
||||
if(element.myBar:IsObjectType('StatusBar') and not element.myBar:GetStatusBarTexture()) then
|
||||
element.myBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.otherBar) then
|
||||
if(element.otherBar:IsObjectType('StatusBar') and not element.otherBar:GetStatusBarTexture()) then
|
||||
element.otherBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.absorbBar) then
|
||||
if(element.absorbBar:IsObjectType('StatusBar') and not element.absorbBar:GetStatusBarTexture()) then
|
||||
element.absorbBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.healAbsorbBar) then
|
||||
if(element.healAbsorbBar:IsObjectType('StatusBar') and not element.healAbsorbBar:GetStatusBarTexture()) then
|
||||
element.healAbsorbBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.overAbsorb) then
|
||||
if(element.overAbsorb:IsObjectType('Texture') and not element.overAbsorb:GetTexture()) then
|
||||
element.overAbsorb:SetTexture([[Interface\RaidFrame\Shield-Overshield]])
|
||||
element.overAbsorb:SetBlendMode('ADD')
|
||||
end
|
||||
end
|
||||
|
||||
if(element.overHealAbsorb) then
|
||||
if(element.overHealAbsorb:IsObjectType('Texture') and not element.overHealAbsorb:GetTexture()) then
|
||||
element.overHealAbsorb:SetTexture([[Interface\RaidFrame\Absorb-Overabsorb]])
|
||||
element.overHealAbsorb:SetBlendMode('ADD')
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.HealthPrediction
|
||||
if(element) then
|
||||
if(element.myBar) then
|
||||
element.myBar:Hide()
|
||||
end
|
||||
|
||||
if(element.otherBar) then
|
||||
element.otherBar:Hide()
|
||||
end
|
||||
|
||||
if(element.absorbBar) then
|
||||
element.absorbBar:Hide()
|
||||
end
|
||||
|
||||
if(element.healAbsorbBar) then
|
||||
element.healAbsorbBar:Hide()
|
||||
end
|
||||
|
||||
if(element.overAbsorb) then
|
||||
element.overAbsorb:Hide()
|
||||
end
|
||||
|
||||
if(element.overHealAbsorb) then
|
||||
element.overHealAbsorb:Hide()
|
||||
end
|
||||
|
||||
self:UnregisterEvent('UNIT_HEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_HEAL_PREDICTION', Path)
|
||||
self:UnregisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
|
||||
self:UnregisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('HealthPrediction', Path, Enable, Disable)
|
||||
Reference in New Issue
Block a user