WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Highlighting lifebloom with pandemic (https://www.wowinterface.com/forums/showthread.php?t=56235)

tehmoku 05-24-18 04:37 PM

Highlighting lifebloom with pandemic
 
Update: https://www.wowinterface.com/downloa...bloomGlow.html

For anyone looking for an addon version of the code posted below.

---------------------------------------------------------------------------------------------------------------------

This person has a script that highlights lifebloom on normal raid frames when it's in pandemic range. Wondering how complex this would be to reproduce.

This is especially useful for lifebloom as you can "bloom" it when it is in this range.



tehmoku 05-26-18 03:44 PM

It seems I've gotten this to work how I want to it work using some hacky timer code.

I'm a bit stumped still on how to get the "dispellable" white border around the icon though.

Quote:

snip

sylvanaar 05-28-18 09:14 PM

I play (badly) a resto druid. What is this about?

tehmoku 05-28-18 10:24 PM

Quote:

Originally Posted by sylvanaar (Post 328184)
I play (badly) a resto druid. What is this about?

If lifebloom is at 30% of its initial duration and you re-cast lifebloom on to that target, the finishing "bloom" will happen. It is essential to only recast it in this window or you lose that burst heal.

Since it is based on a hidden timer, there's no way to know if you can re-cast it to get the bloom effect or not. It's all guessing. On live, it can be anywhere from 4.5 seconds to 5.85 seconds from my testing.

So, I wanted to have some code that highlights lifebloom on raid frames when it is in this essential window so you don't have to guess anymore.

Still not 100% there yet, unfortunately--although I know it is possible from that screenshot I showed.

sylvanaar 05-29-18 09:48 AM

Thanks for that. What does it have to do with pandemic range? Or was that just some use for it?

tehmoku 05-29-18 09:58 AM

Pandemic was a spell for warlocks back in MoP (I think MoP) that allowed you to refresh dots up to 50% without losing any of the damage (aka the dot would just rollover into the new one you casted)

Now that ability is baked in to everything in the game at 30% all hots/dots "rollover," and pandemic is just what people have called it.

Sylen 06-02-18 07:49 AM

Did you make progress on this topic? For the glow effect people usually use this code:

Lua Code:
  1. --Highlight Purgable Buffs on Target and Focus
  2. hooksecurefunc("TargetFrame_UpdateAuras", function(s)
  3.     for i = 1, MAX_TARGET_BUFFS do
  4.         _, _, ic, _, dT = UnitBuff(s.unit, i)
  5.         if(ic and (not s.maxBuffs or i<=s.maxBuffs)) then
  6.             fS=_G[s:GetName()..'Buff'..i..'Stealable']
  7.             if(UnitIsEnemy(PlayerFrame.unit, s.unit) and dT=='Magic') then
  8.                 fS:Show()
  9.             else
  10.                 fS:Hide()
  11.             end
  12.         end
  13.     end
  14. end)

tehmoku 06-02-18 02:34 PM

That code only works on target and focus frames. CompactUnitFrames don't have a Stealable:Show() argument (returns nil) attached to their buff icons because technically you aren't able to steal/purge anything off a friendly target.

tehmoku 06-03-18 10:33 PM

So, for anyone potentially following the thread..

I have finished this finally, and have working code for BfA. (A couple things were removed from UnitBuff, namely spell rank, so this code won't specifically work on live but it's easily fixable if you so choose)

The only, and major problem is that this doesn't update often enough when I need it to. If anyone has any suggestions on how I can update it more frequently, I'm open to suggestion. It updates every time an aura gets updated (applied or removed), but for this to be truly perfect it would probably need to update at least every half second with lifebloom up, regardless of anything else.

As a result, sometimes even though LB can be manually "bloomed" at 5.5 seconds, the highlight won't appear until after that. The amount of time after that varies depending on how often auras are being updated for the unit.

Lua Code:
  1. --Target Frame
  2. function TargetFrame_UpdateAuras_Hook(self)
  3.     local frame, frameName
  4.     local selfName = self:GetName()
  5.  
  6.     for i = 1, MAX_TARGET_BUFFS do
  7.     local buffName, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal,
  8.     spellId, canApplyAura, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, _ = UnitBuff(self.unit, i, nil)
  9.  
  10.         if buffName then
  11.             if spellId == 33763 and casterIsPlayer then
  12.                 frameName = selfName.."Buff"..(i)
  13.                 frame = _G[frameName]
  14.                 if frame and icon and (not self.maxBuffs or i <= self.maxBuffs) then
  15.                     local timeRemaining = (expirationTime - GetTime()) / timeMod
  16.                     local refreshTime = duration * 0.3
  17.                     local frameStealable = _G[frameName.."Stealable"]
  18.  
  19.                     if timeRemaining <= refreshTime then
  20.                         frameStealable:Show()
  21.                     else
  22.                         frameStealable:Hide()
  23.                     end
  24.                 end
  25.                 break
  26.             end
  27.         else
  28.             break
  29.         end
  30.     end
  31. end
  32. hooksecurefunc("TargetFrame_UpdateAuras", TargetFrame_UpdateAuras_Hook)
  33.  
  34. --Compact Unit Frame
  35. function CompactUnitFrame_UtilSetBuff_Hook(buffFrame, unit, index, filter)
  36.     local buffName, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal,
  37.     spellId, canApplyAura, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, _ = UnitBuff(unit, index, filter)
  38.  
  39.     if spellId == 33763 and casterIsPlayer then
  40.         local timeRemaining = (expirationTime - GetTime()) / timeMod
  41.         local refreshTime = duration * 0.3
  42.  
  43.     if not buffFrame.highlight then
  44.         local highlight = buffFrame:CreateTexture(nil, "OVERLAY")
  45.         highlight:SetTexture([[Interface\TargetingFrame\UI-TargetingFrame-Stealable]])
  46.         highlight:SetPoint("TOPLEFT", -3, 3)
  47.         highlight:SetPoint("BOTTOMRIGHT", 3, -3)
  48.         highlight:SetBlendMode("ADD")
  49.         buffFrame.highlight = highlight
  50.     end
  51.  
  52.     if timeRemaining <= refreshTime then
  53.         buffFrame.highlight:Show()
  54.     else
  55.         buffFrame.highlight:Hide()
  56.     end
  57.  
  58.     elseif buffFrame.highlight then
  59.         buffFrame.highlight:Hide()
  60.     end
  61. end
  62. hooksecurefunc("CompactUnitFrame_UtilSetBuff", CompactUnitFrame_UtilSetBuff_Hook)

Ammako 06-04-18 02:45 AM

If you wanted (needed?) it to update every frame, wouldn't it be easier to just hook TargetFrame_OnUpdate and CompactUnitFrame_OnUpdate?

Just be careful that your code not be too demanding so that having it run every frame doesn't risk causing performance issues, and it should be okay. It's not usually recommended to hook OnUpdate, and maybe there's a better solution, but if you absolutely need it to run every frame then OnUpdate is your solution (that's what OnUpdate does, after all.)

