--[[--------------------------------------------------------------------
Ovale Spell Priority
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
file accompanying this program.
--]]--------------------------------------------------------------------
-- This addon tracks the player's current stance.
local _, Ovale = ...
local OvaleStance = Ovale:NewModule("OvaleStance", "AceEvent-3.0")
Ovale.OvaleStance = OvaleStance
--
-- Forward declarations for module dependencies.
local OvaleData = nil
local OvaleState = nil
local ipairs = ipairs
local pairs = pairs
local tinsert = table.insert
local tsort = table.sort
local wipe = table.wipe
local API_GetNumShapeshiftForms = GetNumShapeshiftForms
local API_GetShapeshiftForm = GetShapeshiftForm
local API_GetShapeshiftFormInfo = GetShapeshiftFormInfo
local API_GetSpellInfo = GetSpellInfo
-- Profiling set-up.
local Profiler = Ovale.Profiler
local profiler = nil
do
local group = OvaleStance:GetName()
local function EnableProfiling()
API_GetNumShapeshiftForms = Profiler:Wrap(group, "OvaleStance_API_GetNumShapeshiftForms", GetNumShapeshiftForms)
API_GetShapeshiftForm = Profiler:Wrap(group, "OvaleStance_API_GetShapeshiftForm", GetShapeshiftForm)
API_GetShapeshiftFormInfo = Profiler:Wrap(group, "OvaleStance_API_GetShapeshiftFormInfo", GetShapeshiftFormInfo)
end
local function DisableProfiling()
API_GetNumShapeshiftForms = GetNumShapeshiftForms
API_GetShapeshiftForm = GetShapeshiftForm
API_GetShapeshiftFormInfo = GetShapeshiftFormInfo
end
Profiler:RegisterProfilingGroup(group, EnableProfiling, DisableProfiling)
profiler = Profiler:GetProfilingGroup(group)
end
local OVALE_SPELLID_TO_STANCE = {
-- Death Knight
[API_GetSpellInfo(48263)] = "deathknight_blood_presence",
[API_GetSpellInfo(48265)] = "deathknight_unholy_presence",
[API_GetSpellInfo(48266)] = "deathknight_frost_presence",
-- Druid
[API_GetSpellInfo(768)] = "druid_cat_form",
[API_GetSpellInfo(783)] = "druid_travel_form",
[API_GetSpellInfo(1066)] = "druid_aquatic_form",
[API_GetSpellInfo(5487)] = "druid_bear_form",
[API_GetSpellInfo(24858)] = "druid_moonkin_form",
[API_GetSpellInfo(33943)] = "druid_flight_form",
[API_GetSpellInfo(40120)] = "druid_swift_flight_form",
-- Hunter
[API_GetSpellInfo(5118)] = "hunter_aspect_of_the_cheetah",
[API_GetSpellInfo(13159)] = "hunter_aspect_of_the_pack",
[API_GetSpellInfo(13165)] = "hunter_aspect_of_the_hawk",
[API_GetSpellInfo(109260)] = "hunter_aspect_of_the_iron_hawk",
-- Monk
[API_GetSpellInfo(103985)] = "monk_stance_of_the_fierce_tiger",
[API_GetSpellInfo(115069)] = "monk_stance_of_the_sturdy_ox",
[API_GetSpellInfo(115070)] = "monk_stance_of_the_wise_serpent",
-- Paladin
[API_GetSpellInfo(20154)] = "paladin_seal_of_righteousness",
[API_GetSpellInfo(20164)] = "paladin_seal_of_justice",
[API_GetSpellInfo(20165)] = "paladin_seal_of_insight",
[API_GetSpellInfo(31801)] = "paladin_seal_of_truth",
[API_GetSpellInfo(105361)] = "paladin_seal_of_command",
-- Priest
[API_GetSpellInfo(15473)] = "priest_shadowform",
-- Rogue
[API_GetSpellInfo(1784)] = "rogue_stealth",
[API_GetSpellInfo(51713)] = "rogue_shadow_dance",
-- Warlock
[API_GetSpellInfo(103958)] = "warlock_metamorphosis",
-- Warrior
[API_GetSpellInfo(71)] = "warrior_defensive_stance",
[API_GetSpellInfo(2457)] = "warrior_battle_stance",
[API_GetSpellInfo(2458)] = "warrior_berserker_stance",
}
--
--
-- Whether the stance information is ready for use by other modules.
OvaleStance.ready = false
-- List of available stances, populated by CreateStanceList()
OvaleStance.stanceList = {}
-- Map stance names to stance ID (index on shapeshift/stance bar).
OvaleStance.stanceId = {}
-- Player's current stance.
OvaleStance.stance = nil
--
--
function OvaleStance:OnInitialize()
-- Resolve module dependencies.
OvaleData = Ovale.OvaleData
OvaleState = Ovale.OvaleState
end
function OvaleStance:OnEnable()
self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED", "UpdateStances")
self:RegisterEvent("PLAYER_ALIVE", "UpdateStances")
self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateStances")
self:RegisterEvent("PLAYER_TALENT_UPDATE", "UpdateStances")
self:RegisterEvent("SPELLS_CHANGED", "UpdateStances")
self:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
OvaleState:RegisterState(self, self.statePrototype)
end
function OvaleStance:OnDisable()
OvaleState:UnregisterState(self)
self:UnregisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
self:UnregisterEvent("PLAYER_ALIVE")
self:UnregisterEvent("PLAYER_ENTERING_WORLD")
self:UnregisterEvent("PLAYER_TALENT_UPDATE")
self:UnregisterEvent("SPELLS_CHANGED")
self:UnregisterEvent("UPDATE_SHAPESHIFT_FORM")
self:UnregisterEvent("UPDATE_SHAPESHIFT_FORMS")
end
function OvaleStance:PLAYER_TALENT_UPDATE(event)
-- Clear old stance ID since talent update may overwrite old stance with new one with same ID.
self.stance = nil
UpdateStances()
end
function OvaleStance:UPDATE_SHAPESHIFT_FORM(event)
self:ShapeshiftEventHandler()
end
function OvaleStance:UPDATE_SHAPESHIFT_FORMS(event)
self:ShapeshiftEventHandler()
end
-- Fill OvaleStance.stanceList with stance bar index <-> Ovale stance name mappings.
function OvaleStance:CreateStanceList()
profiler.Start("OvaleStance_CreateStanceList")
wipe(self.stanceList)
wipe(self.stanceId)
local _, name, stanceName
for i = 1, API_GetNumShapeshiftForms() do
_, name = API_GetShapeshiftFormInfo(i)
stanceName = OVALE_SPELLID_TO_STANCE[name]
if stanceName then
self.stanceList[i] = stanceName
self.stanceId[stanceName] = i
end
end
profiler.Stop("OvaleStance_CreateStanceList")
end
-- Print out the list of stances in alphabetical order.
function OvaleStance:DebugStances()
local array = {}
for k, v in pairs(self.stanceList) do
if self.stance == k then
tinsert(array, v .. " (active)")
else
tinsert(array, v)
end
end
tsort(array)
for _, v in ipairs(array) do
Ovale:Print(v)
end
end
function OvaleStance:Debug()
Ovale:FormatPrint("current stance: %s", self.stance)
end
-- Return the current stance's name.
function OvaleStance:GetStance()
return self.stanceList[self.stance]
end
-- Return true if the current stance matches the given name.
function OvaleStance:IsStance(name)
if not name or not self.stance then return false end
if type(name) == "number" then
return name == self.stance
else
return name == self.stanceList[self.stance]
end
end
function OvaleStance:ShapeshiftEventHandler()
profiler.Start("OvaleStance_ShapeshiftEventHandler")
local newStance = API_GetShapeshiftForm()
if self.stance ~= newStance then
self.stance = newStance
self:SendMessage("Ovale_StanceChanged")
end
profiler.Stop("OvaleStance_ShapeshiftEventHandler")
end
function OvaleStance:UpdateStances()
self:CreateStanceList()
self:ShapeshiftEventHandler()
self.ready = true
end
--
--[[----------------------------------------------------------------------------
State machine for simulator.
--]]----------------------------------------------------------------------------
--
OvaleStance.statePrototype = {}
--
--
local statePrototype = OvaleStance.statePrototype
--
--
statePrototype.stance = nil
--
--
-- Initialize the state.
function OvaleStance:InitializeState(state)
state.stance = nil
end
-- Reset the state to the current conditions.
function OvaleStance:ResetState(state)
profiler.Start("OvaleStance_ResetState")
state.stance = self.stance or 0
profiler.Stop("OvaleStance_ResetState")
end
-- Apply the effects of the spell on the player's state, assuming the spellcast completes.
function OvaleStance:ApplySpellAfterCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast)
profiler.Start("OvaleStance_ApplySpellAfterCast")
local si = OvaleData.spellInfo[spellId]
if si and si.to_stance then
local stance = si.to_stance
stance = (type(stance) == "number") and stance or self.stanceId[stance]
state.stance = stance
end
profiler.Stop("OvaleStance_ApplySpellAfterCast")
end
--
--
-- Return true if the stance matches the given name.
statePrototype.IsStance = function(state, name)
if name and state.stance then
if type(name) == "number" then
return name == state.stance
else
return name == OvaleStance.stanceList[state.stance]
end
end
return false
end
--