WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   oUF (Otravi Unit Frames) (https://www.wowinterface.com/forums/forumdisplay.php?f=87)
-   -   HealPrediction (https://www.wowinterface.com/forums/showthread.php?t=48323)

Rainrider 10-08-13 03:24 PM

HealPrediction
 
How are we supposed to implement the oUF's in-house healprediction element in a layout? My problem is how to position the status bars as obviously the example implementation in the comment in the element itself would simply overlap them if I anchor all of them to self.Health:GetTexture(). In Blizzard's heal prediction implementation the absorb bar is anchored either to the healAbsorb or the otherIncomingHeal, based on whether allIncomingHeal is bigger than the current heal absorb. The oUF's element does not support dynamic anchoring.

Aprat from that, Blizzard's heal prediction seems a bit strange (just from looking at the code, can't test this in-game). They seem to not reduce the amount of incoming heals by the amount of heal absorb (apart from when it would overflow the health bar) and always show the incoming heals even if the heal absorb is greater than them. They do reduce the heal absorb by the amount of incoming heals though and it seems they would display both heal absorb and inc heals overlapped (both textures are anchored to the health statusbar texture). Is this correct?

zork 10-08-13 03:26 PM

This is what I'm doing:
Lua Code:
  1. --heal prediction
  2.   func.healPrediction = function(self)
  3.     if not self.cfg.healprediction or (self.cfg.healprediction and not self.cfg.healprediction.show) then return end
  4.     local w = self.Health:GetWidth()
  5.     if w == 0 then
  6.       w = self:GetWidth()-24.5-24.5 --raids and party have no width on the health frame for whatever reason, thus use self and subtract the setpoint values
  7.     end
  8.     -- my heals
  9.     local mhpb = CreateFrame("StatusBar", nil, self.Health)
  10.     mhpb:SetFrameLevel(self.Health:GetFrameLevel())
  11.     mhpb:SetPoint("TOPLEFT", self.Health:GetStatusBarTexture(), "TOPRIGHT", 0, 0)
  12.     mhpb:SetPoint("BOTTOMLEFT", self.Health:GetStatusBarTexture(), "BOTTOMRIGHT", 0, 0)
  13.     mhpb:SetWidth(w)
  14.     mhpb:SetStatusBarTexture(self.cfg.healprediction.texture)
  15.     mhpb:SetStatusBarColor(self.cfg.healprediction.color.myself.r,self.cfg.healprediction.color.myself.g,self.cfg.healprediction.color.myself.b,self.cfg.healprediction.color.myself.a)
  16.     -- other heals
  17.     local ohpb = CreateFrame("StatusBar", nil, self.Health)
  18.     ohpb:SetFrameLevel(self.Health:GetFrameLevel())
  19.     ohpb:SetPoint("TOPLEFT", mhpb:GetStatusBarTexture(), "TOPRIGHT", 0, 0)
  20.     ohpb:SetPoint("BOTTOMLEFT", mhpb:GetStatusBarTexture(), "BOTTOMRIGHT", 0, 0)
  21.     ohpb:SetWidth(w)
  22.     ohpb:SetStatusBarTexture(self.cfg.healprediction.texture)
  23.     ohpb:SetStatusBarColor(self.cfg.healprediction.color.other.r,self.cfg.healprediction.color.other.g,self.cfg.healprediction.color.other.b,self.cfg.healprediction.color.other.a)
  24.     -- Register it with oUF
  25.     self.HealPrediction = {
  26.       myBar = mhpb,
  27.       otherBar = ohpb,
  28.       maxOverflow = self.cfg.healprediction.maxoverflow,
  29.     }
  30.   end

Rainrider 10-08-13 04:22 PM

You are not using the healAbsorbBar. The element got updated for 5.4. You also don't need to explicitly set the frame level to that of the health bar as long as it is your bars' parent.

Apart from that, my current implementation is exactly like yours. I just get some strange positioning and can't track it down. I would also like to mimic blizzard's functionality as close as possible, that's why I wonder how they handle the overlapped bars (if I read their code right) and how to anchor the bars dynamically. I could do the latter in PostUpdate with a lot of code repeating from the element's update function, which would be a waste and is a limitation of the element I think, unless I oversee something. So I would like to know how the blizzard implementation behaves and based on that either make my own oUF element for it or use the default one.

Rainrider 10-08-13 05:40 PM

Just found an easy way to see the whole thing in action: Glyph of Life Tap for heal absorb, Overgrown Lilypad for incoming heal and Sacrificial Pact for shield. I'll probably set for creating my own element, based on blizzard's code.

Freebaser 10-08-13 09:27 PM

This is where you can use PostUpdate, instead of an override function or writing a separate element.

Lua Code:
  1. local function HealPostUpdate = function(hp, unit)
  2.  
  3.     if(hp.absorbBar:GetValue() > 0) then
  4.         hp.absorbBar:ClearAllPoints()
  5.         hp.absorbBar:SetPoint('TOP')
  6.         hp.absorbBar:SetPoint('BOTTOM')
  7.  
  8.         if(hp.healAbsorbBar:GetValue() > 0) then
  9.             hp.absorbBar:SetPoint('LEFT', hp.healAbsorbBar:GetStatusBarTexture(), 'RIGHT')
  10.         else
  11.             hp.absorbBar:SetPoint('LEFT', hp.otherBar:GetStatusBarTexture(), 'RIGHT')
  12.         end
  13.     end
  14. end

Lua Code:
  1. ...
  2.  
  3. self.HealPrediction.PostUpdate = HealPostUpdate

zork 10-09-13 02:09 AM

@Rainrider
I have my own absorbbar module. That's why.

Module
http://code.google.com/p/rothui/sour...otalAbsorb.lua

Create Function
Lua Code:
  1. --total absorb
  2.   func.totalAbsorb = function(self)
  3.     if not self.cfg.totalabsorb or (self.cfg.totalabsorb and not self.cfg.totalabsorb.show) then return end
  4.     local w = self.Health:GetWidth()
  5.     if w == 0 then
  6.       w = self:GetWidth()-24.5-24.5 --raids and party have no width on the health frame for whatever reason, thus use self and subtract the setpoint values
  7.     end
  8.     local absorbBar = CreateFrame("StatusBar", nil, self.Health)
  9.     --new anchorpoint, absorb will now overlay the healthbar from right to left
  10.     absorbBar:SetFrameLevel(self.Health:GetFrameLevel()+1)
  11.     absorbBar:SetPoint("TOPRIGHT", self.Health, 0, 0)
  12.     absorbBar:SetPoint("BOTTOMRIGHT", self.Health, 0, 0)
  13.     absorbBar:SetWidth(w)
  14.     absorbBar:SetStatusBarTexture(self.cfg.totalabsorb.texture)
  15.     absorbBar:SetStatusBarColor(self.cfg.totalabsorb.color.bar.r,self.cfg.totalabsorb.color.bar.g,self.cfg.totalabsorb.color.bar.b,self.cfg.totalabsorb.color.bar.a)    
  16.     absorbBar:SetReverseFill(true)
  17.     -- Register with oUF
  18.     self.TotalAbsorb = absorbBar    
  19.   end

Result:


Basically I overlay the healthbar with the absorb bar from right-to-left. The healprediction is underneath.

That way when loosing health I can easily see how much of the health lost is covered by a shield. My shield display caps at maxhealth.

I see no point in adding absorb bar to the healprediction display. Healprediction fills up health that is lost. Absorbbar shows how much of your health is covered by a shield.

My orb uses the same module, just a different create function.
http://code.google.com/p/rothui/sour...player.lua#389

Quote:

Sidenote

I really would have loved to not using a fake statusbar on my orb. The problem is that when setting
Lua Code:
  1. bar:SetOrientation("VERTICAL")
  2. bar:SetReverseFill(true)

The statusbar texture crop is wrong. At least for what I'm needing. It will look like the texture is moving in from the top, not filling top-to-bottom.
I tried to hook the SetTexCoord function call on the statusbar texture to swap some values but it does not fire :/
Funny enough before applying the Smooth module I tried changing the SetTexCoord via the PostUpdate function but when PostUpdate was called (after SetValue) the SetTexCoord on the statusbar texture had not yet been applied. GetTexCoord() always delivered the old value, never the new one. Wierd! :)