You could throttle it within the hook function if you needed to, to make it run only every other frame, which may help if performance ever became an issue.

pegasu8 06-04-18 08:28 AM

Quote:

Originally Posted by tehmoku (Post 328229)
So, for anyone potentially following the thread..

I have finished this finally, and have working code for BfA. (A couple things were removed from UnitBuff, namely spell rank, so this code won't specifically work on live but it's easily fixable if you so choose)

The only, and major problem is that this doesn't update every frame. If anyone has any suggestions on how I can update it more frequently, I'm open to suggestion. It updates every time an aura gets updated, but for this to be truly perfect it would probably need to update at least every half second with lifebloom up, regardless of anything else.

As a result, sometimes even though LB can be manually "bloomed" at 5.5 seconds, the highlight won't appear until after that. The amount of time after that varies depending on how often auras are being updated for the unit.

Lua Code:
  1. --Target Frame
  2. function TargetFrame_UpdateAuras_Hook(self)
  3.     local frame, frameName
  4.     local selfName = self:GetName()
  5.  
  6.     for i = 1, MAX_TARGET_BUFFS do
  7.     local buffName, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal,
  8.     spellId, canApplyAura, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, _ = UnitBuff(self.unit, i, nil)
  9.  
  10.         if buffName then
  11.             if spellId == 33763 and casterIsPlayer then
  12.                 frameName = selfName.."Buff"..(i)
  13.                 frame = _G[frameName]
  14.                 if frame and icon and (not self.maxBuffs or i <= self.maxBuffs) then
  15.                     local timeRemaining = (expirationTime - GetTime()) / timeMod
  16.                     local refreshTime = duration * 0.3
  17.                     local frameStealable = _G[frameName.."Stealable"]
  18.  
  19.                     if timeRemaining <= refreshTime then
  20.                         frameStealable:Show()
  21.                     else
  22.                         frameStealable:Hide()
  23.                     end
  24.                 end
  25.                 break
  26.             end
  27.         else
  28.             break
  29.         end
  30.     end
  31. end
  32. hooksecurefunc("TargetFrame_UpdateAuras", TargetFrame_UpdateAuras_Hook)
  33.  
  34. --Compact Unit Frame
  35. function CompactUnitFrame_UtilSetBuff_Hook(buffFrame, unit, index, filter)
  36.     local buffName, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal,
  37.     spellId, canApplyAura, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, _ = UnitBuff(unit, index, filter)
  38.  
  39.     if spellId == 33763 and casterIsPlayer then
  40.         local timeRemaining = (expirationTime - GetTime()) / timeMod
  41.         local refreshTime = duration * 0.3
  42.  
  43.     if not buffFrame.highlight then
  44.         local highlight = buffFrame:CreateTexture(nil, "OVERLAY")
  45.         highlight:SetTexture([[Interface\TargetingFrame\UI-TargetingFrame-Stealable]])
  46.         highlight:SetPoint("TOPLEFT", -3, 3)
  47.         highlight:SetPoint("BOTTOMRIGHT", 3, -3)
  48.         highlight:SetBlendMode("ADD")
  49.         buffFrame.highlight = highlight
  50.     end
  51.  
  52.     if timeRemaining <= refreshTime then
  53.         buffFrame.highlight:Show()
  54.     else
  55.         buffFrame.highlight:Hide()
  56.     end
  57.  
  58.     elseif buffFrame.highlight then
  59.         buffFrame.highlight:Hide()
  60.     end
  61. end
  62. hooksecurefunc("CompactUnitFrame_UtilSetBuff", CompactUnitFrame_UtilSetBuff_Hook)

