Johnny C. Lam [03-28-13 - 04:33]
diff --git a/OvaleAura.lua b/OvaleAura.lua
index 40338de..f1a9a2a 100644
--- a/OvaleAura.lua
+++ b/OvaleAura.lua
@@ -26,7 +26,6 @@ local select = select
local strfind = string.find
local tinsert = table.insert
local tsort = table.sort
-local API_IsHarmfulSpell = IsHarmfulSpell
local API_UnitAura = UnitAura
local self_pool = OvalePool:NewPool("OvaleAura_pool")
@@ -48,21 +47,25 @@ local function AddAura(unitGUID, spellId, filter, unitCaster, icon, count, debuf
-- Re-use existing aura by updating its serial number and adding new information
-- if it differs from the old aura.
local mine = (unitCaster == "player")
- local aura
+ local aura, oldAura
if mine then
- if not auraList[spellId].mine then
+ oldAura = auraList[spellId].mine
+ if oldAura then
+ aura = oldAura
+ else
aura = self_pool:Get()
aura.gain = Ovale.now
auraList[spellId].mine = aura
end
- aura = auraList[spellId].mine
else
- if not auraList[spellId].other then
+ oldAura = auraList[spellId].other
+ if oldAura then
+ aura = oldAura
+ else
aura = self_pool:Get()
aura.gain = Ovale.now
auraList[spellId].other = aura
end
- aura = auraList[spellId].other
end
aura.serial = self_serial
@@ -70,7 +73,8 @@ local function AddAura(unitGUID, spellId, filter, unitCaster, icon, count, debuf
count = 1
end
- if not aura.ending or aura.ending < expirationTime or aura.stacks ~= count then
+ local isSameAura = oldAura and oldAura.duration == duration and oldAura.ending == expirationTime and oldAura.stacks == count
+ if not isSameAura and not aura.ending or aura.ending < expirationTime or aura.stacks ~= count then
aura.icon = icon
aura.stacks = count
aura.debuffType = debuffType
@@ -87,6 +91,13 @@ local function AddAura(unitGUID, spellId, filter, unitCaster, icon, count, debuf
aura.source = unitCaster
aura.name = name
aura.value = value
+ if mine then
+ -- This is a new or refreshed aura applied by the player, so set the tick information if needed.
+ local si = OvaleData.spellInfo[spellId]
+ if si and si.tick then
+ aura.tick = OvaleData:GetTickLength(spellId)
+ end
+ end
end
end
@@ -224,24 +235,11 @@ function OvaleAura:COMBAT_LOG_EVENT_UNFILTERED(event, ...)
RemoveAurasForGUID(destGUID)
elseif strfind(event, "SPELL_AURA_") == 1 then
-- KNOWN BUG: an aura refreshed by a spell other than then one that applies it won't cause the CLEU event to fire.
- local spellId, spellName, spellSchool, auraType = select(12, ...)
-
-- Only update for "*target" unit IDs. All others are handled by UNIT_AURA event handler.
local unitId = OvaleGUID:GetUnitId(destGUID)
if unitId and unitId ~= "target" and strfind(unitId, "target") then
UpdateAuras(unitId, destGUID)
end
-
- if sourceGUID == OvaleGUID:GetGUID("player") and (event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" or event == "SPELL_AURA_APPLIED_DOSE") then
- 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
end
end
@@ -313,7 +311,7 @@ function OvaleAura:GetAuraByGUID(guid, spellId, filter, mine, unitId)
end
end
if not aura then return nil end
- return aura.start, aura.ending, aura.stacks, aura.spellHasteMultiplier, aura.value, aura.gain
+ return aura.start, aura.ending, aura.stacks, aura.tick, aura.value, aura.gain
end
function OvaleAura:GetAura(unitId, spellId, filter, mine)
@@ -321,19 +319,19 @@ function OvaleAura:GetAura(unitId, spellId, filter, mine)
if type(spellId) == "number" then
return self:GetAuraByGUID(guid, spellId, filter, mine, unitId)
elseif OvaleData.buffSpellList[spellId] then
- local newStart, newEnding, newStacks, newSpellHasteMultiplier, newValue, newGain
+ local newStart, newEnding, newStacks, newTick, newValue, newGain
for _, v in pairs(OvaleData.buffSpellList[spellId]) do
- local start, ending, stacks, spellHasteMultiplier, value, gain = self:GetAuraByGUID(guid, v, filter, mine, unitId)
+ local start, ending, stacks, tick, value, gain = self:GetAuraByGUID(guid, v, filter, mine, unitId)
if start and (not newStart or stacks > newStacks) then
newStart = start
newEnding = ending
newStacks = stacks
- newSpellHasteMultiplier = spellHasteMultiplier
+ newTick = tick
newValue = value
newGain = gain
end
end
- return newStart, newEnding, newStacks, newSpellHasteMultiplier, newValue, newGain
+ return newStart, newEnding, newStacks, newTick, newValue, newGain
elseif spellId == "Magic" or spellId == "Disease" or spellId == "Curse" or spellId == "Poison" then
return self:GetAuraByGUID(guid, spellId, filter, mine, unitId)
end
@@ -426,7 +424,7 @@ function OvaleAura:Debug()
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)
+ Ovale:Print(guid.. " " ..filter.. " " ..whose.. " " ..spellId.. " " ..aura.name.. " stacks=" ..aura.stacks.. " tick=" ..tostring(aura.tick))
end
end
end
diff --git a/OvaleCondition.lua b/OvaleCondition.lua
index 95bdc01..dabf5cd 100644
--- a/OvaleCondition.lua
+++ b/OvaleCondition.lua
@@ -310,8 +310,8 @@ local function getMine(condition)
return true
end
--- Recherche un aura sur la cible et récupère sa durée et le nombre de stacks
--- return start, ending, stacks, spellHasteMultiplier
+-- Front-end for OvaleState:GetAura() using condition parameters.
+-- return start, ending, stacks, tick, value, gain
local function GetAura(condition)
local unitId = getTarget(condition)
local spellId = condition[1]
@@ -320,21 +320,21 @@ local function GetAura(condition)
if not spellId then
Ovale:Log("GetAura: nil spellId")
- return 0, 0, 0, 0, 0, 0
+ return nil
end
- local start, ending, stacks, spellHasteMultiplier, value, gain = OvaleState:GetAura(unitId, spellId, filter, mine)
+ local start, ending, stacks, tick, value, gain = OvaleState:GetAura(unitId, spellId, filter, mine)
if not start then
Ovale:Log("GetAura: aura " .. tostring(spellId) .. " not found on " .. unitId .. " filter=" .. tostring(filter) .. " mine=" .. tostring(mine))
- return 0, 0, 0, 0, 0, 0
+ return nil
end
local conditionStacks = condition.stacks or 1
if stacks and stacks < conditionStacks then
Ovale:Log("GetAura: aura " .. tostring(spellId) .. " found on " .. unitId .. " but stacks " .. stacks .. " < " .. conditionStacks)
- return 0, 0, 0, 0, 0, 0
+ return nil
end
Ovale:Log("GetAura: aura " .. tostring(spellId) .. " found on " .. unitId .. " start=" .. tostring(start) .. " ending=" .. tostring(ending) .. " stacks=" .. tostring(stacks) .. "/" .. conditionStacks)
- return start, ending, stacks, spellHasteMultiplier, value, gain
+ return start, ending, stacks, tick, value, gain
end
-- Returns:
@@ -562,10 +562,13 @@ OvaleCondition.conditions.debuffduration = OvaleCondition.conditions.buffduratio
OvaleCondition.conditions.buffexpires = function(condition)
local start, ending = GetAura(condition)
+ if not start then
+ ending = 0
+ end
local timeBefore = avecHate(condition[2], condition.haste)
if Ovale.trace then
Ovale:Print("timeBefore = " .. tostring(timeBefore))
- Ovale:Print("start = " .. tostring(ending))
+ Ovale:Print("ending = " .. tostring(ending))
end
return addTime(ending, -timeBefore)
end
@@ -635,6 +638,9 @@ OvaleCondition.conditions.debuffgain = OvaleCondition.conditions.buffgain
OvaleCondition.conditions.buffpresent = function(condition)
local start, ending = GetAura(condition)
+ if not start then
+ start, ending = 0, 0
+ end
local timeBefore = avecHate(condition[2], condition.haste)
return start, addTime(ending, -timeBefore)
end
@@ -660,6 +666,7 @@ OvaleCondition.conditions.debuffpresent = OvaleCondition.conditions.buffpresent
OvaleCondition.conditions.buffstacks = function(condition)
local start, ending, stacks = GetAura(condition)
+ stacks = stacks or 0
return start, ending, stacks, 0, 0
end
OvaleCondition.conditions.debuffstacks = OvaleCondition.conditions.buffstacks
@@ -1957,7 +1964,7 @@ end
--- 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 id The spell ID of the aura or the name of a spell list.
-- @param filter Optional. The type of aura to check.
-- Default is any.
-- Valid values: any, buff, debuff
@@ -1968,11 +1975,10 @@ end
-- @see Ticks, TicksRemain, TickTime
OvaleCondition.conditions.nexttick = function(condition)
- local start, ending, _, spellHasteMultiplier = GetAura(condition)
- local tickLength = OvaleData:GetTickLength(condition[1], spellHasteMultiplier)
- if ending and tickLength then
- while ending - tickLength > OvaleState.currentTime do
- ending = ending - tickLength
+ local start, ending, _, tick = GetAura(condition)
+ if ending and tick then
+ while ending - tick > OvaleState.currentTime do
+ ending = ending - tick
end
return 0, nil, 0, ending, -1
end
@@ -2512,7 +2518,7 @@ end
--- 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 id The spell ID of the aura or the name of a spell list.
-- @param operator Optional. Comparison operator: equal, less, more.
-- @param filter Optional. The type of aura to check.
-- Default is any.
@@ -2536,7 +2542,7 @@ end
--- Get the estimated total number of ticks of a periodic aura.
-- @name Ticks
-- @paramsig number or boolean
--- @param id The aura spell ID.
+-- @param id The spell ID of the aura or the name of a spell list.
-- @param operator Optional. Comparison operator: equal, less, more.
-- @param number Optional. The number to compare against.
-- @return The number of ticks.
@@ -2544,14 +2550,25 @@ end
-- @see NextTick, TicksRemain, TickTime
OvaleCondition.conditions.ticks = function(condition)
- -- TODO: extend to allow checking an existing DoT (how to get DoT duration?)
- local spellId = condition[1]
- local duration, tickLength = OvaleData:GetDuration(spellId, OvalePaperDoll:GetSpellHasteMultiplier(), OvaleState.state.combo, OvaleState.state.holy)
- if tickLength then
- local numTicks = floor(duration / tickLength + 0.5)
+ local start, ending, _, tick = GetAura(condition)
+ local duration, numTicks
+ if start then
+ -- Aura exists on the target
+ if ending and tick and tick > 0 then
+ duration = ending - start
+ numTicks = floor(duration / tick + 0.5)
+ end
+ else
+ duration, tick = OvaleData:GetDuration(condition[1], OvaleState.state.combo, OvaleState.state.holy)
+ if duration and tick and tick > 0 then
+ numTicks = floor(duration / tick + 0.5)
+ end
+ end
+ if numTicks then
return compare(numTicks, condition[2], condition[3])
+ else
+ return nil
end
- return nil
end
--- Get the number of ticks that would be added if the dot is refreshed.
@@ -2568,7 +2585,7 @@ end
--- Get the remaining number of ticks of a periodic aura on a target.
-- @name TicksRemain
-- @paramsig number
--- @param id The aura spell ID.
+-- @param id The spell ID of the aura or the name of a spell list.
-- @param filter Optional. The type of aura to check.
-- Default is any.
-- Valid values: any, buff, debuff
@@ -2582,10 +2599,9 @@ end
-- Spell(shadow_word_pain)
OvaleCondition.conditions.ticksremain = function(condition)
- local start, ending, _, spellHasteMultiplier = GetAura(condition)
- local tickLength = OvaleData:GetTickLength(condition[1], spellHasteMultiplier)
- if ending and tickLength then
- return 0, nil, 1, ending, -1/tickLength
+ local start, ending, _, tick = GetAura(condition)
+ if ending and tick and tick > 0 then
+ return 0, nil, 1, ending, -1/tick
end
return nil
end
@@ -2593,7 +2609,7 @@ end
--- 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 id The spell ID of the aura or the name of a spell list.
-- @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.
@@ -2607,15 +2623,15 @@ end
-- @see NextTick, Ticks, TicksRemain
OvaleCondition.conditions.ticktime = function(condition)
- local start, ending, _, spellHasteMultiplier = GetAura(condition)
- if not start or not ending or start > OvaleState.currentTime or ending < OvaleState.currentTime then
- spellHasteMultiplier = OvalePaperDoll:GetSpellHasteMultiplier()
+ local start, ending, _, tick = GetAura(condition)
+ if not tick then
+ tick = OvaleData:GetTickLength(condition[1])
end
- local tickLength = OvaleData:GetTickLength(condition[1], spellHasteMultiplier)
- if tickLength then
- return compare(tickLength, condition[2], condition[3])
+ if tick then
+ return compare(tick, condition[2], condition[3])
+ else
+ return nil
end
- return nil
end
--- Get the number of seconds elapsed since the player entered combat.
diff --git a/OvaleData.lua b/OvaleData.lua
index 1206945..36313d9 100644
--- a/OvaleData.lua
+++ b/OvaleData.lua
@@ -577,11 +577,21 @@ function OvaleData:GetDamage(spellId, attackpower, spellpower, combo)
return damage
end
-function OvaleData:GetDuration(spellId, spellHasteMultiplier, combo, holy)
- local si = self.spellInfo[spellId]
+function OvaleData:GetDuration(spellId, combo, holy)
+ local si
+ if type(spellId) == "number" then
+ si = self.spellInfo[spellId]
+ elseif OvaleData.buffSpellList[spellId] then
+ for _, v in pairs(OvaleData.buffSpellList[spellId]) do
+ si = self.spellInfo[v]
+ if si then
+ spellId = v
+ break
+ end
+ end
+ end
if si and si.duration then
local duration = si.duration
- spellHasteMultiplier = spellHasteMultiplier or 1
combo = combo or 0
holy = holy or 1
if si.adddurationcp then
@@ -592,7 +602,7 @@ function OvaleData:GetDuration(spellId, spellHasteMultiplier, combo, holy)
end
if si.tick then -- DoT
--DoT duration is tickLength * numberOfTicks.
- local tickLength = self:GetTickLength(spellId, spellHasteMultiplier)
+ local tickLength = self:GetTickLength(spellId)
local numTicks = floor(duration / tickLength + 0.5)
duration = tickLength * numTicks
return duration, tickLength
@@ -603,13 +613,28 @@ function OvaleData:GetDuration(spellId, spellHasteMultiplier, combo, holy)
end
end
-function OvaleData:GetTickLength(spellId, spellHasteMultiplier)
- local si = self.spellInfo[spellId]
+function OvaleData:GetTickLength(spellId)
+ local si
+ if type(spellId) == "number" then
+ si = self.spellInfo[spellId]
+ elseif OvaleData.buffSpellList[spellId] then
+ for _, spellId in pairs(OvaleData.buffSpellList[spellId]) do
+ si = self.spellInfo[spellId]
+ if si then break end
+ end
+ end
if si then
local tick = si.tick or 3
- spellHasteMultiplier = spellHasteMultiplier or 1
- if si.haste == "spell" then
- return tick / spellHasteMultiplier
+ local hasteMultiplier = 1
+ if si.haste then
+ if si.haste == "spell" then
+ hasteMultiplier = OvalePaperDoll:GetSpellHasteMultiplier()
+ elseif si.haste == "melee" then
+ hasteMultiplier = OvalePaperDoll:GetMeleeHasteMultiplier()
+ end
+ end
+ if si.haste then
+ return tick / hasteMultiplier
else
return tick
end
diff --git a/OvaleState.lua b/OvaleState.lua
index a32206d..c52d377 100644
--- a/OvaleState.lua
+++ b/OvaleState.lua
@@ -395,7 +395,7 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ
-- Set the duration to the proper length if it's a DoT.
if auraSpellInfo and auraSpellInfo.duration then
- duration = OvaleData:GetDuration(auraSpellId, OvalePaperDoll:GetSpellHasteMultiplier(), self.state.combo, self.state.holy)
+ duration = OvaleData:GetDuration(auraSpellId, nil, self.state.combo, self.state.holy)
end
-- If aura is specified with a duration, then assume stacks == 1.
@@ -403,7 +403,7 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ
stacks = 1
end
- local oldStart, oldEnding, oldStacks, oldSpellHasteMultiplier = self:GetAuraByGUID(auraGUID, auraSpellId, filter, true, target)
+ local oldStart, oldEnding, oldStacks, oldTick = self:GetAuraByGUID(auraGUID, auraSpellId, filter, true, target)
local newAura = self:NewAura(auraGUID, auraSpellId, filter)
newAura.mine = true
@@ -422,12 +422,10 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ
newAura.stacks = oldStacks + stacks
end
newAura.start = oldStart
- if isDoT and oldEnding > newAura.start then
- -- TODO: check that refreshed DoTs take a new snapshot of player stats.
- local tickLength = OvaleData:GetTickLength(auraSpellId, oldSpellHasteMultiplier)
- local k = floor((oldEnding - endCast) / tickLength)
- newAura.ending = oldEnding - tickLength * k + duration
- newAura.spellHasteMultiplier = OvalePaperDoll:GetSpellHasteMultiplier()
+ if isDoT and oldEnding > newAura.start and oldTick then
+ local k = floor((oldEnding - endCast) / oldTick)
+ newAura.ending = oldEnding - oldTick * k + duration
+ newAura.tick = OvaleData:GetTickLength(auraSpellId)
else
newAura.ending = endCast + duration
end
@@ -452,7 +450,7 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ
newAura.start = endCast
newAura.ending = endCast + duration
if isDoT then
- newAura.spellHasteMultiplier = OvalePaperDoll:GetSpellHasteMultiplier()
+ newAura.tick = OvaleData:GetTickLength(auraSpellId)
end
end
end
@@ -550,7 +548,7 @@ function OvaleState:GetAuraByGUID(guid, spellId, filter, mine, unitId)
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
+ return aura.start, aura.ending, aura.stacks, aura.tick, aura.value, aura.gain
else
Ovale:Log("Aura " .. spellId .. " not found in state for " .. tostring(guid))
return OvaleAura:GetAuraByGUID(guid, spellId, filter, mine, unitId)
@@ -562,19 +560,19 @@ function OvaleState:GetAura(unitId, spellId, filter, mine)
if type(spellId) == "number" then
return self:GetAuraByGUID(guid, spellId, filter, mine, unitId)
elseif OvaleData.buffSpellList[spellId] then
- local newStart, newEnding, newStacks, newSpellHasteMultiplier, newValue, newGain
+ local newStart, newEnding, newStacks, newTick, newValue, newGain
for _, v in pairs(OvaleData.buffSpellList[spellId]) do
- local start, ending, stacks, spellHasteMultiplier, value, gain = self:GetAuraByGUID(guid, v, filter, mine, unitId)
+ local start, ending, stacks, tick, value, gain = self:GetAuraByGUID(guid, v, filter, mine, unitId)
if start and (not newStart or stacks > newStacks) then
newStart = start
newEnding = ending
newStacks = stacks
- newSpellHasteMultiplier = spellHasteMultiplier
+ newTick = tick
newValue = value
newGain = gain
end
end
- return newStart, newEnding, newStacks, newSpellHasteMultiplier, newValue, newGain
+ return newStart, newEnding, newStacks, newTick, newValue, newGain
elseif spellId == "Magic" or spellId == "Disease" or spellId == "Curse" or spellId == "Poison" then
return self:GetAuraByGUID(guid, spellId, filter, mine, unitId)
end