health.lua 7.64 KB
Newer Older
1 2
--[[
# Element: Health Bar
Elv's avatar
Elv committed
3

4
Handles the updating of a status bar that displays the unit's health.
Elv's avatar
Elv committed
5

6
## Widget
Elv's avatar
Elv committed
7

8
Health - A `StatusBar` used to represent the unit's health.
Elv's avatar
Elv committed
9

10
## Sub-Widgets
Elv's avatar
Elv committed
11

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.

## Notes

A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.

## Options

.frequentUpdates   - Indicates whether to use UNIT_HEALTH_FREQUENT instead of UNIT_HEALTH to update the bar (boolean)
.smoothGradient    - 9 color values to be used with the .colorSmooth option (table)

The following options are listed by priority. The first check that returns true decides the color of the bar.

.colorTapping      - Use `self.colors.tapping` to color the bar if the unit isn't tapped by the player (boolean)
.colorDisconnected - Use `self.colors.disconnected` to color the bar if the unit is offline (boolean)
.colorClass        - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
28
                     second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass.html) (boolean)
29 30 31 32 33
.colorClassNPC     - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
.colorClassPet     - Use `self.colors.class[class]` to color the bar if the unit is player controlled, but not a player
                     (boolean)
.colorReaction     - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
                     unit. `reaction` is defined by the return value of
34
                     [UnitReaction](http://wowprogramming.com/docs/api/UnitReaction.html) (boolean)
35 36 37 38
.colorSmooth       - Use `smoothGradient` if present or `self.colors.smooth` to color the bar with a smooth gradient
                     based on the player's current health percentage (boolean)
.colorHealth       - Use `self.colors.health` to color the bar. This flag is used to reset the bar color back to default
                     if none of the above conditions are met (boolean)
Elv's avatar
Elv committed
39

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
## Sub-Widgets Options

.multiplier - Used to tint the background based on the main widgets R, G and B values. Defaults to 1 (number)[0-1]

## Attributes

.disconnected - Indicates whether the unit is disconnected (boolean)

## Examples

    -- Position and size
    local Health = CreateFrame('StatusBar', nil, self)
    Health:SetHeight(20)
    Health:SetPoint('TOP')
    Health:SetPoint('LEFT')
    Health:SetPoint('RIGHT')

    -- Add a background
    local Background = Health:CreateTexture(nil, 'BACKGROUND')
    Background:SetAllPoints(Health)
    Background:SetTexture(1, 1, 1, .5)

    -- Options
    Health.frequentUpdates = true
    Health.colorTapping = true
    Health.colorDisconnected = true
    Health.colorClass = true
    Health.colorReaction = true
    Health.colorHealth = true

    -- Make the background darker.
    Background.multiplier = .5

    -- Register it with oUF
	Health.bg = Background
    self.Health = Health
--]]

local _, ns = ...
local oUF = ns.oUF

local function UpdateColor(element, unit, cur, max)
	local parent = element.__owner
Elv's avatar
Elv committed
83 84

	local r, g, b, t
