Thread Tools Display Modes
09-12-09, 07:26 AM   #1
Aizhia
A Murloc Raider
Join Date: Jul 2009
Posts: 4
Health Bar Smoothing Addon (Code Critique Please)

Hi All,

I'm working on a number of small addon projects to teach myself the basics before moving on to a larger project. What I'm doing is starting with the default UI and going through it making small "improvements" here and there.

The fist one I've done is an addon to smooth the health bars of the default unit frames. I'd appreciate some feedback.

Code:
local _HealthBar_OnValueChanged = HealthBar_OnValueChanged

HealthBar_OnValueChanged = function(healthBar, value, ...)
	_HealthBar_OnValueChanged(healthBar, value, true)
end

local _UnitFrameHealthBar_Update = UnitFrameHealthBar_Update

UnitFrameHealthBar_Update = function(statusbar, unit)
	_UnitFrameHealthBar_Update(statusbar, unit)

	if (not statusbar or statusbar.disconnected) then return end

	local min, max = statusbar:GetMinMaxValues();
	if (max <= min) then return end

	local value = statusbar:GetValue()
	if ( (value < min) or (value > max) ) then return end

	value = (value - min) / (max - min);

	local r, g
	if(value > 0.5) then
		r = (1.0 - value) * 2;
		g = 1.0;
	else
		r = 1.0;
		g = value * 2;
	end
	statusbar:SetStatusBarColor(r, g, 0.0);
end
I'm concerned about the second function I've hooked. It gets called a lot (presumably once per frame for every UnitFrameHealthBar). Am I right to be?

Note: I originally wrote this using events but frames like focustarget and targettarget weren't getting updated because changes to those don't trigger UNIT_HEALTH events.
  Reply With Quote
09-12-09, 07:42 AM   #2
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
My only major qualms are that you don't properly hook and if Blizzard were to change those function in anyway by adding extra arguments or using return values you could muck stuff up in a fairly major way.

Heres an quick example of how to make it more "future proof".

lua Code:
  1. local _HealthBar_OnValueChanged = HealthBar_OnValueChanged
  2.  
  3. HealthBar_OnValueChanged = function(healthBar, value, bol, ...)
  4.     return _HealthBar_OnValueChanged(healthBar, value, true, ...)
  5. end
  6.  
  7. local _UnitFrameHealthBar_Update = UnitFrameHealthBar_Update
  8.  
  9. local function UpdateHelper(statusbar, unit, ...)
  10.     if (not statusbar or statusbar.disconnected) then return ... end
  11.  
  12.     local min, max = statusbar:GetMinMaxValues();
  13.     if (max <= min) then return end
  14.  
  15.     local value = statusbar:GetValue()
  16.     if ( (value < min) or (value > max) ) then return ... end
  17.  
  18.     value = (value - min) / (max - min);
  19.  
  20.     local r, g
  21.     if(value > 0.5) then
  22.         r = (1.0 - value) * 2;
  23.         g = 1.0;
  24.     else
  25.         r = 1.0;
  26.         g = value * 2;
  27.     end
  28.     statusbar:SetStatusBarColor(r, g, 0.0);
  29.     return ...
  30. end
  31.  
  32.  
  33. UnitFrameHealthBar_Update = function(statusbar, unit, ...)
  34.     return UpdateHelper(statusbar, unit, _UnitFrameHealthBar_Update(statusbar, unit, ...))
  35. end
  Reply With Quote
09-12-09, 08:07 AM   #3
Aizhia
A Murloc Raider
Join Date: Jul 2009
Posts: 4
Cool. That makes sense.

Many thanks.
  Reply With Quote
09-12-09, 09:05 AM   #4
xConStruct
A Chromatic Dragonspawn
 
xConStruct's Avatar
AddOn Author - Click to view addons
Join Date: May 2008
Posts: 199
Since you are not modifying the arguments of UnitFrameHealthBar_Update and your code is called after the original function, you could also just use hooksecurefunc and don't care about the whole argument-passing. This approach also avoids any possible tainting.

Code:
hooksecurefunc("UnitFrameHealthBar_Update", function(statusbar, unit)

	if (not statusbar or statusbar.disconnected) then return end

	local min, max = statusbar:GetMinMaxValues();
	if (max <= min) then return end

	local value = statusbar:GetValue()
	if ( (value < min) or (value > max) ) then return end

	value = (value - min) / (max - min);

	local r, g
	if(value > 0.5) then
		r = (1.0 - value) * 2;
		g = 1.0;
	else
		r = 1.0;
		g = value * 2;
	end
	statusbar:SetStatusBarColor(r, g, 0.0);
end)
__________________
« Website | GitHub »

Oh hai!
  Reply With Quote
09-12-09, 04:30 PM   #5
Aizhia
A Murloc Raider
Join Date: Jul 2009
Posts: 4
Even better

I've incorporated both suggestions. Thanks.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Health Bar Smoothing Addon (Code Critique Please)


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off