Johnny C. Lam [11-10-13 - 00:32]
diff --git a/Ovale.toc b/Ovale.toc
index 8b1514e..b34e42c 100644
--- a/Ovale.toc
+++ b/Ovale.toc
@@ -52,6 +52,7 @@ OvaleSpellDamage.lua
OvaleSwing.lua
#
OvaleCompile.lua
+OvaleEclipse.lua
OvaleFuture.lua
OvaleIcone.lua
OvaleIcone.xml
diff --git a/OvaleEclipse.lua b/OvaleEclipse.lua
new file mode 100644
index 0000000..2459d9d
--- /dev/null
+++ b/OvaleEclipse.lua
@@ -0,0 +1,200 @@
+--[[--------------------------------------------------------------------
+ Ovale Spell Priority
+ Copyright (C) 2013 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.
+--]]--------------------------------------------------------------------
+
+--[[
+ This addon tracks Eclipse energy information on druids.
+--]]
+
+local _, Ovale = ...
+local OvaleEclipse = Ovale:NewModule("OvaleEclipse", "AceEvent-3.0")
+Ovale.OvaleEclipse = OvaleEclipse
+
+--<private-static-properties>
+local OvaleAura = Ovale.OvaleAura
+local OvaleData = Ovale.OvaleData
+local OvaleGUID = Ovale.OvaleGUID
+local OvalePower = Ovale.OvalePower
+local OvaleSpellBook = Ovale.OvaleSpellBook
+local OvaleState = Ovale.OvaleState
+local SPELL_POWER_ECLIPSE = SPELL_POWER_ECLIPSE
+
+local select = select
+local API_GetEclipseDirection = GetEclipseDirection
+local API_UnitClass = UnitClass
+local API_UnitPower = UnitPower
+
+-- Player's GUID.
+local self_guid = nil
+-- Player's class.
+local self_class = select(2, API_UnitClass("player"))
+
+local LUNAR_ECLIPSE = ECLIPSE_BAR_LUNAR_BUFF_ID
+local SOLAR_ECLIPSE = ECLIPSE_BAR_SOLAR_BUFF_ID
+local CELESTIAL_ALIGNMENT = 112071
+local EUPHORIA = 81062
+local STARFALL = 48505
+--</private-static-properties>
+
+--<public-static-properties>
+-- Direction that the eclipse status is moving: -1 = "lunar", 0 = "none", 1 = "solar".
+OvaleEclipse.eclipse = 0
+OvaleEclipse.eclipseDirection = 0
+--<public-static-properties>
+
+--<public-static-methods>
+function OvaleEclipse:OnEnable()
+ if self_class == "DRUID" then
+ self_guid = OvaleGUID:GetGUID("player")
+ self:RegisterEvent("ECLIPSE_DIRECTION_CHANGE", "UpdateEclipseDirection")
+ self:RegisterEvent("UNIT_POWER")
+ self:RegisterEvent("UNIT_POWER_FREQUENT", "UNIT_POWER")
+ self:RegisterMessage("Ovale_SpecializationChanged", "UpdateEclipseDirection")
+ self:RegisterMessage("Ovale_StanceChanged", "Update")
+ self:RegisterMessage("Ovale_AuraAdded")
+ OvaleState:RegisterState(self, self.statePrototype)
+ end
+end
+
+function OvaleEclipse:OnDisable()
+ if self_class == "DRUID" then
+ OvaleState:UnregisterState(self)
+ self:UnregisterEvent("ECLIPSE_DIRECTION_CHANGE")
+ self:UnregisterEvent("UNIT_POWER")
+ self:UnregisterEvent("UNIT_POWER_FREQUENT")
+ self:UnregisterMessage("Ovale_AuraAdded")
+ self:UnregisterMessage("Ovale_SpecializationChanged")
+ self:UnregisterMessage("Ovale_StanceChanged")
+ end
+end
+
+function OvaleEclipse:UNIT_POWER(event, unitId, powerToken)
+ if unitId == "player" and powerToken == "ECLIPSE" then
+ self:Update()
+ end
+end
+
+function OvaleEclipse:Ovale_AuraAdded(event, timestamp, guid, spellId, caster)
+ if guid == self_guid then
+ if spellId == LUNAR_ECLIPSE or spellId == SOLAR_ECLIPSE then
+ self:UpdateEclipseDirection()
+ end
+ end
+end
+
+function OvaleEclipse:Update()
+ self:UpdateEclipse()
+ self:UpdateEclipseDirection()
+end
+
+function OvaleEclipse:UpdateEclipse()
+ self.eclipse = API_UnitPower("player", SPELL_POWER_ECLIPSE)
+end
+
+function OvaleEclipse:UpdateEclipseDirection()
+ local direction = API_GetEclipseDirection()
+ if direction == "moon" then
+ self.eclipseDirection = -1
+ elseif direction == "sun" then
+ self.eclipseDirection = 1
+ else -- if direction == "none" then
+ if self.eclipse < 0 then
+ self.eclipseDirection = -1
+ elseif self.eclipse > 0 then
+ self.eclipseDirection = 1
+ else -- if self.eclipse == 0 then
+ self.eclipseDirection = 0
+ end
+ end
+end
+--</public-static-methods>
+
+--[[----------------------------------------------------------------------------
+ State machine for simulator.
+--]]----------------------------------------------------------------------------
+
+--<public-static-properties>
+OvaleEclipse.statePrototype = {
+ eclipseDirection = nil,
+}
+--</public-static-properties>
+
+--<public-static-methods>
+-- Initialize the state.
+function OvaleEclipse:InitializeState(state)
+ state.eclipseDirection = nil
+end
+
+-- Reset the state to the current conditions.
+function OvaleEclipse:ResetState(state)
+ state.eclipse = self.eclipse or 0
+ state.eclipseDirection = self.eclipseDirection
+end
+
+-- Apply the effects of the spell on the player's state, assuming the spellcast completes.
+function OvaleEclipse:ApplySpellOnPlayer(state, spellId, startCast, endCast, nextCast, nocd, targetGUID, spellcast)
+ -- If the spellcast has already ended, then the effects on the player have already occurred.
+ if endCast <= OvaleState.now then
+ return
+ end
+
+ local si = OvaleData.spellInfo[spellId]
+ if si and si.eclipse then
+ local eclipse = state.eclipse
+ local direction = state.eclipseDirection
+ local energy = si.eclipse
+
+ if energy == 0 then
+ -- Spell resets Eclipse energy to zero, but leaves the Eclipse direction intact.
+ eclipse = 0
+ else -- if energy ~= 0 then
+ -- If there is no Eclipse direction yet, then start moving in the direction generated
+ -- by the energy of the spellcast.
+ if direction == 0 then
+ direction = (energy < 0) and -1 or 1
+ end
+ if si.eclipsedir then
+ energy = energy * direction
+ end
+ if state:GetAura("player", CELESTIAL_ALIGNMENT, "HELPFUL", true) then
+ -- Celestial Alignment prevents gaining Eclipse energy during its duration.
+ energy = 0
+ elseif OvaleSpellBook:IsKnownSpell(EUPHORIA)
+ and not state:GetAura("player", LUNAR_ECLIPSE, "HELPFUL", true)
+ and not state:GetAura("player", SOLAR_ECLIPSE, "HELPFUL", true) then
+ -- Euphoria: While not in an Eclipse state, your spells generate double the normal
+ -- amount of Solar or Lunar energy.
+ energy = energy * 2
+ end
+ -- Only adjust Eclipse energy if the spell moves the Eclipse bar in the right direction.
+ if (direction <= 0 and energy < 0) or (direction >= 0 and energy > 0) then
+ eclipse = eclipse + energy
+ end
+ -- Clamp Eclipse energy to min/max values and note that an Eclipse state will be reached after the spellcast.
+ if eclipse <= -100 then
+ eclipse = -100
+ direction = 1
+ state:AddEclipse(endCast, LUNAR_ECLIPSE)
+ -- Reaching Lunar Eclipse resets the cooldown of Starfall.
+ local cd = state:GetCD(STARFALL)
+ if cd then
+ cd.start = 0
+ cd.duration = 0
+ cd.enable = 0
+ end
+ elseif eclipse >= 100 then
+ eclipse = 100
+ direction = -1
+ state:AddEclipse(endCast, SOLAR_ECLIPSE)
+ end
+ end
+ state.eclipse = eclipse
+ state.eclipseDirection = direction
+ end
+end
+--</public-static-methods>
diff --git a/OvalePower.lua b/OvalePower.lua
index 1b993cc..6b5f232 100644
--- a/OvalePower.lua
+++ b/OvalePower.lua
@@ -252,7 +252,7 @@ function OvalePower:ApplySpellOnPlayer(state, spellId, startCast, endCast, nextC
end
if si then
- -- Update power state except for eclipse energy.
+ -- Update power state except for eclipse energy (handled by OvaleEclipse).
for powerType, powerInfo in pairs(self.POWER_INFO) do
if powerType ~= "eclipse" then
local cost = si[powerType]
diff --git a/OvaleState.lua b/OvaleState.lua
index 85eb824..9eda4dd 100644
--- a/OvaleState.lua
+++ b/OvaleState.lua
@@ -9,7 +9,7 @@
--]]--------------------------------------------------------------------
-- Keep the current state in the simulation
--- XXX Split out Eclipse and Runes modules (Druid and DeathKnight modules?).
+-- XXX Split out Runes module.
local _, Ovale = ...
local OvaleState = Ovale:NewModule("OvaleState")
@@ -18,11 +18,9 @@ Ovale.OvaleState = OvaleState
--<private-static-properties>
local OvaleData = Ovale.OvaleData
local OvaleQueue = Ovale.OvaleQueue
-local OvaleSpellBook = Ovale.OvaleSpellBook
local pairs = pairs
local select = select
-local API_GetEclipseDirection = GetEclipseDirection
local API_GetRuneCooldown = GetRuneCooldown
local API_GetRuneType = GetRuneType
local API_GetTime = GetTime
@@ -38,12 +36,6 @@ local self_runesCD = {}
local self_class = select(2, API_UnitClass("player"))
-- Whether the state of the simulator has been initialized.
local self_stateIsInitialized = false
-
--- Aura IDs for Eclipse buffs.
-local LUNAR_ECLIPSE = 48518
-local SOLAR_ECLIPSE = 48517
--- Spell ID for Starfall (Balance specialization spell).
-local STARFALL = 48505
--</private-static-properties>
--<public-static-properties>
@@ -212,93 +204,28 @@ function OvaleState:ApplySpellOnPlayer(spellId, startCast, endCast, nextCast, no
so only consider spells that have not yet finished casting in the simulator.
--]]
if endCast > self.now then
- -- Adjust the player's resources.
- self:ApplySpellCost(spellId, startCast, endCast)
- end
-end
-
--- Apply the effects of the spell on the target's state when it lands on the target.
-function OvaleState:ApplySpellOnTarget(spellId, startCast, endCast, nextCast, nocd, targetGUID, spellcast)
- self:InvokeMethod("ApplySpellOnTarget", spellId, startCast, endCast, nextCast, nocd, targetGUID, spellcast)
-end
-
--- Adjust the player's resources in the simulator from casting the given spell.
-function OvaleState:ApplySpellCost(spellId, startCast, endCast)
- local si = OvaleData.spellInfo[spellId]
-
- if si then
- -- Eclipse
- if si.eclipse then
- local energy = si.eclipse
- local direction = self:GetEclipseDir()
- if si.eclipsedir then
- energy = energy * direction
+ local si = OvaleData.spellInfo[spellId]
+ if si then
+ -- Runes
+ if si.blood and si.blood < 0 then
+ AddRune(startCast, 1, si.blood)
end
- -- Euphoria: While not in an Eclipse state, your spells generate double the normal amount of Solar or Lunar energy.
- if OvaleSpellBook:IsKnownSpell(81062)
- and not self.state:GetAura("player", LUNAR_ECLIPSE, "HELPFUL", true)
- and not self.state:GetAura("player", SOLAR_ECLIPSE, "HELPFUL", true) then
- energy = energy * 2
+ if si.unholy and si.unholy < 0 then
+ AddRune(startCast, 2, si.unholy)
end
- -- Only adjust Eclipse energy if the spell moves the Eclipse bar in the right direction.
- if (direction < 0 and energy < 0) or (direction > 0 and energy > 0) then
- self.state.eclipse = self.state.eclipse + energy
+ if si.frost and si.frost < 0 then
+ AddRune(startCast, 3, si.frost)
end
- -- Clamp Eclipse energy to min/max values and note that an Eclipse state will be reached after the spellcast.
- if self.state.eclipse <= -100 then
- self.state.eclipse = -100
- self.state:AddEclipse(endCast, LUNAR_ECLIPSE)
- -- Reaching Lunar Eclipse resets the cooldown of Starfall.
- local cd = self.state:GetCD(STARFALL)
- if cd then
- cd.start = 0
- cd.duration = 0
- cd.enable = 0
- end
- elseif self.state.eclipse >= 100 then
- self.state.eclipse = 100
- self.state:AddEclipse(endCast, SOLAR_ECLIPSE)
+ if si.death and si.death < 0 then
+ AddRune(startCast, 4, si.death)
end
end
-
- -- Runes
- if si.blood and si.blood < 0 then
- AddRune(startCast, 1, si.blood)
- end
- if si.unholy and si.unholy < 0 then
- AddRune(startCast, 2, si.unholy)
- end
- if si.frost and si.frost < 0 then
- AddRune(startCast, 3, si.frost)
- end
- if si.death and si.death < 0 then
- AddRune(startCast, 4, si.death)
- end
end
end
--- Returns 1 if moving toward Solar or -1 if moving toward Lunar.
-function OvaleState:GetEclipseDir()
- local stacks = select(3, self.state:GetAura("player", SOLAR_ECLIPSE, "HELPFUL", true))
- if stacks and stacks > 0 then
- return -1
- else
- stacks = select(3, self.state:GetAura("player", LUNAR_ECLIPSE, "HELPFUL", true))
- if stacks and stacks > 0 then
- return 1
- elseif self.state.eclipse < 0 then
- return -1
- elseif self.state.eclipse > 0 then
- return 1
- else
- local direction = API_GetEclipseDirection()
- if direction == "moon" then
- return -1
- else -- direction == "sun" then
- return 1
- end
- end
- end
+-- Apply the effects of the spell on the target's state when it lands on the target.
+function OvaleState:ApplySpellOnTarget(spellId, startCast, endCast, nextCast, nocd, targetGUID, spellcast)
+ self:InvokeMethod("ApplySpellOnTarget", spellId, startCast, endCast, nextCast, nocd, targetGUID, spellcast)
end
-- Returns the cooldown time before all of the required runes are available.
diff --git a/conditions/EclipseDir.lua b/conditions/EclipseDir.lua
index 2cdf664..4a7352b 100644
--- a/conditions/EclipseDir.lua
+++ b/conditions/EclipseDir.lua
@@ -18,6 +18,7 @@ do
--- Get the current direction of the Eclipse status on the Eclipse bar for balance druids.
-- A negative number means heading toward Lunar Eclipse.
-- A positive number means heading toward Solar Eclipse.
+ -- Zero means it can head in either direction.
-- @name EclipseDir
-- @paramsig number or boolean
-- @param operator Optional. Comparison operator: less, atMost, equal, atLeast, more.
@@ -31,7 +32,7 @@ do
local function EclipseDir(condition)
local comparator, limit = condition[1], condition[2]
- local value = OvaleState:GetEclipseDir()
+ local value = OvaleState.state.eclipseDirection
return Compare(value, comparator, limit)
end