Skip to content

Commit

Permalink
3.5-release
Browse files Browse the repository at this point in the history
Wrath Classic 3.4.1 and Retail 10.0.5 compatibility.
Non-healer group leaders now treated as offtanks.
Classic Era healers detected via combat log heals.
Retain white border after combat for selected target.
Readme.md added more addon options explanation.
  • Loading branch information
mikfhan committed Jan 24, 2023
2 parents bbd2a83 + 8e3f52c commit a8b2c23
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 59 deletions.
156 changes: 117 additions & 39 deletions NamePlatesThreat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ local function initVariables(oldAcct) -- only the variables below are used by th
newAcct["neutralsColor"] = {r= 0, g=112, b=222} -- blue neutral not in group fight
newAcct["enablePlayers"] = true -- also color nameplates for player characters
newAcct["pvPlayerColor"] = {r=245, g=140, b=186} -- pink player not in group fight
newAcct["gradientColor"] = true -- update nameplate color gradients (some CPU usage)
newAcct["gradientColor"] = false -- update nameplate color gradients (some CPU usage)
newAcct["gradientPrSec"] = 5 -- update color gradients this many times per second
newAcct["youTankCombat"] = true -- unique colors in combat instead of colors above
newAcct["youTank7color"] = {r=255, g= 0, b= 0} -- red healers tanking by threat
Expand Down Expand Up @@ -57,6 +57,7 @@ NPT.thisUpdate = 0
NPT.offTanks = {}
NPT.nonTanks = {}
NPT.offHeals = {}
NPT.nonHeals = {}
NPT.threat = {}

local NPTframe = CreateFrame("Frame", nil, NPT) -- options panel for tweaking the addon
Expand All @@ -65,7 +66,11 @@ NPTframe.lastSwatch = nil
local function resetFrame(plate)
if plate.UnitFrame.unit and UnitCanAttack("player", plate.UnitFrame.unit) then
if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
plate.UnitFrame.healthBar.border:SetVertexColor(0, 0, 0, 1)
if UnitIsUnit(plate.UnitFrame.unit, "target") then
plate.UnitFrame.healthBar.border:SetVertexColor(1, 1, 1, 1)
else
plate.UnitFrame.healthBar.border:SetVertexColor(0, 0, 0, 1)
end
end
plate.UnitFrame.healthBar:SetStatusBarColor(plate.UnitFrame.healthBar.r, plate.UnitFrame.healthBar.g, plate.UnitFrame.healthBar.b, plate.UnitFrame.healthBar.a)
end
Expand Down Expand Up @@ -139,61 +144,77 @@ local function getGroupRoles()
local collectedTanks = {}
local collectedOther = {}
local collectedHeals = {}
local collectedPlayer, unitPrefix, unit, i, unitRole = 0
local isInRaid = IsInRaid()
local collectedPlayer, unitPrefix, unit, i, unitRole, raidRank = "NONE"

if GetNumGroupMembers() > 0 then
if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
collectedPlayer = GetSpecializationRole(GetSpecialization())
end
-- mikfhan: WoW Classic has no unit spec but talent panel has a group role up top
if collectedPlayer ~= "TANK" then
collectedPlayer = UnitGroupRolesAssigned("player")
end
end
if collectedPlayer ~= "TANK" and collectedPlayer ~= "HEALER" then
collectedPlayer = "DAMAGER"
end
if UnitExists("pet") then
if NPTacct.showPetThreat or collectedPlayer == "TANK" then
table.insert(collectedTanks, "pet")
else
table.insert(collectedOther, "pet")
end
end
if isInRaid then
if IsInRaid() then
unitPrefix = "raid"
else
unitPrefix = "party"
end

