WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Filter Buffs/Debuffs on Default Nameplates (https://www.wowinterface.com/forums/showthread.php?t=55729)

Sylen 09-10-17 06:27 AM

Filter Buffs/Debuffs on Default Nameplates
 
TL;TR:
Is there a clean way you can filter(whitelist) the buffs/debuffs shown on the default blizzard nameplates (including the new personal resource display)?


I tried to modify the default filter to show all harmful spells by a player but as far as i can tell it achieved nothing. This is the code i am using for it
Code:

hooksecurefunc(NamePlateDriverFrame, "OnUnitAuraUpdate", function(self, unit)
        local filter;
        if UnitIsUnit("player", unit) then
                filter = "HELPFUL|INCLUDE_NAME_PLATE_ONLY";
        else
                local reaction = UnitReaction("player", unit);
                if reaction and reaction <= 4 then
                        -- Reaction 4 is neutral and less than 4 becomes increasingly more hostile
                        filter = "HARMFUL|PLAYER";
                else
                        filter = "NONE";
                end
        end
 
        local nameplate = C_NamePlate.GetNamePlateForUnit(unit);
        if (nameplate) then
                nameplate.UnitFrame.BuffFrame:UpdateBuffs(nameplate.namePlateUnitToken, filter);
        end
end)

After some research i stumbled upon this thread in which the same problem is identified by Ketho but it seems nobody found a solution.

I researched more and found this script/macro on the mmo-champion forums, which stated by the author does the following:
"I was also disappointed the nameplates weren't showing all buffs on me so this script makes it show ALL buffs except indefinite buffs or buffs that last more than about a minute. It also doesn't show buffs with the SpellID specified by b so you can add your own unwanted SpellIDs to b or just leave it as b={} if you don't care."
Source
Code:

/run local b={196608,126896};local gn=UnitAura;local function fn(...)local a={gn(...)};a[15]=a[6]~=nil and not tContains(b,a[11])and abs(a[6]-31)<31;return unpack(a);end UnitAura=fn;
This script does indeed work but it uses a blacklist-filtering and i felt like creating a blacklist for all buffs i don't want to see on myself is too much work.
I figured what i need is a whitelist filter so i changed the script to this:
Code:

--Filter buffs/debuffs on nameplates, personal resource display
local filter = CreateFrame("Frame")
filter:RegisterEvent("PLAYER_ENTERING_WORLD")

filter:SetScript("OnEvent", function()
        --This filters debuffs and buffs(personal resource display)
        local Whitelist = {}
       
        local gn = UnitAura
        local function Filter(...)
                local AllBuffs = {gn(...)}
                AllBuffs[15] = AllBuffs[6] ~= nil and tContains(Whitelist, AllBuffs[11]) and abs(AllBuffs[6]-31)<31 return unpack(AllBuffs) end
        UnitAura = Filter
end)

The whitelist filter works just fine but another problem now occured, the script eats tremendous amounts of memory while running for a longer time resulting in a performance loss and fps drop.
At this point it overextends my coding knowledge and i don't really know how to move on.

CC_WOW 09-13-17 04:44 AM

I'm not an expert by any means, but some basic profiling tells me that each time the Filter function is called you use an additional 700-800 bytes of memory (sometimes more) which are never freed (that part is the problem). This is probably the result of you re-creating tables every time the code is execute with the { ... } constructor - see http://lua-users.org/wiki/OptimisingGarbageCollection

Running collectgarbage("collect") would help, but it is obviously not a practical solution unless you do it at a given threshold only. Normally, the garbage collector would mark the unused table and should collect ("sweep") it automatically, but in my tests it simply hasn't done that and I couldn't tell you why - I assume it runs when too much memory has been used, which should still be long before you are getting FPS drops.

PS: Is overwriting APIs like that really a good idea? UnitAura is used by at least Blizzard_NamePlates and also in the BuffFrame (I think). But someone else surely is more proficient than I am in these things :P

Sylen 09-13-17 06:42 AM

I will have a look into this.

As far as overwriting Blizzard functions goes, i'm not really a fan of doing it but i haven't found a clean solution to filter the buffs.

I also still don't really understand how Blizzard itself filters the buffs. When I am playing on my Feral Druid and spec into Savage Roar, it is displayed above the PersonalResourceDisplay. The question is, how does the game know that it has to show this buff in particular. So there must be some kind of filtering already in place. The only important thing is, can you access it by Lua or is it somewhere in the C code. I couldn't find a pre-set whitelist in the interface code so I'm guessing you can not access it.

Ammako 09-13-17 11:20 AM

Google brought me to this thread on MMOC, with a script which seems to work:

Code:

local whitelist = {
        ["Goremaw's Bite"] = "player",
        ["Night Terrors"] = "player",
        ["Nightblade"] = "player",
        ["Symbols of Death"] = "player"
}

local function newShouldShowBuff(_,name,caster)
        return name and (whitelist[name] == caster or whitelist[name] == "all")
end

local function Mixin(baseFrame)
        baseFrame.UnitFrame.BuffFrame.ShouldShowBuff = newShouldShowBuff
end

local f = CreateFrame("Frame")
f:RegisterEvent("NAME_PLATE_UNIT_ADDED")
f:SetScript("OnEvent", function(_,_,unitId)
        Mixin(C_NamePlate.GetNamePlateForUnit(unitId))
end)

for _,baseFrame in pairs(C_NamePlate.GetNamePlates()) do
        Mixin(baseFrame)
end

Keep in mind this is a strict whitelist filter; buffs that normally show on nameplates as per default UI will be hidden unless they are added to the whitelist (I think that was already what you wanted, either way.)

https://gfycat.com/violetoldfashionedgraywolf

Haven't tested this for too long so I can't tell you if it runs into memory issues, but at least it doesn't make me puke inside my mouth by overwriting a global function.


Edit: Playing a bit more with this code enabled, it doesn't look like this works well at all. I had a few debuffs that weren't whitelisted that appeared on nameplates anyway.
Maybe somebody can figure out why it happens and fix the script, or come up with a different solution altogether :/

Sylen 09-18-17 08:26 AM

Hey, thanks for your input Ammako. I'm gonna try this new code out for a while and will report my results back here.

Can you by any chance remember some of the buffs/debuffs that were not whitelisted, but showed up anyway?

Ammako 09-18-17 11:38 AM

I was in Suramar fishing for the daily, and the Paladin Judgement debuff was showing on the mini-boss' nameplate. I think there may have been another one but I can't remember.

All I had in the whitelist were those four sub rogue buffs/debuffs; I didn't even mean to keep this code running and had simply forgotten to comment it out, but that's probably a good thing because I wouldn't have caught the issue otherwise.

Sylen 09-18-17 03:02 PM

I was able to reproduce this issue. There are several buffs / debuffs shown that are not in the whitelist.

I queued some random battlegrounds and noticed that the collectable buffs (berserk, heal, sprint) show up aswell as the indefinite buffs you get for defending a flag.

Sylen 09-20-17 04:03 AM

Running this code the past days in different environments leads me to the conclusion that there is no logic behind which buffs/debuffs show up in spite of that they are not whitelisted.
I will add an additional blacklist filter for now. Let's see if this gets out of hand fairly quickly or if the list is clearly arranged.


All times are GMT -6. The time now is 03:10 AM.

vBulletin © 2020, Jelsoft Enterprises Ltd
© 2004 - 2020 MMOUI