Rainrider 10-09-13 01:08 PM

@Freebaser
Oh, I haven't thought about getting the status bar values. I'll also have to offset the healAbsorb and figure out the visibility of the bars when they overlap. Wouldn't it still be better to pass myIncomingHeal, otherIncomingHeal, totalAbsorb, myCurrentHealAbsorb and maxHealth to PostUpdate as this would spare the global calls (don't know if statusbar:GetValue() is a global or something else actually)?

Rainrider 10-09-13 02:42 PM

Ok, that's what I got so far:

PostUpdate:
lua Code:
  1. local PostUpdateHealPrediction = function(element, unit, overAbsorb, overHealAbsorb)
  2.     local health = element.__owner.Health
  3.     local _, maxHealth = health:GetMinMaxValues()
  4.     local myBar = element.myBar
  5.     local absorbBar = element.absorbBar
  6.     local healAbsorbBar = element.healAbsorbBar
  7.     local myCurrentHealAbsorb = UnitGetTotalHealAbsorbs(unit) or 0
  8.     local myCurrentHealAbsorbPercent = myCurrentHealAbsorb / maxHealth
  9.     local healAbsorbValue = healAbsorbBar:GetValue()
  10.     local healAbsorbPercent = healAbsorbValue / maxHealth
  11.  
  12.     if (absorbBar:GetValue() > 0) then
  13.         absorbBar:ClearAllPoints()
  14.         absorbBar:SetPoint("TOP")
  15.         absorbBar:SetPoint("BOTTOM")
  16.  
  17.         if (healAbsorbValue > 0) then
  18.             absorbBar:SetPoint("LEFT", healAbsorbBar:GetStatusBarTexture(), "RIGHT", 0, 0)
  19.         else
  20.             absorbBar:SetPoint("LEFT", element.otherBar:GetStatusBarTexture(), "RIGHT", 0, 0)
  21.         end
  22.     end
  23.  
  24.     if (healAbsorbValue > 0) then
  25.         print("healAbsorbValue > 0", unit, healAbsorbPercent)
  26.         healAbsorbBar:ClearAllPoints()
  27.         healAbsorbBar:SetPoint("TOP")
  28.         healAbsorbBar:SetPoint("BOTTOM")
  29.         healAbsorbBar:SetPoint("LEFT", health:GetStatusBarTexture(), "RIGHT", -(230 * healAbsorbPercent), 0)
  30.     end
  31.  
  32.     myBar:ClearAllPoints()
  33.     myBar:SetPoint("TOP")
  34.     myBar:SetPoint("BOTTOM")
  35.     myBar:SetPoint("LEFT", health:GetStatusBarTexture(), "RIGHT", -(230 * myCurrentHealAbsorbPercent), 0)
  36. end