for i = 1, GetNumGroupMembers() do
for i = 1, MAX_RAID_MEMBERS do
unit = unitPrefix .. i
if not UnitIsUnit(unit, "player") then
unitRole = "NONE"
if unitPrefix == "party" and i >= GetNumGroupMembers() then
break
elseif UnitExists(unit) then
unitRole = UnitGroupRolesAssigned(unit)
if isInRaid and unitRole ~= "TANK" then
_, _, _, _, _, _, _, _, _, unitRole = GetRaidRosterInfo(i)
if unitRole == "MAINTANK" then
if unitRole ~= "TANK" and unitRole ~= "HEALER" then
if UnitIsGroupLeader(unit) then
raidRank = 3
elseif unitPrefix == "raid" then
_, raidRank, _, _, _, _, _, _, _, unitRole = GetRaidRosterInfo(i)
else
raidRank = 0
end
if unitRole == "MAINTANK" or unitRole == "MAINASSIST" or raidRank > 0 then
unitRole = "TANK"
end
end
if unitRole == "TANK" then
table.insert(collectedTanks, unit)
elseif unitRole == "HEALER" then
table.insert(collectedHeals, unit)
if UnitIsUnit(unit, "player") then
collectedPlayer = unitRole
else
table.insert(collectedOther, unit)
end
unit = unitPrefix .. "pet" .. i
if UnitExists(unit) then
if NPTacct.showPetThreat or unitRole == "TANK" then
if unitRole == "TANK" then
table.insert(collectedTanks, unit)
elseif unitRole == "HEALER" then
table.insert(collectedHeals, unit)
else
table.insert(collectedOther, unit)
end
unit = unitPrefix .. "pet" .. i
if UnitExists(unit) then
if NPTacct.showPetThreat or unitRole == "TANK" then
table.insert(collectedTanks, unit)
else
table.insert(collectedOther, unit)
end
end
end
end
end
-- mikfhan: Outside raid groups the player is not counted amongst the party members
if GetNumGroupMembers() > 0 then
if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
-- mikfhan: Retail will use player spec regardless of the group role chosen earlier
collectedPlayer = GetSpecializationRole(GetSpecialization())
elseif unitPrefix == "party" then
-- mikfhan: Wrath Classic has no unit spec but talent panel has a party role up top
collectedPlayer = UnitGroupRolesAssigned("player")
if UnitIsGroupLeader("player") and collectedPlayer ~= "HEALER" then
-- mikfhan: Classic Era using party leader since roles did not even exist back then
collectedPlayer = "TANK"
end
end
end
if collectedPlayer ~= "TANK" and collectedPlayer ~= "HEALER" then
collectedPlayer = "DAMAGER"
end
if UnitExists("pet") then
if NPTacct.showPetThreat or collectedPlayer == "TANK" then
table.insert(collectedTanks, "pet")
else
table.insert(collectedOther, "pet")
end
end
return collectedTanks, collectedPlayer, collectedOther, collectedHeals
end

