Thread Tools Display Modes
10-02-13, 03:05 PM   #1
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
Can't seem to get classcolors to work

I'm fairly sure I've posted a thread like this every time I've made my return to WoW after any period of absence, but here we go again because I couldn't find my old ones in my post history.

I want to color my health background by class, but I can't seem to get it to work and when I do get it to work, I get various little (and some not so little) issues that end with me scratching my head and wondering what I'm doing wrong.

So here goes.

This is my HealthBG code.
Code:
local HealthBG = Health:CreateTexture(nil, 'BORDER')
HealthBG:SetAllPoints()
HealthBG:SetTexture(BARTEXTURE)
local _, class = UnitClass(unit)
local classColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]	
HealthBG:SetVertexColor(classColor)
This makes the background black, which means it just flat out doesn't work. No error, but I'm fairly sure it comes down to an incorrect use of the classColor variable. I'm fairly sure I need to specify further, so I did this.

Code:
local HealthBG = Health:CreateTexture(nil, 'BORDER')
HealthBG:SetAllPoints()
HealthBG:SetTexture(BARTEXTURE)
local _, class = UnitClass(unit)
local classColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]	
HealthBG:SetVertexColor(classColor.r, classColor.g, classColor.b)
And this works! But I now get an error, and only the player frame spawns. No target frame, no pet frame, nothing.
The error I get is this:
Code:
oUF_Opie-1\layout.lua:119: attempt to index local "classColor" (a nil value)
So I'm stumped. Why does it work on my player frame but completely kill the target frame?

I know I could probably achieve my goal through a postupdatehealth function (if those still exist in oUF?) but I'd like to avoid that if possible!
__________________
All I see is strobe lights blinding me in my hindsight.
  Reply With Quote
10-02-13, 10:30 PM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
(1) Your first code doesn't work because "color" there is a table value, and SetVertexColor requires 3 or 4 number values, for the red, green, blue, and (optionally) alpha components of the color.

(2) With your second code, you're getting an error because "target" (for example) doesn't actually point to a unit at login when oUF is making the frame, since you don't have a target yet at that time. Also, even if it worked, that section of code only runs once, when the frame is created, so it would be stuck with the color of whatever unit had that token at that time -- for example, if you were targeting a druid when the target frame was created, and later targeted a mage, the frame would still be orange.

(3) PostUpdate is the way to go, and there's not really any logical reason to "avoid that if possible". That's like saying, "well, I'm thirsty, and I know I could slake my thirst by drinking something, but I'd like to avoid that if possible". That's how you do it, so just do it.

Code:
-- This goes OUTSIDE of your spawn function:
local function Health_PostUpdate(bar, unit, health, maxHealth)
   local _, class = UnitClass(unit)
   local color = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[class or ""]
   if color then
      bar.bg:SetVertexColor(color.r, color.g, color.b)
   else
      -- Fall back to dark gray:
      bar.bg:SetVertexColor(0.25, 0.25, 0.25)
   end
end

-- This goes INSIDE your spawn function:
local HealthBG = Health:CreateTexture(nil, 'BORDER')
HealthBG:SetAllPoints()
HealthBG:SetTexture(BARTEXTURE)
Health.bg = HealthBG

Health.PostUpdate = Health_PostUpdate
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
10-03-13, 03:38 AM   #3
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
Thank you Phanx! I guess I'll use the PostUpdate then.

The reason I wanted to avoid it wasn't for any real reason, but rather just because I was curious if I could do it outside of it, now that you've explained how it works it obviously sounds silly, even to me.

Out of more curiosity, is there a reason this line was changed?

Code:
local classColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]

local color = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[class or ""]
What's the difference apart from the variable name?

Thanks for the help!
__________________
All I see is strobe lights blinding me in my hindsight.
  Reply With Quote
10-03-13, 05:50 AM   #4
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
Its a compact check that uses CUSTOM_CLASS_COLORS if available, and falls back on RAID_CLASS_COLORS if not.

