Add files via upload
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
## Title: RelationshipsThreatPlates - OctoWoW
|
## Title: RelationshipsThreatPlates - OctoWoW
|
||||||
## Notes: OctoWoW-compatible RelationshipsThreatPlates
|
## Notes: OctoWoW-compatible RelationshipsThreatPlates
|
||||||
## Author: Packaged By Relationship
|
## Author: Packaged By Relationship
|
||||||
## Version: 1.1
|
## Version: 1.2
|
||||||
## SavedVariables: RelationshipsThreatPlatesDB
|
## SavedVariables: RelationshipsThreatPlatesDB
|
||||||
## X-Website: https://github.com/Relationship-OctoWoW/RelationshipsThreatPlates
|
## X-Website: https://github.com/Relationship-OctoWoW/RelationshipsThreatPlates
|
||||||
## X-GitHub: https://github.com/Relationship-OctoWoW/RelationshipsThreatPlates
|
## X-GitHub: https://github.com/Relationship-OctoWoW/RelationshipsThreatPlates
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ addon.MAJOR = 1
|
|||||||
addon.MINOR = 1
|
addon.MINOR = 1
|
||||||
|
|
||||||
-- Version string
|
-- Version string
|
||||||
TP_VERSION = "2.3.1"
|
TP_VERSION = "2.4.0"
|
||||||
TP_ADDON_NAME = "RelationshipsThreatPlates"
|
TP_ADDON_NAME = "RelationshipsThreatPlates"
|
||||||
|
|
||||||
-- ==================================================================
|
-- ==================================================================
|
||||||
@@ -21,9 +21,11 @@ TP_ADDON_NAME = "RelationshipsThreatPlates"
|
|||||||
local DEFAULT_CONFIG = {
|
local DEFAULT_CONFIG = {
|
||||||
enabled = true,
|
enabled = true,
|
||||||
showText = true,
|
showText = true,
|
||||||
|
tankMode = false,
|
||||||
|
targetSnap100 = true,
|
||||||
barHeight = 6,
|
barHeight = 6,
|
||||||
barAlpha = 0.5,
|
barAlpha = 0.5,
|
||||||
barOffsetY = 20,
|
barOffsetY = 24,
|
||||||
barOffsetX = -17.8,
|
barOffsetX = -17.8,
|
||||||
barWidthScale = 0.8,
|
barWidthScale = 0.8,
|
||||||
fontSize = 9,
|
fontSize = 9,
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ function addon.GUI:BuildSettings(parent)
|
|||||||
|
|
||||||
local slider = CreateFrame("Slider", "RelationshipsThreatPlatesSlider_" .. configKey, parent, "OptionsSliderTemplate")
|
local slider = CreateFrame("Slider", "RelationshipsThreatPlatesSlider_" .. configKey, parent, "OptionsSliderTemplate")
|
||||||
slider:SetWidth(W - 60)
|
slider:SetWidth(W - 60)
|
||||||
slider:SetHeight(16)
|
slider:SetHeight(10)
|
||||||
slider:SetPoint("TOPLEFT", parent, "TOPLEFT", MARGIN, -y)
|
slider:SetPoint("TOPLEFT", parent, "TOPLEFT", MARGIN, -y)
|
||||||
slider:SetOrientation("HORIZONTAL")
|
slider:SetOrientation("HORIZONTAL")
|
||||||
slider:SetMinMaxValues(minVal, maxVal)
|
slider:SetMinMaxValues(minVal, maxVal)
|
||||||
@@ -364,6 +364,8 @@ function addon.GUI:BuildSettings(parent)
|
|||||||
if thumbTexture then
|
if thumbTexture then
|
||||||
thumbTexture:SetTexture(C.SOLID)
|
thumbTexture:SetTexture(C.SOLID)
|
||||||
thumbTexture:SetVertexColor(unpack(C.ACCENT))
|
thumbTexture:SetVertexColor(unpack(C.ACCENT))
|
||||||
|
thumbTexture:SetWidth(8)
|
||||||
|
thumbTexture:SetHeight(14)
|
||||||
end
|
end
|
||||||
|
|
||||||
local lowText = getglobal(sliderName .. "Low")
|
local lowText = getglobal(sliderName .. "Low")
|
||||||
@@ -403,7 +405,9 @@ function addon.GUI:BuildSettings(parent)
|
|||||||
-- ==============================================================
|
-- ==============================================================
|
||||||
SectionLabel("General")
|
SectionLabel("General")
|
||||||
CheckBox("Enable Threat Plates", "enabled", "Show threat bars above nameplates")
|
CheckBox("Enable Threat Plates", "enabled", "Show threat bars above nameplates")
|
||||||
CheckBox("Show Threat Text", "showText", "Display percentage in the bar")
|
CheckBox("Show Threat Text", "showText", "Display value in the bar")
|
||||||
|
CheckBox("Tank Mode", "tankMode", "Show raw threat lead over 2nd place instead of %")
|
||||||
|
CheckBox("Snap to 100% when Targeted", "targetSnap100", "Force 100% while a mob is focused on you")
|
||||||
CheckBox("Smooth Colours", "smoothColors", "Gradient colour transition")
|
CheckBox("Smooth Colours", "smoothColors", "Gradient colour transition")
|
||||||
|
|
||||||
-- ==============================================================
|
-- ==============================================================
|
||||||
@@ -412,7 +416,7 @@ function addon.GUI:BuildSettings(parent)
|
|||||||
SectionLabel("Appearance")
|
SectionLabel("Appearance")
|
||||||
Slider("Bar Height", "barHeight", 2, 20, 1, "px")
|
Slider("Bar Height", "barHeight", 2, 20, 1, "px")
|
||||||
Slider("Bar Width Scale", "barWidthScale", 0.3, 1.0, 0.05, "")
|
Slider("Bar Width Scale", "barWidthScale", 0.3, 1.0, 0.05, "")
|
||||||
Slider("Bar Offset Y", "barOffsetY", 0, 20, 1, "px")
|
Slider("Bar Offset Y", "barOffsetY", 0, 50, 1, "px")
|
||||||
Slider("Bar Offset X", "barOffsetX", -50, 50, 0.1, "px")
|
Slider("Bar Offset X", "barOffsetX", -50, 50, 0.1, "px")
|
||||||
Slider("Bar Alpha", "barAlpha", 0.1, 1.0, 0.1, "")
|
Slider("Bar Alpha", "barAlpha", 0.1, 1.0, 0.1, "")
|
||||||
Slider("Font Size", "fontSize", 6, 16, 1, "pt")
|
Slider("Font Size", "fontSize", 6, 16, 1, "pt")
|
||||||
@@ -437,6 +441,44 @@ function addon.GUI:BuildSettings(parent)
|
|||||||
CheckBox("Show on Neutral", "showOnNeutral", "Show threat bars on neutral units")
|
CheckBox("Show on Neutral", "showOnNeutral", "Show threat bars on neutral units")
|
||||||
CheckBox("Show on Friendly", "showOnFriendly", "Show threat bars on friendly units")
|
CheckBox("Show on Friendly", "showOnFriendly", "Show threat bars on friendly units")
|
||||||
|
|
||||||
|
-- ==============================================================
|
||||||
|
-- Reset button at bottom
|
||||||
|
-- ==============================================================
|
||||||
|
y = y + 10
|
||||||
|
local resetBtn = CreateFrame("Button", nil, parent)
|
||||||
|
resetBtn:SetWidth(W - MARGIN * 2)
|
||||||
|
resetBtn:SetHeight(22)
|
||||||
|
resetBtn:SetPoint("TOPLEFT", parent, "TOPLEFT", MARGIN, -y)
|
||||||
|
SafeSetBackdrop(resetBtn, {
|
||||||
|
bgFile = C.SOLID,
|
||||||
|
edgeFile = C.SOLID,
|
||||||
|
tile = false, tileSize = 0,
|
||||||
|
edgeSize = 1,
|
||||||
|
})
|
||||||
|
resetBtn:SetBackdropColor(unpack(C.BUTTON_BG))
|
||||||
|
resetBtn:SetBackdropBorderColor(unpack(C.BORDER))
|
||||||
|
|
||||||
|
local resetText = resetBtn:CreateFontString(nil, "OVERLAY")
|
||||||
|
resetText:SetFont(FONT_NORMAL, FONT_SIZE, "OUTLINE")
|
||||||
|
resetText:SetPoint("CENTER", resetBtn, "CENTER", 0, 0)
|
||||||
|
resetText:SetTextColor(unpack(C.BUTTON_TEXT))
|
||||||
|
resetText:SetText("Reset to Defaults")
|
||||||
|
resetBtn:SetFontString(resetText)
|
||||||
|
|
||||||
|
resetBtn:SetScript("OnEnter", function()
|
||||||
|
this:SetBackdropColor(unpack(C.BUTTON_HOVER))
|
||||||
|
end)
|
||||||
|
resetBtn:SetScript("OnLeave", function()
|
||||||
|
this:SetBackdropColor(unpack(C.BUTTON_BG))
|
||||||
|
end)
|
||||||
|
resetBtn:SetScript("OnClick", function()
|
||||||
|
SlashCmdList["THREATPLATES"]("reset")
|
||||||
|
if addon.Nameplates and addon.Nameplates.RecreateAll then
|
||||||
|
addon.Nameplates:RecreateAll()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
y = y + 22 + 8
|
||||||
|
|
||||||
-- Return total content height for scroll setup
|
-- Return total content height for scroll setup
|
||||||
return y
|
return y
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -897,10 +897,12 @@ function addon.Nameplates:ApplyThreatToPlate(data, pct, situation)
|
|||||||
-- Smooth the percentage
|
-- Smooth the percentage
|
||||||
local oldPct = data.lastPct or 0
|
local oldPct = data.lastPct or 0
|
||||||
local smoothPct
|
local smoothPct
|
||||||
if pct == 0 then
|
-- Snap instantly when jumping to full aggro (100%) or dropping to 0
|
||||||
smoothPct = 0
|
-- (mob switched target). Smooth intermediate transitions moderately.
|
||||||
|
if pct == 0 or pct >= 99.5 or math.abs(pct - oldPct) > 40 then
|
||||||
|
smoothPct = pct
|
||||||
else
|
else
|
||||||
smoothPct = oldPct + (pct - oldPct) * 0.3
|
smoothPct = oldPct + (pct - oldPct) * 0.6
|
||||||
end
|
end
|
||||||
data.lastPct = smoothPct
|
data.lastPct = smoothPct
|
||||||
|
|
||||||
@@ -948,8 +950,20 @@ function addon.Nameplates:ApplyThreatToPlate(data, pct, situation)
|
|||||||
|
|
||||||
-- Update text
|
-- Update text
|
||||||
if data.text then
|
if data.text then
|
||||||
local displayPct = math.floor(pct + 0.5)
|
local textStr
|
||||||
data.text:SetText(displayPct .. "%")
|
if RelationshipsThreatPlatesDB.tankMode and data.plateName then
|
||||||
|
-- Tank mode: show raw threat lead over the 2nd-highest player
|
||||||
|
-- (positive = you have that much lead as top-threat holder;
|
||||||
|
-- negative = you're that much behind the current top).
|
||||||
|
textStr = addon.Threat:GetTankDisplayForMob(data.plateName)
|
||||||
|
if not textStr or textStr == "--" then
|
||||||
|
-- Fall back to % when no absolute values are available.
|
||||||
|
textStr = math.floor(pct + 0.5) .. "%"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
textStr = math.floor(pct + 0.5) .. "%"
|
||||||
|
end
|
||||||
|
data.text:SetText(textStr)
|
||||||
|
|
||||||
if pct >= 90 then
|
if pct >= 90 then
|
||||||
data.text:SetTextColor(1, 0.2, 0.2, 1)
|
data.text:SetTextColor(1, 0.2, 0.2, 1)
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ local partyNames = {}
|
|||||||
local partyUnits = {}
|
local partyUnits = {}
|
||||||
|
|
||||||
-- Update throttle (seconds)
|
-- Update throttle (seconds)
|
||||||
local THROTTLE = 0.2
|
local THROTTLE = 0.1
|
||||||
|
-- Cache of per-mob tank-mode details, keyed by mob UID (name in vanilla).
|
||||||
|
-- Populated by UpdateUnitThreat via ThreatEngine, and read by the Nameplates
|
||||||
|
-- module when rendering the tank-mode text (raw threat lead).
|
||||||
|
local tankDetailsCache = {}
|
||||||
|
|
||||||
-- ==================================================================
|
-- ==================================================================
|
||||||
-- Safe API call helpers
|
-- Safe API call helpers
|
||||||
@@ -647,12 +651,54 @@ function addon.Threat:UpdateUnitThreat(unit)
|
|||||||
mobTargetName = mt
|
mobTargetName = mt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
-- TARGET-SNAP override: if the mob is currently targeting the
|
||||||
|
-- player, force display to 100% (aggro). Some mobs pick focused
|
||||||
|
-- / random targets regardless of threat, so the plate should
|
||||||
|
-- immediately snap to 100% while targeted, and fall back to the
|
||||||
|
-- real threat % when the mob switches targets.
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
local targetSnapped = false
|
||||||
|
if RelationshipsThreatPlatesDB and RelationshipsThreatPlatesDB.targetSnap100
|
||||||
|
and mobTargetName and playerName and mobTargetName == playerName then
|
||||||
|
local ok_pc, pc = pcall(UnitAffectingCombat, "player")
|
||||||
|
if ok_pc and pc then
|
||||||
|
pct = 100
|
||||||
|
situation = 3
|
||||||
|
targetSnapped = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
-- Compute raw tank-mode details (player threat vs 2nd highest).
|
||||||
|
-- Uses ThreatEngine's combat-log-parsed absolute values when
|
||||||
|
-- available. This is what the nameplate renders in Tank Mode.
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
local ok_mn, mobName = pcall(UnitName, unit)
|
||||||
|
if ok_mn and mobName then
|
||||||
|
local ePct, eSit, ePlayerThreat, eTopThreat, eHasGroup, eTopPlayer, eSecondThreat =
|
||||||
|
addon.ThreatEngine:GetThreatOnTarget(mobName)
|
||||||
|
|
||||||
|
tankDetailsCache[uid] = {
|
||||||
|
playerThreat = ePlayerThreat or 0,
|
||||||
|
topThreat = eTopThreat or 0,
|
||||||
|
secondThreat = eSecondThreat or 0,
|
||||||
|
topPlayer = eTopPlayer,
|
||||||
|
hasAggro = (eTopPlayer == playerName) or targetSnapped,
|
||||||
|
hasGroupData = eHasGroup or false,
|
||||||
|
targetSnapped = targetSnapped,
|
||||||
|
mobTargetName = mobTargetName,
|
||||||
|
lastUpdate = GetTime(),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
threatCache[uid] = {
|
threatCache[uid] = {
|
||||||
pct = pct,
|
pct = pct,
|
||||||
situation = situation,
|
situation = situation,
|
||||||
unit = unit,
|
unit = unit,
|
||||||
lastUpdate = GetTime(),
|
lastUpdate = GetTime(),
|
||||||
mobTargetName = mobTargetName,
|
mobTargetName = mobTargetName,
|
||||||
|
targetSnapped = targetSnapped,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Also store in group threat cache for cross-reference
|
-- Also store in group threat cache for cross-reference
|
||||||
@@ -681,6 +727,76 @@ function addon.Threat:GetCachedThreat(uid)
|
|||||||
return 0, 0
|
return 0, 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- Tank-mode details for a mob (by UID / name in vanilla).
|
||||||
|
-- Returns a table (or nil) with:
|
||||||
|
-- playerThreat, topThreat, secondThreat, topPlayer,
|
||||||
|
-- hasAggro, hasGroupData, targetSnapped, mobTargetName
|
||||||
|
-- ==================================================================
|
||||||
|
function addon.Threat:GetTankDetails(uid)
|
||||||
|
if not uid then return nil end
|
||||||
|
local d = tankDetailsCache[uid]
|
||||||
|
if not d then return nil end
|
||||||
|
if GetTime() - d.lastUpdate > 5 then return nil end
|
||||||
|
return d
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- Format a raw threat value as a compact signed string.
|
||||||
|
-- Examples: 12345 -> "+12.3K", -845 -> "-845", 0 -> "0"
|
||||||
|
-- ==================================================================
|
||||||
|
function addon.Threat:FormatThreatLead(v)
|
||||||
|
if not v then return "--" end
|
||||||
|
local a = math.abs(v)
|
||||||
|
local sign = ""
|
||||||
|
if v > 0 then sign = "+" elseif v < 0 then sign = "-" end
|
||||||
|
if a >= 100000 then
|
||||||
|
return sign .. string.format("%.0fK", a / 1000)
|
||||||
|
elseif a >= 10000 then
|
||||||
|
return sign .. string.format("%.1fK", a / 1000)
|
||||||
|
elseif a >= 1000 then
|
||||||
|
return sign .. string.format("%.2fK", a / 1000)
|
||||||
|
else
|
||||||
|
return sign .. string.format("%d", a)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- Return the display string for tank mode given a plate's mob name.
|
||||||
|
-- Uses the ThreatEngine directly (works even without a unit token,
|
||||||
|
-- e.g. for unique-name plates).
|
||||||
|
-- Returns: string like "+1.20K" or "-450", or "--" if unknown.
|
||||||
|
-- ==================================================================
|
||||||
|
function addon.Threat:GetTankDisplayForMob(mobName)
|
||||||
|
if not mobName then return "--" end
|
||||||
|
local d = tankDetailsCache[mobName]
|
||||||
|
if not d or (GetTime() - d.lastUpdate > 5) then
|
||||||
|
-- Query ThreatEngine on demand (no cache hit).
|
||||||
|
local _, _, playerThreat, topThreat, _, topPlayer, secondThreat =
|
||||||
|
addon.ThreatEngine:GetThreatOnTarget(mobName)
|
||||||
|
if not playerThreat or playerThreat <= 0 then
|
||||||
|
return "--"
|
||||||
|
end
|
||||||
|
local lead
|
||||||
|
if topPlayer == playerName then
|
||||||
|
lead = playerThreat - (secondThreat or 0)
|
||||||
|
else
|
||||||
|
lead = playerThreat - (topThreat or 0)
|
||||||
|
end
|
||||||
|
return self:FormatThreatLead(lead)
|
||||||
|
end
|
||||||
|
|
||||||
|
if d.playerThreat <= 0 then return "--" end
|
||||||
|
local lead
|
||||||
|
if d.hasAggro then
|
||||||
|
lead = d.playerThreat - (d.secondThreat or 0)
|
||||||
|
else
|
||||||
|
lead = d.playerThreat - (d.topThreat or 0)
|
||||||
|
end
|
||||||
|
return self:FormatThreatLead(lead)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- ==================================================================
|
-- ==================================================================
|
||||||
-- Get threat percentage by mob NAME (no unit token required)
|
-- Get threat percentage by mob NAME (no unit token required)
|
||||||
-- This is the fallback for when FindUnitByName couldn't resolve
|
-- This is the fallback for when FindUnitByName couldn't resolve
|
||||||
|
|||||||
@@ -1268,30 +1268,34 @@ end
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|
||||||
function addon.ThreatEngine:GetThreatOnTarget(mobName)
|
function addon.ThreatEngine:GetThreatOnTarget(mobName)
|
||||||
if not mobName then return 0, 0, 0, 0, false, nil end
|
if not mobName then return 0, 0, 0, 0, false, nil, 0 end
|
||||||
|
|
||||||
-- Check if we have threat data for this mob
|
-- Check if we have threat data for this mob
|
||||||
local mobThreat = threatData[mobName]
|
local mobThreat = threatData[mobName]
|
||||||
if not mobThreat then
|
if not mobThreat then
|
||||||
return 0, 0, 0, 0, false, nil
|
return 0, 0, 0, 0, false, nil, 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Find player's threat and top threat
|
-- Find player's threat, top threat and second-highest threat
|
||||||
local playerThreat = mobThreat[playerName] or 0
|
local playerThreat = mobThreat[playerName] or 0
|
||||||
local topThreat = 0
|
local topThreat = 0
|
||||||
local topPlayer = nil
|
local topPlayer = nil
|
||||||
|
local secondThreat = 0
|
||||||
local sourceCount = 0
|
local sourceCount = 0
|
||||||
|
|
||||||
for source, value in pairs(mobThreat) do
|
for source, value in pairs(mobThreat) do
|
||||||
sourceCount = sourceCount + 1
|
sourceCount = sourceCount + 1
|
||||||
if value > topThreat then
|
if value > topThreat then
|
||||||
|
secondThreat = topThreat
|
||||||
topThreat = value
|
topThreat = value
|
||||||
topPlayer = source
|
topPlayer = source
|
||||||
|
elseif value > secondThreat then
|
||||||
|
secondThreat = value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if topThreat <= 0 then
|
if topThreat <= 0 then
|
||||||
return 0, 0, 0, 0, false, nil
|
return 0, 0, 0, 0, false, nil, 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Calculate the player's percentage relative to top threat
|
-- Calculate the player's percentage relative to top threat
|
||||||
@@ -1314,7 +1318,7 @@ function addon.ThreatEngine:GetThreatOnTarget(mobName)
|
|||||||
-- (via addon communication or party combat log parsing).
|
-- (via addon communication or party combat log parsing).
|
||||||
local hasGroupData = (sourceCount > 1)
|
local hasGroupData = (sourceCount > 1)
|
||||||
|
|
||||||
return pct, sit, playerThreat, topThreat, hasGroupData, topPlayer
|
return pct, sit, playerThreat, topThreat, hasGroupData, topPlayer, secondThreat
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user