Creation function (or whatever it should be called):
lua Code:
  1. local AddHealPredictionBar = function(self, unit)
  2.     local health = self.Health
  3.  
  4.     local hab = CreateFrame("StatusBar", nil, health)
  5.     hab:SetStatusBarTexture([[Interface\RaidFrame\Absorb-Fill]])
  6.     hab:SetPoint("TOP")
  7.     hab:SetPoint("BOTTOM")
  8.     hab:SetPoint("LEFT", health:GetStatusBarTexture(), "RIGHT")
  9.     hab:SetWidth(230)
  10.  
  11.     local mhpb = CreateFrame("StatusBar", nil, health)
  12.     mhpb:SetStatusBarTexture(ns.media.TEXTURE)
  13.     mhpb:SetStatusBarColor(0, 0.5, 0.5, 0.5)
  14.     mhpb:SetPoint("TOP")
  15.     mhpb:SetPoint("BOTTOM")
  16.     mhpb:SetPoint("LEFT", health:GetStatusBarTexture(), "RIGHT")
  17.     mhpb:SetWidth(230)
  18.  
  19.     local ohpb = CreateFrame("StatusBar", nil, health)
  20.     ohpb:SetStatusBarTexture(ns.media.TEXTURE)
  21.     ohpb:SetStatusBarColor(0, 1, 0, 0.5)
  22.     ohpb:SetPoint("TOP")
  23.     ohpb:SetPoint("BOTTOM")
  24.     ohpb:SetPoint("LEFT", mhpb:GetStatusBarTexture(), "RIGHT")
  25.     ohpb:SetWidth(230)
  26.  
  27.     local absorb = CreateFrame("StatusBar", nil, health)
  28.     absorb:SetStatusBarTexture(ns.media.TEXTURE)
  29.     absorb:SetStatusBarColor(1, 1, 1, 0.5)
  30.     absorb:SetPoint("TOP")
  31.     absorb:SetPoint("BOTTOM")
  32.     absorb:SetPoint("LEFT", ohpb:GetStatusBarTexture(), "RIGHT")
  33.     absorb:SetWidth(230)
  34.  
  35.     local overAbsorb = health:CreateTexture(nil, "OVERLAY")
  36.     overAbsorb:SetTexture([[Interface\RaidFrame\Shield-Overshield]])
  37.     overAbsorb:SetBlendMode("ADD")
  38.     overAbsorb:SetPoint("TOP")
  39.     overAbsorb:SetPoint("BOTTOM")
  40.     overAbsorb:SetPoint("LEFT", health, "RIGHT", -7, 0)
  41.     overAbsorb:Hide()
  42.  
  43.     self.HealPrediction = {
  44.         healAbsorbBar = hab,
  45.         myBar = mhpb,
  46.         otherBar = ohpb,
  47.         absorbBar = absorb,
  48.         overAbsorbGlow = overAbsorb,
  49.         maxOverflow = unit == "target" and 1.25 or 1,
  50.         PostUpdate = PostUpdateHealPrediction
  51.     }
  52. end
  53. ns.AddHealPredictionBar = AddHealPredictionBar