Code:
CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
and
Code:
(CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[class]
is the same thing.


The part in the brackets validifies the class, so that if UnitClass returns nil, it falls back to "" (empty string).
Personally, I would fall back to "PRIEST" or something, a neutral white color .
  Reply With Quote
10-03-13, 06:50 AM   #5
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
I see!

I guess I can take this thread to ask another question, I can't seem to get an HP text working on my party frames anymore, it just doesn't show up no matter what I change about it. I've tried moving it around, I've tried rearranging the code a bit (a ton, actually. I barely know where things are anymore! ) and I've tried changing the tag I use in case that was the fault, but none work. It just doesn't show, no error or anything.

These are the relevant parts to my party frames in my Shared function:
Code:
	local HealthValue = Health:CreateFontString(nil, 'OVERLAY')
	HealthValue:SetPoint('RIGHT', -7, -1)
	HealthValue:SetFont(FONT, FONTSIZE, FONTSTYLE)
	HealthValue:SetJustifyH('RIGHT')
	HealthValue.frequentUpdates = 1/4
	self.HealthValue = HealthValue
	
	local PowerValue = self.Health:CreateFontString(nil, 'OVERLAY')	
	
	if(unit=='player' or unit=='party') then				
		PowerValue:SetFont(FONT, FONTSIZE, FONTSTYLE)
		PowerValue:SetJustifyH('LEFT')
		PowerValue.frequentUpdates = 0.1
		if(unit=='player') then
			self:Tag(PowerValue, '[oppower]')
			PowerValue:SetPoint('LEFT', 7, -1)
			PowerValue:SetPoint('RIGHT', self.HealthValue, 'LEFT', -3)
		else
			self:Tag(PowerValue, '[oppartypp]')
			PowerValue:SetPoint('LEFT', 7, 0)
			PowerValue:SetPoint('RIGHT', self.HealthValue, 'LEFT', -3)
			HealthValue:SetPoint('RIGHT', -7, 0)
		end
	end
And this is the party stuff in my UnitSpecific function:
Code:
	party = function(self)
		local Name = self.Health:CreateFontString(nil, 'OVERLAY')
		Name:SetPoint('CENTER', 0, 0)
		Name:SetPoint('CENTER', self, 'CENTER')
		Name:SetFont(FONT, FONTSIZE, FONTSTYLE)
		Name:SetJustifyH('CENTER')
		self:Tag(Name, '[opname]')

		local RoleIcon = self:CreateTexture(nil, 'ARTWORK')
		RoleIcon:SetPoint('LEFT', self, 'RIGHT', 3, 0)
		RoleIcon:SetSize(14, 14)
		RoleIcon:SetAlpha(1)
		self.LFDRole = RoleIcon

		local ReadyCheck = self:CreateTexture(nil, 'OVERLAY')
		ReadyCheck:SetPoint('LEFT', self, 'RIGHT', 3, 0)
		ReadyCheck:SetSize(14, 14)
		self.ReadyCheck = ReadyCheck

		self:HookScript('OnEnter', function() RoleIcon:SetAlpha(1) end)
		self:HookScript('OnLeave', function() RoleIcon:SetAlpha(0) end)
		self.Tag(HealthValue, '[ophealth]')

		self.Health:SetAllPoints()
	end,
I spawn my party frames using p3lim's header code:
Code:
self:SpawnHeader(nil, nil, 'custom [group:party] show; [@raid3,exists] hide; [@raid26,exists] hide; hide',
		'showParty', true, 'showRaid', false, 'showPlayer', false, 'yOffset', -4,
		'oUF-initialConfigFunction', [[
			self:SetHeight(24)
			self:SetWidth(159)
		]]
	):SetPoint('TOP', oUF_opUnitFramesPlayer, 'BOTTOM', 0, -10)
And then I hide Blizzard's party frames using oUF's DisableBlizzard function.

The party frames spawn just fine, they work great when it comes to my power tag and name tag, but my HP tag just doesn't show up.

Oh yeah, the tag I want to show is this:
Code:
oUF.Tags.Methods['oppartyhp'] = function(unit)
	local cur, max = UnitHealth(unit), UnitHealthMax(unit)
	
	if(cur ~= max and not UnitIsDeadOrGhost(unit)) then
		return ('|cffff0000-%s|r'):format(ShortValue(max - cur))
	else
		return ('%s'):format(ShortValue(max))
	end
end
For my full .lua file, go here. For the tags file, go here. Word of caution: They're messy.

I've tried moving the "self.Tag(HealthValue, '[ophealth]')" line to my Shared function (it's currently in my UnitSpecific function) but to no avail.

