[Feature] Tank aggro pulling - Percent setting
Ganbin opened this issue ยท 9 comments
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.
Line 5978 in d8923e1
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.
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.
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.
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.
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
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.
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. ๐
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.
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 ^^.
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.