Add files via upload
This commit is contained in:
@@ -94,6 +94,25 @@ local playerInCombat = false
|
||||
-- members when the player is NOT in combat themselves.
|
||||
local groupInCombat = false
|
||||
|
||||
-- ============================================================
|
||||
-- Multi-mob incoming-attack tracking (v2.6.2)
|
||||
--
|
||||
-- Vanilla WoW 1.12 exposes NO unit token for a mob that isn't
|
||||
-- currently targeted / mouseovered / party-targeted. That meant
|
||||
-- earlier versions only lit the threat bar on the ONE enemy the
|
||||
-- player had targeted. To show bars for EVERY enemy in combat with
|
||||
-- the group, we parse the incoming-combat chat events (mob->player
|
||||
-- and mob->party) and remember which mob names have hit or missed
|
||||
-- a group member recently. UpdateAllPlates then treats any plate
|
||||
-- whose mob name is in this table as "in combat" and displays a
|
||||
-- threat bar even when its health bar hasn't dropped yet and no
|
||||
-- unit token is available.
|
||||
-- ============================================================
|
||||
local mobsAttackingGroup = {}
|
||||
local mobsAttackingPlayer = {}
|
||||
local MOB_ATTACK_TTL = 6.0 -- seconds a mob stays flagged as attacking
|
||||
local INCOMING_PARSERS = {}
|
||||
|
||||
-- ============================================================
|
||||
-- Safe API helpers
|
||||
-- ============================================================
|
||||
@@ -414,6 +433,67 @@ local function BuildAllParsers()
|
||||
" party damage, " .. table.getn(PARTY_HEAL_PARSERS) ..
|
||||
" party heal, " .. table.getn(PARTY_PERIODIC_PARSERS) ..
|
||||
" party periodic parsers built")
|
||||
|
||||
-- ========================================
|
||||
-- INCOMING (mob -> player/party) parsers (v2.6.2)
|
||||
-- Used to detect that a specific mob NAME is actively engaged
|
||||
-- with the group even though we have no unit token for it.
|
||||
-- We only care about the first capture (the mob / source name).
|
||||
-- Any OTHERSELF or OTHEROTHER GlobalString whose first %s is the
|
||||
-- attacker qualifies. Some of these constants may not exist on
|
||||
-- every Turtle/OctoWoW build; missing ones are silently skipped.
|
||||
-- ========================================
|
||||
local incomingSources = {
|
||||
-- Melee mob -> player
|
||||
"COMBATHITOTHERSELF", "COMBATHITCRITOTHERSELF",
|
||||
"COMBATHITSCHOOLOTHERSELF", "COMBATHITCRITSCHOOLOTHERSELF",
|
||||
"MISSEDOTHERSELF",
|
||||
"VSDODGEOTHERSELF", "VSPARRYOTHERSELF", "VSBLOCKOTHERSELF",
|
||||
"VSABSORBOTHERSELF", "VSIMMUNEOTHERSELF", "VSRESISTOTHERSELF",
|
||||
"VSDEFLECTOTHERSELF", "VSEVADEOTHERSELF",
|
||||
-- Spell mob -> player
|
||||
"SPELLLOGOTHERSELF", "SPELLLOGSCHOOLOTHERSELF",
|
||||
"SPELLLOGCRITOTHERSELF", "SPELLLOGCRITSCHOOLOTHERSELF",
|
||||
"SPELLMISSOTHERSELF", "SPELLDODGEDOTHERSELF",
|
||||
"SPELLPARRIEDOTHERSELF", "SPELLBLOCKEDOTHERSELF",
|
||||
"SPELLRESISTOTHERSELF", "SPELLIMMUNEOTHERSELF",
|
||||
"SPELLEVADEDOTHERSELF", "SPELLDEFLECTEDOTHERSELF",
|
||||
"SPELLREFLECTOTHERSELF",
|
||||
-- Periodic (mob DoT ticking on player)
|
||||
"PERIODICAURADAMAGEOTHERSELF",
|
||||
-- Melee mob -> other (party member)
|
||||
"COMBATHITOTHEROTHER", "COMBATHITCRITOTHEROTHER",
|
||||
"COMBATHITSCHOOLOTHEROTHER", "COMBATHITCRITSCHOOLOTHEROTHER",
|
||||
"MISSEDOTHEROTHER",
|
||||
"VSDODGEOTHEROTHER", "VSPARRYOTHEROTHER", "VSBLOCKOTHEROTHER",
|
||||
"VSABSORBOTHEROTHER", "VSIMMUNEOTHEROTHER", "VSRESISTOTHEROTHER",
|
||||
"VSDEFLECTOTHEROTHER", "VSEVADEOTHEROTHER",
|
||||
-- Spell mob -> other (party member)
|
||||
"SPELLLOGOTHEROTHER", "SPELLLOGSCHOOLOTHEROTHER",
|
||||
"SPELLLOGCRITOTHEROTHER", "SPELLLOGCRITSCHOOLOTHEROTHER",
|
||||
"SPELLMISSOTHEROTHER", "SPELLDODGEDOTHEROTHER",
|
||||
"SPELLPARRIEDOTHEROTHER", "SPELLBLOCKEDOTHEROTHER",
|
||||
"SPELLRESISTOTHEROTHER", "SPELLIMMUNEOTHEROTHER",
|
||||
-- Periodic (mob DoT ticking on party member)
|
||||
"PERIODICAURADAMAGEOTHEROTHER",
|
||||
}
|
||||
for i = 1, table.getn(incomingSources) do
|
||||
local gname = incomingSources[i]
|
||||
local fs = getglobal(gname)
|
||||
if fs then
|
||||
local r = FormatToRegex(fs)
|
||||
if r then
|
||||
local toPlayer = false
|
||||
if string.find(gname, "OTHERSELF") or string.find(gname, "TOSELF") then
|
||||
toPlayer = true
|
||||
end
|
||||
INCOMING_PARSERS[table.getn(INCOMING_PARSERS) + 1] =
|
||||
{ regex = r, globalVar = gname, toPlayer = toPlayer }
|
||||
end
|
||||
end
|
||||
end
|
||||
addon:ui_print("Threat engine: " .. table.getn(INCOMING_PARSERS) ..
|
||||
" incoming (mob->group) parsers built")
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
@@ -1137,6 +1217,79 @@ end
|
||||
-- Event handler for combat log events
|
||||
-- ============================================================
|
||||
|
||||
-- Mark a mob name as actively attacking someone in the group.
|
||||
-- Filters out anything that is obviously a player (self or a cached
|
||||
-- party/raid member class). Unknown names are assumed to be mobs.
|
||||
local function MarkMobAttackingGroup(name)
|
||||
if not name or name == "" then return end
|
||||
if playerName and name == playerName then return end
|
||||
if partyClassCache and partyClassCache[name] then return end
|
||||
mobsAttackingGroup[name] = GetTime()
|
||||
end
|
||||
|
||||
-- Same as MarkMobAttackingGroup, but flags the mob as specifically
|
||||
-- attacking the player. Used to distinguish "attacking me" from
|
||||
-- "attacking a party member" in the nameplate fallback branches.
|
||||
local function MarkMobAttackingPlayer(name)
|
||||
if not name or name == "" then return end
|
||||
if playerName and name == playerName then return end
|
||||
if partyClassCache and partyClassCache[name] then return end
|
||||
mobsAttackingPlayer[name] = GetTime()
|
||||
end
|
||||
|
||||
-- Parse an incoming combat-log message and, if it matches any known
|
||||
-- mob->group pattern, flag the first capture (the source mob name).
|
||||
local function ParseIncomingMessage(msg)
|
||||
if not msg or not INCOMING_PARSERS then return end
|
||||
for i = 1, table.getn(INCOMING_PARSERS) do
|
||||
local p = INCOMING_PARSERS[i]
|
||||
local _, _, c1 = string.find(msg, p.regex)
|
||||
if c1 then
|
||||
MarkMobAttackingGroup(c1)
|
||||
if p.toPlayer then
|
||||
MarkMobAttackingPlayer(c1)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Public API: is this mob name currently flagged as attacking the group?
|
||||
function addon.ThreatEngine:IsMobAttackingGroup(mobName)
|
||||
if not mobName then return false end
|
||||
local t = mobsAttackingGroup[mobName]
|
||||
if not t then return false end
|
||||
if GetTime() - t > MOB_ATTACK_TTL then
|
||||
mobsAttackingGroup[mobName] = nil
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Public API: is this mob name currently flagged as specifically
|
||||
-- attacking the player (not just any group member)?
|
||||
function addon.ThreatEngine:IsMobAttackingPlayer(mobName)
|
||||
if not mobName then return false end
|
||||
local t = mobsAttackingPlayer[mobName]
|
||||
if not t then return false end
|
||||
if GetTime() - t > MOB_ATTACK_TTL then
|
||||
mobsAttackingPlayer[mobName] = nil
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Public API: return the raw table (name -> lastSeen). Caller must not
|
||||
-- mutate it. Used mainly by debug commands.
|
||||
function addon.ThreatEngine:GetMobsAttackingGroup()
|
||||
return mobsAttackingGroup
|
||||
end
|
||||
|
||||
-- Called by the event frame for any CREATURE_VS_* combat log event.
|
||||
function addon.ThreatEngine:OnIncomingCombat(ev, msg)
|
||||
ParseIncomingMessage(msg)
|
||||
end
|
||||
|
||||
function addon.ThreatEngine:OnCombatEvent(ev, msg)
|
||||
if not msg then return end
|
||||
if not playerName then return end
|
||||
@@ -1545,6 +1698,8 @@ end
|
||||
|
||||
function addon.ThreatEngine:ClearAll()
|
||||
threatData = {}
|
||||
mobsAttackingGroup = {}
|
||||
mobsAttackingPlayer = {}
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
@@ -1809,6 +1964,20 @@ function addon.ThreatEngine:Initialize()
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE")
|
||||
|
||||
-- Incoming combat: mob attacking player / party. Used by v2.6.2
|
||||
-- multi-mob threat display to flag mobs that are engaged with
|
||||
-- the group but for which we have no unit token.
|
||||
combatFrame:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_MISSES")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_PARTY_MISSES")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_VS_SELF_DAMAGE")
|
||||
combatFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_VS_PARTY_DAMAGE")
|
||||
|
||||
combatFrame:SetScript("OnEvent", function()
|
||||
-- Vanilla 1.12: event name is in global 'event', args in global arg1..arg9
|
||||
-- IMPORTANT: we must NOT shadow 'event' with a local or parameter
|
||||
@@ -1838,6 +2007,18 @@ function addon.ThreatEngine:Initialize()
|
||||
elseif event == "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS"
|
||||
or event == "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS" then
|
||||
addon.ThreatEngine:OnPartyPeriodicEvent(event, arg1)
|
||||
-- Incoming combat: mob attacking player / party (v2.6.2)
|
||||
elseif event == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS"
|
||||
or event == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES"
|
||||
or event == "CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS"
|
||||
or event == "CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES"
|
||||
or event == "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE"
|
||||
or event == "CHAT_MSG_SPELL_CREATURE_VS_SELF_MISSES"
|
||||
or event == "CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE"
|
||||
or event == "CHAT_MSG_SPELL_CREATURE_VS_PARTY_MISSES"
|
||||
or event == "CHAT_MSG_SPELL_PERIODIC_CREATURE_VS_SELF_DAMAGE"
|
||||
or event == "CHAT_MSG_SPELL_PERIODIC_CREATURE_VS_PARTY_DAMAGE" then
|
||||
addon.ThreatEngine:OnIncomingCombat(event, arg1)
|
||||
end
|
||||
|
||||
-- Handle non-combat events
|
||||
|
||||
Reference in New Issue
Block a user