EDIT: Actually, come to think of it, it doesn't work for my Focus frame or Pet frame either. Odd.
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 10-03-13 at 07:08 AM.
  Reply With Quote
10-03-13, 11:26 AM   #6
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
The tag name in your 2nd snippet says "ophealth", not "oppartyhp".

Edit: You've also not specified an event and/or update interval for it.

Last edited by p3lim : 10-03-13 at 11:28 AM.
  Reply With Quote
10-03-13, 01:13 PM   #7
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
Oh yeah, sorry, should've mentioned. I changed it from oppartyhp to ophealth to see if it was the tag that was the issue, ophealth is my general tag for HP. It didn't work.

The event thing sounds likely, I'll try that.

EDIT: Right, so I added event checks to the tags but it still doesn't work. I can't get it to show with any tag.
I figured it might have been me trying to use SetPoint twice, so I changed that but that wasn't it either.
I then figured it might be there but hidden, so I made sure it wasn't by setting it's alpha to 1, no go.
I then figured it might be there but hidden under the unitframe, so I made sure it wasn't by setting the strata and frame level to 'HIGH' and 10 respectively, but no go. Atleast I ruled it out.

New code:
Code:
	local HealthValue = Health:CreateFontString(nil, 'OVERLAY')
	if(unit~='pet' or unit~='focus' or unit~='party') then
		HealthValue:SetPoint('RIGHT', -7, -1)
	else
		HealthValue:SetPoint('RIGHT', -7, 0)
		HealthValue:SetAlpha(1)
		HealthValue:SetFrameStrata('HIGH')
		HealthValue:SetFrameLevel(10)
	end
        HealthValue:SetFont(FONT, FONTSIZE, FONTSTYLE)
        HealthValue:SetJustifyH('RIGHT')
        HealthValue.frequentUpdates = 1/4
        self.HealthValue = HealthValue
       
        local PowerValue = self.Health:CreateFontString(nil, 'OVERLAY')
       
        if(unit=='player' or unit=='party') then                               
                PowerValue:SetFont(FONT, FONTSIZE, FONTSTYLE)
                PowerValue:SetJustifyH('LEFT')
                PowerValue.frequentUpdates = 0.1
                if(unit=='player') then
                        self:Tag(PowerValue, '[oppower]')
                        PowerValue:SetPoint('LEFT', 7, -1)
                        PowerValue:SetPoint('RIGHT', self.HealthValue, 'LEFT', -3)
                else
                        self:Tag(PowerValue, '[oppartypp]')
                        PowerValue:SetPoint('LEFT', 7, 0)
                        PowerValue:SetPoint('RIGHT', self.HealthValue, 'LEFT', -3)
                end
        end
Code:
--[[
	Party outputs
]]--
oUF.Tags.Methods['oppartyhp'] = function(unit)
	local cur, max = UnitHealth(unit), UnitHealthMax(unit)
	
	if(cur ~= max and not UnitIsDeadOrGhost(unit)) then
		return ('|cffff0000-%s|r'):format(ShortValue(max - cur))
	else
		return ('%s'):format(ShortValue(max))
	end
end
oUF.Tags.Events['oppartyhp'] = 'UNIT_HEALTH UNIT_MAXHEALTH UNIT_NAME UNIT_POWER UNIT_MAXPOWER'
Note that the focus frame isn't spawning the HP text either, and that uses my regular HP tag which works fine on Target and ToT.
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 10-03-13 at 01:56 PM.
  Reply With Quote