85 86 87 88 89 90 91
	if(element.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapDenied(unit)) then
		t = parent.colors.tapped
	elseif(element.colorDisconnected and element.disconnected) then
		t = parent.colors.disconnected
	elseif(element.colorClass and UnitIsPlayer(unit)) or
		(element.colorClassNPC and not UnitIsPlayer(unit)) or
		(element.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
Elv's avatar
Elv committed
92
		local _, class = UnitClass(unit)
93 94 95 96
		t = parent.colors.class[class]
	elseif(element.colorReaction and UnitReaction(unit, 'player')) then
		t = parent.colors.reaction[UnitReaction(unit, 'player')]
	elseif(element.colorSmooth) then
Simpy's avatar
Simpy committed
97
		r, g, b = parent:ColorGradient(cur, max, unpack(element.smoothGradient or parent.colors.smooth))
98 99
	elseif(element.colorHealth) then
		t = parent.colors.health
Elv's avatar
Elv committed
100 101 102 103 104 105
	end

	if(t) then
		r, g, b = t[1], t[2], t[3]
	end

106 107
	if(r or g or b) then
		element:SetStatusBarColor(r, g, b)
108

109 110 111
		local bg = element.bg
		if(bg) then
			local mu = bg.multiplier or 1
Elv's avatar
Elv committed
112 113 114
			bg:SetVertexColor(r * mu, g * mu, b * mu)
		end
	end
115
end
Elv's avatar
Elv committed
116

117
local function Update(self, event, unit)
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
	if(not unit or self.unit ~= unit) then return end
	local element = self.Health

	--[[ Callback: Health:PreUpdate(unit)
	Called before the element has been updated.

	* self - the Health element
	* unit - the unit for which the update has been triggered (string)
	--]]
	if(element.PreUpdate) then
		element:PreUpdate(unit)
	end

	local cur, max = UnitHealth(unit), UnitHealthMax(unit)
	local disconnected = not UnitIsConnected(unit)
	element:SetMinMaxValues(0, max)

	if(disconnected) then
		element:SetValue(max)
	else
		element:SetValue(cur)
	end

	element.disconnected = disconnected

	--[[ Override: Health:UpdateColor(unit, cur, max)
	Used to completely override the internal function for updating the widgets' colors.

	* self - the Health element
	* unit - the unit for which the update has been triggered (string)
	* cur  - the unit's current health value (number)
	* max  - the unit's maximum possible health value (number)
	--]]
	element:UpdateColor(unit, cur, max)

	--[[ Callback: Health:PostUpdate(unit, cur, max)
	Called after the element has been updated.

	* self - the Health element
	* unit - the unit for which the update has been triggered (string)
	* cur  - the unit's current health value (number)
	* max  - the unit's maximum possible health value (number)
	--]]
	if(element.PostUpdate) then
		return element:PostUpdate(unit, cur, max)
Elv's avatar
Elv committed
163 164 165
	end
end

166 167 168 169 170 171 172 173
local function Path(self, ...)
	--[[ Override: Health.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 (string)
	--]]
Elv's avatar
Elv committed
174 175 176
	return (self.Health.Override or Update) (self, ...)
end

177
local function ForceUpdate(element)
Elv's avatar
Elv committed
178 179 180
	return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
end

Merathilis's avatar
Merathilis committed
181 182
--[[ Health:SetFrequentUpdates(state)
Used to toggle frequent updates.
Simpy's avatar
Simpy committed
183

Merathilis's avatar
Merathilis committed
184 185 186 187
* self  - the Health element
* state - the desired state of frequent updates (boolean)
--]]
local function SetFrequentUpdates(element, state)
Azilroka's avatar
Azilroka committed
188 189 190
	if(element.frequentUpdates ~= state) then
		element.frequentUpdates = state
		if(element.frequentUpdates) then
Azilroka's avatar
Azilroka committed
191
			element.__owner:UnregisterEvent('UNIT_HEALTH', Path)
Azilroka's avatar
Azilroka committed
192 193 194
			element.__owner:RegisterEvent('UNIT_HEALTH_FREQUENT', Path)
		else
			element.__owner:UnregisterEvent('UNIT_HEALTH_FREQUENT', Path)
Azilroka's avatar
Azilroka committed
195
			element.__owner:RegisterEvent('UNIT_HEALTH', Path)
Azilroka's avatar
Azilroka committed
196 197
		end
	end
Merathilis's avatar
Merathilis committed
198 199
end

200 201 202 203 204
local function Enable(self, unit)
	local element = self.Health
	if(element) then
		element.__owner = self
		element.ForceUpdate = ForceUpdate
Merathilis's avatar
Merathilis committed
205
		element.SetFrequentUpdates = SetFrequentUpdates
Elv's avatar
Elv committed
206

Azilroka's avatar
Azilroka committed
207
		if(element.frequentUpdates) then
208
			self:RegisterEvent('UNIT_HEALTH_FREQUENT', Path)
Azilroka's avatar
Azilroka committed
209 210
		else
			self:RegisterEvent('UNIT_HEALTH', Path)
Azilroka's avatar
Azilroka committed
211
		end
212 213

		self:RegisterEvent('UNIT_MAXHEALTH', Path)
Elv's avatar
Elv committed
214
		self:RegisterEvent('UNIT_CONNECTION', Path)
215
		self:RegisterEvent('UNIT_FACTION', Path) -- For tapping
Elv's avatar
Elv committed
216

217 218 219
		if(element:IsObjectType('StatusBar') and not element:GetStatusBarTexture()) then
			element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
		end
Elv's avatar
Elv committed
220

221 222
		if(not element.UpdateColor) then
			element.UpdateColor = UpdateColor
Elv's avatar
Elv committed
223 224
		end

225 226
		element:Show()

Elv's avatar
Elv committed
227 228 229 230
		return true
	end
end

231 232 233 234 235
local function Disable(self)
	local element = self.Health
	if(element) then
		element:Hide()

Elv's avatar
Elv committed
236 237 238 239 240 241 242 243 244
		self:UnregisterEvent('UNIT_HEALTH_FREQUENT', Path)
		self:UnregisterEvent('UNIT_HEALTH', Path)
		self:UnregisterEvent('UNIT_MAXHEALTH', Path)
		self:UnregisterEvent('UNIT_CONNECTION', Path)
		self:UnregisterEvent('UNIT_FACTION', Path)
	end
end

oUF:AddElement('Health', Path, Enable, Disable)