#region File Description //----------------------------------------------------------------------------- // CombatAction.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using RolePlayingGameData; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; #endregion namespace RolePlaying { /// /// An action taken by an individual character in combat. /// /// /// Note that party actions, like Flee, are not represented here. These are only /// the actions that individual characters, on either side, can perform in combat. /// abstract class CombatAction { #region State /// /// Returns true if the action is offensive, targeting the opponents. /// public abstract bool IsOffensive { get; } /// /// Returns true if this action requires a target. /// public abstract bool IsTargetNeeded { get; } #endregion #region Combat Stage /// /// Stages of the action as it is executed. /// public enum CombatActionStage { /// /// The initial state, with no action taken yet. /// NotStarted, /// /// The action is getting ready to start. /// /// /// Spell actions stay in this stage while the casting animation plays. /// Preparing, /// /// The effect is traveling to the target, if needed. /// /// /// The character walks to melee targets while in this stage. Spell effects /// also travel to the target while in this state. /// Advancing, /// /// The action is being applied to the target(s). /// Executing, /// /// The effect is returning from the target, if needed. /// /// /// The character walks back from the melee target while in this stage. /// Returning, /// /// The action is performing any final actions. /// Finishing, /// /// The action is complete. /// Complete, }; /// /// The current state of the action. /// protected CombatActionStage stage = CombatActionStage.NotStarted; /// /// The current state of the action. /// public CombatActionStage Stage { get { return stage; } } /// /// Starts a new combat stage. Called right after the stage changes. /// /// The stage never changes into NotStarted. protected virtual void StartStage() { switch (stage) { case CombatActionStage.Preparing: // called from Start() break; case CombatActionStage.Advancing: break; case CombatActionStage.Executing: break; case CombatActionStage.Returning: break; case CombatActionStage.Finishing: break; case CombatActionStage.Complete: break; } } /// /// Update the action for the current stage. /// /// /// This function is guaranteed to be called at least once per stage. /// protected virtual void UpdateCurrentStage(GameTime gameTime) { switch (stage) { case CombatActionStage.NotStarted: break; case CombatActionStage.Preparing: break; case CombatActionStage.Advancing: break; case CombatActionStage.Executing: break; case CombatActionStage.Returning: break; case CombatActionStage.Finishing: break; case CombatActionStage.Complete: break; } } /// /// Returns true if the combat action is ready to proceed to the next stage. /// protected virtual bool IsReadyForNextStage { get { switch (stage) { case CombatActionStage.Preparing: // ready to advance? break; case CombatActionStage.Advancing: // ready to execute? break; case CombatActionStage.Executing: // ready to return? break; case CombatActionStage.Returning: // ready to finish? break; case CombatActionStage.Finishing: // ready to complete? break; } // fall through - the action doesn't care about the state, so move on return true; } } #endregion #region Combatant /// /// The character performing this action. /// protected Combatant combatant; /// /// The character performing this action. /// public Combatant Combatant { get { return combatant; } } /// /// Returns true if the character can use this action. /// public virtual bool IsCharacterValidUser { get { return true; } } #endregion #region Target /// /// The target of the action. /// public Combatant Target = null; /// /// The number of adjacent targets in each direction that are affected. /// protected int adjacentTargets = 0; /// /// The number of adjacent targets in each direction that are affected. /// public int AdjacentTargets { get { return adjacentTargets; } } #endregion #region Heuristic /// /// The heuristic used to compare actions of this type to similar ones. /// public abstract int Heuristic { get; } /// /// Compares the combat actions by their heuristic, in descending order. /// public static int CompareCombatActionsByHeuristic( CombatAction a, CombatAction b) { return b.Heuristic.CompareTo(a.Heuristic); } #endregion #region Initialization /// /// Constructs a new CombatAction object. /// /// The combatant performing the action. public CombatAction(Combatant combatant) { // check the parameter if (combatant == null) { throw new ArgumentNullException("combatant"); } // assign the parameter this.combatant = combatant; Reset(); } /// /// Reset the action so that it may be started again. /// public virtual void Reset() { // set the state to not-started stage = CombatActionStage.NotStarted; } /// /// Start executing the combat action. /// public virtual void Start() { // set the state to the first step stage = CombatActionStage.Preparing; StartStage(); } #endregion #region Updating /// /// Updates the action over time. /// public virtual void Update(GameTime gameTime) { // update the current stage UpdateCurrentStage(gameTime); // if the action is ready for the next stage, then advance if ((stage != CombatActionStage.NotStarted) && (stage != CombatActionStage.Complete) && IsReadyForNextStage) { switch (stage) { case CombatActionStage.Preparing: stage = CombatActionStage.Advancing; break; case CombatActionStage.Advancing: stage = CombatActionStage.Executing; break; case CombatActionStage.Executing: stage = CombatActionStage.Returning; break; case CombatActionStage.Returning: stage = CombatActionStage.Finishing; break; case CombatActionStage.Finishing: stage = CombatActionStage.Complete; break; } StartStage(); } } #endregion #region Drawing /// /// Draw any elements of the action that are independent of the character. /// public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch) { } #endregion } }