local addonName, EchoInternal = ...; -- Mouse Frame local mouseFrame = CreateFrame("Frame", "EchoInternalMouseFrame", UIParent); mouseFrame:SetWidth(1); mouseFrame:SetHeight(1); mouseFrame:SetScript("OnUpdate",function () local scale = 1 / UIParent:GetEffectiveScale(); local x, y = GetCursorPosition(); mouseFrame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x * scale, y * scale); end) -- Sneak local ACE_COMM = LibStub("AceComm-3.0Multi") local ACE_SERIALIZER = LibStub("AceSerializer-3.0") local PRIVATE_AURA_COMM_PREFIX = "PRIV_AURA_COMM" local MACRO_PREFIX = "MACRO_COMM" local internal = {}; internal.debugMode = true internal.resetPeriod = 8 internal.currentServerTimeMillis = 0 internal.debounce = {} internal.processedAuraIds = {} internal.registeredAuraAnchors = {} -- Setup --------------------------------------------------------------------------------------------------------------- function internal:Initialize() if not self.isInitialized then self:Log('Initializing...') self:InitServerTimeUpdater() self:FindAndHookTooltipFrame() ACE_COMM:RegisterComm(PRIVATE_AURA_COMM_PREFIX, function(...) self:ProcessCommMessage(...) end, true) ACE_COMM:RegisterComm(MACRO_PREFIX, function(...) self:ProcessMacroComm(...) end) self.isInitialized = true end end function internal:InitServerTimeUpdater() local rolloverTimeMillis = 0 local currentServerTime = GetServerTime() CreateFrame("Frame"):SetScript("OnUpdate", function() local currentMillis = GetTime() - math.floor(GetTime()) if GetServerTime() ~= currentServerTime then currentServerTime = GetServerTime() rolloverTimeMillis = currentMillis end if currentMillis >= rolloverTimeMillis then self.currentServerTimeMillis = GetServerTime() + currentMillis - rolloverTimeMillis else self.currentServerTimeMillis = GetServerTime() + currentMillis - rolloverTimeMillis + 1 end end) end function internal:FindAndHookTooltipFrame() self:Log('Initializing frame finder...') self:InitializeAllPrivateAuraAnchors() CreateFrame("Frame"):SetScript("OnUpdate", function(tooltipFrameFinderFrame) if PrivateAurasTooltipTextLeft3 then tooltipFrameFinderFrame:SetScript("OnUpdate", nil) tooltipFrameFinderFrame:Hide() self:HookTooltipFrame() end end) end function internal:HookTooltipFrame() self:Log('Hooking PrivateAurasTooltip...') local function processPrivateAuraInfo(PrivateAurasTooltipFrame, PrivateAuraFrame, ...) self:ProcessPrivateAuraInfo(PrivateAuraFrame) end hooksecurefunc(PrivateAurasTooltipTextLeft3:GetParent(), "SetOwner", processPrivateAuraInfo) self:InitializeAllPrivateAuraAnchors() end -- Core --------------------------------------------------------------------------------------------------------------- function internal:ProcessCommMessage(_, serializedPacket, channel, sender) local status, privateAuraCommPacket = ACE_SERIALIZER:Deserialize(serializedPacket) if status and privateAuraCommPacket then self:ScanPrivateAuraCommPacket(privateAuraCommPacket) end end function internal:ProcessMacroComm(_, macroNum, channel, sender) local num = tonumber(macroNum) local unit = Ambiguate(sender, "none") if num and unit then --self:Log("Received Macro Info", num, unit) WeakAuras.ScanEvents("ECHO_PRIVATE_AURA", num, unit) end end function internal:IsAuraProcessed(privateAuraCommPacket) local auraInfo = privateAuraCommPacket.auraInfo local key = privateAuraCommPacket.destGUID.."-"..auraInfo.spellId; local lockoutNext = self.processedAuraIds[key]; if(not lockoutNext) then return false; end return lockoutNext > GetTime(); end function internal:ScanPrivateAuraCommPacket(privateAuraCommPacket) if(not internal.spellToMacro[privateAuraCommPacket.auraInfo.spellId]) then return; end local auraInfo = privateAuraCommPacket.auraInfo if not internal:IsAuraProcessed(privateAuraCommPacket) then auraInfo.unit = UnitTokenFromGUID(privateAuraCommPacket.destGUID) auraInfo.expirationTime = self:ConvertToLocalTime(privateAuraCommPacket.expirationTimeServer) self.processedAuraIds[privateAuraCommPacket.destGUID.."-"..auraInfo.spellId] = auraInfo.expirationTime == 0 and (GetTime() + internal.resetPeriod) or (GetTime() + (auraInfo.expirationTime - GetTime())); local unit = UnitExists(UnitName(auraInfo.unit)) and UnitName(auraInfo.unit) or auraInfo.unit --WeakAuras.ScanEvents("ECHO_PRIVATE_AURA", auraInfo) self:Log("Sending ScanEvents for", auraInfo.unit, auraInfo.spellId, unit); local delay = 0.5 + math.random() C_Timer.After(delay, function() WeakAuras.ScanEvents("ECHO_PRIVATE_AURA_AUTO", internal.spellToMacro[auraInfo.spellId] or auraInfo.spellId, unit, auraInfo) end) --vdt:AddData(auraInfo) end end function internal:ProcessPrivateAuraInfo(PrivateAuraFrame) --self:Log('Detected Aura on unit', PrivateAuraFrame.unit, 'at index', PrivateAuraFrame.anchorInfo.auraIndex) self:RemovePrivateAuraAnchor(PrivateAuraFrame.anchorInfo.anchorID) self:SendCommMessage({ auraInfo = PrivateAuraFrame.auraInfo, destGUID = UnitGUID(PrivateAuraFrame.unit), expirationTimeServer = self:ConvertToServerTime(PrivateAuraFrame.auraInfo.expirationTime) }) if(self.debouceTimer and not self.debouceTimer:IsCancelled()) then --self:Log('Cancelling reset timer...') self.debouceTimer:Cancel() end self.debouceTimer = C_Timer.NewTicker(self.resetPeriod, function() --self:Log('Resetting...'); self.debouceTimer = nil; table.wipe(internal.processedAuraIds); self:InitializeAllPrivateAuraAnchors() end,1); end function internal:InitializeAllPrivateAuraAnchors() self:RemoveAllPrivateAuraAnchors() --self:Log("Adding all raid frame anchors...") for unitToken in EchoInternal:IterateGroupMembers() do for auraIndex = 1, 2 do local anchorId = C_UnitAuras.AddPrivateAuraAnchor({ unitToken = unitToken, auraIndex = auraIndex, parent = mouseFrame, showCountdownFrame = false, showCountdownNumbers = false, iconInfo = { iconAnchor = { point = "CENTER", relativeTo = mouseFrame, relativePoint = "CENTER", offsetX = 0, offsetY = 0 }, iconWidth = 1, iconHeight = 1, } }) table.insert(self.registeredAuraAnchors, anchorId); end end end function internal:RemoveAllPrivateAuraAnchors() --self:Log("Removing all raid frame anchors...") for _, anchorId in ipairs(self.registeredAuraAnchors) do C_UnitAuras.RemovePrivateAuraAnchor(anchorId) end table.wipe(self.registeredAuraAnchors) end function internal:RemovePrivateAuraAnchor(anchorId) --self:Log('Removing anchor', anchorId) C_UnitAuras.RemovePrivateAuraAnchor(anchorId) tDeleteItem(self.registeredAuraAnchors, anchorId) end -- Util ---------------------------------------------------------------------------------------------------------------- function internal:ConvertToServerTime(localTimeMillis) if(localTimeMillis == 0 or not localTimeMillis) then return 0; end local localTimeDiff = localTimeMillis - GetTime() return self.currentServerTimeMillis + localTimeDiff end function internal:ConvertToLocalTime(serverTimeMillis) if(serverTimeMillis == 0 or not serverTimeMillis) then return 0; end local serverTimeDiff = serverTimeMillis - self.currentServerTimeMillis return GetTime() + serverTimeDiff end function internal:Debounce(key, debounceTime) if self.debounce[key] and self.debounce[key] > GetTime() then return false end self.debounce[key] = GetTime() + debounceTime return true end function internal:SendCommMessage(privateAuraCommPacket) local channel = IsInRaid() and "RAID" or "GUILD" local serializedPacket = ACE_SERIALIZER:Serialize(privateAuraCommPacket) ACE_COMM:SendCommMessage(PRIVATE_AURA_COMM_PREFIX, serializedPacket, channel, nil, "ALERT") end function internal:SendMacroComm(num) local channel = IsInRaid() and "RAID" or "GUILD" ACE_COMM:SendCommMessage(MACRO_PREFIX, tostring(num), channel, nil, "ALERT") end function internal:Log(...) if (self.debugMode) then --print("PRIVATE AURA:", ...) if (UnitIsGroupLeader("player")) then EchoInternal:RemoteLog("PRIVATE AURA AUTO", ...); end end end function EchoInternal:InitPrivateAura() internal:Initialize(); end internal.spellToMacro = { [426370] = 1, -- Darkflame Cleave - Fyrakk [428970] = 1, -- Shadow Cage - Fyrakk [428988] = 2, -- MoltenEruption - Fyrakk [423601] = 2, -- Seed of Amirdrassil - Fyrakk [429903] = 1, -- Flamebound - Fyrakk [429906] = 2, -- Shadowbound - Fyrakk [426010] = 1, -- fixate - Smolderon [410317] = 2, -- Test 1 [410326] = 1, -- Test 2 }