Plater Nameplates

Plater Nameplates

64M Downloads

[Feature] Tank aggro pulling - Percent setting

Ganbin opened this issue ยท 9 comments

commented

Hello,

I play Druid tank on TBC.

I really like the tanking colors, however, there is one option that I feel is missing. We cannot set the percentage when we want to display the color for when we start to loose aggro.

I see that you are using the status == 2 of the UnitDetailedThreatSituation function to define that we are losing the aggro.

elseif (threatStatus == 2) then --is tanking with risk of aggro loss

I have tested another addon (Threat Plates) where you can define the percentage when we want the color to change when we start to loose aggro.

They seems to use the threatpct of the UnitDetailedThreatSituation UnitDetailedThreatSituation

I think this setting is missing because most of the time, when the color change, it is already too late and I loose the aggro juste 1 or 2 second after. With the other addon, I can set up a percentage and I know in advance when someone start to become close to me.

I don't know if this is an easy task, I have look at the code but I'm not sure how to implement this feature by myself.

Hope my request was clear enough. Sorry I'm bad to explain things.

commented

What I would like is :
When someone is at 80% (this value should be a setting) of aggro behind me, the nameplate color start to change, so I'm aware that I should push more aggro on this enemy.

This is specially useful when tanking multiple enemies, it helps to know when to change the target.

commented

This is a prime example for things that can easily be achieved with modding. I suggest taking a look at the available "Force Threat Colors" mod. There are a few versions around on wago.io which are more or less the same.
That can be stripped down to just check for the percentage and set the color accordingly. No need for the rest.

commented

UnitDetailedThreatSituation is between two units, in that case you and the npc.
The percentage value returned is the relative percent from you towards the first player on the threat table, iirc. Not sure if it updates towards the second player, if they gain up on your threat.
There is a mod which shows threat % on the nameplate on wago.io, you could try that to test it.

commented

Hello, you are totally right and I have figured out this yesterday. I have spend some time to try to implement the best I can and I end up with this mod :
https://wago.io/sgI9x0D0e

I basically build a threat table and take the first 2, and depending on who tank and who is the second (and especially at what percentage is the second) I will adapt the color of the nameplate.

I will try this afternoon if this is not too much heavy code to run when we are 25 and with many mobs. Hope it will works smoothly.

I feel a bit afraid that the for loop run so many times and I'm sure I could optimize stuff. let see how it work out.

function (self, unitId, unitFrame, envTable,modTable)
  if Plater.IsPlayerTank() and not UnitIsPlayer(unitId) and (IsInRaid() or IsInGroup()) then
    local threatTable = {}
    for i= 1, GetNumGroupMembers() do -- loop all party / raid members
        -- init party unit id (raid1 - raid40 or party1 - party5)
        local partyUnitId = 'party'..i
        if IsInRaid() then -- sometime IsInGroup() fails
            partyUnitId = 'raid'..i
        elseif IsInGroup() then
            partyUnitId = 'party'..i
        end
        if UnitExists(partyUnitId) then
            local classFilename, _ = UnitClassBase(partyUnitId) -- get class to know if it is a tank
            local isTank = false
            if classFilename == "WARRIOR" then
                isTank = GetShapeshiftForm() == 2 or IsEquippedItemType("Shields") -- Defensive Stance or shield
            elseif classFilename == "DRUID" then
                isTank = GetShapeshiftForm() == 1 -- Bear Form
            end
            if not isTank then
                isTank = GetPartyAssignment("MAINTANK", partyUnitId) or false
            end

            local isTanking,_,threatpct,_,_ = UnitDetailedThreatSituation(partyUnitId, unitId)
            local line = {
                unitId=partyUnitId,
                isTanking=isTanking or false,
                threatpct=threatpct or 0,
                isTank=isTank or false
            }
            table.insert(threatTable, line)
        end
    end
    table.sort(threatTable, function (left, right)
            return left.threatpct > right.threatpct
    end)
    -- for index, data in ipairs(threatTable) do
    --     print(index)

    --     for key, value in pairs(data) do
    --         print('\t', key, value)
    --     end
    -- end

    local mainAggro = threatTable[1]
    local secondAggro = threatTable[2]
    local percentPullChangeColor = modTable.config["percentPullChangeColor"]
    local color=nil

    if mainAggro.isTanking then
        if UnitIsUnit(mainAggro.unitId,"player") then -- if I (player) tank
            if (secondAggro.threatpct >= percentPullChangeColor) and secondAggro.isTank then
                color=modTable.config["offtankpull"]
            elseif (secondAggro.threatpct >= percentPullChangeColor) then
                color=modTable.config["pullaggro"]
            else
                color=modTable.config["itank"]
            end
        else
            -- another unit is tanking
            if not mainAggro.isTank then
                color=modTable.config["noaggro"]
            elseif (secondAggro.threatpct >= percentPullChangeColor) and secondAggro.isTank then
                color=modTable.config["offtankpull"]
            elseif (secondAggro.threatpct >= percentPullChangeColor) then
                color=modTable.config["pullaggro"]
            else
                color=modTable.config["offtank"]
            end
        end
    end

    if (color) then
        Plater.SetNameplateColor (unitFrame, color)
    end
  end
end

commented

I can guarantee that this will cause fps drops with a full raid and a few nameplates.

I suggest using the already available cached values on the nameplate instead. The values from UnitDetailedThreatSituation return the offset to the second unit on the threat list already. I don't think it is necessary to scan the whole raid.

commented

Ok, I was pretty sure that would be the case, but sadly I could not find how to get the threat table and especially the first 2 players in the threat table of a mob without recalculating it every frame. I had a look at threatclassic 2 addon and it seems they do something similar but only for 1 mob and they have a delay to update it every 0.25 sec

I don't see how UnitDetailedThreatSituation can give me the offset of the second unit on the threat table

Also for the cached value on the nameplate, I could only find threat values according to myself but not on the second in the threat table. I'm not really sure how the other addon do it efficiently, I will have to study more the code in Threat Plate addon.

I know this is maybe not the best place to ask question so I thank you very much for your ideas. ๐Ÿ‘

commented

I was also thinking of adding some code to execute the code only after 0.5 second or something like that to reduce the load. I will see.

commented

Thank you for the answer.

I have tested my code today in SSC, it was dropping the fps to 20-40 fps but it was playable but not nice. So I. deactivate it. BUT it was working like a charm the way I wanted.

My issue is that I want to know who is the second in the aggro table when I'm tanking or when another tank is tanking. And I don't find anyway to do that without calculating the threat table for the whole raid. I will try to improve and optimize the code so it don't use too much resources. I will post the update here but it is a little painfull that I can only test it in raid it will slow done the testing phase ^^.

commented

Ok I have made a lot of optimization and now I don't get much of a drop rate. I still have to test it as a Tank because I only test this version with my healer while I was in bear form only to test it.

If you are interested to see the code here is the plater mod : https://wago.io/sgI9x0D0e

I basically create the table when entering combat and update only the threat during the nameplate update. I also add a throttle settings to not calculate every update.