From e199f128987cd0cc21120301f111658e0e6ad930 Mon Sep 17 00:00:00 2001 From: "Johnny C. Lam" Date: Tue, 19 Mar 2013 23:31:41 +0000 Subject: [PATCH] Fix ticket #196 - DebuffPresent(Magic) wrong with Pally buffs The problem was caused by the Buff*() and Debuff*() conditions being aliases for each other that actually just checked every aura on a target, regardless of whether it was a buff or a debuff, e.g., the following two conditions returned the same result: DebuffPresent(Magic) BuffPresent(Magic) This made it impossible to do something like the following if the player had any dispellable raid buffs: if DebuffPresent(Magic) Spell(cleanse) Fix this by splitting out the buffs and debuffs per unit into separate lists in OvaleAura and OvaleState, and teaching all of the methods that manipulate or reference the aura tables to take an additional ``filter'' argument that can be ``HELPFUL'' (buff), ``HARMFUL'' (debuff) or nil (either). Introduce a new condition parameter ``filter''. The ``filter'' parameter is used to narrow down the auras that Ovale inspects to check a condition. If specified, its valid values are ``buff'', ``debuff'' or ``any'', defaulting to ``any''. The Buff*() and Debuff*() conditions implicitly set the filter to ``buff'' or ``debuff'', respectively. git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@802 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- OvaleAura.lua | 193 +++++++++++++++++++++++++++++++--------------------- OvaleCompile.lua | 13 ++++ OvaleCondition.lua | 71 +++++++++++++------ OvaleState.lua | 107 ++++++++++++++++++----------- 4 files changed, 243 insertions(+), 141 deletions(-) diff --git a/OvaleAura.lua b/OvaleAura.lua index c8c1778..ff59f30 100644 --- a/OvaleAura.lua +++ b/OvaleAura.lua @@ -23,17 +23,22 @@ local OvalePool = Ovale.OvalePool local pairs = pairs local select = select local strfind = string.find +local API_IsHarmfulSpell = IsHarmfulSpell local API_UnitAura = UnitAura local self_baseDamageMultiplier = 1 local self_pool = OvalePool:NewPool("OvaleAura_pool") +-- self_aura[guid][filter][spellId]["mine" or "other"] = { aura properties } local self_aura = {} local self_serial = 0 -- -- -local function AddAura(unitGUID, spellId, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name, value) - local auraList = self_aura[unitGUID] +local function AddAura(unitGUID, spellId, filter, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name, value) + if not self_aura[unitGUID][filter] then + self_aura[unitGUID][filter] = {} + end + local auraList = self_aura[unitGUID][filter] if not auraList[spellId] then auraList[spellId] = {} end @@ -87,12 +92,15 @@ local function RemoveAurasForGUID(guid) -- Return all auras for the given GUID to the aura pool. if not guid or not self_aura[guid] then return end Ovale:DebugPrint("aura", "Removing auras for guid " .. guid) - for spellId, whoseTable in pairs(self_aura[guid]) do - for whose, aura in pairs(whoseTable) do - whoseTable[whose] = nil - self_pool:Release(aura) + for filter, auraList in pairs(self_aura[guid]) do + for spellId, whoseTable in pairs(auraList) do + for whose, aura in pairs(whoseTable) do + whoseTable[whose] = nil + self_pool:Release(aura) + end + auraList[spellId] = nil end - self_aura[guid][spellId] = nil + self_aura[guid][filter] = nil end self_aura[guid] = nil @@ -131,7 +139,7 @@ function OvaleAura:OnDisable() end function OvaleAura:COMBAT_LOG_EVENT_UNFILTERED(event, ...) - local time, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) + local timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) if event == "UNIT_DIED" then RemoveAurasForGUID(destGUID) @@ -146,8 +154,12 @@ function OvaleAura:COMBAT_LOG_EVENT_UNFILTERED(event, ...) end if sourceGUID == OvaleGUID:GetGUID("player") and (event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" or event == "SPELL_AURA_APPLIED_DOSE") then - if self:GetAuraByGUID(destGUID, spellId, true) then - local aura = self_aura[destGUID][spellId].mine + local filter = "HELPFUL" + if API_IsHarmfulSpell(spellName) then + filter = "HARMFUL" + end + if self:GetAuraByGUID(destGUID, spellId, filter, true) then + local aura = self_aura[destGUID][filter][spellId].mine aura.spellHasteMultiplier = OvalePaperDoll:GetSpellHasteMultiplier() end end @@ -196,25 +208,25 @@ function OvaleAura:UpdateAuras(unitId, unitGUID) local i = 1 - local mode = "HELPFUL" + local filter = "HELPFUL" local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellId local canApplyAura, isBossDebuff, isCastByPlayer, value1, value2, value3 while (true) do name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellId, - canApplyAura, isBossDebuff, isCastByPlayer, value1, value2, value3 = API_UnitAura(unitId, i, mode) + canApplyAura, isBossDebuff, isCastByPlayer, value1, value2, value3 = API_UnitAura(unitId, i, filter) if not name then - if mode == "HELPFUL" then - mode = "HARMFUL" + if filter == "HELPFUL" then + filter = "HARMFUL" i = 1 else break end else - AddAura(unitGUID, spellId, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name, value1) + AddAura(unitGUID, spellId, filter, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name, value1) if debuffType then -- TODO: not very clean -- should be computed by OvaleState:GetAura - AddAura(unitGUID, debuffType, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name, value1) + AddAura(unitGUID, debuffType, filter, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name, value1) end if unitId == "player" then @@ -225,28 +237,29 @@ function OvaleAura:UpdateAuras(unitId, unitGUID) i = i + 1 end end - + --Removes expired auras - local auraList = self_aura[unitGUID] - for spellId,whoseTable in pairs(auraList) do - for whose,aura in pairs(whoseTable) do - if aura.serial ~= self_serial then - Ovale:DebugPrint("aura", "Removing "..aura.name.." from "..whose .. ", serial = " ..self_serial.. " aura.serial = " ..aura.serial) - whoseTable[whose] = nil - self_pool:Release(aura) + for filter, auraList in pairs(self_aura[unitGUID]) do + for spellId, whoseTable in pairs(auraList) do + for whose, aura in pairs(whoseTable) do + if aura.serial ~= self_serial then + Ovale:DebugPrint("aura", "Removing " ..filter.. " " ..aura.name.. " from " ..whose.. ", serial = " ..self_serial.. " aura.serial = " ..aura.serial) + whoseTable[whose] = nil + self_pool:Release(aura) + end + end + if not next(whoseTable) then + auraList[spellId] = nil end end - if not next(whoseTable) then - Ovale:DebugPrint("aura", "Removing "..spellId) - auraList[spellId] = nil + if not next(auraList) then + self_aura[unitGUID][filter] = nil end end - - --Clear unit if all aura have been deleted - if not next(auraList) then + if not next(self_aura[unitGUID]) then self_aura[unitGUID] = nil end - + if unitId == "player" then self_baseDamageMultiplier = damageMultiplier end @@ -255,11 +268,12 @@ function OvaleAura:UpdateAuras(unitId, unitGUID) end -- Public methods -function OvaleAura:GetAuraByGUID(guid, spellId, mine, unitId) +function OvaleAura:GetAuraByGUID(guid, spellId, filter, mine, unitId) if not guid then Ovale:Log(tostring(guid) .. " does not exists in OvaleAura") return nil end + local auraTable = self_aura[guid] if not auraTable then if not unitId then @@ -277,71 +291,92 @@ function OvaleAura:GetAuraByGUID(guid, spellId, mine, unitId) return nil end end - local whoseTable = auraTable[spellId] - if not whoseTable then return nil end - local aura - if mine or mine == 1 then - aura = whoseTable.mine - elseif whoseTable.other then - aura = whoseTable.other + + local whose, aura + if filter then + if auraTable[filter] then + local whoseTable = auraTable[filter][spellId] + if whoseTable then + if mine then + aura = whoseTable.mine + else + whose, aura = next(whoseTable) + end + end + end else - aura = whoseTable.mine + local whoseTable + for _, auraList in pairs(auraTable) do + whoseTable = auraList[spellId] + if whoseTable then + if mine then + aura = whoseTable.mine + else + whose, aura = next(whoseTable) + end + if aura then break end + end + end end if not aura then return nil end return aura.start, aura.ending, aura.stacks, aura.spellHasteMultiplier, aura.value, aura.gain end -function OvaleAura:GetAura(unitId, spellId, mine) - return self:GetAuraByGUID(OvaleGUID:GetGUID(unitId), spellId, mine, unitId) +function OvaleAura:GetAura(unitId, spellId, filter, mine) + return self:GetAuraByGUID(OvaleGUID:GetGUID(unitId), spellId, filter, mine, unitId) end function OvaleAura:GetStealable(unitId) local auraTable = self_aura[OvaleGUID:GetGUID(unitId)] - if not auraTable then - return nil - end - local starting,ending - - for spellId, ownerTable in pairs(auraTable) do - local aura = ownerTable.other + if not auraTable then return nil end + + -- only buffs are stealable + local auraList = auraTable.HELPFUL + if not auraList then return nil end + + local start, ending + for spellId, whoseTable in pairs(auraList) do + local aura = whoseTable.other if aura and aura.stealable then - if not starting or aura.start < starting then - starting = aura.start + if aura.start and (not start or aura.start < start) then + start = aura.start end - if not ending or aura.ending > ending then + if aura.ending and (not ending or aura.ending > ending) then ending = aura.ending end end end - return starting, ending + return start, ending end -- Look for the last of my aura on any targt that will expires. -- Returns its expiration time -function OvaleAura:GetExpirationTimeOnAnyTarget(spellId, excludingTarget) - local ending = nil - local starting = nil +function OvaleAura:GetExpirationTimeOnAnyTarget(spellId, filter, excludingTarget) + local start, ending local count = 0 - - for unitId,auraTable in pairs(self_aura) do - if unitId ~= excludingTarget then - if auraTable[spellId] then - local aura = auraTable[spellId].mine - if aura then - local newEnding = aura.ending - local newStarting = aura.start - if newStarting and (not starting or newStarting < starting) then - starting = newStarting - end - if newEnding and (not ending or newEnding > ending) then - ending = newEnding + + local aura + for guid, auraTable in pairs(self_aura) do + if guid ~= excludingTarget then + for auraFilter, auraList in pairs(auraTable) do + if not filter or auraFilter == filter then + if auraList[spellId] then + aura = auraList[spellId].mine + if aura then + if aura.start and (not start or aura.start < start) then + start = aura.start + end + if aura.ending and (not ending or aura.ending > ending) then + ending = aura.ending + end + count = count + 1 + end end - count = count + 1 end - end + end end end - return starting, ending, count + return start, ending, count end function OvaleAura:GetDamageMultiplier(spellId) @@ -355,7 +390,7 @@ function OvaleAura:GetDamageMultiplier(spellId) if auraTable then for filter, filterInfo in pairs(si.damageAura) do for auraSpellId, multiplier in pairs(filterInfo) do - if auraTable[auraSpellId] then + if auraTable[filter] and auraTable[filter][auraSpellId] then damageMultiplier = damageMultiplier * multiplier end end @@ -368,14 +403,14 @@ end function OvaleAura:Debug() self_pool:Debug() - for guid,auraTable in pairs(self_aura) do - Ovale:Print("***"..guid) - for spellId,whoseTable in pairs(auraTable) do - for whose,aura in pairs(whoseTable) do - Ovale:Print(guid.." "..whose.." "..spellId .. " "..aura.name .. " stacks ="..aura.stacks) + for guid, auraTable in pairs(self_aura) do + for filter, auraList in pairs(auraTable) do + for spellId, whoseTable in pairs(auraList) do + for whose, aura in pairs(whoseTable) do + Ovale:Print(guid.. " " ..filter.. " " ..whose.. " " ..spellId.. " " ..aura.name.. " stacks=" ..aura.stacks) + end end end end - Ovale:Print("------") end -- diff --git a/OvaleCompile.lua b/OvaleCompile.lua index c914355..58c482f 100644 --- a/OvaleCompile.lua +++ b/OvaleCompile.lua @@ -198,6 +198,19 @@ local function ParseFunction(prefix, func, params) func = strlower(func) + -- "debuff" and "buff" conditions implicitly set their aura filter. + if not paramList.filter then + if strfind(func, "debuff") == 1 then + paramList.filter = "debuff" + elseif strfind(func, "buff") == 1 then + paramList.filter = "buff" + elseif strfind(func, "otherdebuff") == 1 then + paramList.filter = "debuff" + elseif strfind(func, "otherbuff") == 1 then + paramList.filter = "buff" + end + end + local node = self_pool:Get() node.type = "function" node.func = func diff --git a/OvaleCondition.lua b/OvaleCondition.lua index 0e39e9c..78dabd8 100644 --- a/OvaleCondition.lua +++ b/OvaleCondition.lua @@ -178,6 +178,17 @@ local function getTarget(condition) end end +local function getFilter(condition) + if condition.filter then + if condition.filter == "debuff" then + return "HARMFUL" + elseif condition.filter == "buff" then + return "HELPFUL" + end + end + return nil +end + local function addTime(time1, duration) if not time1 then return nil @@ -209,11 +220,11 @@ end -- that can be on any unit except the target -- Returns the first to expires, the last to expires -- Returns nil if the debuff is not present -local function getOtherAura(spellId, suppTime, excludingTarget) +local function getOtherAura(spellId, filter, suppTime, excludingTarget) if excludingTarget then excludingTarget = OvaleGUID:GetGUID(excludingTarget) end - return OvaleState:GetExpirationTimeOnAnyTarget(spellId, excludingTarget) + return OvaleState:GetExpirationTimeOnAnyTarget(spellId, filter, excludingTarget) end local function GetRuneCount(type, death) @@ -283,14 +294,14 @@ local function testValue(comparator, limit, value, atTime, rate) end end -local function getAura(target, spellId, mine) +local function getAura(target, spellId, filter, mine) if type(spellId) == "number" then - return OvaleState:GetAura(target, spellId, mine) + return OvaleState:GetAura(target, spellId, filter, mine) elseif OvaleData.buffSpellList[spellId] then local newStart, newEnding, newStacks, newSpellHasteMultiplier, newValue, newGain local start, ending, stacks, spellHasteMultiplier, value, gain for _, v in pairs(OvaleData.buffSpellList[spellId]) do - start, ending, stacks, spellHasteMultiplier, value, gain = OvaleState:GetAura(target, v, mine) + start, ending, stacks, spellHasteMultiplier, value, gain = OvaleState:GetAura(target, v, filter, mine) if start and (not newStart or stacks > newStacks) then newStart = start newEnding = ending @@ -302,7 +313,7 @@ local function getAura(target, spellId, mine) end return newStart, newEnding, newStacks, newSpellHasteMultiplier, newValue, newGain elseif spellId == "Magic" or spellId == "Disease" or spellId == "Curse" or spellId == "Poison" then - return OvaleState:GetAura(target, spellId, mine) + return OvaleState:GetAura(target, spellId, filter, mine) end end @@ -334,7 +345,7 @@ local function GetTargetAura(condition, target) local spellId = condition[1] local mine = getMine(condition) - local auraStart, auraEnding, auraStacks, auraSpellHasteMultiplier, auraValue, auraGain = getAura(target, spellId, mine) + local auraStart, auraEnding, auraStacks, auraSpellHasteMultiplier, auraValue, auraGain = getAura(target, spellId, getFilter(condition), mine) if not auraStart then Ovale:Log("Aura "..spellId.." not found on " .. target .. " mine=" .. tostring(mine)) return 0,0,0,0 @@ -515,7 +526,7 @@ end -- @see DebuffCount OvaleCondition.conditions.buffcount = function(condition) - local start, ending, count = OvaleState:GetExpirationTimeOnAnyTarget(condition[1]) + local start, ending, count = OvaleState:GetExpirationTimeOnAnyTarget(condition[1], getFilter(condition)) return start, ending, count, 0, 0 end OvaleCondition.conditions.debuffcount = OvaleCondition.conditions.buffcount @@ -1598,7 +1609,7 @@ OvaleCondition.conditions.isstunned = function(condition) end --- Get the damage done by the most recent damage event for the given spell. --- If the spell is a damage-over-time (DoT) aura, then it gives the damage done by the most recent tick. +-- If the spell is a periodic aura, then it gives the damage done by the most recent tick. -- @name LastSpellDamage -- @paramsig number or boolean -- @param id The spell ID. @@ -1969,10 +1980,13 @@ OvaleCondition.conditions.nextswing = function(condition) return 0, nil, 0, OvaleSwing:GetNext(condition[1]), 0, -1 end ---- Get the number of seconds until the next tick of a damage-over-time (DoT) aura on the target. +--- Get the number of seconds until the next tick of a periodic aura on the target. -- @name NextTick -- @paramsig number -- @param id The aura spell ID. +-- @param filter Optional. The type of aura to check. +-- Default is any. +-- Valid values: any, buff, debuff -- @param target Optional. Sets the target to check. The target may also be given as a prefix to the condition. -- Defaults to target=player. -- Valid values: player, target, focus, pet. @@ -1995,35 +2009,39 @@ end -- 1: spell id -- return: bool -- alias: otherauraexpires -OvaleCondition.conditions.otherdebuffexpires = function(condition) - local minTime, maxTime = getOtherAura(condition[1], condition[3], "target") +OvaleCondition.conditions.otherauraexpires = function(condition) + local minTime, maxTime = getOtherAura(condition[1], getFilter(condition), condition[3], "target") if minTime then local timeBefore = condition[2] or 0 return minTime - timeBefore, nil end return 0, nil end -OvaleCondition.conditions.otherauraexpires = OvaleCondition.conditions.otherdebuffexpires +OvaleCondition.conditions.otherbuffexpires = OvaleCondition.conditions.otherauraexpires +OvaleCondition.conditions.otherdebuffexpires = OvaleCondition.conditions.otherauraexpires -- Check if the aura is present on any other unit than the current target -- return: bool -- alias: otheraurapresent -OvaleCondition.conditions.otherdebuffpresent = function(condition) - local minTime, maxTime = getOtherAura(condition[1], condition[3], "target") +OvaleCondition.conditions.otheraurapresent = function(condition) + local minTime, maxTime = getOtherAura(condition[1], getFilter(condition), condition[3], "target") if maxTime and maxTime>0 then local timeBefore = condition[2] or 0 return 0, addTime(maxTime, -timeBefore) end return nil end -OvaleCondition.conditions.otheraurapresent = OvaleCondition.conditions.otherdebuffpresent +OvaleCondition.conditions.otherbuffpresent = OvaleCondition.conditions.otheraurapresent +OvaleCondition.conditions.otherdebuffpresent = OvaleCondition.conditions.otheraurapresent -- Get the maximum aura remaining duration on any target -- return: number OvaleCondition.conditions.otherauraremains = function(condition) - local minTime, maxTime = getOtherAura(condition[1]) + local minTime, maxTime = getOtherAura(condition[1], getFilter(condition)) return 0, nil, 0, maxTime, -1 end +OvaleCondition.conditions.otherbuffremains = OvaleCondition.conditions.otherauraremains +OvaleCondition.conditions.otherdebuffremains = OvaleCondition.conditions.otherauraremains --- Test if the target exists and is alive. -- @name Present @@ -2486,11 +2504,14 @@ OvaleCondition.conditions.threat = function(condition) return compare(threatpct, condition[1], condition[2]) end ---- Get the current tick value of a damage-over-time (DoT) aura on the target. +--- Get the current tick value of a periodic aura on the target. -- @name TickValue -- @paramsig number or boolean -- @param id The aura spell ID. -- @param operator Optional. Comparison operator: equal, less, more. +-- @param filter Optional. The type of aura to check. +-- Default is any. +-- Valid values: any, buff, debuff -- @param number Optional. The number to compare against. -- @param target Optional. Sets the target to check. The target may also be given as a prefix to the condition. -- Defaults to target=player. @@ -2503,11 +2524,11 @@ end -- Spell(purifying_brew) OvaleCondition.conditions.tickvalue = function(condition) - local value = select(5, getAura(getTarget(condition.target), condition[1], getMine(condition))) or 0 + local value = select(5, getAura(getTarget(condition.target), condition[1], getFilter(condition), getMine(condition))) or 0 return compare(value, condition[2], condition[3]) end ---- Get the estimated total number of ticks of a damage-over-time (DoT) aura. +--- Get the estimated total number of ticks of a periodic aura. -- @name Ticks -- @paramsig number or boolean -- @param id The aura spell ID. @@ -2539,10 +2560,13 @@ OvaleCondition.conditions.ticksadded = function(condition) return 0, nil, 0, 0, 0 end ---- Get the remaining number of ticks of a damage-over-time (DoT) aura on a target. +--- Get the remaining number of ticks of a periodic aura on a target. -- @name TicksRemain -- @paramsig number -- @param id The aura spell ID. +-- @param filter Optional. The type of aura to check. +-- Default is any. +-- Valid values: any, buff, debuff -- @param target Optional. Sets the target to check. The target may also be given as a prefix to the condition. -- Defaults to target=player. -- Valid values: player, target, focus, pet. @@ -2561,12 +2585,15 @@ OvaleCondition.conditions.ticksremain = function(condition) return nil end ---- Get the number of seconds between ticks of a damage-over-time (DoT) aura on a target. +--- Get the number of seconds between ticks of a periodic aura on a target. -- @name TickTime -- @paramsig number or boolean -- @param id The aura spell ID. -- @param operator Optional. Comparison operator: equal, less, more. -- @param number Optional. The number to compare against. +-- @param filter Optional. The type of aura to check. +-- Default is any. +-- Valid values: any, buff, debuff -- @param target Optional. Sets the target to check. The target may also be given as a prefix to the condition. -- Defaults to target=player. -- Valid values: player, target, focus, pet. diff --git a/OvaleState.lua b/OvaleState.lua index f6afa68..4aff7eb 100644 --- a/OvaleState.lua +++ b/OvaleState.lua @@ -110,7 +110,7 @@ function OvaleState:UpdatePowerRates() end -- Blade Flurry (combat rogue) - if OvaleState:GetAura("player", 13877, true) then + if OvaleState:GetAura("player", 13877, "HELPFUL", true) then energyRegen = energyRegen * 0.8 end @@ -120,7 +120,7 @@ function OvaleState:UpdatePowerRates() end -- Adrenaline Rush (rogue) - if OvaleState:GetAura("player", 13750, true) then + if OvaleState:GetAura("player", 13750, "HELPFUL", true) then energyRegen = energyRegen * 2 end end @@ -246,7 +246,7 @@ function OvaleState:AddSpellToStack(spellId, startCast, endCast, nextCast, nocd, -- Add extra resource generated by presence of a buff. local buffParam = "buff_" .. tostring(k) local buffAmoumtParam = buffParam .. "_amount" - if newSpellInfo[k] < 0 and newSpellInfo[buffParam] and self:GetAura("player", newSpellInfo[buffParam], true) then + if newSpellInfo[k] < 0 and newSpellInfo[buffParam] and self:GetAura("player", newSpellInfo[buffParam], nil, true) then local buffAmount = newSpellInfo[buffAmountParam] or 1 self.state[k] = self.state[k] + buffAmount end @@ -271,7 +271,7 @@ function OvaleState:AddSpellToStack(spellId, startCast, endCast, nextCast, nocd, elseif newSpellInfo.combo > 0 then self.state.combo = self.state.combo + newSpellInfo.combo -- Add extra combo points generated by presence of a buff. - if newSpellInfo.buff_combo and self:GetAura("player", newSpellInfo.buff_combo, true) then + if newSpellInfo.buff_combo and self:GetAura("player", newSpellInfo.buff_combo, nil, true) then local buffAmount = newSpellInfo.buff_combo_amount or 1 self.state.combo = self.state.combo + buffAmount end @@ -315,7 +315,7 @@ function OvaleState:AddSpellToStack(spellId, startCast, endCast, nextCast, nocd, end --On vérifie si le buff "buffnocd" est présent, auquel cas le CD du sort n'est pas déclenché if newSpellInfo.buffnocd and not nocd then - local buffStart, buffEnding, buffStacks = self:GetAura("player", newSpellInfo.buffnocd, true) + local buffStart, buffEnding, buffStacks = self:GetAura("player", newSpellInfo.buffnocd, nil, true) if self.traceAura then if buffStart then Ovale:Print("buffnocd stacks = "..tostring(buffStacks).." start="..tostring(buffStart).." ending = "..tostring(buffEnding)) @@ -394,8 +394,8 @@ function OvaleState:AddSpellToStack(spellId, startCast, endCast, nextCast, nocd, stacks = 1 end - local oldStart, oldEnding, oldStacks, oldSpellHasteMultiplier = self:GetAuraByGUID(auraGUID, auraSpellId, true, target) - local newAura = self:NewAura(auraGUID, auraSpellId) + local oldStart, oldEnding, oldStacks, oldSpellHasteMultiplier = self:GetAuraByGUID(auraGUID, auraSpellId, true, filter, target) + local newAura = self:NewAura(auraGUID, auraSpellId, filter) newAura.mine = true @@ -510,69 +510,96 @@ function OvaleState:GetComputedSpellCD(spellId) end function OvaleState:AddEclipse(endCast, spellId) - local newAura = self:NewAura(OvaleGUID:GetGUID("player"), spellId) + local newAura = self:NewAura(OvaleGUID:GetGUID("player"), spellId, "HELPFUL") newAura.start = endCast + 0.5 newAura.stacks = 1 newAura.ending = nil end -function OvaleState:GetAuraByGUID(guid, spellId, mine, target) - if self.aura[guid] and self.aura[guid][spellId] and self.aura[guid][spellId].serial == self.serial then - Ovale:Log("Found aura " .. spellId .. " on " .. tostring(guid)) - local aura = self.aura[guid][spellId] +function OvaleState:GetAuraByGUID(guid, spellId, filter, mine, target) + local aura + if mine then + local auraTable = self.aura[guid] + if auraTable then + if filter then + local auraList = auraTable[filter] + if auraList then + if auraList[spellId] and auraList[spellId].serial == self.serial then + aura = auraList[spellId] + end + end + else + for auraFilter, auraList in pairs(auraTable) do + if auraList[spellId] and auraList[spellId].serial == self.serial then + aura = auraList[spellId] + filter = auraFilter + break + end + end + end + end + end + if aura then + Ovale:Log("Found " .. filter .. " aura " .. spellId .. " on " .. tostring(guid)) return aura.start, aura.ending, aura.stacks, aura.spellHasteMultiplier, aura.value, aura.gain else Ovale:Log("Aura " .. spellId .. " not found in state for " .. tostring(guid)) - return OvaleAura:GetAuraByGUID(guid, spellId, mine, target) + return OvaleAura:GetAuraByGUID(guid, spellId, filter, mine, target) end end -function OvaleState:GetAura(target, spellId, mine) - return self:GetAuraByGUID(OvaleGUID:GetGUID(target), spellId, mine, target) +function OvaleState:GetAura(target, spellId, filter, mine) + return self:GetAuraByGUID(OvaleGUID:GetGUID(target), spellId, filter, mine, target) end -function OvaleState:GetExpirationTimeOnAnyTarget(spellId, excludingTarget) - local starting, ending, count = OvaleAura:GetExpirationTimeOnAnyTarget(spellId, excludingTarget) - for unitId,auraTable in pairs(self.aura) do - if unitId ~= excludingTarget then - local aura = auraTable[spellId] - if aura and aura.serial == self.serial then - local newEnding = aura.ending - local newStarting = aura.start - if newStarting and (not starting or newStarting < starting) then - starting = newStarting - end - if newEnding and (not ending or newEnding > ending) then - ending = newEnding +function OvaleState:GetExpirationTimeOnAnyTarget(spellId, filter, excludingTarget) + local start, ending, count = OvaleAura:GetExpirationTimeOnAnyTarget(spellId, filter, excludingTarget) + local aura + for guid, auraTable in pairs(self.aura) do + if guid ~= excludingTarget then + for auraFilter, auraList in pairs(auraTable) do + if not filter or auraFilter == filter then + aura = auraList[spellId] + if aura and aura.serial == self.serial then + if aura.start and (not start or aura.start < start) then + start = aura.start + end + if aura.ending and (not ending or aura.ending > ending) then + ending = aura.ending + end + count = count + 1 + end end - count = count + 1 end end end - return starting, ending, count + return start, ending, count end -function OvaleState:NewAura(guid, spellId) +function OvaleState:NewAura(guid, spellId, filter) if not self.aura[guid] then self.aura[guid] = {} end - if not self.aura[guid][spellId] then - self.aura[guid][spellId] = {} + if not self.aura[guid][filter] then + self.aura[guid][filter] = {} + end + if not self.aura[guid][filter][spellId] then + self.aura[guid][filter][spellId] = {} end - local myAura = self.aura[guid][spellId] - myAura.serial = self.serial - myAura.mine = true - myAura.gain = self.currentTime - return myAura + local aura = self.aura[guid][filter][spellId] + aura.serial = self.serial + aura.mine = true + aura.gain = self.currentTime + return aura end function OvaleState:GetEclipseDir() - local stacks = select(3, self:GetAura("player", 48517)) -- Solar + local stacks = select(3, self:GetAura("player", 48517, "HELPFUL")) -- Solar if stacks and stacks > 0 then return -1 else - stacks = select(3, self:GetAura("player", 48518)) --Lunar + stacks = select(3, self:GetAura("player", 48518, "HELPFUL")) --Lunar if stacks and stacks > 0 then return 1 elseif self.state.eclipse < 0 then -- 1.7.9.5