Johnny C. Lam [12-12-14 - 20:41]
diff --git a/BestAction.lua b/BestAction.lua
index 23dbf31..396740a 100644
--- a/BestAction.lua
+++ b/BestAction.lua
@@ -247,38 +247,15 @@ local function GetActionSpellInfo(element, state, target)
local texture = state:GetSpellInfoProperty(spellId, "texture", target)
actionTexture = "Interface\\Icons\\" .. texture
end
- -- Fix spell cooldown information using primary resource requirements specified in SpellInfo().
+ -- Extend the cooldown duration if the spell needs additional time to pool resources.
if actionCooldownStart and actionCooldownDuration then
- -- Get the maximum time before all "primary" resources are ready.
- local atTime = state.currentTime
- for powerType in pairs(OvalePower.PRIMARY_POWER) do
- if si[powerType] then
- local t = state.currentTime + state:TimeToPower(spellId, target, powerType)
- if atTime < t then
- atTime = t
- end
- end
- end
- if actionCooldownStart > 0 then
+ local seconds = state:GetTimeToSpell(spellId, target)
+ if seconds > 0 then
+ local atTime = state.currentTime + seconds
if atTime > actionCooldownStart + actionCooldownDuration then
state:Log("Delaying spell ID '%s' for primary resource.", spellId)
actionCooldownDuration = atTime - actionCooldownStart
end
- else
- actionCooldownStart = state.currentTime
- actionCooldownDuration = atTime - actionCooldownStart
- end
-
- local blood = state:GetSpellInfoProperty(spellId, "blood", target)
- local frost = state:GetSpellInfoProperty(spellId, "frost", target)
- local unholy = state:GetSpellInfoProperty(spellId, "unholy", target)
- local death = state:GetSpellInfoProperty(spellId, "death", target)
- if blood or frost or unholy or death then
- -- Spell requires runes.
- local ending = state.currentTime + state:GetRunesCooldown(blood, unholy, frost, death)
- if ending > actionCooldownStart + actionCooldownDuration then
- actionCooldownDuration = ending - actionCooldownStart
- end
end
end
end
@@ -462,7 +439,7 @@ function OvaleBestAction:ComputeAction(element, state)
local timeSpan = GetTimeSpan(element)
local priority, result
- state:Log("[%d] evaluating action: %s(%s)", element.nodeId, element.name, element.paramsAsString)
+ state:Log("[%d] evaluating action: %s(%s)", nodeId, element.name, element.paramsAsString)
local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
actionUsable, actionShortcut, actionIsCurrent, actionEnable, actionType, actionId, actionTarget = self:GetActionInfo(element, state)
@@ -489,12 +466,19 @@ function OvaleBestAction:ComputeAction(element, state)
-- If the action is not on cooldown, then treat it like it's immediately ready.
local start
- if actionCooldownDuration and actionCooldownStart and actionCooldownStart > 0 then
- start = actionCooldownDuration + actionCooldownStart
+ if actionCooldownStart and actionCooldownStart > 0 then
+ -- Spell is on cooldown.
+ if actionCooldownDuration and actionCooldownDuration > 0 then
+ state:Log("[%s] Action %s is on cooldown (start=%f, duration=%f).", nodeId, action, actionCooldownStart, actionCooldownDuration)
+ start = actionCooldownStart + actionCooldownDuration
+ else
+ state:Log("[%s] Action %s is waiting on the GCD (start=%f).", nodeId, action, actionCooldownStart)
+ start = actionCooldownStart
+ end
else
+ state:Log("[%s] Action %s is off cooldown.", nodeId, action)
start = state.currentTime
end
-
state:Log("[%d] start=%f nextCast=%s", nodeId, start, state.nextCast)
-- If the action is available before the end of the current spellcast, then wait until we can first cast the action.
diff --git a/Cooldown.lua b/Cooldown.lua
index 01bea0e..c51744b 100644
--- a/Cooldown.lua
+++ b/Cooldown.lua
@@ -25,6 +25,9 @@ local API_GetSpellCharges = GetSpellCharges
local API_GetSpellCooldown = GetSpellCooldown
local API_UnitClass = UnitClass
+-- Spell ID for the dummy Global Cooldown spell.
+local GLOBAL_COOLDOWN = 61304
+
-- Register for profiling.
OvaleProfiler:RegisterProfiling(OvaleCooldown)
@@ -116,21 +119,37 @@ end
-- then cycle through all spells associated with that spell ID to find the cooldown
-- information.
function OvaleCooldown:GetSpellCooldown(spellId)
- local start, duration, enable
+ local cdStart, cdDuration, cdEnable = 0, 0, 1
+ local gcdStart, gcdDuration = API_GetSpellCooldown(GLOBAL_COOLDOWN)
if self_sharedCooldownSpells[spellId] then
for id in pairs(self_sharedCooldownSpells[spellId]) do
- start, duration, enable = self:GetSpellCooldown(id)
+ local start, duration, enable = self:GetSpellCooldown(id)
if start then break end
end
else
+ local start, duration, enable
local index, bookType = OvaleSpellBook:GetSpellBookIndex(spellId)
if index and bookType then
start, duration, enable = API_GetSpellCooldown(index, bookType)
else
start, duration, enable = API_GetSpellCooldown(spellId)
end
+ if start and start > 0 then
+ if duration > gcdDuration then
+ -- Spell is on cooldown.
+ cdStart, cdDuration, cdEnable = start, duration, enable
+ else
+ -- GCD is active, so set the start to when the spell can next be cast.
+ cdStart = start + duration
+ cdDuration = 0
+ cdEnable = enable
+ end
+ else
+ -- Spell is ready now.
+ cdStart, cdDuration, cdEnable = start, duration, enable
+ end
end
- return start, duration, enable
+ return cdStart, cdDuration, cdEnable
end
-- Return the base GCD and caster status.
@@ -359,7 +378,7 @@ end
-- already on cooldown or the duration if cast at the specified time.
statePrototype.GetSpellCooldownDuration = function(state, spellId, atTime, target)
local start, duration = state:GetSpellCooldown(spellId)
- if start + duration > atTime then
+ if duration > 0 and start + duration > atTime then
state:Log("Spell %d is on cooldown for %fs starting at %s.", spellId, duration, start)
else
local si = OvaleData.spellInfo[spellId]
diff --git a/Ovale.toc b/Ovale.toc
index fc8b6b4..106f8a1 100644
--- a/Ovale.toc
+++ b/Ovale.toc
@@ -45,6 +45,7 @@ Latency.lua
Lexer.lua
PaperDoll.lua
Power.lua
+Runes.lua
Score.lua
Scripts.lua
SimulationCraft.lua
@@ -67,7 +68,6 @@ Enemies.lua
HonorAmongThieves.lua
PassiveAura.lua
Recount.lua
-Runes.lua
ShadowWordDeath.lua
Skada.lua
SpellDamage.lua
diff --git a/SpellBook.lua b/SpellBook.lua
index ab76b53..25220eb 100644
--- a/SpellBook.lua
+++ b/SpellBook.lua
@@ -16,8 +16,10 @@ local OvaleDebug = Ovale.OvaleDebug
local OvaleProfiler = Ovale.OvaleProfiler
-- Forward declarations for module dependencies.
+local OvaleCooldown = nil
local OvaleData = nil
local OvalePower = nil
+local OvaleRunes = nil
local OvaleState = nil
local ipairs = ipairs
@@ -147,8 +149,10 @@ end
--<public-static-methods>
function OvaleSpellBook:OnInitialize()
-- Resolve module dependencies.
+ OvaleCooldown = Ovale.OvaleCooldown
OvaleData = Ovale.OvaleData
OvalePower = Ovale.OvalePower
+ OvaleRunes = Ovale.OvaleRunes
OvaleState = Ovale.OvaleState
end
@@ -521,4 +525,38 @@ statePrototype.IsUsableSpell = function(state, spellId, target)
OvaleSpellBook:StopProfiling("OvaleSpellBook_state_IsUsableSpell")
return isUsable, noMana
end
+
+-- Get the number of seconds before the spell is ready to be cast, either due to cooldown or resources.
+statePrototype.GetTimeToSpell = function(state, spellId, target)
+ local timeToSpell = 0
+ -- Cooldown.
+ do
+ local start, duration = state:GetSpellCooldown(spellId)
+ local seconds = (duration > 0) and (start + duration - state.currentTime) or 0
+ if timeToSpell < seconds then
+ timeToSpell = seconds
+ end
+ end
+ -- Pooled resource.
+ do
+ local seconds = state:TimeToPower(spellId, target)
+ if timeToSpell < seconds then
+ timeToSpell = seconds
+ end
+ end
+ -- Death knight runes.
+ do
+ local blood = state:GetSpellInfoProperty(spellId, "blood", target)
+ local unholy = state:GetSpellInfoProperty(spellId, "unholy", target)
+ local frost = state:GetSpellInfoProperty(spellId, "frost", target)
+ local death = state:GetSpellInfoProperty(spellId, "death", target)
+ if blood or unholy or frost or death then
+ local seconds = state:GetRunesCooldown(blood, unholy, frost, death)
+ if timeToSpell < seconds then
+ timeToSpell = seconds
+ end
+ end
+ end
+ return timeToSpell
+end
--</state-methods>
diff --git a/conditions.lua b/conditions.lua
index 0b73571..37a3eff 100644
--- a/conditions.lua
+++ b/conditions.lua
@@ -5402,33 +5402,7 @@ do
local function TimeToSpell(condition, state)
local spellId, comparator, limit = condition[1], condition[2], condition[3]
local target = ParseCondition(condition, state, "target")
- local seconds = 0
- -- Cooldown
- do
- local start, duration = state:GetSpellCooldown(spellId)
- local timeToCooldown = start + duration - state.currentTime
- if seconds < timeToCooldown then
- seconds = timeToCooldown
- end
- end
- -- Pooled resource.
- do
- local timeToPower = state:TimeToPower(spellId, target)
- if seconds < timeToPower then
- seconds = timeToPower
- end
- end
- -- Runes.
- local blood = state:GetSpellInfoProperty(spellId, "blood", target)
- local unholy = state:GetSpellInfoProperty(spellId, "unholy", target)
- local frost = state:GetSpellInfoProperty(spellId, "frost", target)
- local death = state:GetSpellInfoProperty(spellId, "death", target)
- if blood or unholy or frost or death then
- local timeToRunes = state:GetRunesCooldown(blood, unholy, frost, death)
- if seconds < timeToRunes then
- seconds = timeToRunes
- end
- end
+ local seconds = state:GetTimeToSpell(spellId, target)
if seconds == 0 then
return Compare(0, comparator, limit)
elseif seconds < INFINITY then