10-03-13, 02:51 PM   #8
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
Try adding prints in various places to see if stuff is created/fired/updated at all.
  Reply With Quote
10-03-13, 03:24 PM   #9
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
Added 3 prints, one at:
Code:
		local HealthValue = Health:CreateFontString(nil, 'OVERLAY')
		if(unit~='pet' or unit~='focus' or unit~='party') then
			HealthValue:SetPoint('RIGHT', -7, -1)
		else
			HealthValue:SetPoint('RIGHT', -7, 0)
			HealthValue:SetAlpha(1)
			HealthValue:SetFrameStrata('HIGH')
			HealthValue:SetFrameLevel(10)
			print('healthvalue 1')
		end
One at:
Code:
if(unit ~= 'party' and unit ~= 'raid' and unit ~= 'boss') then
                if(unit == 'focus') then               
                        Health:SetAllPoints()                       
                        self.Tag(HealthValue, '[ophealth]')
			print('healthvalue 2')
                elseif(unit == 'pet') then
                        Health:SetAllPoints()
                        self:SetSize(120, 18)
                end
        end
and one at:
Code:
        party = function(self)
                local Name = self.Health:CreateFontString(nil, 'OVERLAY')
                Name:SetPoint('CENTER', 0, 0)
                Name:SetPoint('CENTER', self, 'CENTER')
                Name:SetFont(FONT, FONTSIZE, FONTSTYLE)
                Name:SetJustifyH('CENTER')
                self:Tag(Name, '[opname]')
 
                local RoleIcon = self:CreateTexture(nil, 'ARTWORK')
                RoleIcon:SetPoint('LEFT', self, 'RIGHT', 3, 0)
                RoleIcon:SetSize(14, 14)
                RoleIcon:SetAlpha(1)
                self.LFDRole = RoleIcon
 
                local ReadyCheck = self:CreateTexture(nil, 'OVERLAY')
                ReadyCheck:SetPoint('LEFT', self, 'RIGHT', 3, 0)
                ReadyCheck:SetSize(14, 14)
                self.ReadyCheck = ReadyCheck
 
                self:HookScript('OnEnter', function() RoleIcon:SetAlpha(1) end)
                self:HookScript('OnLeave', function() RoleIcon:SetAlpha(0) end)
                self.Tag(self.HealthValue, '[oppartyhp]')
		print('healthvalue 3')
 
                self.Health:SetAllPoints()
        end,
2 and 3 loaded, 1 did not. So it seems the problem is in the first snippet? Maybe I need to add more prints.

EDIT: I moved the first snippet around into it's own if statement. SetFrameStrata and SetFrameLevel gave me errors, so I commented those out and now the print is sent, but still no HP text.
Code:
		if(unit=='party') then
			HealthValue:SetPoint('RIGHT', -7, 0)
			HealthValue:SetAlpha(1)
			--HealthValue:SetFrameStrata('HIGH')
			--HealthValue:SetFrameLevel(10)
			print('healthvalue 1')
		end
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 10-03-13 at 03:39 PM.
  Reply With Quote
10-04-13, 05:51 AM   #10
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
I don't see a font set to that.
  Reply With Quote
10-04-13, 07:51 AM   #11
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
There is, it just wasn't in the last post as it was unchanged from previous posts.

The full part where I spawn the fontstring is now this:
Code:
		local HealthValue = Health:CreateFontString(nil, 'OVERLAY')
		if(unit~='pet' or unit~='focus' or unit~='party') then
			HealthValue:SetPoint('RIGHT', -7, -1)
		end
		HealthValue:SetFont(FONT, FONTSIZE, FONTSTYLE)
		HealthValue:SetJustifyH('RIGHT')
		HealthValue.frequentUpdates = 1/4
		self.HealthValue = HealthValue
	   
		if(unit=='party') then
			HealthValue:SetPoint('RIGHT', -7, 0)
			HealthValue:SetAlpha(1)
			--HealthValue:SetFrameStrata('HIGH')
			--HealthValue:SetFrameLevel(10)
			print('healthvalue 1')
		end