Can you post a working script which also works in Legion still?

tehmoku 06-04-18 12:52 PM

Quote:

Originally Posted by Ammako (Post 328230)
If you wanted (needed?) it to update every frame, wouldn't it be easier to just hook TargetFrame_OnUpdate and CompactUnitFrame_OnUpdate?

Yeah, I don't want to actually run it OnUpdate. That's entirely too demanding for this. I was hoping there was a more elegant solution that someone else may be able to tell me.

I was hooking buffFrame to OnUpdate, and it worked well, but it was just too much considering it only really needs to be a fraction of that for 30% of the time a single buff is active.

Although I'm unconvinced--maybe in practice there's enough UNIT_AURA events firing that it won't be a real issue, but if not I'll go back to OnUpdate if needed.

Quote:

Originally Posted by pegasu8 (Post 328232)
Can you post a working script which also works in Legion still?

Yes, change lines 7/8 and 36/37 in the code to this

Lua Code:
  1. local buffName, _, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, _ = UnitBuff(unit, index, filter)

tehmoku 06-04-18 03:10 PM

So, here is the code for running on a throttled OnUpdate (just change the update interval to whatever you want).

Note: I only really care about raid frames being highly accurate, and I left the target frame how it was.

Fair warning, it's quite a bit more taxing on your CPU. It's a lot more reliable though, and probably what I will be using. This code is for legion, but just remove the underscore next to buffName on line 21 and it will work for BfA.