Anyone a better idea?

Btw, shouldn't the oUF element break the update if maxHealth == 0?

Freebaser 10-09-13 08:39 PM

You can drop the PostUpdate healAbsorbPercent and healAbsorbBar:SetPoint stuff. Use something like this when creating the bar.

Lua Code:
  1. local healAbsorbBar = CreateFrame("StatusBar", nil, self.Health)
  2. healAbsorbBar:SetStatusBarTexture[[Interface\RaidFrame\Absorb-Fill]]
  3. healAbsorbBar:SetPoint("TOP")
  4. healAbsorbBar:SetPoint("BOTTOM")
  5. healAbsorbBar:SetPoint("LEFT", self.Health:GetStatusBarTexture(), "RIGHT", -(self.Health:GetWidth()), 0)
  6. healAbsorbBar:SetWidth(self.Health:GetWidth())
  7. healAbsorbBar:SetReverseFill(true)
  8. healAbsorbBar:Hide()

zork 10-10-13 01:36 AM

self.Health:GetWidth() returns 0 for me on group header units.

Freebaser 10-10-13 02:14 AM

Quote:

Originally Posted by zork (Post 285694)
self.Health:GetWidth() returns 0 for me on group header units.

Make sure it runs after self.Health:SetSize/SetWidth or replace it with a static value. If you're using the entire frame (e.g. self.Health:SetAllPoints(self)) you could use self:GetWidth()

Rainrider 10-10-13 04:34 AM

Quote:

Originally Posted by Freebaser (Post 285690)
You can drop the PostUpdate healAbsorbPercent and healAbsorbBar:SetPoint stuff. Use something like this when creating the bar.

Lua Code:
  1. local healAbsorbBar = CreateFrame("StatusBar", nil, self.Health)
  2. healAbsorbBar:SetStatusBarTexture[[Interface\RaidFrame\Absorb-Fill]]
  3. healAbsorbBar:SetPoint("TOP")
  4. healAbsorbBar:SetPoint("BOTTOM")
  5. healAbsorbBar:SetPoint("LEFT", self.Health:GetStatusBarTexture(), "RIGHT", -(self.Health:GetWidth()), 0)
  6. healAbsorbBar:SetWidth(self.Health:GetWidth())
  7. healAbsorbBar:SetReverseFill(true)
  8. healAbsorbBar:Hide()

Nice one, thank you.

It appears that local _, maxHealth = health:GetMinMaxValues() is not a save way to retrieve maxHealth as it returns 0 after /reloadui when I apply a heal absorb on me and then target myself. Subsequent targeting seems to return correct values. Wasn't able to reproduce this with UnitHealthMax(unit).

My code so far:
lua Code:
  1. local PostUpdateHealPrediction = function(element, unit, overAbsorb, overHealAbsorb)
  2.     local health = element.__owner.Health
  3.     local maxHealth = UnitHealthMax(unit)
  4.     local myBar = element.myBar
  5.     local absorbBar = element.absorbBar
  6.     local healAbsorbBar = element.healAbsorbBar
  7.     local myCurrentHealAbsorb = UnitGetTotalHealAbsorbs(unit) or 0
  8.     local myCurrentHealAbsorbPercent = myCurrentHealAbsorb / maxHealth
  9.  
  10.     if (absorbBar:GetValue() > 0) then
  11.         absorbBar:ClearAllPoints()
  12.         absorbBar:SetPoint("TOP")
  13.         absorbBar:SetPoint("BOTTOM")
  14.  
  15.         if (healAbsorbBar:GetValue() > 0) then
  16.             absorbBar:SetPoint("LEFT", healAbsorbBar:GetStatusBarTexture(), "RIGHT", 0, 0)
  17.         else
  18.             absorbBar:SetPoint("LEFT", element.otherBar:GetStatusBarTexture(), "RIGHT", 0, 0)
  19.         end
  20.     end
  21.  
  22.     if (overHealAbsorb) then
  23.         element.overHealAbsorbGlow:Show()
  24.         myBar:Hide() -- will this hide otherBar as well? Is hiding it the right way to go
  25.     else
  26.         element.overHealAbsorbGlow:Hide()
  27.         myBar:ClearAllPoints()
  28.         myBar:SetPoint("TOP")
  29.         myBar:SetPoint("BOTTOM")
  30.         myBar:SetPoint("LEFT", health:GetStatusBarTexture(), "RIGHT", -(230 * myCurrentHealAbsorbPercent), 0)
  31.         myBar:Show()
  32.     end
  33.  
  34.     if (overAbsorb) then
  35.         element.overAbsorbGlow:Show()
  36.     else
  37.         element.overAbsorbGlow:Hide()
  38.     end
  39. end