This is my latest attempt, I've noticed a few interesting things.

I can't use an elseif statement for the last part like so:
Code:
		local HealthValue = Health:CreateFontString(nil, 'OVERLAY')
		if(unit~='pet' or unit~='focus' or unit~='party') then
			HealthValue:SetPoint('RIGHT', -7, -1)
		elseif(unit=='party') then
			HealthValue:SetPoint('RIGHT', -7, 0)
			HealthValue:SetAlpha(1)
			--HealthValue:SetFrameStrata('HIGH')
			--HealthValue:SetFrameLevel(10)
			print('healthvalue 1')
		end
		HealthValue:SetFont(FONT, FONTSIZE, FONTSTYLE)
		HealthValue:SetJustifyH('RIGHT')
		HealthValue.frequentUpdates = 1/4
		self.HealthValue = HealthValue
...because then it won't print, for whatever reason.
It also won't print if I just use a general "else" statement, like I need to in order to cover Focus, Party and Pet, all three suffer from the issue of no HP text right now.

The HP text still displays fine for Player, Target, Target of Target. Just nothing for the other frames.

EDIT: Pastebin of full code: http://pastebin.com/NZavvg2e
__________________
All I see is strobe lights blinding me in my hindsight.
  Reply With Quote
10-04-13, 08:18 AM   #12
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Code:
if(unit~='pet' or unit~='focus' or unit~='party') then
should be
Code:
if(unit~='pet' and unit~='focus' and unit~='party') then
The methods SetFrameLevel and SetFrameStrata only work on frames, for fontstrings and textures you would use SetDrawLayer.
  Reply With Quote
10-04-13, 08:33 AM   #13
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
Hmm, using 'or' works on all other places in the code though. But I gave it a shot, and it didn't work.

The print is sent now, however!

Only changed code from previous post:
Code:
		local HealthValue = Health:CreateFontString(nil, 'OVERLAY')
		if(unit~='pet' and unit~='focus' and unit~='party') then
			HealthValue:SetPoint('RIGHT', -7, -1)
		else
			HealthValue:SetPoint('RIGHT', -7, 0)
			HealthValue:SetAlpha(1)
			--HealthValue:SetFrameStrata('HIGH')
			--HealthValue:SetFrameLevel(10)
			print('healthvalue 1')
		end
		HealthValue:SetFont(FONT, FONTSIZE, FONTSTYLE)
		HealthValue:SetJustifyH('RIGHT')
		HealthValue.frequentUpdates = 1/4
		self.HealthValue = HealthValue
EDIT: Just to show what I'm talking about, I took a screenshot.


As you can see, the HP text works just fine on Target and ToT, they use the same tag as my Focus frame, but the Focus frame shows nothing.
Party doesn't show anything either, but that's a different tag. I've tried with all my different tags and none show for it.
You can ignore the player frame, it works as intended.
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 10-04-13 at 08:38 AM.
  Reply With Quote
10-04-13, 08:55 AM   #14
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
In your unit specific function for party you have:
Code:
self.Tag(self.HealthValue, '[oppartyhp]')
which should be:
Code:
self:Tag(self.HealthValue, '[oppartyhp]')
Edit:
You need to add the following to your unit specific function for focus:
Code:
self:Tag(self.HealthValue, '[ophealth]')

Last edited by Vrul : 10-04-13 at 09:04 AM.
  Reply With Quote
10-04-13, 09:09 AM   #15
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
Wow. That did it.

Thank you so much! I knew it was something as silly as that.
__________________
All I see is strobe lights blinding me in my hindsight.
  Reply With Quote

WoWInterface » Featured Projects » oUF (Otravi Unit Frames) » Can't seem to get classcolors to work


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