Johnny C. Lam [05-11-14 - 08:10]
diff --git a/OvaleCooldown.lua b/OvaleCooldown.lua
index 6ba4aae..6a98618 100644
--- a/OvaleCooldown.lua
+++ b/OvaleCooldown.lua
@@ -9,7 +9,7 @@
--]]--------------------------------------------------------------------
local _, Ovale = ...
-local OvaleCooldown = Ovale:NewModule("OvaleCooldown")
+local OvaleCooldown = Ovale:NewModule("OvaleCooldown", "AceEvent-3.0")
Ovale.OvaleCooldown = OvaleCooldown
--<private-static-properties>
@@ -20,6 +20,7 @@ local OvalePaperDoll = nil
local OvaleStance = nil
local OvaleState = nil
+local API_GetSpellCharges = GetSpellCharges
local API_GetSpellCooldown = GetSpellCooldown
local API_UnitHealth = UnitHealth
local API_UnitHealthMax = UnitHealthMax
@@ -27,6 +28,8 @@ local API_UnitClass = UnitClass
-- Player's class.
local _, self_class = API_UnitClass("player")
+-- Current age of cooldown state.
+local self_serial = 0
--</private-static-properties>
--<public-static-methods>
@@ -40,11 +43,22 @@ function OvaleCooldown:OnInitialize()
end
function OvaleCooldown:OnEnable()
+ self:RegisterEvent("SPELL_UPDATE_CHARGES", "Update")
+ self:RegisterEvent("SPELL_UPDATE_USABLE", "Update")
+ self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", "Update")
OvaleState:RegisterState(self, self.statePrototype)
end
function OvaleCooldown:OnDisable()
OvaleState:UnregisterState(self)
+ self:UnregisterEvent("SPELL_UPDATE_CHARGES")
+ self:UnregisterEvent("SPELL_UPDATE_USABLE")
+ self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED")
+end
+
+function OvaleCooldown:Update()
+ -- Advance age of current cooldown state.
+ self_serial = self_serial + 1
end
-- Return the GCD after the given spellId is cast.
@@ -118,9 +132,12 @@ end
-- Reset the state to the current conditions.
function OvaleCooldown:ResetState(state)
for _, cd in pairs(state.cd) do
- cd.start = nil
- cd.duration = nil
- cd.enable = 0
+ -- Remove outdated cooldown state.
+ if cd.serial and cd.serial < self_serial then
+ for k in pairs(cd) do
+ cd[k] = nil
+ end
+ end
end
end
@@ -139,95 +156,153 @@ function OvaleCooldown:ApplySpellAfterCast(state, spellId, targetGUID, startCast
local si = OvaleData.spellInfo[spellId]
if si then
local cd = state:GetCD(spellId)
- if cd then
- cd.start = isChanneled and startCast or endCast
- cd.duration = si.cd or 0
- cd.enable = 1
-
- -- Test for no cooldown.
- if nocd then
- cd.duration = 0
- else
- -- There is no cooldown if the buff named by "buffnocd" parameter is present.
- if si.buffnocd then
- local aura = state:GetAura("player", si.buffnocd)
- if state:IsActiveAura(aura) then
- Ovale:Logf("buffnocd stacks = %s, start = %s, ending = %s, startCast = %f", aura.stacks, aura.start, aura.ending, startCast)
- if aura.start <= startCast and startCast < aura.ending then
- cd.duration = 0
- end
- end
- end
+ cd.start = isChanneled and startCast or endCast
+ cd.duration = si.cd or 0
+ cd.enable = 1
- -- There is no cooldown if the target's health percent is below what's specified
- -- with the "targetlifenocd" parameter.
- local target = OvaleGUID:GetUnitId(targetGUID)
- if target and si.targetlifenocd then
- local healthPercent = API_UnitHealth(target) / API_UnitHealthMax(target) * 100
- if healthPercent < si.targetlifenocd then
- cd.duration = 0
- end
+ -- If the spell has charges, then remove a charge.
+ if cd.charges and cd.charges > 0 then
+ cd.chargeStart = cd.start
+ cd.charges = cd.charges - 1
+ if cd.charges == 0 then
+ cd.duration = cd.chargeDuration
+ end
+ end
+
+ -- Test for no cooldown.
+ if nocd then
+ cd.duration = 0
+ else
+ -- There is no cooldown if the buff named by "buff_no_cd" parameter is present.
+ local buffNoCooldown = si.buff_no_cd or si.buffnocd
+ if buffNoCooldown then
+ local aura = state:GetAura("player", buffNoCooldown)
+ if state:IsActiveAura(aura, cd.start) then
+ Ovale:Logf("buff_no_cd stacks = %s, start = %s, ending = %s, cd.start = %f", aura.stacks, aura.start, aura.ending, cd.start)
+ cd.duration = 0
end
end
- -- Adjust cooldown duration if it is affected by haste: "cd_haste=melee" or "cd_haste=spell".
- if cd.duration > 0 and si.cd_haste then
- if si.cd_haste == "melee" then
- cd.duration = cd.duration / state:GetMeleeHasteMultiplier(spellcast.snapshot)
- elseif si.cd_haste == "spell" then
- cd.duration = cd.duration / state:GetSpellHasteMultiplier(spellcast.snapshot)
+ -- There is no cooldown if the target's health percent is below what's specified
+ -- with the "target_health_pct_no_cd" parameter.
+ local target = OvaleGUID:GetUnitId(targetGUID)
+ local targetHealthPctNoCooldown = si.target_health_pct_no_cd or si.targetlifenocd
+ if target and targetHealthPctNoCooldown then
+ local healthPercent = API_UnitHealth(target) / API_UnitHealthMax(target) * 100
+ if healthPercent < targetHealthPctNoCooldown then
+ cd.duration = 0
end
end
+ end
- Ovale:Logf("Spell %d cooldown info: start=%f, duration=%f", spellId, cd.start, cd.duration)
+ -- Adjust cooldown duration if it is affected by haste: "cd_haste=melee" or "cd_haste=spell".
+ if cd.duration > 0 and si.cd_haste then
+ if si.cd_haste == "melee" then
+ cd.duration = cd.duration / state:GetMeleeHasteMultiplier(spellcast.snapshot)
+ elseif si.haste == "ranged" then
+ cd.duration = cd.duration / OvalePaperDoll:GetSpellHasteMultiplier()
+ elseif si.cd_haste == "spell" then
+ cd.duration = cd.duration / state:GetSpellHasteMultiplier(spellcast.snapshot)
+ end
end
+
+ Ovale:Logf("Spell %d cooldown info: start=%f, duration=%f", spellId, cd.start, cd.duration)
end
end
--</public-static-methods>
--<state-methods>
+statePrototype.DebugCooldown = function(state)
+ for spellId, cd in pairs(state.cd) do
+ if cd.start then
+ if cd.charges then
+ Ovale:FormatPrint("Spell %s cooldown: start=%f, duration=%f, charges=%d, maxCharges=%d, chargeStart=%f, chargeDuration=%f",
+ spellId, cd.start, cd.duration, cd.charges, cd.start, cd.duration)
+ else
+ Ovale:FormatPrint("Spell %s cooldown: start=%f, duration=%f", spellId, cd.start, cd.duration)
+ end
+ end
+ end
+end
+
-- Return the table holding the simulator's cooldown information for the given spell.
statePrototype.GetCD = function(state, spellId)
- if spellId then
- local si = OvaleData.spellInfo[spellId]
- if si and si.cd then
- local cdname = si.sharedcd and si.sharedcd or spellId
- if not state.cd[cdname] then
- state.cd[cdname] = {}
+ local cdName = spellId
+ local si = OvaleData.spellInfo[spellId]
+ if si and si.sharedcd then
+ cdName = si.sharedcd
+ end
+ if not state.cd[cdName] then
+ state.cd[cdName] = {}
+ end
+
+ -- Populate the cooldown information from the current game state if it is outdated.
+ local cd = state.cd[cdName]
+ if not cd.start or not cd.serial or cd.serial < self_serial then
+ local start, duration, enable = API_GetSpellCooldown(spellId)
+ if start and start > 0 then
+ charges = 0
+ end
+ if si and si.forcecd then
+ if si.forcecd then
+ start, duration = API_GetSpellCooldown(si.forcecd)
end
- return state.cd[cdname]
+ end
+ cd.serial = self_serial
+ cd.start = start
+ cd.duration = duration
+ cd.enable = enable
+
+ local charges, maxCharges, chargeStart, chargeDuration = API_GetSpellCharges(spellId)
+ if charges then
+ cd.charges = charges
+ cd.maxCharges = maxCharges
+ cd.chargeStart = chargeStart
+ cd.chargeDuration = chargeDuration
end
end
- return nil
+
+ -- Advance the cooldown state to the current time.
+ local now = state.currentTime
+ if cd.start then
+ if cd.start + cd.duration <= now then
+ cd.start = 0
+ cd.duration = 0
+ end
+ end
+ if cd.charges then
+ local charges, maxCharges, chargeStart, chargeDuration = cd.charges, cd.maxCharges, cd.chargeStart, cd.chargeDuration
+ while chargeStart + chargeDuration <= now and charges < maxCharges do
+ chargeStart = chargeStart + chargeDuration
+ charges = charges + 1
+ end
+ cd.charges = charges
+ cd.chargeStart = chargeStart
+ end
+
+ return cd
end
-- Return the cooldown for the spell in the simulator.
statePrototype.GetSpellCooldown = function(state, spellId)
- local start, duration, enable
local cd = state:GetCD(spellId)
- if cd and cd.start then
- start, duration, enable = cd.start, cd.duration, cd.enable
- else
- start, duration, enable = API_GetSpellCooldown(spellId)
- local si = OvaleData.spellInfo[spellId]
- if si and si.forcecd then
- start, duration = API_GetSpellCooldown(si.forcecd)
- end
- end
- return start, duration, enable
+ return cd.start, cd.duration, cd.enable
+end
+
+-- Return the information on the number of charges for the spell in the simulator.
+statePrototype.GetSpellCharges = function(state, spellId)
+ local cd = state:GetCD(spellId)
+ return cd.charges, cd.maxCharges, cd.chargeStart, cd.chargeDuration
end
-- Force the cooldown of a spell to reset at the specified time.
statePrototype.ResetSpellCooldown = function(state, spellId, atTime)
- if atTime >= state.currentTime then
- local start, duration, enable = state:GetSpellCooldown(spellId)
- if start + duration > state.currentTime then
- local cd = state:GetCD(spellId)
- if cd then
- cd.start = state.currentTime
- cd.duration = atTime - state.currentTime
- cd.enable = 1
- end
+ local now = state.currentTime
+ if atTime >= now then
+ local cd = state:GetCD(spellId)
+ if cd.start + cd.duration > now then
+ cd.start = now
+ cd.duration = atTime - now
end
end
end
diff --git a/conditions/SpellChargeCooldown.lua b/conditions/SpellChargeCooldown.lua
index 723836f..655a75f 100644
--- a/conditions/SpellChargeCooldown.lua
+++ b/conditions/SpellChargeCooldown.lua
@@ -1,6 +1,6 @@
--[[--------------------------------------------------------------------
Ovale Spell Priority
- Copyright (C) 2013 Johnny C. Lam
+ Copyright (C) 2013, 2014 Johnny C. Lam
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License in the LICENSE
@@ -11,10 +11,11 @@ local _, Ovale = ...
do
local OvaleCondition = Ovale.OvaleCondition
+ local OvaleState = Ovale.OvaleState
- local API_GetSpellCharges = GetSpellCharges
local Compare = OvaleCondition.Compare
local TestValue = OvaleCondition.TestValue
+ local state = OvaleState.state
--- Get the cooldown in seconds on a spell before it gains another charge.
-- @name SpellChargeCooldown
@@ -31,8 +32,8 @@ do
local function SpellChargeCooldown(condition)
local spellId, comparator, limit = condition[1], condition[2], condition[3]
- local charges, maxCharges, start, duration = API_GetSpellCharges(spellId)
- if charges < maxCharges then
+ local charges, maxCharges, start, duration = state:GetSpellCharges(spellId)
+ if charges and charges < maxCharges then
return TestValue(start, start + duration, duration, start, -1, comparator, limit)
end
return Compare(0, comparator, limit)
diff --git a/conditions/SpellCharges.lua b/conditions/SpellCharges.lua
index c7827cd..977c590 100644
--- a/conditions/SpellCharges.lua
+++ b/conditions/SpellCharges.lua
@@ -1,6 +1,6 @@
--[[--------------------------------------------------------------------
Ovale Spell Priority
- Copyright (C) 2013 Johnny C. Lam
+ Copyright (C) 2013, 2014 Johnny C. Lam
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License in the LICENSE
@@ -11,9 +11,10 @@ local _, Ovale = ...
do
local OvaleCondition = Ovale.OvaleCondition
+ local OvaleState = Ovale.OvaleState
- local API_GetSpellCharges = GetSpellCharges
local Compare = OvaleCondition.Compare
+ local state = OvaleState.state
--- Get the number of charges of the spell.
-- @name SpellCharges
@@ -30,8 +31,9 @@ do
local function SpellCharges(condition)
local spellId, comparator, limit = condition[1], condition[2], condition[3]
- local value = API_GetSpellCharges(spellId)
- return Compare(value, comparator, limit)
+ local charges, maxCharges, start, duration = state:GetSpellCharges(spellId)
+ charges = charges or 0
+ return Compare(charges, comparator, limit)
end
OvaleCondition:RegisterCondition("charges", true, SpellCharges)
diff --git a/conditions/SpellCooldown.lua b/conditions/SpellCooldown.lua
index e8977a4..da57cbe 100644
--- a/conditions/SpellCooldown.lua
+++ b/conditions/SpellCooldown.lua
@@ -1,22 +1,19 @@
--[[--------------------------------------------------------------------
Ovale Spell Priority
Copyright (C) 2012, 2013 Sidoine
- Copyright (C) 2012, 2013 Johnny C. Lam
+ Copyright (C) 2012, 2013, 2014 Johnny C. Lam
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License in the LICENSE
file accompanying this program.
--]]--------------------------------------------------------------------
-
local _, Ovale = ...
do
local OvaleCondition = Ovale.OvaleCondition
- local OvaleSpellBook = Ovale.OvaleSpellBook
local OvaleState = Ovale.OvaleState
- local type = type
local Compare = OvaleCondition.Compare
local TestValue = OvaleCondition.TestValue
local state = OvaleState.state
@@ -35,18 +32,7 @@ do
local function SpellCooldown(condition)
local spellId, comparator, limit = condition[1], condition[2], condition[3]
- local start, duration
- if type(spellId) == "string" then
- local sharedCd = state.cd[spellId]
- if not sharedCd then
- return nil
- end
- start, duration = sharedCd.start, sharedCd.duration
- elseif not OvaleSpellBook:IsKnownSpell(spellId) then
- return nil
- else
- start, duration = state:GetSpellCooldown(spellId)
- end
+ local start, duration = state:GetSpellCooldown(spellId)
if start > 0 and duration > 0 then
return TestValue(start, start + duration, duration, start, -1, comparator, limit)
end
diff --git a/scripts/ovale_hunter_spells.lua b/scripts/ovale_hunter_spells.lua
index bff664b..abd8123 100644
--- a/scripts/ovale_hunter_spells.lua
+++ b/scripts/ovale_hunter_spells.lua
@@ -56,9 +56,8 @@ Define(cobra_shot 77767)
Define(counter_shot 147362)
SpellInfo(counter_shot cd=24)
Define(crouching_tiger_hidden_chimera_talent 3)
-Define(deterrence 19263)
- SpellInfo(deterrence cd=180)
- SpellInfo(deterrence addcd=-60 talent=crouching_tiger_hidden_chimera_talent)
+Define(deterrence 148467)
+ SpellInfo(deterrence cd=5)
Define(dire_beast 120679)
SpellInfo(dire_beast cd=30)
Define(dire_beast_talent 11)
diff --git a/scripts/ovale_monk_spells.lua b/scripts/ovale_monk_spells.lua
index 316b815..0d9487d 100644
--- a/scripts/ovale_monk_spells.lua
+++ b/scripts/ovale_monk_spells.lua
@@ -19,7 +19,7 @@ Define(breath_of_fire 115181)
SpellInfo(breath_of_fire chi=2)
Define(brewmaster_training 117967)
Define(chi_brew 115399)
- SpellInfo(chi_brew cd=45 chi=-2)
+ SpellInfo(chi_brew chi=-2)
Define(chi_brew_talent 9)
Define(chi_burst 123986)
SpellInfo(chi_burst cd=30)
diff --git a/scripts/ovale_warlock_spells.lua b/scripts/ovale_warlock_spells.lua
index 5226fc3..dbb70fe 100644
--- a/scripts/ovale_warlock_spells.lua
+++ b/scripts/ovale_warlock_spells.lua
@@ -43,18 +43,18 @@ Define(dark_regeneration 108359)
Define(dark_regeneration_talent 1)
Define(dark_intent 109773)
Define(dark_soul_knowledge 113861)
- SpellInfo(dark_soul_knowledge cd=120)
+ SpellInfo(dark_soul_knowledge cd=120 talent=!archimondes_darkness_talent)
SpellAddBuff(dark_soul_knowledge dark_soul_knowledge_buff=1)
Define(dark_soul_knowledge_buff 113858)
SpellInfo(dark_soul_knowledge_buff duration=20)
Define(dark_soul_instability 113858)
- SpellInfo(dark_soul_instability cd=120)
+ SpellInfo(dark_soul_instability cd=120 talent=!archimondes_darkness_talent)
SpellAddBuff(dark_soul_instability dark_soul_instability_buff=1)
Define(dark_soul_instability_buff 113858)
SpellInfo(dark_soul_instability_buff duration=20)
Define(dark_soul_misery 113860)
- SpellInfo(dark_soul_misery cd=120)
- SpellAddBuff(dark_soul_misery dark_soul_misery_buff=1)
+ SpellInfo(dark_soul_misery cd=120 talent=!archimondes_darkness_talent)
+ SpellAddBuffoul_misery dark_soul_misery_buff=1)
Define(dark_soul_misery_buff 113858)
SpellInfo(dark_soul_misery_buff duration=20)
Define(demonic_circle_teleport 48020)