From 5ef01174d6ce29545b07c0e0793b4188510c610e Mon Sep 17 00:00:00 2001 From: Meow <30401521+me0wg4ming@users.noreply.github.com> Date: Sat, 11 Apr 2026 21:10:57 +0200 Subject: [PATCH] New module - InnervateCall (only for druids) - This module will call in group/raid and battleground if you innervated yourself or someone else. - The module will inform your group/raid/battleground if innervate is ready again. --- modules/innervatecall.lua | 132 ++++++++++++++++++++++++++++++++++++++ pfUI.lua | 14 +++- 2 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 modules/innervatecall.lua diff --git a/modules/innervatecall.lua b/modules/innervatecall.lua new file mode 100644 index 00000000..2e75a137 --- /dev/null +++ b/modules/innervatecall.lua @@ -0,0 +1,132 @@ +-- Innervate Callout Module +-- Announces Innervate casts via raid/party/battleground chat +-- Registers AURA_CAST events directly - zero polling, pure event-driven + +pfUI:RegisterNewModule("innervatecall", "Innervate Callout", "DRUID") +pfUI:RegisterModule("innervatecall", "vanilla", function () + -- Requires Nampower for AURA_CAST events + if not GetNampowerVersion then return end + + -- Only load for druids + local _, playerClass = UnitClass("player") + if playerClass ~= "DRUID" then return end + + local INNERVATE_SPELLID = 29166 + + -- Cache player GUID + local playerGuid = nil + local function GetPlayerGuid() + if not playerGuid and GetUnitGUID then + playerGuid = GetUnitGUID("player") + end + return playerGuid + end + + -- GUID → name resolution for the target + local function ResolveTargetName(targetGuid) + if not targetGuid or not GetUnitGUID then return nil end + + -- Check player self-cast + if GetPlayerGuid() == targetGuid then + return UnitName("player") + end + + -- Check current target (most common case for other-cast) + local curGuid = GetUnitGUID("target") + if curGuid == targetGuid then + return UnitName("target") + end + + -- Scan raid/party for GUID match + for i = 1, GetNumRaidMembers() do + local unit = "raid" .. i + if GetUnitGUID(unit) == targetGuid then + return UnitName(unit) + end + end + for i = 1, GetNumPartyMembers() do + local unit = "party" .. i + if GetUnitGUID(unit) == targetGuid then + return UnitName(unit) + end + end + + return nil + end + + -- Determine chat channel based on group context + local function GetAnnounceChannel() + local _, instanceType = IsInInstance() + if instanceType == "pvp" then + return "BATTLEGROUND" + end + + if GetNumRaidMembers() > 0 then + return "RAID" + end + + if GetNumPartyMembers() > 0 then + return "PARTY" + end + + return nil + end + + -- Event frame - registers AURA_CAST directly (bypasses libdebuff hooks + -- which are gated behind ownDebuffs/pendingCasts checks meant for debuffs) + local frame = CreateFrame("Frame") + -- AURA_CAST_ON_SELF fires when a buff lands ON the player + -- AURA_CAST_ON_OTHER fires when a buff lands on someone else + -- Both needed: self-innervate = ON_SELF, innervate on others = ON_OTHER + -- casterGuid check prevents announcing other druids' innervates + frame:RegisterEvent("AURA_CAST_ON_SELF") + frame:RegisterEvent("AURA_CAST_ON_OTHER") + frame:RegisterEvent("PLAYER_LOGOUT") + frame:SetScript("OnEvent", function() + if event == "PLAYER_LOGOUT" then + this:UnregisterAllEvents() + this:SetScript("OnEvent", nil) + return + end + + -- AURA_CAST args: arg1=spellId, arg2=casterGuid, arg3=targetGuid + local spellId = arg1 + local casterGuid = arg2 + local targetGuid = arg3 + + if spellId ~= INNERVATE_SPELLID then return end + + -- Only announce our own casts + if casterGuid ~= GetPlayerGuid() then return end + + -- Resolve target name from GUID + local targetName = ResolveTargetName(targetGuid) or "Unknown" + + -- Determine channel + local channel = GetAnnounceChannel() + if not channel then return end -- solo, no announcement + + SendChatMessage(">> Innervate casted on " .. targetName .. " <<", channel) + + -- Schedule "ready" announcement when cooldown expires + -- Use GetSpellIdCooldown for precise remaining time, fallback to 360s + local cdRemaining = 360 + if GetSpellIdCooldown then + local cd = GetSpellIdCooldown(INNERVATE_SPELLID) + if cd and cd.cooldownRemainingMs and cd.cooldownRemainingMs > 0 then + cdRemaining = cd.cooldownRemainingMs / 1000 + end + end + + local readyAt = GetTime() + cdRemaining + frame:SetScript("OnUpdate", function() + if GetTime() >= readyAt then + frame:SetScript("OnUpdate", nil) + local ch = GetAnnounceChannel() + if ch then + SendChatMessage(">> Innervate is ready <<", ch) + end + end + end) + end) +end) diff --git a/pfUI.lua b/pfUI.lua index 5eda0491..6ecad2e1 100644 --- a/pfUI.lua +++ b/pfUI.lua @@ -258,17 +258,20 @@ end -- a one-time prompt asking if they want to enable them. pfUI.new_modules = {} -function pfUI:RegisterNewModule(name, label) - table.insert(pfUI.new_modules, { name = name, label = label }) +function pfUI:RegisterNewModule(name, label, class) + table.insert(pfUI.new_modules, { name = name, label = label, class = class }) end function pfUI:CheckNewModules() pfUI_init.seen_modules = pfUI_init.seen_modules or {} local pending = 0 + local _, playerClass = UnitClass("player") for _, entry in pairs(pfUI.new_modules) do if not pfUI_init.seen_modules[entry.name] and pfUI_init["finalize"] then - pending = pending + 1 + if not entry.class or entry.class == playerClass then + pending = pending + 1 + end end end @@ -287,6 +290,10 @@ function pfUI:CheckNewModules() for _, entry in pairs(pfUI.new_modules) do local name = entry.name if not pfUI_init.seen_modules[name] then + -- Skip modules restricted to a different class + if entry.class and entry.class ~= playerClass then + -- don't mark as seen - player might have a druid alt later + else pfUI_init.seen_modules[name] = true -- Only prompt existing users (firstrun wizard already ran) @@ -312,6 +319,7 @@ function pfUI:CheckNewModules() } StaticPopup_Show("PFUI_NEW_MODULE_" .. strupper(name)) end + end -- else (class match) end end end