Lua Code:
  1. local ONUPDATE_INTERVAL = 0.5
  2. local lastUpdate = 0
  3.  
  4. --Compact Unit Frames
  5. hooksecurefunc("CompactUnitFrame_OnUpdate",function(frame, elapsed)
  6. lastUpdate = lastUpdate + elapsed
  7.  
  8.     if lastUpdate >= ONUPDATE_INTERVAL then
  9.         lastUpdate = 0
  10.  
  11.         local index = 1
  12.         local frameNum = 1
  13.         local filter = nil
  14.  
  15.         while ( frameNum <= frame.maxBuffs ) do
  16.             local buffNames = UnitBuff(frame.displayedUnit, index, filter)
  17.             if ( buffNames ) then
  18.                 if ( CompactUnitFrame_UtilShouldDisplayBuff(frame.displayedUnit, index, filter) and not CompactUnitFrame_UtilIsBossAura(frame.displayedUnit, index, filter, true) ) then
  19.                     local buffFrame = frame.buffFrames[frameNum]
  20.  
  21.                     local buffName, _, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal,
  22.                     spellId, canApplyAura, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, _ = UnitBuff(frame.displayedUnit, index, filter)
  23.  
  24.                     if spellId == 33763 and casterIsPlayer then
  25.                         local timeRemaining = (expirationTime - GetTime()) / timeMod
  26.                         local refreshTime = duration * 0.3
  27.  
  28.                         if not buffFrame.highlight then
  29.                             local highlight = buffFrame:CreateTexture(nil, "OVERLAY")
  30.                             highlight:SetTexture([[Interface\TargetingFrame\UI-TargetingFrame-Stealable]])
  31.                             highlight:SetPoint("TOPLEFT", -3, 3)
  32.                             highlight:SetPoint("BOTTOMRIGHT", 3, -3)
  33.                             highlight:SetBlendMode("ADD")
  34.                             buffFrame.highlight = highlight
  35.                         end
  36.  
  37.                         if timeRemaining <= refreshTime then
  38.                             buffFrame.highlight:Show()
  39.                         else
  40.                             buffFrame.highlight:Hide()
  41.                         end
  42.  
  43.                     elseif buffFrame.highlight then
  44.                         buffFrame.highlight:Hide()
  45.                     end
  46.  
  47.                     frameNum = frameNum + 1
  48.                 end
  49.             else
  50.                 break
  51.             end
  52.             index = index + 1
  53.         end
  54.     end
  55. end)

Kakjens 06-06-18 06:55 PM

Lua Code:
  1. local index = 1
  2. local frameNum = 1
  3. local filter = nil
could be moved after lastUpdate = 0.
frame.displayedUnit gets accessed quite often, so maybe a local variable is warranted.
I would suggest fixing indentation of lines 27-40, otherwise
Lua Code:
  1. elseif buffFrame.highlight then
  2.     buffFrame.highlight:Hide()
  3. end
will look weird.
Also, I would have tried to track the player I cast Lifebloom.

tehmoku 06-17-18 04:57 PM

It turns out the OnUpdate code was unnecessary. Lifebloom doesn't update often enough when you just have your own buffs, but CompactUnitFrame_UtilSetBuff fires very often under normal use case, resulting in desired accuracy.

https://www.wowinterface.com/downloa...bloomGlow.html

For anyone following the thread or people coming from google, here is the addon if you don't want to worry about what to do with code or whatever.

Cheers :banana:


All times are GMT -6. The time now is 01:48 PM.

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