Compare with Previous | Blame | View Log
-- PowaAura Classes -- class.lua -- Compatible with Lua 5.1 (not 5.0). function PowaClass(base,ctor) local c = {} -- a new class instance if not ctor and type(base) == 'function' then ctor = base; base = nil; elseif type(base) == 'table' then -- our new class is a shallow copy of the base class! for i,v in pairs(base) do c[i] = v; end if (type(ctor)=="table") then for i,v in pairs(ctor) do c[i] = v; end ctor = nil; end c._base = base; end -- the class will be the metatable for all its objects, -- and they will look up their methods in it. c.__index = c -- expose a ctor which can be called by <classname>(<args>) local mt = {} mt.__call = function(class_tbl,...) local obj = {} setmetatable(obj,c) if ctor then --PowaAuras:Message("Call constructor "..tostring(ctor)); ctor(obj,...) end return obj end if ctor then c.init = ctor; else if base and base.init then c.init = base.init; ctor = base.init; end end c.is_a = function(self,klass) local m = getmetatable(self) while m do if m == klass then return true end m = m._base end return false end setmetatable(c,mt) return c end cPowaStacks = PowaClass(function(stacker, id, base) stacker.enabled = false; stacker.x = 0; stacker.y = 0; stacker.a = 1.0; stacker.h = 1.0; stacker.Transparent = false; stacker.HideLeadingZeros = false; --PowaAuras:Message("cPowaTimer"); if (base) then for k, v in pairs (stacker) do --PowaAuras:Message(" base."..tostring(k).."="..tostring(base[k])); local varType = type(v); if (varType == "string" or varType == "boolean" or varType == "number") then if (base[k] ~= nil) then stacker[k] = base[k]; end end end end stacker.Showing = false; stacker.id = id; end); function cPowaStacks:Update() PowaAuras:UnitTestInfo("Stacks.Update ",self.id); local aura = PowaAuras.Auras[self.id]; if (aura == nil) then PowaAuras:UnitTestInfo("Stacks aura missing"); return; end if (self.enabled==false) then PowaAuras:UnitTestInfo("Stacks disabled"); return; end local newvalue = 0; if (PowaAuras.ModTest) then newvalue = random(1,12); else newvalue = aura.StackCount; end if (not newvalue or newvalue==0) then local frame = PowaAuras.StacksFrames[self.id]; if (frame and frame:IsVisible()) then frame:Hide(); end self.Showing = false; return; end PowaAuras:CreateStacksFrameIfMissing(self.id); self:ShowValue(aura, newvalue); self.Showing = true; self.HideRequest = false; end function cPowaStacks:ShowValue(aura, newvalue) local frame = PowaAuras.StacksFrames[self.id]; if (aura.texmode == 1) then frame.texture:SetBlendMode("ADD"); else frame.texture:SetBlendMode("DISABLE"); end local auraTexture = PowaAuras.Textures[self.id]; if (auraTexture) then if auraTexture:GetObjectType() == "Texture" then frame.texture:SetVertexColor(auraTexture:GetVertexColor()); elseif auraTexture:GetObjectType() == "FontString" then frame.texture:SetVertexColor(auraTexture:GetTextColor()); end else timerFrame.texture:SetVertexColor(aura.r,aura.g,aura.b); end --PowaAuras:Message("newvalue=", newvalue); local deci = math.floor(newvalue / 10); local uni = math.floor(newvalue - (deci*10)); --PowaAuras:Message("Show stacks: ",deci, " ", uni); local tStep = PowaAuras.Tstep; if (deci==0) then frame.texture:SetTexCoord(tStep , tStep * 1.5, tStep * uni, tStep * (uni+1)); else frame.texture:SetTexCoord(tStep * uni, tStep * (uni+1), tStep * deci, tStep * (deci+1)); end if (not frame:IsVisible()) then --PowaAuras:Message("Show Stacks Frame for ", self.id); frame:Show(); end end function cPowaStacks:Hide() --PowaAuras:Message("Hide Stacks Frame for ", self.id, " ", self.Showing, " ", PowaAuras.StacksFrames[self.id]); if (not self.Showing) then return; end if (PowaAuras.StacksFrames[self.id]) then PowaAuras.StacksFrames[self.id]:Hide(); end self.Showing = false; self.HideRequest = true; end function cPowaStacks:Delete() self:Hide(); if PowaAuras.StacksFrames[self.id] then PowaAuras.StacksFrames[self.id] = nil; end end ------- Timer ------- cPowaTimer = PowaClass(function(timer, id, base) timer.enabled = false; timer.x = 0; timer.y = 0; timer.a = 1.0; timer.h = 1.0; timer.cents = true; timer.dual = false; timer.Transparent = false; timer.HideLeadingZeros = false; --PowaAuras:Message("cPowaTimer"); if (base) then for k, v in pairs (timer) do --PowaAuras:Message(" base."..tostring(k).."="..tostring(base[k])); local varType = type(v); if (varType == "string" or varType == "boolean" or varType == "number") then if (base[k] ~= nil) then timer[k] = base[k]; end end end end timer.Showing = false; timer.id = id; --for k,v in pairs (timer) do -- PowaAuras:Message(" "..tostring(k).."="..tostring(v)); --end end); --- ------------------------------------------------------------------------------------------------- TIMERS function cPowaTimer:Update(elapsed) PowaAuras:UnitTestInfo("Timer.Update ",self.id); --PowaAuras:Message("Timer.Update ",self.id); local aura = PowaAuras.Auras[self.id]; if (aura == nil) then PowaAuras:UnitTestInfo("Timer aura missing"); --PowaAuras:Message("Timer aura missing"); return; end if (self.enabled==false) then PowaAuras:UnitTestInfo("Timer disabled"); --PowaAuras:Message("Timer disabled"); return; end --PowaAuras:Message("Showing=", aura.Showing); --PowaAuras:Message("CanHaveTimer=", aura.CanHaveTimer); --PowaAuras:Message("CanHaveTimerOnInverse=", aura.CanHaveTimerOnInverse); --PowaAuras:Message("Inverse=", aura.inverse); --PowaAuras:Message("CooldownAura=", aura.CooldownAura); local auraShowing = aura.Showing and not aura.HideRequest; if (not PowaAuras.ModTest and ((not auraShowing and not aura.CooldownAura) or (auraShowing and aura.CooldownAura))) then return; end local debugCycle; if (PowaAuras.NextDebugCheck>0 and PowaAuras.DebugTimer > PowaAuras.NextDebugCheck) then PowaAuras.DebugTimer = 0; --PowaAuras:Message("Update Timer #",self.id); --OK debugCycle = true; end local newvalue; --- Determine the value to display in the timer if (PowaAuras.ModTest) then newvalue = random(0,99) + (random(0, 99) / 100); elseif (aura.timerduration > 0) then--- if a user defined timer is active for the aura override the rest if (aura.target or aura.targetfriend) and (PowaAuras.ResetTargetTimers == true) then self.CustomDuration = aura.timerduration; else self.CustomDuration = math.max(self.CustomDuration - elapsed, 0); end newvalue = self.CustomDuration; else newvalue = aura:GetDuration(self.DurationInfo); end if (debugCycle) then PowaAuras:Message("newvalue=",newvalue); --OK end PowaAuras:UnitTestInfo("Timer newvalue", newvalue); --PowaAuras:Message("Timer newvalue=", newvalue); if (newvalue and newvalue > 0) then --- Time has value to display PowaAuras:CreateTimerFrameIfMissing(self.id); local large = newvalue; if (newvalue > 60.00) then large = newvalue / 60; end large = math.min (99.00, large); if (debugCycle) then PowaAuras:Message("large=",large); --OK end self:ShowValue(aura, 1, large); if (debugCycle) then PowaAuras:Message("cents=",self.cents); --OK end if (self.cents) then local small; if (newvalue > 60.00) then small = math.fmod(newvalue,60); else small = (newvalue - math.floor(newvalue)) * 100; end if (debugCycle) then PowaAuras:Message("small=",small); --OK end self:ShowValue(aura, 2, small); end self.Showing = true; if (self.HideRequest) then self.HideRequest = false; end elseif (self.Showing) then if (debugCycle) then PowaAuras:Message("HideTimerFrames"); --OK end --PowaAuras:Message("HideTimerFrames"); self:Hide(); PowaAuras:TestThisEffect(self.id); end end function cPowaTimer:ShowValue(aura, frameIndex, newvalue) local timerFrame = PowaAuras.TimerFrame[self.id][frameIndex]; if (aura.texmode == 1) then timerFrame.texture:SetBlendMode("ADD"); else timerFrame.texture:SetBlendMode("DISABLE"); end local auraTexture = PowaAuras.Textures[self.id]; if (auraTexture) then if auraTexture:GetObjectType() == "Texture" then timerFrame.texture:SetVertexColor(auraTexture:GetVertexColor()); elseif auraTexture:GetObjectType() == "FontString" then timerFrame.texture:SetVertexColor(auraTexture:GetTextColor()); end else timerFrame.texture:SetVertexColor(aura.r,aura.g,aura.b); end --PowaAuras:Message("newvalue=", newvalue); local deci = math.floor(newvalue / 10); local uni = math.floor(newvalue - (deci*10)); --PowaAuras:Message("Show timer: ",deci, " ", uni, " ", PowaAuras.Auras[k].Timer.HideLeadingZeros); local tStep = PowaAuras.Tstep; if (deci==0 and self.HideLeadingZeros) then timerFrame.texture:SetTexCoord(tStep , tStep * 1.5, tStep * uni, tStep * (uni+1)); else timerFrame.texture:SetTexCoord(tStep * uni, tStep * (uni+1), tStep * deci, tStep * (deci+1)); end if (not timerFrame:IsVisible()) then --PowaAuras:Message("Show timer frame"); timerFrame:Show(); -- Timer Frame end --PowaAuras:Message("Show #3 ", k, " ", i, " ", j, " ", seconds); --PowaAuras:Message("deci=", deci, " uni=", uni); end function cPowaTimer:HideFrame(i) if (PowaAuras.TimerFrame[self.id] and PowaAuras.TimerFrame[self.id][i]) then --PowaAuras:Message("Hide Timer Frame ", i," for ", self.id); PowaAuras.TimerFrame[self.id][i]:Hide(); end end function cPowaTimer:Hide() if (not self.Showing) then return; end if PowaAuras.TimerFrame[self.id] then self:HideFrame(1); self:HideFrame(2); end self.Showing = false; self.HideRequest = true; --PowaAuras:Message("Hide timer frame"); end function cPowaTimer:Delete() self:Hide(); if PowaAuras.TimerFrame[self.id] then PowaAuras.TimerFrame[self.id][1] = nil; PowaAuras.TimerFrame[self.id][2] = nil; PowaAuras.TimerFrame[self.id] = nil; end end ------------cPowaAura---------------- -- cPowaAura is the base class and is not instanced directly, the other classes inherit properties and methods from it --=========================== cPowaAura = PowaClass(function(aura, id, base) --PowaAuras:Message("cPowaAura constructor " .. tostring(id)); aura.off = false; aura.bufftype = PowaAuras.BuffTypes.Buff; aura.buffname = ""; aura.texmode = 1; aura.wowtex = false; aura.customtex = false; aura.textaura = false; aura.owntex = false; aura.realaura = 1; aura.texture = 1; aura.customname = ""; aura.aurastext = ""; aura.aurastextfont = 1; aura.icon = ""; aura.timerduration = 0; -- Sound Settings aura.sound = 0; aura.soundfile = ""; aura.customsound = ""; -- Animation Settings aura.begin = 0; aura.anim1 = 1; aura.anim2 = 0; aura.speed = 1.00; aura.finish = 1; aura.duration = 0; aura.isSecondary = false; -- Appearance Settings aura.alpha = 0.75; aura.size = 0.75; aura.torsion = 1; aura.symetrie = 0; aura.x = 0; aura.y = -30; aura.randomcolor = false; aura.r = 1.0; aura.g = 1.0; aura.b = 1.0; aura.inverse = false; aura.ignoremaj = true; aura.exact = false; aura.stacks = 0; aura.stacksLower = 0; aura.stacksOperator = PowaAuras.DefaultOperator; aura.threshold = 50; aura.thresholdinvert = false; aura.mine = false; aura.focus = false; aura.target = false; aura.targetfriend = false; aura.raid = false; aura.groupOrSelf = false; aura.party = false; aura.groupany = true; aura.optunitn = false; aura.unitn = ""; aura.isinraid = false; aura.ismounted = false; aura.ignoreResting = true; aura.inVehicle = false; aura.combat = 0; aura.spec1 = true; aura.spec2 = true; aura.gcd = false; aura.stance = 10; aura.multiids = ""; aura.tooltipCheck = ""; if (base) then for k, v in pairs (aura) do local varType = type(v); if (varType == "string" or varType == "boolean" or varType == "number") then if (base[k] ~= nil) then aura[k] = base[k]; end end end if (base.Timer) then --if ((base.CanHaveTimerOnInverse or base.CanHaveTimer) and base.Timer) then aura.Timer = cPowaTimer(id, base.Timer); end if (base.Stacks and not base.isSecondary) then aura.Stacks = cPowaStacks(id, base.Stacks); end end if (not aura.Timer) then --if ((base.CanHaveTimerOnInverse or base.CanHaveTimer) and not aura.Timer) then aura.Timer = cPowaTimer(id); end if (base.CanHaveStacks and not aura.Stacks and not aura.isSecondary) then aura.Stacks = cPowaStacks(id); end if (aura.Timer) then aura.Timer.Showing = false; aura.Timer.HideRequest = false; end if (aura.Stacks) then aura.Stacks.Showing = false; aura.Stacks.HideRequest = false; end aura.Showing = false; aura.HideRequest = false; aura.id = id; end); function cPowaAura:TimerShowing() if (not self.Timer) then return false; end return self.Timer.Showing; end function cPowaAura:StacksShowing() if (not self.Stacks) then return false; end return self.Stacks.Showing; end function cPowaAura:HideShowTabs() if ((self.CanHaveTimer and not self.inverse) or (self.CanHaveTimerOnInverse and self.inverse)) then PowaEditorTab3:Show(); if (not self.Timer) then self.Timer = cPowaTimer(self.id); end else PowaEditorTab3:Hide(); if (self.Timer) then self.Timer.enabled = false; end end if (self.CanHaveStacks and not self.inverse) then PowaEditorTab5:Show(); if (not self.Stacks) then self.Stacks = cPowaStacks(self.id); end else PowaEditorTab5:Hide(); if (self.Stacks) then self.Stacks.enabled = false; end end end function cPowaAura:GetDuration(durationInfo) --PowaAuras:Message("GetDuration=", durationInfo); if (durationInfo and durationInfo > 0) then return math.max(durationInfo - GetTime(), 0); end return 0; end function cPowaAura:CreateFrames() local frame = self:GetFrame(); if (frame==nil) then PowaAuras:UnitTestInfo("New Frames", self.id); PowaAuras:UnitTestDebug("Creating frame for aura ", self.id); --- Frame --- frame = CreateFrame("Frame","Frame"..self.id, UIParent); self:SetFrame(frame); frame:SetFrameStrata("LOW"); frame:Hide(); frame.baseL = 256; frame.baseH = 256; end local texture = self:GetTexture(); if (texture==nil) then PowaAuras:UnitTestInfo("New Texture", self.id); if self.textaura then PowaAuras:UnitTestDebug("Creating new textstring texture for aura ", self.id); texture = frame:CreateFontString(nil, "OVERLAY"); texture:ClearAllPoints(); texture:SetPoint("CENTER",frame); texture:SetFont(STANDARD_TEXT_FONT, 20); texture:SetTextColor(self.r,self.g,self.b); texture:SetJustifyH("CENTER"); else texture = frame:CreateTexture(nil,"BACKGROUND"); texture:SetBlendMode("ADD"); texture:SetAllPoints(frame); --- attache la texture a la frame frame.texture = texture; end self:SetTexture(texture); else if self.textaura then PowaAuras:UnitTestDebug("textaura ", texture:GetObjectType()); if texture:GetObjectType() == "Texture" then PowaAuras:UnitTestInfo("Converting to textstring texture for aura ", self.id); PowaAuras:UnitTestDebug("Converting to textstring texture for aura ", self.id); texture:SetTexture(nil); texture = frame:CreateFontString(nil, "OVERLAY"); texture:ClearAllPoints(); texture:SetPoint("CENTER",frame); texture:SetFont(STANDARD_TEXT_FONT, 20); texture:SetTextColor(self.r,self.g,self.b); texture:SetJustifyH("CENTER"); self:SetTexture(texture); end else if texture:GetObjectType() == "FontString" then PowaAuras:UnitTestInfo("Converting from textstring texture for aura ", self.id); texture:SetText(""); texture = frame:CreateTexture(nil,"BACKGROUND"); texture:SetBlendMode("ADD"); texture:SetAllPoints(frame); --- attache la texture a la frame frame.texture = texture; self:SetTexture(texture); end end end return frame, texture; end function cPowaAura:Hide() PowaAuras:UnitTestInfo("Aura.Hide ", self.id); local frame = self:GetFrame(); if (frame) then frame:Hide(); end if (not self.isSecondary) then if (self.Timer and PowaAuras.ModTest) then self.Timer:Hide(); end if (self.Stacks) then self.Stacks:Hide(); end local frame = PowaAuras.Frames[self.id]; if (frame) then frame:Hide(); end local secondaryAura = PowaAuras.SecondaryAuras[self.id]; if (secondaryAura) then secondaryAura:Hide(); end end self.Showing = false; end function cPowaAura:AddEffect(i) table.insert(PowaAuras.AurasByType[self.AuraType], i); end function cPowaAura:IsPlayerAura() return (not self.target) and (not self.targetfriend) and (not self.party) and (not self.raid) and (not (self.groupOrSelf and (GetNumPartyMembers()>0 or GetNumRaidMembers()>0))) and (not self.focus) and (not self.optunitn); end function cPowaAura:CheckState(giveReason) --- player aura but player is dead if (self:IsPlayerAura() and self.WeAreAlive == false) then if (not giveReason) then return false; end return false, "Player is DEAD"; end --- n'affiche pas si la cible est inexistante ou morte if ((self.target or self.targetfriend) and (UnitName("target") == nil or UnitIsDead("target") or UnitName("target") == UnitName("player")) ) then if (not giveReason) then return false; end if (UnitName("target") == nil) then return false, "no Target"; end if (UnitName("target") == UnitName("player")) then return false, "Target is you"; end return false, "Target DEAD"; end --- regarde si la cible est ennemie if (self.target and self.targetfriend == false and UnitIsFriend("player","target")) then --- cible amie alors que faut pas if (not giveReason) then return false; end return false, "Target is fiendly"; end --- party if (self.party and not ((GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0))) then --- partycheck yes, but not in party if (not giveReason) then return false; end return false, "Not in Party"; end --- focus if (self.focus and (UnitName("focus") == nil or UnitIsDead("focus") or UnitName("focus") == UnitName("player"))) then --- focuscheck if (not giveReason) then return false; end return false, "No focus"; end --- unit if (self.optunitn and not ((GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0) or UnitExists("pet"))) then --- Unitn yes, but not in party/raid or with pet if (not giveReason) then return false; end return false, "Can't find custom unit not in party, raid or with pet unit="..tostring(self.unitn); end --- raid if (self.raid and numrm == 0) then --- raidcheck yes, but not in raid if (not giveReason) then return false; end return false, "Not in raid"; end --- regarde si la cible est amie if (self.target == false and self.targetfriend and not UnitIsFriend("player","target")) then --- cible ennemie if (not giveReason) then return false; end return false, "Target not friend"; end --- dual spec check if ((not self.spec2 and PowaAuras.ActiveTalentGroup == 2) or (not self.spec1 and PowaAuras.ActiveTalentGroup == 1)) then if (not giveReason) then return false; end return false, "Aura not active for this talent spec"; end --- mode combat, cache si besoin if ((PowaAuras.WeAreInCombat == true and self.combat == 2) or (PowaAuras.WeAreInCombat == false and self.combat == 1)) then if (not giveReason) then return false; end return false, "Not in combat"; end if (PowaAuras.WeAreInRaid == false and self.isinraid == true) then if (not giveReason) then return false; end return false, "Not in raid"; end if (PowaAuras.WeAreMounted ~= self.ismounted) then if (not giveReason) then return false; end if (PowaAuras.WeAreMounted) then return false, "Mounted"; else return false, "Not Mounted"; end end if (PowaAuras.WeAreInVehicle ~= self.inVehicle) then if (not giveReason) then return false; end return false, "Not In Vehicle"; end -- It's not dead it's restin' if (self.ignoreResting and (IsResting()==1) and (not PowaAuras.WeAreInCombat)) then if (not giveReason) then return false; end return false, "Resting"; end if (not giveReason) then return true; end return true, "State OK"; end function cPowaAura:ShouldShow(giveReason, reverse) PowaAuras:UnitTestInfo("ShouldShow", self.id); local result, reason = self:CheckState(giveReason); if (result) then result, reason = self:CheckIfShouldShow(giveReason); if (result~=nil and (self.inverse or reverse) and not (self.inverse and reverse)) then result = not result; if (giveReason) then reason = reason .." (inverted)"; end end end if (result) then PowaAuras:Debug("Aura Should Show ", self.id, " because ", reason); else PowaAuras:Debug("Aura won't Show ", self.id, " because ", reason); end return result, reason; end function cPowaAura:Display() PowaAuras:Message("Aura Display id=", self.id); --OK for k,v in pairs (self) do PowaAuras:Message(" "..tostring(k).." = "..tostring(v)); --OK end end function cPowaAura:GetFrame() if (self.isSecondary) then return PowaAuras.SecondaryFrames[self.id]; end return PowaAuras.Frames[self.id]; end function cPowaAura:GetTexture() if (self.isSecondary) then return PowaAuras.SecondaryTextures[self.id]; end return PowaAuras.Textures[self.id]; end function cPowaAura:SetFrame(frame) if (self.isSecondary) then PowaAuras.SecondaryFrames[self.id] = frame; return; end PowaAuras.Frames[self.id] = frame; end function cPowaAura:SetTexture(texture) if (self.isSecondary) then PowaAuras.SecondaryTextures[self.id] = texture; return; end PowaAuras.Textures[self.id] = texture; end function cPowaAura:GetSpellNameFromMatch(spellMatch) local _, _,spellId = string.find(spellMatch, "%[(%d+)%]") if (spellId) then local spellName, rank, spellIcon = GetSpellInfo(tonumber(spellId)); return spellName, spellIcon; end return spellMatch; end function cPowaAura:SetStacks(text) local _, _,curStacksLower, curOperator, curStacks = string.find(text, "(%d*)(%D+)(%d*)") if (curStacks == nil or curStacks == "") then curStacks = "0"; end local stacks = tonumber(curStacks); PowaAuras:Debug(stacks); if (stacks ~= self.stacks) then if (stacks > 100) or (stacks < 0) then stacks = 0; end self.stacks = stacks or 0; end if (curStacksLower == nil or curStacksLower == "") then curStacksLower = "0"; end local stacksLower = tonumber(curStacksLower); PowaAuras:Debug(stacksLower); if (stacksLower ~= self.stacksLower) then if (stacksLower > 100) or (stacksLower < 0) or (stacksLower > stacks) then stacksLower = 0; end self.stacksLower = stacksLower or 0; end if (curOperator ~= self.stacksOperator) then if (not PowaAuras.allowedOperators[curOperator]) then curOperator = PowaAuras.DefaultOperator; end self.stacksOperator = curOperator; end end function cPowaAura:Trim(s) return (string.gsub(s, "^%s*(.-)%s*$", "%1")); end function cPowaAura:MatchSpell(spellName, spellTexture, textToFind) if (spellName==nil or textToFind==nil) then return false; end if (textToFind=="*") then return true; end PowaAuras:Debug(" MatchSpell spellName =",spellName); PowaAuras:Debug(" spellTexture=",spellTexture); PowaAuras:Debug(" textToFind =",textToFind); for pword in string.gmatch(textToFind, "[^/]+") do pword = self:Trim(pword); if (string.len(pword)>0) then local textToSearch; local textureMatch; if string.find(pword, "_") then _, _,textToSearch = string.find(spellTexture, "([%w_]*)$") else textToSearch = spellName; pword, textureMatch = self:GetSpellNameFromMatch(pword); end PowaAuras:Debug("textureMatch=", textureMatch); if (not textureMatch or textureMatch==spellTexture) then if (textToSearch) then if (self.ignoremaj) then textToSearch = string.upper(textToSearch) pword = string.upper(pword); end PowaAuras:Debug("pword=", pword); PowaAuras:Debug("search=", textToSearch); if (self.exact) then PowaAuras:Debug("exact=", (textToSearch == pword)); if (textToSearch == pword) then return true; end else PowaAuras:Debug("find=", string.find(textToSearch, pword, 1, true)); if (string.find(textToSearch, pword, 1, true)) then return true; end end end end end end return nil; end function cPowaAura:MatchText(textToSearch, textToFind) if (textToSearch==nil or textToFind==nil) then return false; end if (textToFind=="*") then return true; end PowaAuras:Debug("MatchText textToSearch=",textToSearch," textToFind=",textToFind); if (self.ignoremaj) then textToFind = string.upper(textToFind); textToSearch = string.upper(textToSearch); end PowaAuras:Debug("MatchText textToSearch=",textToSearch," textToFind=",textToFind, " ignoremaj=", self.ignoremaj, " exact=", self.exact); if (self.exact) then return (textToSearch == textToFind); end for pword in string.gmatch(textToFind, "[^/]+") do PowaAuras:Debug("pword=", pword," find=",string.find(textToSearch, pword, 1, true)); if (string.find(textToSearch, pword, 1, true)) then return true; end end return nil; end function cPowaAura:CreateAuraString() local tempstr, varpref= "", ""; for k, v in pairs (self) do --- multi condition checks not supported for export. if k == "multiids" then v = ""; end local varType = type(v); if (varType == "string" or varType == "boolean" or varType == "number") then tempstr = tempstr..k..":"..string.sub(varType,1,2) if (varType == "string") then tempstr = tempstr..v; else tempstr = tempstr..tostring(v); end tempstr = tempstr.."; "; end end if (self.Timer) then for k, v in pairs (self.Timer) do local varType = type(v); if (varType == "string" or varType == "boolean" or varType == "number") then tempstr = tempstr.."timer."..k..":"..string.sub(varType,1,2); if (varType == "string") then tempstr = tempstr..v; else tempstr = tempstr..tostring(v); end tempstr = tempstr.."; "; end end end if tempstr and tempstr ~= "" then tempstr = strtrim(tempstr); tempstr = string.sub(tempstr, 1, string.len(tempstr)-1); end PowaAuras:Debug("Aura-string length: "..tostring(string.len(tempstr))); return tempstr; end function cPowaAura:GetUnit() if (self.target or self.targetfriend) then return "target"; elseif (self.focus) then return "focus"; elseif (self.party) then return "party"; elseif (self.raid) then return "raid"; elseif (self.groupOrSelf) then return "groupOrSelf"; elseif (self.optunitn) then return self.unitn; else return "player"; end return nil; end function cPowaAura:CheckAllUnits(giveReason) local unit = self:GetUnit(); PowaAuras:Debug("on unit "..unit); local numpm = GetNumPartyMembers(); local numrm = GetNumRaidMembers(); if unit == "party" then for pm = 1, numpm do unit = "party"..pm; if self:CheckUnit(unit) then if (not giveReason) then return true; end return true, unit.." "..self.MatchReason; end end elseif unit == "raid" then for rm = 1, numrm do unit = "raid"..rm; if self:CheckUnit(unit) then if (not giveReason) then return true; end return true, unit.." "..self.MatchReason; end end elseif unit == "groupOrSelf" then if (numrm>0) then for rm = 1, numrm do unit = "raid"..rm; if self:CheckUnit(unit) then if (not giveReason) then return true; end return true, unit.." "..self.MatchReason; end end elseif (numpm>0) then for pm = 1, numpm do unit = "party"..pm; if self:CheckUnit(unit) then if (not giveReason) then return true; end return true, unit.." "..self.MatchReason; end end if self:CheckUnit("player") then if (not giveReason) then return true; end return true, unit.." "..self.MatchReason; end end else if self:CheckUnit(unit) then if (not giveReason) then return true; end return true, unit.." "..self.MatchReason; end end if (not giveReason) then return false; end return false, unit.." "..self.NoMatchReason; end function cPowaAura:CheckStacks(count) local operator = self.stacksOperator or PowaAuras.DefaultOperator; local stacks = self.stacks or 0; local stacksLower = self.stacksLower or 0; PowaAuras:Debug("Stack op=",operator," stacks=",stacks,"Stack Count=",count); return ((operator == "=" and stacks == 0) or (operator == ">=" and count >= stacks) or (operator == "<=" and count <= stacks) or (operator == ">" and count > stacks) or (operator == "<" and count < stacks) or (operator == "=" and count == stacks) or (operator == "-" and count >= stacksLower and count <= stacks) or (operator == "!" and count ~= stacks)); end cPowaBuffBase = PowaClass(cPowaAura, {CanHaveTimer=true, CanHaveStacks=true}); function cPowaBuffBase:AddEffect(i) if not self.target and not self.targetfriend and not self.party and not self.raid and not self.groupOrSelf and not self.focus and not self.optunitn then --- self-buff table.insert(PowaAuras.AurasByType.Buffs, i); end if self.party then --- partybuff cible table.insert(PowaAuras.AurasByType.PartyBuffs, i); end if self.focus then --- focus buffs table.insert(PowaAuras.AurasByType.FocusBuffs, i); end if self.raid then --- raid buffs table.insert(PowaAuras.AurasByType.RaidBuffs, i); end if self.groupOrSelf then --- groupOrSelf buffs table.insert(PowaAuras.AurasByType.GroupOrSelfBuffs, i); end if self.optunitn then --- unit buffs table.insert(PowaAuras.AurasByType.UnitBuffs, i); end if (self.target or self.targetfriend) then --- target buff table.insert(PowaAuras.AurasByType.TargetBuffs, i); end end function cPowaBuffBase:IsPresent(unittarget, s) PowaAuras:Debug("IsPresent on ",unittarget," buffid ",s," type", self.buffAuraType); local auraName, _, auraTexture, count, _, _, expirationTime, caster = UnitAura(unittarget, s, self.buffAuraType); if (auraName == nil) then return nil; end PowaAuras:Debug("Aura=",auraName," count=",count," expirationTime=", expirationTime," caster=",caster); if (not self:CompareAura(unittarget, s, auraName, auraTexture)) then --PowaAuras:Debug("CompareAura not found"); return false; end local isMine = (caster~=nil) and UnitExists(caster) and UnitIsUnit("player", caster); local bemine = self.mine; --PowaAuras:Message("Bemine=",bemine," isMine=",isMine); if (bemine and isMine) or (not bemine) then if (self:CheckStacks(count)) then --PowaAuras:Message("Present!"); if (self.Timer) then self.Timer.DurationInfo = expirationTime; end if (self.Stacks) then self.StackCount = count; end return true; end end return false; end function cPowaBuffBase:CheckTooltip(text, target, index) if (text==nil or string.len(text) == 0) then return true; end PowaAuras:Debug("Search in tooltip for ",text); PowaAuras_Tooltip:SetOwner(UIParent, "ANCHOR_NONE"); PowaAuras_Tooltip:SetUnitAura(target, index, self.buffAuraType); for z = 1, PowaAuras_Tooltip:NumLines() do PowaAuras:UnitTestDebug("Check tooltip line ",z); local textlinel = getglobal("PowaAuras_TooltipTextLeft"..z); local textl = textlinel:GetText(); local tooltipText = ""; if textl then tooltipText = tooltipText..textl; end local textliner = getglobal("PowaAuras_TooltipTextRight"..z); local textr = textliner:GetText(); if textr then tooltipText = tooltipText..textr; end if (tooltipText ~= "") then PowaAuras:UnitTestDebug("| "..text.." |"); if (string.find(tooltipText, text, 1, true)) then PowaAuras_Tooltip:Hide(); return true; end end end PowaAuras_Tooltip:Hide(); return false; end function cPowaBuffBase:CompareAura(target, z, auraName, auraTexture, giveReason) --PowaAuras:Debug("CompareAura",z," ",auraName, auraTexture); if self:MatchSpell(auraName, auraTexture, self.buffname) then PowaAuras:UnitTestDebug("Aura match found! ", self.id); if (not self:CheckTooltip(self.tooltipCheck, target, z)) then PowaAuras:UnitTestDebug("Tooltip no match found!"); if (not giveReason) then return false; end return false, target.." has "..self.auraType.." "..auraName.." but tooltip does not match"; end local tempicon; if (self.owntex == true) then getglobal("PowaIconTexture"):SetTexture(auraTexture); tempicon = getglobal("PowaIconTexture"):GetTexture(); if (self.icon ~= tempicon) then self.icon = tempicon; end end if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture(auraTexture); self.icon = getglobal("PowaIconTexture"):GetTexture(); end if (not giveReason) then return true; end return true, target.." has "..self.auraType.." "..auraName; end if (not giveReason) then return false; end return false, target.." does not have "..self.auraType.." "..self.buffname; end function cPowaBuffBase:CheckAllAuraSlots(target, giveReason) PowaAuras:UnitTestDebug("-------------"); PowaAuras:UnitTestDebug("CheckAllAuraSlots for ", target); for i = 1, 40 do local present = self:IsPresent(target, i); if (present==nil) then if (not giveReason) then return false; end return false, target.." doesn't have "..self.auraType.." "..self.buffname; end if (present) then PowaAuras:UnitTestDebug("CheckAllAuraSlots Present!"); if (not giveReason) then return true; end return true, target .." has "..self.auraType.." "..self.buffname; end end if (not giveReason) then return false; end return false, target.." doesn't have "..self.auraType.." "..self.buffname; end function cPowaBuffBase:CheckGroup(group, count, giveReason) for groupId = 1, count do local present = self:CheckAllAuraSlots(group..groupId, false); if (present) then if (self.groupany == true) then PowaAuras:UnitTestDebug("CheckGroup("..group..") Present!"); if (not giveReason) then return true; end return true, group..groupId .." has "..self.auraType.." "..self.buffname; end elseif (self.groupany==false) then if (not giveReason) then return false; end return false, "Not all in "..group.." has "..self.auraType.." "..self.buffname; end end if (self.groupany==false) then PowaAuras:UnitTestDebug("CheckGroup("..group..") All Present!"); if (not giveReason) then return true; end return true, "All in "..group.." has "..self.auraType.." "..self.buffname; end if (not giveReason) then return false; end return false, "No one in "..group.." has "..self.auraType.." "..self.buffname; end function cPowaBuffBase:CheckIfShouldShow(giveReason) PowaAuras:UnitTestInfo("CheckIfShouldShow ",self.buffAuraType," aura"); PowaAuras:Debug("Check " .. self.buffAuraType .. " aura"); local numpm = GetNumPartyMembers(); local numrm = GetNumRaidMembers(); --- targets if (self.target or self.targetfriend) then PowaAuras:UnitTestDebug("on target or friendlytarget"); return self:CheckAllAuraSlots("target", giveReason); end --- focus buff if self.focus then PowaAuras:UnitTestDebug("on focus"); return self:CheckAllAuraSlots("focus", giveReason); end --- unit buff if self.optunitn then PowaAuras:UnitTestDebug("on unit "..self.unitn); return self:CheckAllAuraSlots(self.unitn, giveReason); end --- raid buff if self.raid then PowaAuras:UnitTestDebug("on raid size=", numrm); return self:CheckGroup("raid", numrm, giveReason); end --- partybuff if self.party then PowaAuras:UnitTestDebug("on party size=", numpm); return self:CheckGroup("party", numpm, giveReason); end if (self.groupOrSelf) then --- Group or Self Buff PowaAuras:UnitTestDebug("on Group or Self"); if (numrm>0) then PowaAuras:UnitTestDebug("GoS on raidunit"); return self:CheckGroup("raid", numrm, giveReason); -- includes player end if (numpm>0) then PowaAuras:UnitTestDebug("GoS on partyunit or self"); local presentOnSelf, reason = self:CheckAllAuraSlots("player", giveReason); if (presentOnSelf and self.groupany) then if (not giveReason) then return true; end return true, reason; end if (not presentOnSelf and not self.groupany) then if (not giveReason) then return false; end return false, reason; end return self:CheckGroup("party", numpm, giveReason); end PowaAuras:UnitTestDebug("GoS on player"); return self:CheckAllAuraSlots("player", giveReason); end --- player buff PowaAuras:Debug("on player"); return self:CheckAllAuraSlots("player", giveReason); end cPowaBuff = PowaClass(cPowaBuffBase, {buffAuraType = "HELPFUL", auraType="buff"}); cPowaDebuff = PowaClass(cPowaBuffBase, {buffAuraType = "HARMFUL", auraType="debuff"}); cPowaTypeDebuff = PowaClass(cPowaBuffBase, {buffAuraType = "HARMFUL", auraType="debuff type"}); function cPowaTypeDebuff:IsPresent(target, z) local removeable; if (self.mine) then removeable = 1; end local name, _, texture, count, typeDebuff, _, expirationTime = UnitDebuff(target, z, removeable); if (not name) then return false; end PowaAuras:Debug("TypeDebuff IsPresent on ",target," buffid ",z," removeable ",removeable); if (self.mine and typeDebuff==nil) then return false; end PowaAuras:UnitTestDebug("Debuff ",name," type ",typeDebuff); local typeDebuffName; if (typeDebuff ~= nil) then typeDebuffName = PowaAuras.Text.DebuffType[typeDebuff]; end local typeDebuffCatName = PowaAuras.Text.DebuffCatType[PowaAuras.DebuffCatSpells[name]]; if (typeDebuffName == nil and typeDebuffCatName==nil) then typeDebuffName = PowaAuras.Text.aucun; end PowaAuras:UnitTestDebug("typeDebuffName ",typeDebuffName); PowaAuras:UnitTestDebug("typeDebuffCatName ",typeDebuffCatName); PowaAuras:UnitTestDebug("self.buffname ",self.buffname); if self:MatchText(typeDebuffName, self.buffname) or self:MatchText(typeDebuffCatName, self.buffname) then if (self.Timer) then self.Timer.DurationInfo = expirationTime; end if (self.Stacks) then self.StackCount = count; end if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture(texture); self.icon = getglobal("PowaIconTexture"):GetTexture(); end return true; end return false; end -- This is not really AoE it is periodic damage, could be a DoT or a ground effect damage cPowaAoE = PowaClass(cPowaAura, {AuraType = "Aoe"}); function cPowaAoE:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check AoE"); if (PowaAuras.DoResetAoe == true) then --- probablement mort, on reset l'effet if (not giveReason) then return false; end return false, "AoE reset"; elseif (PowaAuras.AoeAuraAdded ~= "") then --- debuff ajoute if self:MatchSpell(PowaAuras.AoeAuraAdded, PowaAuras.AoeAuraTexture, self.buffname) then if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture("Interface\\icons\\Spell_fire_meteorstorm"); self.icon = getglobal("PowaIconTexture"):GetTexture(); end if (not giveReason) then return true; end return true, "AoE Added "..self.buffname; end elseif (PowaAuras.AoeAuraFaded ~= "") then if self:MatchSpell(PowaAuras.AoeAuraFaded, PowaAuras.AoeAuraTexture, self.buffname) then if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture("Interface\\icons\\Spell_fire_meteorstorm"); self.icon = getglobal("PowaIconTexture"):GetTexture(); end if (not giveReason) then return true; end return true, "AoE Faded "..self.buffname; end end if (not self.Showing or self.HideRequest) then if (not giveReason) then return false; end return false, "AoE expired"; else if (not giveReason) then return true; end return true, "AoE active"; end end cPowaEnchant = PowaClass(cPowaAura, {AuraType = "Enchants", CanHaveTimer=true, CanHaveTimerOnInverse=true, CanHaveStacks=true, CooldownAura=true}); function cPowaEnchant:GetDuration(durationInfo) if (durationInfo and durationInfo > 0) then return durationInfo / 1000; end return 0; end function cPowaEnchant:CheckforEnchant(slot, enchantText, textToFind) PowaAuras:Debug("Check enchant ("..enchantText..") active in slot",slot); --PowaAuras:Message("Check enchant ("..enchantText..") active in slot",slot); PowaAuras_Tooltip:SetOwner(UIParent, "ANCHOR_NONE"); PowaAuras_Tooltip:SetInventoryItem("player", slot); PowaAuras:UnitTestDebug("search in tooltip for ", textToFind); --PowaAuras:Message("search in tooltip for ", textToFind); for z = 1, PowaAuras_Tooltip:NumLines() do PowaAuras:UnitTestDebug("Check tooltip line ",z); --PowaAuras:Message("Check tooltip line ",z); local textlinel = getglobal("PowaAuras_TooltipTextLeft"..z); local textl = textlinel:GetText(); local text = ""; if textl then text = text..textl; end local textliner = getglobal("PowaAuras_TooltipTextRight"..z); local textr = textliner:GetText(); if textr then text = text..textr; end if (text ~= "") then PowaAuras:UnitTestDebug("| "..text.." |"); --PowaAuras:Message("| "..text.." |"); if (self:MatchText(text, textToFind)) then PowaAuras_Tooltip:Hide(); return true; end end end PowaAuras_Tooltip:Hide(); return false; end function cPowaEnchant:SetForEnchant(loc, slot, charges, index) PowaAuras:Debug(loc,":found ",self.buffname," in the tooltip!"); if (self:CheckStacks(charges)) then if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture( GetInventoryItemTexture("player", slot) ); self.icon = getglobal("PowaIconTexture"):GetTexture(); end if (self.Stacks) then self.StackCount = count; end return true; end return false; end function cPowaEnchant:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check weapon enchant"); local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo(); local checkMain = true; local checkOff = true; for pword in string.gmatch(self.buffname, "[^/]+") do if (pword==PowaAuras.Text.mainHand) then checkMain = true; checkOff = false; elseif (pword==PowaAuras.Text.offHand) then checkOff = true; checkMain = false; else if (hasMainHandEnchant and checkMain) then if (self:CheckforEnchant(16, PowaAuras.Text.mainHand, pword)) then if (self:SetForEnchant("MH", 16, mainHandCharges, 1)) then if (self.Timer) then self.Timer.DurationInfo = mainHandExpiration; end if (self.Stacks) then self.StackCount = mainHandCharges; end if (not giveReason) then return true; end return true, "Main Hand "..self.buffname.." enchant found"; end end end if (hasOffHandEnchant and checkOff) then if (self:CheckforEnchant(17, PowaAuras.Text.offHand, pword)) then if (self:SetForEnchant("OH", 17, offHandCharges, 2)) then if (self.Timer) then self.Timer.DurationInfo = offHandExpiration; end if (self.Stacks) then self.StackCount = offHandCharges; end if (not giveReason) then return true; end return true, "Off Hand "..self.buffname.." enchant found"; end end end end end if (not giveReason) then return false; end return false, "No enchant found on weapons"; end cPowaCombo = PowaClass(cPowaAura, {AuraType = "Combo", CanHaveStacks=true}); function cPowaCombo:CheckIfShouldShow(giveReason) if (not(PowaAuras.playerclass == "ROGUE" or (PowaAuras.playerclass=="DRUID" and GetShapeshiftForm()==3))) then return nil, "You do not use combo points"; end PowaAuras:Debug("Check Combos"); local nCombo = tostring(GetComboPoints("player")); PowaAuras:UnitTestDebug("nCombo=", nCombo, " self.buffname=", self.buffname); if self:MatchText(nCombo, self.buffname) then if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture("Interface\\icons\\inv_sword_48"); self.icon = getglobal("PowaIconTexture"):GetTexture(); end if (self.Stacks) then self.StackCount = nCombo; end if (not giveReason) then return true; end return true, "Combo points "..nCombo.." match "..self.buffname; end if (not giveReason) then return false; end return false, "Combo points "..nCombo.." no match with "..self.buffname; end cPowaActionReady = PowaClass(cPowaAura, {AuraType = "Actions", CanHaveTimer=true, CanHaveTimerOnInverse=true, CooldownAura=true}); function cPowaActionReady:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check Action / Button:", self.slot); if (not self.slot or self.slot == 0) then if (not giveReason) then return false; end return false, "Action not set"; end local isUsable = IsUsableAction(self.slot); local cdstart, cdduration, enable = GetActionCooldown(self.slot); PowaAuras:UnitTestDebug("cdstart= ",cdstart," duration= ",cdduration); if (cdduration > 0.2 and cdduration < 1.7 and self.gcd == false) then if (isUsable == 1) then --- utilisable, pas de cooldown if (not giveReason) then return true; end return true, "Action Ready"; end else if (isUsable == 1 and cdstart == 0) then if (not giveReason) then return true; end return true, "Action Ready"; end end if (self.Timer) then if (enable>0) then self.Timer.DurationInfo = cdstart + cdduration; else self.Timer.DurationInfo = 0; end end if (not giveReason) then return false; end return false, "Action Not Ready, on cooldown"; end cPowaOwnSpell = PowaClass(cPowaAura, {AuraType = "OwnSpells", CanHaveTimer=true, CanHaveTimerOnInverse=true, CooldownAura=true}); function cPowaOwnSpell:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check Spell:", self.buffname); --PowaAuras:Message("Check Spell:", self.buffname); local reason = ""; for pword in string.gmatch(self.buffname, "[^/]+") do local spellName, spellIcon = self:GetSpellNameFromMatch(pword); if (self.icon == "") then if (not spellIcon) then _, _, spellIcon = GetSpellInfo(spellName); end if (spellIcon) then getglobal("PowaIconTexture"):SetTexture(spellIcon); self.icon = getglobal("PowaIconTexture"):GetTexture(); end end local show = false; local cdstart, cdduration, enabled = GetSpellCooldown(spellName); PowaAuras:UnitTestDebug("cdstart= ",cdstart," duration= ",cdduration," enabled= ",enabled); --PowaAuras:Message("cdstart= ",cdstart," duration= ",cdduration," enabled= ",enabled); if (enabled) then local isUsable = IsUsableSpell(spellName); if (cdduration > 0.2 and cdduration < 1.7 and self.gcd == false) then show = (isUsable == 1); else show = (isUsable == 1 and cdstart == 0); end --PowaAuras:Message("show= ",show," self.Timer= ",self.Timer); if (show) then --self.duration = math.max(cdstart + cdduration - GetTime(), 0) if (not giveReason) then return true; end return true, "Spell "..spellName.." usable"; else if (self.Timer) then self.Timer.DurationInfo = cdstart + cdduration; --PowaAuras:Message("Set DurationInfo= ",self.Timer.DurationInfo); end if (giveReason) then reason = reason..spellName.." not usable "; end end elseif (giveReason) then reason = reason..spellName.." not enabled " end end if (not giveReason) then return false; end if (reason == "") then return false, "Spell "..self.buffname.." not found"; end return false, reason end cPowaAuraStats = PowaClass(cPowaAura); function cPowaAuraStats:AddEffect(i) if not self.target and not self.targetfriend and not self.party and not self.raid and not self.focus and not self.optunitn then table.insert(PowaAuras.AurasByType[self.ValueName], i); end if self.optunitn then table.insert(PowaAuras.AurasByType["NamedUnit"..self.ValueName], i); end if self.focus then table.insert(PowaAuras.AurasByType["Focus"..self.ValueName], i); end if (self.target or self.targetfriend) then --- TargetHealth table.insert(PowaAuras.AurasByType["Target"..self.ValueName], i); end if self.party then table.insert(PowaAuras.AurasByType["Party"..self.ValueName], i); end if self.raid then table.insert(PowaAuras.AurasByType["Raid"..self.ValueName], i); end end function cPowaAuraStats:CheckUnit(unit) PowaAuras:Debug("CheckUnit " .. unit); if (not self:IsCorrectPowerType(unit)) then PowaAuras:UnitTestDebug("Correct powertype " ,self:IsCorrectPowerType(unit)); return nil; end if (UnitIsDeadOrGhost(unit)) then PowaAuras:UnitTestDebug("Correct powertype dead ", UnitIsDeadOrGhost(unit)); return false; end local curValue = self:UnitValue(unit); local maxValue = self:UnitValueMax(unit); PowaAuras:UnitTestDebug("curValue=", curValue, " maxValue=", maxValue); if (curValue==nil or maxValue==nil) then return false; end local curpercenthp = (curValue / maxValue) * 100; if self.thresholdinvert then thresholdvalidate = (curpercenthp > self.threshold); else thresholdvalidate = (curpercenthp < self.threshold) end if (thresholdvalidate) then if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture("Interface\\icons\\Spell_fire_meteorstorm"); self.icon = getglobal("PowaIconTexture"):GetTexture(); end return true; end return false; end function cPowaAuraStats:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check Stat "..self.ValueName); return self:CheckAllUnits(giveReason); end cPowaHealth = PowaClass(cPowaAuraStats, {ValueName = "Health", MatchReason="Health low", NoMatchReason="Health not low enough"}); function cPowaHealth:IsCorrectPowerType(unit) return true; end function cPowaHealth:UnitValue(unit) return UnitHealth(unit); end function cPowaHealth:UnitValueMax(unit) return UnitHealthMax(unit); end cPowaMana = PowaClass(cPowaAuraStats, {ValueName = "Mana", MatchReason="Mana low", NoMatchReason="Mana not low enough"}); function cPowaMana:IsCorrectPowerType(unit) local powerType = UnitPowerType(unit); return (powerType and powerType == 0); end function cPowaMana:UnitValue(unit) PowaAuras:Debug("Mana UnitValue for ", unit); return UnitPower(unit); end function cPowaMana:UnitValueMax(unit) PowaAuras:Debug("Mana UnitValueMax for ", unit); return UnitPowerMax(unit); end cPowaEnergyRagePower = PowaClass(cPowaMana, {ValueName = "RageEnergy", MatchReason="EnergyRagePower low", NoMatchReason="EnergyRagePower not low enough"}); function cPowaEnergyRagePower:IsCorrectPowerType(unit) local powerType = UnitPowerType(unit); return (powerType and powerType > 0); end cPowaAggro = PowaClass(cPowaAura, {ValueName = "Aggro", MatchReason="has aggro", NoMatchReason="does not have aggro"}); function cPowaAggro:AddEffect(i) if not self.target and not self.targetfriend and not self.party and not self.raid and not self.focus and not self.optunitn then --- self Aggro table.insert(PowaAuras.AurasByType.Aggro, i); end if self.party then --- party Aggro table.insert(PowaAuras.AurasByType.PartyAggro, i); end if self.raid then --- raid Aggro table.insert(PowaAuras.AurasByType.RaidAggro, i); end end function cPowaAggro:CheckUnit(unit) --PowaAuras:Message(unit," UnitThreatSituation=", UnitThreatSituation(unit)); return (UnitThreatSituation(unit) or -1)> 0; end function cPowaAggro:CheckIfShouldShow(giveReason) if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture("Interface\\icons\\Ability_Warrior_EndlessRage"); self.icon = getglobal("PowaIconTexture"):GetTexture(); end PowaAuras:Debug("Check Aggro status"); return self:CheckAllUnits(giveReason); end cPowaPvP = PowaClass(cPowaAura, {MatchReason="PvP flag set", NoMatchReason="PvP flag not set"}); function cPowaPvP:AddEffect(i) if not self.target and not self.targetfriend and not self.party and not self.raid and not self.focus and not self.optunitn then --- self pvp flag table.insert(PowaAuras.AurasByType.PvP, i); end if (self.target or self.targetfriend) then --- target flag table.insert(PowaAuras.AurasByType.TargetPvP, i); end if self.party then --- party pvp flagged table.insert(PowaAuras.AurasByType.PartyPvP, i); end if self.raid then --- raid pvp flagged table.insert(PowaAuras.AurasByType.RaidPvP, i); end end function cPowaPvP:CheckUnit(unit) return UnitIsPVP(unit); end function cPowaPvP:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check PvP Flag"); return self:CheckAllUnits(giveReason); end cPowaSpellAlert = PowaClass(cPowaAura); function cPowaSpellAlert:AddEffect(i) if not self.target and not self.focus then --- any enemy casts table.insert(PowaAuras.AurasByType.Spells, i); end if self.target then --- target casts table.insert(PowaAuras.AurasByType.TargetSpells, i); end if self.focus then --- focus casts table.insert(PowaAuras.AurasByType.FocusSpells, i); end end function cPowaSpellAlert:CreateSpellFrame(endtime, spellicon) local tempicon; if (self.owntex == true) then getglobal("PowaIconTexture"):SetTexture(spellicon); tempicon = getglobal("PowaIconTexture"):GetTexture(); if (self.icon ~= tempicon) then self.icon = tempicon; end end if (self.icon == "") then getglobal("PowaIconTexture"):SetTexture(spellicon); self.icon = getglobal("PowaIconTexture"):GetTexture(); end end function cPowaSpellAlert:GetDuration(durationInfo) if (durationInfo and durationInfo > 0) then return durationInfo / 1000; end return 0; end function cPowaSpellAlert:CheckUnit(unit) if not UnitExists(unit) or UnitIsDead(unit) or not UnitCanAttack(unit, "player") then PowaAuras:UnitTestDebug(unit, " exists=", UnitExists(unit), " dead=", UnitIsDeadOrGhost(unit), " hostile=", UnitCanAttack(unit, "player")); return false; end local spellname, _, _, spellicon, _, endtime = UnitCastingInfo(unit); if not spellname then spellname, _, _, spellicon, _, endtime = UnitChannelInfo(unit); end if not spellname then -- not casting PowaAuras:UnitTestDebug(unit, " is not casting"); return false; end if self:MatchSpell(spellname, spellicon, self.buffname, true) then if (self.Timer) then self.Timer.DurationInfo = endtime; end self:CreateSpellFrame(endtime, spellicon); return true; end PowaAuras:UnitTestDebug(unit, " is casting ", spellname, " no match"); return false; end function cPowaSpellAlert:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check if target/focus is casting ", self.buffname); -- Check self target/focus first if (self:CheckUnit("target")) then if (not giveReason) then return true; end return true, "Target casting "..self.buffname; end if (self:CheckUnit("focus")) then if (not giveReason) then return true; end return true, "Focus casting "..self.buffname; end --- Scan raid targets local numrm = GetNumRaidMembers(); if numrm > 0 then for i=1, numrm do if (self:CheckUnit("raid"..i.."target")) then if (not giveReason) then return true; end return true, "Raid"..i.."Target casting "..self.buffname; end end else -- Scan party targets local numpm = GetNumPartyMembers(); if numpm > 0 then for i=1, numpm do if (self:CheckUnit("party"..i.."target")) then if (not giveReason) then return true; end return true, "Party"..i.."Target casting "..self.buffname; end end end end if (not giveReason) then return false; end return false, "Nobody's target casting "..self.buffname; end cPowaStance = PowaClass(cPowaAura, {AuraType = "Stance"}); function cPowaStance:CheckIfShouldShow(giveReason) PowaAuras:Debug("Check Stance"); local nStance = GetShapeshiftForm(false); PowaAuras:UnitTestDebug("nStance = "..tostring(nStance).." / self.stance = "..tostring(self.stance)); if (nStance == self.stance and self.icon == "") then local icon = GetShapeshiftFormInfo(nStance); getglobal("PowaIconTexture"):SetTexture(icon); self.icon = getglobal("PowaIconTexture"):GetTexture(); end if (nStance == self.stance)then if (not giveReason) then return true; end return true, "Stances match"; end if (not giveReason) then return false; end return false, "Stances don't match"; end -- Concrete Classes PowaAuras.AuraClasses = { [PowaAuras.BuffTypes.Buff]=cPowaBuff, [PowaAuras.BuffTypes.Debuff]=cPowaDebuff, [PowaAuras.BuffTypes.TypeDebuff]=cPowaTypeDebuff, [PowaAuras.BuffTypes.AoE]=cPowaAoE, [PowaAuras.BuffTypes.Enchant]=cPowaEnchant, [PowaAuras.BuffTypes.Combo]=cPowaCombo, [PowaAuras.BuffTypes.ActionReady]=cPowaActionReady, [PowaAuras.BuffTypes.Health]=cPowaHealth, [PowaAuras.BuffTypes.Mana]=cPowaMana, [PowaAuras.BuffTypes.EnergyRagePower]=cPowaEnergyRagePower, [PowaAuras.BuffTypes.Aggro]=cPowaAggro, [PowaAuras.BuffTypes.PvP]=cPowaPvP, [PowaAuras.BuffTypes.SpellAlert]=cPowaSpellAlert, [PowaAuras.BuffTypes.Stance]=cPowaStance, [PowaAuras.BuffTypes.OwnSpell]=cPowaOwnSpell, } -- Instance concrete class based on type function PowaAuras:AuraFactory(auraType, id, base) local class = self.AuraClasses[auraType]; if (class) then --self:Message("AuraFactory "..tostring(auraType).." id="..tostring(id).." class="..tostring(class)); if (base == nil) then base = {}; end base.bufftype = auraType; return class(id, base); end self:Message("AuraFactory unknown "..tostring(auraType).." id="..tostring(id)); --OK return nil; end