From 02c793a5de9200556fd3b6e8a894285f979c5940 Mon Sep 17 00:00:00 2001 From: avitasia Date: Fri, 20 Feb 2026 08:45:58 -0800 Subject: [PATCH] add new UNIT event options --- Localization.lua | 42 +++++++++++++++ helper.lua | 102 ++++++++++++++++++++++++++++++++++++ settings.lua | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+) diff --git a/Localization.lua b/Localization.lua index 7cf73e2..a8dcb82 100644 --- a/Localization.lua +++ b/Localization.lua @@ -139,6 +139,27 @@ L:RegisterTranslations("enUS", function() ["Enable Spell Energize Events"] = true, ["Whether to enable SPELL_ENERGIZE_BY_SELF, SPELL_ENERGIZE_BY_OTHER, and SPELL_ENERGIZE_ON_SELF events."] = true, + + ["Unit Event Filters"] = true, + ["Controls which unit identifiers trigger unit events (UNIT_HEALTH, UNIT_COMBAT, etc.). In the base game the same event can fire multiple times for the same unit, once per identifying string (e.g. 'party1', 'raid1', 'mouseover'). Disabling unused identifiers reduces redundant event calls. Note: 'player', 'target', and 'pet' (your own pet) always trigger regardless of these settings, as they are critical."] = true, + + ["Enable Pet Unit Events"] = true, + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for party and raid pet identifiers ('party1pet', 'raid1pet', etc.). Party pets additionally require Enable Party Unit Events to be on; raid pets additionally require Enable Raid Unit Events to be on. Your own pet ('pet') always fires events regardless of this setting."] = true, + + ["Enable Party Unit Events"] = true, + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for party member identifiers ('party1', 'party2', 'party3', 'party4'). Also required alongside Enable Pet Unit Events for party pet identifiers to fire."] = true, + + ["Enable Raid Unit Events"] = true, + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for raid member identifiers ('raid1' through 'raid40'). Also required alongside Enable Pet Unit Events for raid pet identifiers to fire."] = true, + + ["Enable Mouseover Unit Events"] = true, + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for the 'mouseover' unit identifier."] = true, + + ["Enable GUID Unit Events"] = true, + ["Whether to fire unit events (UNIT_HEALTH, UNIT_MANA, UNIT_AURA, etc.) using the raw GUID as the unit token, mirroring SuperWoW behavior. Fires for every unit the client tracks — not just named tokens like 'player', 'party1', 'raid1' — which can cause significant event spam in raids, BGs, and crowded zones. Older addons (e.g. pfUI) written for standard named tokens may have performance issues receiving GUID-based events. Addons needing GUID tracking (e.g. Automarker, Cursive) should use the new dedicated UNIT_HEALTH_GUID, UNIT_MANA_GUID, etc. events instead, allowing this to be safely disabled."] = true, + + ["Enable GUID Unit Event Filtering"] = true, + ["When enabled, suppresses high-frequency GUID events that cause spam in older addons — specifically UNIT_AURA, UNIT_HEALTH, UNIT_MANA, and similar events below UNIT_COMBAT, plus UNIT_NAME_UPDATE, UNIT_PORTRAIT_UPDATE, UNIT_INVENTORY_CHANGED, and PLAYER_GUILD_UPDATE. UNIT_COMBAT_GUID and other less frequent GUID events are still fired. Has no effect if Enable GUID Unit Events is disabled. This is a direct replacement for the 'Filter GUID Events' option in PerfBoost."] = true, } end) @@ -281,5 +302,26 @@ L:RegisterTranslations("zhCN", function() ["Enable Spell Energize Events"] = "启用法术回能事件", ["Whether to enable SPELL_ENERGIZE_BY_SELF, SPELL_ENERGIZE_BY_OTHER, and SPELL_ENERGIZE_ON_SELF events."] = "是否启用 SPELL_ENERGIZE_BY_SELF、SPELL_ENERGIZE_BY_OTHER 和 SPELL_ENERGIZE_ON_SELF 事件。", + + ["Unit Event Filters"] = "单位事件过滤器", + ["Controls which unit identifiers trigger unit events (UNIT_HEALTH, UNIT_COMBAT, etc.). In the base game the same event can fire multiple times for the same unit, once per identifying string (e.g. 'party1', 'raid1', 'mouseover'). Disabling unused identifiers reduces redundant event calls. Note: 'player', 'target', and 'pet' (your own pet) always trigger regardless of these settings, as they are critical."] = "控制哪些单位标识符触发单位事件(UNIT_HEALTH、UNIT_COMBAT 等)。在原版游戏中,同一单位可能因多个标识符(如 'party1'、'raid1'、'mouseover')重复触发同一事件。禁用不需要的标识符可减少冗余事件调用。注意:'player'(自身)、'target'(目标)和 'pet'(自己的宠物)始终会触发,不受此处设置影响,因为它们是关键标识符。", + + ["Enable Pet Unit Events"] = "启用宠物单位事件", + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for party and raid pet identifiers ('party1pet', 'raid1pet', etc.). Party pets additionally require Enable Party Unit Events to be on; raid pets additionally require Enable Raid Unit Events to be on. Your own pet ('pet') always fires events regardless of this setting."] = "是否为队伍和团队宠物标识符('party1pet'、'raid1pet' 等)触发单位事件(UNIT_HEALTH、UNIT_COMBAT 等)。队伍宠物还需同时开启「启用队伍单位事件」;团队宠物还需同时开启「启用团队单位事件」。自己的宠物('pet')始终触发事件,不受此设置影响。", + + ["Enable Party Unit Events"] = "启用队伍单位事件", + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for party member identifiers ('party1', 'party2', 'party3', 'party4'). Also required alongside Enable Pet Unit Events for party pet identifiers to fire."] = "是否为队伍成员标识符('party1'、'party2'、'party3'、'party4')触发单位事件(UNIT_HEALTH、UNIT_COMBAT 等)。同时也是队伍宠物标识符触发的必要条件(需与「启用宠物单位事件」共同开启)。", + + ["Enable Raid Unit Events"] = "启用团队单位事件", + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for raid member identifiers ('raid1' through 'raid40'). Also required alongside Enable Pet Unit Events for raid pet identifiers to fire."] = "是否为团队成员标识符('raid1' 至 'raid40')触发单位事件(UNIT_HEALTH、UNIT_COMBAT 等)。同时也是团队宠物标识符触发的必要条件(需与「启用宠物单位事件」共同开启)。", + + ["Enable Mouseover Unit Events"] = "启用鼠标悬停单位事件", + ["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for the 'mouseover' unit identifier."] = "是否为 'mouseover'(鼠标悬停)单位标识符触发单位事件(UNIT_HEALTH、UNIT_COMBAT 等)。", + + ["Enable GUID Unit Events"] = "启用GUID单位事件", + ["Whether to fire unit events (UNIT_HEALTH, UNIT_MANA, UNIT_AURA, etc.) using the raw GUID as the unit token, mirroring SuperWoW behavior. Fires for every unit the client tracks — not just named tokens like 'player', 'party1', 'raid1' — which can cause significant event spam in raids, BGs, and crowded zones. Older addons (e.g. pfUI) written for standard named tokens may have performance issues receiving GUID-based events. Addons needing GUID tracking (e.g. Automarker, Cursive) should use the new dedicated UNIT_HEALTH_GUID, UNIT_MANA_GUID, etc. events instead, allowing this to be safely disabled."] = "是否使用原始 GUID 作为单位标识符触发单位事件(UNIT_HEALTH、UNIT_MANA、UNIT_AURA 等),模拟 SuperWoW 行为。此功能会对客户端跟踪的所有单位触发事件——不仅限于 'player'、'party1'、'raid1' 等命名标识符——在团队、战场和人口密集区域可能产生大量事件。为标准命名标识符设计的旧版插件(如 pfUI)在收到 GUID 事件时可能出现性能问题。需要 GUID 跟踪的插件(如 Automarker、Cursive)应改用专用的 UNIT_HEALTH_GUID、UNIT_MANA_GUID 等事件,届时可安全禁用此选项。", + + ["Enable GUID Unit Event Filtering"] = "启用GUID单位事件过滤", + ["When enabled, suppresses high-frequency GUID events that cause spam in older addons — specifically UNIT_AURA, UNIT_HEALTH, UNIT_MANA, and similar events below UNIT_COMBAT, plus UNIT_NAME_UPDATE, UNIT_PORTRAIT_UPDATE, UNIT_INVENTORY_CHANGED, and PLAYER_GUILD_UPDATE. UNIT_COMBAT_GUID and other less frequent GUID events are still fired. Has no effect if Enable GUID Unit Events is disabled. This is a direct replacement for the 'Filter GUID Events' option in PerfBoost."] = "启用后,将屏蔽对旧版插件造成刷屏的高频 GUID 事件——具体包括 UNIT_COMBAT 以下的事件(如 UNIT_AURA、UNIT_HEALTH、UNIT_MANA 等),以及 UNIT_NAME_UPDATE、UNIT_PORTRAIT_UPDATE、UNIT_INVENTORY_CHANGED 和 PLAYER_GUILD_UPDATE。UNIT_COMBAT_GUID 及其他低频 GUID 事件仍会正常触发。若已禁用「启用GUID单位事件」,则此设置无效。此选项直接替代 PerfBoost 中的「过滤GUID事件」功能。", } end) diff --git a/helper.lua b/helper.lua index ce34fd6..7562562 100644 --- a/helper.lua +++ b/helper.lua @@ -654,3 +654,105 @@ end --Nampower:RegisterEvent("SPELL_MISS_SELF", createSpellMissHandler("SPELL_MISS_SELF")) --Nampower:RegisterEvent("SPELL_MISS_OTHER", createSpellMissHandler("SPELL_MISS_OTHER")) + +if not Nampower:HasMinimumVersion(2, 39, 0) then + return +end + +-- UNIT_INVENTORY_CHANGED - fires when a unit's inventory changes (standard named token variant) +-- Parameters: unit (string) - unit token like "player", "target", "party1", etc. + +-- UNIT_INVENTORY_CHANGED_GUID - fires when a unit's inventory changes (GUID variant) +-- Parameters: +-- guid (string) - unit GUID e.g. "0xF5300000000000A5" +-- isPlayer (int) - 1 if the unit is the active player, 0 otherwise +-- isTarget (int) - 1 if the unit is the current locked target, 0 otherwise +-- isMouseover (int) - 1 if the unit is the current mouseover, 0 otherwise +-- isPet (int) - 1 if the unit is the active player's pet, 0 otherwise +-- partyIndex (int) - party slot (1-4) if the unit is a party member, 0 otherwise +-- raidIndex (int) - raid slot (1-40) if the unit is a raid member, 0 otherwise + +local function onUnitInventoryChanged(unit) + print(string.format("UNIT_MODEL_CHANGED: %s", unit)) +end + +local function onUnitInventoryChangedGuid(guid, isPlayer, isTarget, isMouseover, isPet, partyIndex, raidIndex) + print(string.format( + "UNIT_MODEL_CHANGED_GUID: %s | isPlayer:%d isTarget:%d isMouseover:%d isPet:%d party:%d raid:%d", + guid, isPlayer, isTarget, isMouseover, isPet, partyIndex, raidIndex + )) +end + +--Nampower:RegisterEvent("UNIT_MODEL_CHANGED", onUnitInventoryChanged) +--Nampower:RegisterEvent("UNIT_MODEL_CHANGED_GUID", onUnitInventoryChangedGuid) + +-- UNIT_MANA - fires when a unit's mana changes (standard named token variant) +-- Parameters: unit (string) - unit token like "player", "target", "party1", etc. + +-- UNIT_MANA_GUID - fires when a unit's mana changes (GUID variant) +-- Parameters: +-- guid (string) - unit GUID e.g. "0xF5300000000000A5" +-- isPlayer (int) - 1 if the unit is the active player, 0 otherwise +-- isTarget (int) - 1 if the unit is the current locked target, 0 otherwise +-- isMouseover (int) - 1 if the unit is the current mouseover, 0 otherwise +-- isPet (int) - 1 if the unit is the active player's pet, 0 otherwise +-- partyIndex (int) - party slot (1-4) if the unit is a party member, 0 otherwise +-- raidIndex (int) - raid slot (1-40) if the unit is a raid member, 0 otherwise + +local function onUnitMana(unit) + print(string.format("UNIT_MANA: %s", unit)) +end + +local function onUnitManaGuid(guid, isPlayer, isTarget, isMouseover, isPet, partyIndex, raidIndex) + if UnitName(guid) == "Tankeboy" or UnitName(guid) == "Icansummon" then + print(string.format( + "UNIT_MANA_GUID: %s | isPlayer:%d isTarget:%d isMouseover:%d isPet:%d party:%d raid:%d", + UnitName(guid), isPlayer, isTarget, isMouseover, isPet, partyIndex, raidIndex + )) + end +end + +--Nampower:RegisterEvent("UNIT_MANA", onUnitMana) +--Nampower:RegisterEvent("UNIT_MANA_GUID", onUnitManaGuid) + +-- UNIT_COMBAT - fires when a unit participates in combat (standard named token variant) +-- Parameters: +-- unit (string) - unit token like "player", "target", "party1", etc. +-- action (string) - e.g. "WOUND", "MISS", "DODGE", "PARRY", "BLOCK", "EVADE", "IMMUNE", "REFLECT", "ABSORB", "INTERRUPT" +-- critical (string) - "CRITICAL" if a crit, "" otherwise +-- damage (int) - raw damage amount (0 for non-damaging outcomes) +-- school (int) - damage school (0=Physical, 1=Holy, 2=Fire, 3=Nature, 4=Frost, 5=Shadow, 6=Arcane) + +-- UNIT_COMBAT_GUID - fires once per combat feedback event, identified by GUID +-- Unlike other GUID events, carries full combat detail rather than unit membership flags. +-- Parameters: +-- guid (string) - unit GUID e.g. "0xF5300000000000A5" +-- action (string) - e.g. "WOUND", "MISS", "DODGE", "PARRY", "BLOCK", "EVADE", "IMMUNE", "REFLECT", "ABSORB", "INTERRUPT" +-- damage (int) - raw damage amount (0 for non-damaging outcomes like dodge/miss) +-- school (int) - damage school (0=Physical, 1=Holy, 2=Fire, 3=Nature, 4=Frost, 5=Shadow, 6=Arcane) +-- hitInfo (int) - hit info bitfield +-- isInteract (int) - 1 if the unit matches the current interact target, 0 otherwise +-- isPet (int) - 1 if the unit is the active player's pet, 0 otherwise +-- partyIndex (int) - party slot (1-4) if the unit is a party member, 0 otherwise +-- raidIndex (int) - raid slot (1-40) if the unit is a raid member, 0 otherwise + +local function onUnitCombat(unit, action, critical, damage, school) + local schoolName = GetSpellSchoolName(school) + local critText = critical == "CRITICAL" and " (CRIT)" or "" + print(string.format( + "UNIT_COMBAT: %s | %s | %d %s damage%s", + unit, action, damage, schoolName, critText + )) +end + +local function onUnitCombatGuid(guid, action, damage, school, hitInfo, isInteract, isPet, partyIndex, raidIndex) + local name = UnitName(guid) + local schoolName = GetSpellSchoolName(school) + print(string.format( + "UNIT_COMBAT_GUID: %s | %s | %d %s | hitInfo:%d isInteract:%d isPet:%d party:%d raid:%d", + name, action, damage, schoolName, hitInfo, isInteract, isPet, partyIndex, raidIndex + )) +end + +--Nampower:RegisterEvent("UNIT_COMBAT", onUnitCombat) +--Nampower:RegisterEvent("UNIT_COMBAT_GUID", onUnitCombatGuid) diff --git a/settings.lua b/settings.lua index 09356f3..5838495 100644 --- a/settings.lua +++ b/settings.lua @@ -133,6 +133,14 @@ function Nampower:SavePerCharacterSettings() end end + if Nampower.cmdtable.args.advanced_options.args.unit_events then + for settingKey, settingData in pairs(Nampower.cmdtable.args.advanced_options.args.unit_events.args) do + if string.find(settingKey, "NP_") == 1 then + settingData.set(settingData.get()) -- trigger the set function for each setting with the current value + end + end + end + for settingKey, settingData in pairs(Nampower.cmdtable.args.qol_options.args) do if string.find(settingKey, "NP_") == 1 then settingData.set(settingData.get()) -- trigger the set function for each setting with the current value @@ -168,6 +176,17 @@ function Nampower:ApplySavedSettings() end end + if Nampower.cmdtable.args.advanced_options.args.unit_events then + for settingKey, settingData in pairs(Nampower.cmdtable.args.advanced_options.args.unit_events.args) do + -- only apply settings that are prefixed with NP_ + if string.find(settingKey, "NP_") == 1 then + if Nampower.db.profile[settingKey]~= nil then + settingData.set(Nampower.db.profile[settingKey]) + end + end + end + end + for settingKey, settingData in pairs(Nampower.cmdtable.args.qol_options.args) do -- only apply settings that are prefixed with NP_ if string.find(settingKey, "NP_") == 1 then @@ -942,6 +961,119 @@ if Nampower:HasMinimumVersion(2, 26, 0) then } end +if Nampower:HasMinimumVersion(2, 39, 0) then + Nampower.cmdtable.args.advanced_options.args.unit_events = { + type = "group", + name = L["Unit Event Filters"], + desc = L["Controls which unit identifiers trigger unit events (UNIT_HEALTH, UNIT_COMBAT, etc.). In the base game the same event can fire multiple times for the same unit, once per identifying string (e.g. 'party1', 'raid1', 'mouseover'). Disabling unused identifiers reduces redundant event calls. Note: 'player', 'target', and 'pet' (your own pet) always trigger regardless of these settings, as they are critical."], + order = 200, + args = { + NP_EnableUnitEventsPet = { + type = "toggle", + name = L["Enable Pet Unit Events"], + desc = L["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for party and raid pet identifiers ('party1pet', 'raid1pet', etc.). Party pets additionally require Enable Party Unit Events to be on; raid pets additionally require Enable Raid Unit Events to be on. Your own pet ('pet') always fires events regardless of this setting."], + order = 5, + get = function() + return GetCVar("NP_EnableUnitEventsPet") == "1" + end, + set = function(v) + Nampower.db.profile.NP_EnableUnitEventsPet = v + if v == true then + SetCVar("NP_EnableUnitEventsPet", "1") + else + SetCVar("NP_EnableUnitEventsPet", "0") + end + end, + }, + NP_EnableUnitEventsParty = { + type = "toggle", + name = L["Enable Party Unit Events"], + desc = L["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for party member identifiers ('party1', 'party2', 'party3', 'party4'). Also required alongside Enable Pet Unit Events for party pet identifiers to fire."], + order = 10, + get = function() + return GetCVar("NP_EnableUnitEventsParty") == "1" + end, + set = function(v) + Nampower.db.profile.NP_EnableUnitEventsParty = v + if v == true then + SetCVar("NP_EnableUnitEventsParty", "1") + else + SetCVar("NP_EnableUnitEventsParty", "0") + end + end, + }, + NP_EnableUnitEventsRaid = { + type = "toggle", + name = L["Enable Raid Unit Events"], + desc = L["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for raid member identifiers ('raid1' through 'raid40'). Also required alongside Enable Pet Unit Events for raid pet identifiers to fire."], + order = 15, + get = function() + return GetCVar("NP_EnableUnitEventsRaid") == "1" + end, + set = function(v) + Nampower.db.profile.NP_EnableUnitEventsRaid = v + if v == true then + SetCVar("NP_EnableUnitEventsRaid", "1") + else + SetCVar("NP_EnableUnitEventsRaid", "0") + end + end, + }, + NP_EnableUnitEventsMouseover = { + type = "toggle", + name = L["Enable Mouseover Unit Events"], + desc = L["Whether to fire unit events (UNIT_HEALTH, UNIT_COMBAT, etc.) for the 'mouseover' unit identifier."], + order = 25, + get = function() + return GetCVar("NP_EnableUnitEventsMouseover") == "1" + end, + set = function(v) + Nampower.db.profile.NP_EnableUnitEventsMouseover = v + if v == true then + SetCVar("NP_EnableUnitEventsMouseover", "1") + else + SetCVar("NP_EnableUnitEventsMouseover", "0") + end + end, + }, + NP_EnableUnitEventsGuid = { + type = "toggle", + name = L["Enable GUID Unit Events"], + desc = L["Whether to fire unit events (UNIT_HEALTH, UNIT_MANA, UNIT_AURA, etc.) using the raw GUID as the unit token, mirroring SuperWoW behavior. Fires for every unit the client tracks — not just named tokens like 'player', 'party1', 'raid1' — which can cause significant event spam in raids, BGs, and crowded zones. Older addons (e.g. pfUI) written for standard named tokens may have performance issues receiving GUID-based events. Addons needing GUID tracking (e.g. Automarker, Cursive) should use the new dedicated UNIT_HEALTH_GUID, UNIT_MANA_GUID, etc. events instead, allowing this to be safely disabled."], + order = 30, + get = function() + return GetCVar("NP_EnableUnitEventsGuid") == "1" + end, + set = function(v) + Nampower.db.profile.NP_EnableUnitEventsGuid = v + if v == true then + SetCVar("NP_EnableUnitEventsGuid", "1") + else + SetCVar("NP_EnableUnitEventsGuid", "0") + end + end, + }, + NP_EnableUnitEventsGuidFiltering = { + type = "toggle", + name = L["Enable GUID Unit Event Filtering"], + desc = L["When enabled, suppresses high-frequency GUID events that cause spam in older addons — specifically UNIT_AURA, UNIT_HEALTH, UNIT_MANA, and similar events below UNIT_COMBAT, plus UNIT_NAME_UPDATE, UNIT_PORTRAIT_UPDATE, UNIT_INVENTORY_CHANGED, and PLAYER_GUILD_UPDATE. UNIT_COMBAT_GUID and other less frequent GUID events are still fired. Has no effect if Enable GUID Unit Events is disabled. This is a direct replacement for the 'Filter GUID Events' option in PerfBoost."], + order = 35, + get = function() + return GetCVar("NP_EnableUnitEventsGuidFiltering") == "1" + end, + set = function(v) + Nampower.db.profile.NP_EnableUnitEventsGuidFiltering = v + if v == true then + SetCVar("NP_EnableUnitEventsGuidFiltering", "1") + else + SetCVar("NP_EnableUnitEventsGuidFiltering", "0") + end + end, + }, + }, + } +end + local deuce = Nampower:NewModule("Nampower Options Menu") deuce.hasFuBar = IsAddOnLoaded("FuBar") and FuBar deuce.consoleCmd = not deuce.hasFuBar