第一次发版v0.1.0

This commit is contained in:
rucky
2026-03-20 10:20:05 +08:00
commit 017e37a365
17 changed files with 6166 additions and 0 deletions

204
Threat.lua Normal file
View File

@@ -0,0 +1,204 @@
NanamiPlates_Threat = {}
local NP = NanamiPlates
local string_find = string.find
local string_sub = string.sub
local string_format = string.format
local string_gfind = string.gfind
local pairs = pairs
local ipairs = ipairs
local tonumber = tonumber
local tostring = tostring
local GetTime = GetTime
local UnitName = UnitName
local UnitExists = UnitExists
local UnitIsUnit = UnitIsUnit
local UnitInRaid = UnitInRaid
local UnitInParty = UnitInParty
local SendAddonMessage = SendAddonMessage
local GP_TankModeThreats = {}
local GP_Threats = {}
local GP_TankPlayers = {}
NanamiPlates_Threat.GP_TankModeThreats = GP_TankModeThreats
NanamiPlates_Threat.GP_Threats = GP_Threats
NanamiPlates_Threat.GP_TankPlayers = GP_TankPlayers
local function GP_Split(str, delimiter)
local result = {}
local pattern = "([^" .. delimiter .. "]+)"
for match in string_gfind(str, pattern) do
table.insert(result, match)
end
return result
end
local function GP_HandleTankModePacket(packet)
local startPos = string_find(packet, "TMTv1=")
if not startPos then return end
local dataStr = string_sub(packet, startPos + 6)
for k in pairs(GP_TankModeThreats) do GP_TankModeThreats[k] = nil end
local entries = GP_Split(dataStr, ";")
for _, entry in ipairs(entries) do
local parts = GP_Split(entry, ":")
if parts[1] and parts[2] and parts[3] and parts[4] then
GP_TankModeThreats[parts[2]] = {
creature = parts[1],
name = parts[3],
perc = tonumber(parts[4]) or 0
}
end
end
end
local function GP_HandleThreatPacket(packet)
local startPos = string_find(packet, "TWTv4=")
if not startPos then return end
local dataStr = string_sub(packet, startPos + 6)
for k in pairs(GP_Threats) do GP_Threats[k] = nil end
local entries = GP_Split(dataStr, ";")
for _, entry in ipairs(entries) do
local parts = GP_Split(entry, ":")
if parts[1] and parts[3] and parts[4] then
GP_Threats[parts[1]] = {
threat = tonumber(parts[3]) or 0,
perc = tonumber(parts[4]) or 0,
tank = (parts[6] == "1")
}
end
end
end
local NP_ADDON_PREFIX = "NanamiPlates"
local TANK_BROADCAST_DEBOUNCE = 5
local lastTankBroadcast = 0
function NanamiPlates_Threat.BroadcastTankMode(force)
local now = GetTime()
if not force and (now - lastTankBroadcast) < TANK_BROADCAST_DEBOUNCE then return end
local playerRole = NP and NP.playerRole
local isTank = (playerRole == "TANK")
local msg = isTank and "TM=1" or "TM=0"
local myName = UnitName("player")
if myName then
GP_TankPlayers[myName] = isTank or nil
end
if UnitInRaid("player") then
SendAddonMessage(NP_ADDON_PREFIX, msg, "RAID")
lastTankBroadcast = now
elseif UnitInParty() then
SendAddonMessage(NP_ADDON_PREFIX, msg, "PARTY")
lastTankBroadcast = now
end
end
function NanamiPlates_Threat.IsPlayerTank(playerName)
if not playerName then return false end
return GP_TankPlayers[playerName] == true
end
local function GP_HandleTankModeMessage(sender, msg)
if string_find(msg, "TM=") then
local isTank = string_sub(msg, 4, 4) == "1"
GP_TankPlayers[sender] = isTank or nil
end
end
function NanamiPlates_Threat.GetTWTankModeThreat(mobGUID, mobName)
local playerName = UnitName("player")
if mobGUID then
local data = GP_TankModeThreats[mobGUID]
if data then
local playerHasAggro = (data.name == playerName)
return true, playerHasAggro, data.name, data.perc or 0
end
end
if mobName then
for guid, data in pairs(GP_TankModeThreats) do
if data.creature == mobName then
local playerHasAggro = (data.name == playerName)
return true, playerHasAggro, data.name, data.perc or 0
end
end
end
return false, false, nil, 0
end
function NanamiPlates_Threat.GetGPThreatData()
local playerName = UnitName("player")
local playerPct = 0
local highestOtherPct = 0
local hasData = false
local threatHolderName = nil
for name, data in pairs(GP_Threats) do
hasData = true
local pct = data.perc or 0
if name == playerName then
playerPct = pct
else
if pct > highestOtherPct then highestOtherPct = pct end
end
if pct >= 100 then threatHolderName = name end
end
return hasData, (playerPct >= 100), playerPct, highestOtherPct, threatHolderName
end
function NanamiPlates_Threat.IsInPlayerGroup(unit)
if not unit or not UnitExists(unit) then return false end
if UnitIsUnit(unit, "player") then return true end
for i = 1, 4 do
if UnitIsUnit(unit, "party" .. i) then return true end
end
if UnitInRaid("player") then
for i = 1, 40 do
if UnitIsUnit(unit, "raid" .. i) then return true end
end
end
if UnitIsUnit(unit, "pet") then return true end
for i = 1, 4 do
if UnitIsUnit(unit, "partypet" .. i) then return true end
end
return false
end
local NP_ThreatFrame = CreateFrame("Frame")
NP_ThreatFrame:RegisterEvent("CHAT_MSG_ADDON")
NP_ThreatFrame:RegisterEvent("PARTY_MEMBERS_CHANGED")
NP_ThreatFrame:RegisterEvent("RAID_ROSTER_UPDATE")
NP_ThreatFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
NP_ThreatFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
NP_ThreatFrame:SetScript("OnEvent", function()
if event == "CHAT_MSG_ADDON" then
local prefix = arg1
local msg = arg2 or ""
local sender = arg4
if string_find(msg, "TMTv1=") then GP_HandleTankModePacket(msg) end
if string_find(msg, "TWTv4=") then GP_HandleThreatPacket(msg) end
if prefix == NP_ADDON_PREFIX and msg and sender then
GP_HandleTankModeMessage(sender, msg)
end
elseif event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE"
or event == "ZONE_CHANGED_NEW_AREA" or event == "PLAYER_ENTERING_WORLD" then
NanamiPlates_Threat.BroadcastTankMode(true)
end
end)
NanamiPlates.Threat = NanamiPlates_Threat