Expand Down Expand Up @@ -627,6 +648,8 @@ if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
NPT:RegisterEvent("PLAYER_SOFT_INTERACT_CHANGED")
NPT:RegisterEvent("PLAYER_SOFT_FRIEND_CHANGED")
NPT:RegisterEvent("PLAYER_SOFT_ENEMY_CHANGED")
elseif WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then
NPT:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
NPT:RegisterEvent("NAME_PLATE_UNIT_ADDED")
NPT:RegisterEvent("PLAYER_TARGET_CHANGED")
Expand All @@ -650,6 +673,7 @@ NPT:SetScript("OnEvent", function(self, event, arg1)
resetFrame(plate)
end
NPT.threat = {}
NPT.nonHeals = {}
NPT.offTanks, NPT.playerRole, NPT.nonTanks, NPT.offHeals = getGroupRoles()
C_Timer.NewTimer(0.1, callback)
elseif event == "PLAYER_SOFT_INTERACT_CHANGED" or event == "PLAYER_SOFT_FRIEND_CHANGED" or
Expand All @@ -668,6 +692,60 @@ NPT:SetScript("OnEvent", function(self, event, arg1)
if plate and plate.UnitFrame then
resetFrame(plate)
end
elseif event == "COMBAT_LOG_EVENT_UNFILTERED" and GetNumGroupMembers() > 0 then
local timestamp, subevent, _, sourceGUID, _, sourceFlags, _, destGUID = CombatLogGetCurrentEventInfo()
local COMBATLOG_FILTER_GROUPHEAL = bit.bor(
COMBATLOG_OBJECT_AFFILIATION_MINE
, COMBATLOG_OBJECT_AFFILIATION_PARTY
, COMBATLOG_OBJECT_AFFILIATION_RAID
, COMBATLOG_OBJECT_REACTION_FRIENDLY
, COMBATLOG_OBJECT_CONTROL_PLAYER
, COMBATLOG_OBJECT_TYPE_PLAYER
)
if CombatLog_Object_IsA(sourceFlags, COMBATLOG_FILTER_GROUPHEAL) then
--print(timestamp .. " " .. sourceGUID .. " " .. format("0x%X", sourceFlags))
if subevent == "SPELL_HEAL" or subevent == "SPELL_PERIODIC_HEAL" then
if sourceGUID ~= destGUID and string.sub(destGUID, 1, 6) == "Player" then
NPT.nonHeals[sourceGUID] = timestamp
if sourceGUID == UnitGUID("player") then
if NPT.playerRole == "DAMAGER" then
--print("player is now HEALER")
NPT.playerRole = "HEALER"
end
else
local key, unit
for key, unit in pairs(NPT.nonTanks) do
if sourceGUID == UnitGUID(unit) then
--print(unit .. " is now HEALER")
table.insert(NPT.offHeals, unit)
table.remove(NPT.nonTanks, key)
break
end
end
end
end
elseif subevent == "SPELL_DAMAGE" or subevent == "SPELL_PERIODIC_DAMAGE" then
if NPT.nonHeals[sourceGUID] and NPT.nonHeals[sourceGUID] < timestamp - 60 then
NPT.nonHeals[sourceGUID] = nil
if sourceGUID == UnitGUID("player") then
if NPT.playerRole == "HEALER" then
--print("player is now DAMAGER")
NPT.playerRole = "DAMAGER"
end
else
local key, unit
for key, unit in pairs(NPT.offHeals) do
if sourceGUID == UnitGUID(unit) then
--print(unit .. " is now DAMAGER")
table.insert(NPT.nonTanks, unit)
table.remove(NPT.offHeals, key)
break
end
end
end
end
end
end
end
end)
NPT:SetScript("OnUpdate", function(self, elapsed)
Expand Down
4 changes: 2 additions & 2 deletions NamePlatesThreat.toc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Interface: 100002
## Interface: 100005
## Title: NamePlatesThreat
## Notes: Colors the nameplate healthbar according to threat.
## Version: 3.4
## Version: 3.5
## Author: int3ro, exochron & mikfhan
## SavedVariables: NPTacct
NamePlatesThreat.lua
2 changes: 1 addition & 1 deletion NamePlatesThreat_TBC.toc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Interface: 20504
## Title: NamePlatesThreat
## Notes: Colors the nameplate healthbar according to threat.
## Version: 3.4
## Version: 3.5
## Author: int3ro, exochron & mikfhan
## SavedVariables: NPTacct
NamePlatesThreat.lua
2 changes: 1 addition & 1 deletion NamePlatesThreat_Vanilla.toc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Interface: 11403
## Title: NamePlatesThreat
## Notes: Colors the nameplate healthbar according to threat.
## Version: 3.4
## Version: 3.5
## Author: int3ro, exochron & mikfhan
## SavedVariables: NPTacct
NamePlatesThreat.lua
4 changes: 2 additions & 2 deletions NamePlatesThreat_Wrath.toc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Interface: 30400
## Interface: 30401
## Title: NamePlatesThreat
## Notes: Colors the nameplate healthbar according to threat.
## Version: 3.4
## Version: 3.5
## Author: int3ro, exochron & mikfhan
## SavedVariables: NPTacct
NamePlatesThreat.lua
51 changes: 37 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,56 @@
# Blizzard Nameplates - Threat
Extremely lightweight addon which colors the default blizzard nameplates according to threat.
See general usage in **bold** below. Settings are saved in your WoW \_retail\_ (or similar) subfolder:
WTF\Account\\\<userid\>\SavedVariables\NamePlatesThreat.lua
You can tweak settings/colors below from Escape menu > Interface/Options > AddOns > NamePlatesThreat

General advice is everyone should attack red nameplates, then tanks should attack orange before yellow while others attack green before gray nameplates.
**Everyone should attack red, then tanks attack orange before yellow, others attack green before gray.**

You can tweak a few settings and colors below from Escape menu > Interface > AddOns > NamePlatesThreat:
"Color Non-Friendly Nameplates" addon option you can quickly disable if you want Blizzard colors always.
"Color Nameplate Border Only" (retail only) ensures healthbar inside still uses original Blizzard colors.

Colors Out of Combat (2.4-release):
The addon decides player roles via Set Role right-clicking their player portrait, with some exceptions:
Retail treats you purely by your talent spec, regardless of group role (you can still Set Role on others).
Wrath lets you Set Role default via the round icon top right of your talent panel (or Set Role on others).
Classic Era has no roles; leader or raid maintank/assist are tank, others healing within last 60 seconds.
"Color Group Pets as Tanks" is an addon option that treats all pets as a tank even if their player is not.

PINK: Player is Out of Combat (only if PvP colors enabled and no target)
VIOLET: Hostile Out of Combat (or gray if fighting totems/NPCs/others)
BLUE: Neutral Out of Combat (or gray if fighting totems/NPCs/others)
"Color out of Dungeons" and "Color Out of Combat" if disabled use Blizzard colors outside those situations.
Out of combat topmost three colors below indicate if enemy is a player, or hostile/neutral NPC reputation.
"Color Player Characters" for PvP enemies depending on role they are targeting (never based on NPC threat).

Playing as Tank spec (2.4-release):
**Colors Out of Combat (2.7-release and newer):**
VIOLET: Hostile Out of Combat (turns blue if fighting totems/NPCs/others)
BLUE: Neutral Out of Combat (or hostiles fighting totems/NPCs/others)
PINK: Player is Out of Combat (only if PvP colors enabled and no target)

**Playing as Tank role (2.7-release and newer):**
RED: Healers have High Threat (emergency! get on it asap)
ORANGE: Damage has High Threat (not good, defend your dps)
YELLOW: Tanks have Low Threat (offtanks struggle, help them)
GRAY: You have the Low Threat (tanking, but not perfect)
GRAY: You have the Low Threat (or offtanks have high threat)
GREEN: You have the High Threat (perfect tank, ignore these)

Damage or Heal spec (2.4-release):

**Damage or Heal role (2.7-release and newer):**
RED: Healers have High Threat (emergency! get on it asap)
ORANGE: You have the High Threat (disengage! find a tank)
YELLOW: You have the Low Threat (hold attacks, wait for tank)
GRAY: Damage has High Threat (okay to attack, but not much)
GREEN: Tanks have High Threat (fire at will, tanks are on it)

Settings are saved in your World of Warcraft _retail_ subfolder:
WTF\Account\<userid>\SavedVariables\NamePlatesThreat.lua

Anyone from TidyPlates who prefer old colors before 1.8-release can find them in Issue #4 third comment, which has a SavedVariables file you can overwrite (remember to logout your characters while doing so).
"Color Nameplates by Threat" you can disable if you only wish to color enemies by their target instead of threat, it still uses the colors below.
The role colors just below lets you customize colors when you have the tank role, you can disable checkbox above again after tweaking the colors.
Notice there is both a color for "you" and "tanks" even when you have a tank role, this is so you know if YOU have aggro or an offtank buddy does.
"Unique Colors In-Between" lets you pick custom colors when someone is using taunt skills, if disabled addon just reuses the colors from above.

"Unique Colors as Non-Tank Role" lets you pick custom colors if you are a damager/healer role, otherwise addon reuses the color to the left of it.
Notice there is a color for "you" but also healers and damage, this is so you know if YOU have aggro or if another damage/healer buddy has aggro.
Note also how some role colors mention "you have the low threat" or "tanks have low threat" etc, this is when taunt skills are used to keep aggro.
Note also how healers have a different color from damage; healers are very important so ALL players should help tanks defend them.

"Color Gradient Updates Per Second" is an advanced feature; x times per second it fades the color between high and low as threat percent changes.
Example if you are tank with high threat (green by default) then as threat is dropping toward only 100% it will fade toward the low color (gray).
World of Warcraft generally treats anyone with 100% threat or more as "having aggro" for that enemy, and only taunt skills can override this.
It may be crucial information as a tank to know if you are losing threat to one of the other players in the group, so they should cool off a bit.
This option is advanced because color fading makes it harder to see exactly who has aggro when close to the 100% low threat target switchover.
Having this information for hard-hitting bosses may still be preferred by some tanks.

0 comments on commit a8b2c23

Please sign in to comment.