using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Content; namespace CarFire { /// /// Trigger options modify trigger behavior. /// [Flags] public enum TriggerOptions { Default = 0x00, Reset = 0x01, // The script will be reset each time. Once = 0x02, // Trigger can only be fired once. Continuous = 0x04, // Trigger is always checked each update. } /// /// A trigger is an invisible entity whose only purpose is /// to check for a player to step on it and then run a script. /// public class Trigger : IEntity { #region Public Methods /// /// Construct a trigger entity. /// /// The entity identifier. /// The position. /// The key-value pairs. /// The game reference. public Trigger(char identifier, Point position, Dictionary info, Game game) { mId = identifier; mGame = game; mCoordinates = position; Functions functions = new Functions(this, game); string script; if (info.TryGetValue("script", out script)) { mScript = new Script(script, functions); } else throw new Exception("Triggers must define a script."); string options; if (info.TryGetValue("options", out options)) { string[] list = Parse.List(options); if (list != null) { foreach (string option in list) { TriggerOptions? flag = Parse.Constant(option); if (flag != null) mFlags |= flag.Value; } } } } /// /// Check for a player and execute the trigger script if /// there is a player on this cell. /// public void Call() { if (!mIsExpired) { Player player = mGame.GetPlayerAtCoordinates(mCoordinates); if (player != null) { if (!mIsFinished || (mFlags & TriggerOptions.Continuous) == TriggerOptions.Continuous) { mIsFinished = mScript.Run(player); if (mIsFinished && (mFlags & TriggerOptions.Once) == TriggerOptions.Once) mIsExpired = true; else if ((mFlags & TriggerOptions.Reset) == TriggerOptions.Reset) mScript.Reset(); } } else mIsFinished = false; } } /// /// Calls the trigger. /// /// Unused. public virtual void Update(TimeSpan timeSpan) { Call(); } public virtual void LoadContent(ContentManager contentManager) { // No implementation needed. } public virtual void Draw(SpriteBatch spriteBatch) { // No implementation needed. } public bool IsCollidable { get { return false; } } public Vector2 Position { get { return new Vector2(mCoordinates.X, mCoordinates.Y); } } public Point Coordinates { get { return mCoordinates; } set { mCoordinates = value; } } public char Identifier { get { return mId; } } public Game Game { get { return mGame; } } #endregion #region Private Types /// /// The script bindings. /// class Functions { // Always evaluates to true. public bool True(Player player, string[] args) { return true; } // Always evaluates to false. public bool False(Player player, string[] args) { return false; } // Check the player's inventory for an entity. // Arg1: Entity identifier. public bool Has(Player player, string[] args) { if (args.Length == 0) return false; char? entity = Parse.Char(args[0]); if (entity != null) { foreach (IEntity item in player.Inventory) { if (entity == item.Identifier) return true; } } return false; } // Put the trigger in the player's inventory. public bool PickUp(Player player, string[] args) { IEntity entity = mGame.RemoveEntity(mTrigger); if (entity != null) { player.Inventory.Add(entity); return true; } return false; } // Drop an entity from the player's inventory here. // Arg1: Entity identifier. public bool Drop(Player player, string[] args) { if (args.Length == 0) return false; char? entity = Parse.Char(args[0]); if (entity != null) { foreach (IEntity item in player.Inventory) { if (entity == item.Identifier) { player.Inventory.Remove(item); mGame.State.Entities.Add(item); item.Coordinates = mTrigger.Coordinates; return true; } } } return false; } // Use an entity in the player's inventory, disposing it. // Arg1: Entity identifier. public bool Use(Player player, string[] args) { if (args.Length == 0) return false; char? entity = Parse.Char(args[0]); if (entity != null) { foreach (IEntity item in player.Inventory) { if (entity == item.Identifier) { player.Inventory.Remove(item); return true; } } } return false; } // Wait for a ceretain number of ticks. // Arg1: Number of ticks. public bool Wait(Player player, string[] args) { if (args.Length == 0) return false; if (mTicks == 0) { int? timer = Parse.Integer(args[0]); if (timer != null) { mTicks = 1; mTimerTicks = timer.Value; } } else if (++mTicks >= mTimerTicks) { mTicks = 0; return true; } return false; } // Print each argument to the console as a string. public bool Print(Player player, string[] args) { foreach (string arg in args) { string line = Parse.String(arg); if (line != null) Console.WriteLine(line); } return true; } // Change a cell's tile on the map. // Arg1: The coordinates. // Arg2: The character representing the tile. public bool Set(Player player, string[] args) { if (args.Length < 2) return false; Point? coord = Parse.Coordinates(args[0]); if (coord != null) { char? tile = Parse.Char(args[1]); if (tile != null) { mGame.State.Map.SetCell(coord.Value, tile.Value); return true; } } return false; } // Move on to the next level. public bool Next(Player player, string[] args) { mGame.AdvanceLevel(); return true; } // Restart the current level. public bool Reset(Player player, string[] args) { mGame.Reset(); return true; } public Functions(IEntity trigger, Game game) { mTrigger = trigger; mGame = game; } IEntity mTrigger; Game mGame; int mTicks; int mTimerTicks; } #endregion #region Private Variables Script mScript; TriggerOptions mFlags; bool mIsFinished; bool mIsExpired; char mId; Game mGame; Point mCoordinates; #endregion } }