lua Code:
  1. local AddHealPredictionBar = function(self, unit)
  2.     local health = self.Health
  3.  
  4.     local hab = CreateFrame("StatusBar", nil, health)
  5.     hab:SetStatusBarTexture(ns.media.TEXTURE)
  6.     hab:SetStatusBarColor(0.75, 0.75, 0, 0.5)
  7.     hab:SetPoint("TOP")
  8.     hab:SetPoint("BOTTOM")
  9.     hab:SetPoint("LEFT", health:GetStatusBarTexture(), "RIGHT", -230, 0)
  10.     hab:SetWidth(230)
  11.     hab:SetReverseFill(true)
  12.  
  13.     local mhpb = CreateFrame("StatusBar", nil, health)
  14.     mhpb:SetStatusBarTexture(ns.media.TEXTURE)
  15.     mhpb:SetStatusBarColor(0, 0.5, 0.5, 0.5)
  16.     mhpb:SetPoint("TOP")
  17.     mhpb:SetPoint("BOTTOM")
  18.     mhpb:SetPoint("LEFT", health:GetStatusBarTexture(), "RIGHT")
  19.     mhpb:SetWidth(230)
  20.  
  21.     local ohpb = CreateFrame("StatusBar", nil, health)
  22.     ohpb:SetStatusBarTexture(ns.media.TEXTURE)
  23.     ohpb:SetStatusBarColor(0, 1, 0, 0.5)
  24.     ohpb:SetPoint("TOP")
  25.     ohpb:SetPoint("BOTTOM")
  26.     ohpb:SetPoint("LEFT", mhpb:GetStatusBarTexture(), "RIGHT")
  27.     ohpb:SetWidth(230)
  28.  
  29.     local absorb = CreateFrame("StatusBar", nil, health)
  30.     absorb:SetStatusBarTexture(ns.media.TEXTURE)
  31.     absorb:SetStatusBarColor(1, 1, 1, 0.5)
  32.     absorb:SetPoint("TOP")
  33.     absorb:SetPoint("BOTTOM")
  34.     absorb:SetPoint("LEFT", ohpb:GetStatusBarTexture(), "RIGHT")
  35.     absorb:SetWidth(230)
  36.  
  37.     local overAbsorb = health:CreateTexture(nil, "OVERLAY")
  38.     overAbsorb:SetTexture([[Interface\RaidFrame\Shield-Overshield]])
  39.     overAbsorb:SetBlendMode("ADD")
  40.     overAbsorb:SetPoint("TOP")
  41.     overAbsorb:SetPoint("BOTTOM")
  42.     overAbsorb:SetPoint("LEFT", health, "RIGHT", -7, 0)
  43.     overAbsorb:Hide()
  44.  
  45.     local overHealAbsorb = health:CreateTexture(nil, "OVERLAY")
  46.     overHealAbsorb:SetTexture([[Interface\RaidFrame\Absorb-Overabsorb]])
  47.     overHealAbsorb:SetBlendMode("ADD")
  48.     overHealAbsorb:SetPoint("TOP")
  49.     overHealAbsorb:SetPoint("BOTTOM")
  50.     overHealAbsorb:SetPoint("RIGHT", health, "LEFT", 7, 0)
  51.     overHealAbsorb:Hide()
  52.  
  53.     self.HealPrediction = {
  54.         healAbsorbBar = hab,
  55.         myBar = mhpb,
  56.         otherBar = ohpb,
  57.         absorbBar = absorb,
  58.         overAbsorbGlow = overAbsorb,
  59.         overHealAbsorbGlow = overHealAbsorb,
  60.         maxOverflow = unit == "target" and 1.25 or 1,
  61.         PostUpdate = PostUpdateHealPrediction
  62.     }
  63. end
  64. ns.AddHealPredictionBar = AddHealPredictionBar

@zork
I also have issues with 0 returns for GetWidth(), I'll open a new thread for it.

zork 10-10-13 04:49 AM

I just do self:GetWidth(). If you have a setpoint on your health that affects the width you just need to substract it.

Rainrider 10-10-13 05:27 AM

I opened a thread for this at http://www.wowinterface.com/forums/s...ad.php?t=48331


All times are GMT -6. The time now is 01:09 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI