--[[-------------------------------------------------------------------- Copyright (C) 2012 Sidoine De Wispelaere. Copyright (C) 2012, 2013, 2014 Johnny C. Lam. See the file LICENSE.txt for copying permission. --]]-------------------------------------------------------------------- --[[ This addon is the core of the state machine for the simulator. --]] local OVALE, Ovale = ... local OvaleState = Ovale:NewModule("OvaleState") Ovale.OvaleState = OvaleState --<private-static-properties> local L = Ovale.L local OvaleDebug = Ovale.OvaleDebug local OvaleQueue = Ovale.OvaleQueue local pairs = pairs -- Registered state prototypes from which mix-in methods are added to state machines. local self_statePrototype = {} local self_stateAddons = OvaleQueue:NewQueue("OvaleState_stateAddons") OvaleDebug:RegisterDebugging(OvaleState) --</private-static-properties> --<public-static-properties> -- The state for the simulator. OvaleState.state = {} --</public-static-properties> --<public-static-methods> function OvaleState:OnEnable() self:RegisterState(self, self.statePrototype) end function OvaleState:OnDisable() self:UnregisterState(self) end function OvaleState:RegisterState(stateAddon, statePrototype) self_stateAddons:Insert(stateAddon) self_statePrototype[stateAddon] = statePrototype -- Mix-in addon's state prototype into OvaleState.state. for k, v in pairs(statePrototype) do self.state[k] = v end end function OvaleState:UnregisterState(stateAddon) local stateModules = OvaleQueue:NewQueue("OvaleState_stateModules") while self_stateAddons:Size() > 0 do local addon = self_stateAddons:Remove() if stateAddon ~= addon then stateModules:Insert(addon) end end self_stateAddons = stateModules -- Release resources used by the state machine managed by the addon. if stateAddon.CleanState then stateAddon:CleanState(self.state) end -- Remove mix-in methods from addon's state prototype. local statePrototype = self_statePrototype[stateAddon] if statePrototype then for k in pairs(statePrototype) do self.state[k] = nil end end self_statePrototype[stateAddon] = nil end function OvaleState:InvokeMethod(methodName, ...) for _, addon in self_stateAddons:Iterator() do if addon[methodName] then addon[methodName](addon, ...) end end end --</public-static-methods> --[[---------------------------------------------------------------------------- State machine for simulator. --]]---------------------------------------------------------------------------- --<public-static-properties> OvaleState.statePrototype = {} --</public-static-properties> --<private-static-properties> local statePrototype = OvaleState.statePrototype --</private-static-properties> --<state-properties> -- Whether this object is a state machine. statePrototype.isState = true -- Whether the state of the simulator has been initialized. statePrototype.isInitialized = nil -- Table of state variables added by scripts that is reset on every refresh. statePrototype.futureVariable = nil -- Table of state variables added by scripts that is reset only when out of combat. statePrototype.variable = nil --</state-properties> --<public-static-methods> -- Initialize the state. function OvaleState:InitializeState(state) state.futureVariable = {} state.variable = {} end -- Reset the state to the current conditions. function OvaleState:ResetState(state) for k in pairs(state.futureVariable) do state.futureVariable[k] = nil end -- TODO: What conditions should trigger resetting state variables? -- For now, reset/remove all state variables if out of combat. if not state.inCombat then for k in pairs(state.variable) do state:Log("Resetting state variable '%s'.", k) state.variable[k] = nil end end end -- Release state resources prior to removing from the simulator. function OvaleState:CleanState(state) for k in pairs(state.futureVariable) do state.futureVariable[k] = nil end for k in pairs(state.variable) do state.variable[k] = nil end end --</public-static-methods> --<state-methods> statePrototype.Initialize = function(state) if not state.isInitialized then OvaleState:InvokeMethod("InitializeState", state) state.isInitialized = true end end statePrototype.Reset = function(state) OvaleState:InvokeMethod("ResetState", state) end -- Get the value of the named state variable. If missing, then return 0. statePrototype.GetState = function(state, name) return state.futureVariable[name] or state.variable[name] or 0 end -- Put a value into the named state variable. statePrototype.PutState = function(state, name, value, isFuture) if isFuture then state:Log("Setting future state: %s = %s.", name, value) state.futureVariable[name] = value else OvaleState:Debug("Advancing combat state: %s = %s.", name, value) state:Log("Advancing combat state: %s = %s.", name, value) state.variable[name] = value end end -- Logging function. statePrototype.Log = function(state, ...) return OvaleDebug:Log(...) end --</state-methods>