diff --git a/MudEngine/Commands/CommandExit.cs b/MudEngine/Commands/CommandExit.cs
index c9f875b..8d10d4b 100644
--- a/MudEngine/Commands/CommandExit.cs
+++ b/MudEngine/Commands/CommandExit.cs
@@ -1,9 +1,11 @@
-using System;
+//Microsoft.NET Framework
+using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
+//Mud Designer Game Engine
using MudEngine.FileSystem;
using MudEngine.GameObjects.Characters;
using MudEngine.GameManagement;
@@ -12,45 +14,73 @@ using MudEngine.GameObjects.Environment;
namespace MudEngine.Commands
{
+ ///
+ /// The Exit command is used to exit the MUD game.
+ /// Using this command while connected to a MUD server will perform a disconnect from the server.
+ /// Using the command while running the game in offline mode will simply shut down the game.
+ ///
public class CommandExit : IGameCommand
{
+ ///
+ /// Used by the Command Engine to allow for overriding any other commands that contain the same name.
+ /// TODO: Does Overriding Commands still work? This is part of some old code I wrote several years back and might be broke.
+ ///
public Boolean Override { get; set; }
+
+ ///
+ /// The name of the command.
+ /// If Override is set to true, this command will override any other command that contains the same name.
+ ///
public String Name { get; set; }
+
+ ///
+ /// A collection of strings that contains helpfull information for this Command.
+ /// When the user enteres 'Help Exit' the game will print the content of this collection.
+ /// This is treated like a virtual book, each entry in the collection is printed as a new line.
+ ///
public List Help { get; set; }
+ ///
+ /// Constructor for the class.
+ ///
public CommandExit()
{
+ //Instance the help collection and add our help information to it.
+ //Typically the Help content is placed within the constructor, but this particular help document
+ //needs to access information from the player, so we will build our Help collection in the Execute command.
Help = new List();
- Help.Add("Exits the game cleanly.");
}
+ ///
+ /// Executes the command.
+ /// This method is called from the Command Engine, it is not recommended that you call this method directly.
+ ///
+ ///
+ ///
public void Execute(String command, BaseCharacter player)
{
+ //Check if the game is multiplayer.
+ //Multiplayer games require disconnecting from the server and letting other players in the same Room know
+ //that this player has left.
if (player.ActiveGame.IsMultiplayer)
{
- //Let other players know that the user walked in.
- for (Int32 i = 0; i != player.ActiveGame.GetPlayerCollection().Length; i++)
- {
- if (player.ActiveGame.GetPlayerCollection()[i].Name == player.Name)
- continue;
+ //Query the Active Games Player collection so that we can build a collection of Players that need to be
+ //informed of the Player disconnecting from the Server.
+ var playerQuery =
+ from p in player.ActiveGame.GetPlayerCollection()
+ where !p.Name.StartsWith("New") && p.Name != player.Name && p.CurrentWorldLocation == player.CurrentWorldLocation
+ select p;
- String room = player.ActiveGame.GetPlayerCollection()[i].CurrentRoom.Name;
- String realm = player.ActiveGame.GetPlayerCollection()[i].CurrentRoom.Realm;
- String zone = player.ActiveGame.GetPlayerCollection()[i].CurrentRoom.Zone;
-
- if ((room == player.CurrentRoom.Name) && (realm == player.CurrentRoom.Realm) && (zone == player.CurrentRoom.Zone))
- {
- player.ActiveGame.GetPlayerCollection()[i].Send(player.Name + " has left.");
- }
- }
+ //Inform each player found in our LINQ query that the player has disconnected from the Server.
+ foreach (BaseCharacter p in playerQuery)
+ p.Send(player.Name + " has left."); ;
+ //TODO: If a player is in a Group then s/he needs to be removed upon disconnecting.
player.Disconnect();
}
else
{
- //Save the player prior to attempting to shutdown.
- //Player saving is handled in the server disconnect code but not in game shutdown.
- player.Save(player.ActiveGame.DataPaths.Players);
+ //Call the game's shutdown method which will save all objects and exit the game gracefully.
player.ActiveGame.Shutdown();
}
}
diff --git a/MudEngine/Commands/CommandGetTime.cs b/MudEngine/Commands/CommandGetTime.cs
index b138375..cc5b9a7 100644
--- a/MudEngine/Commands/CommandGetTime.cs
+++ b/MudEngine/Commands/CommandGetTime.cs
@@ -1,27 +1,59 @@
-using System;
+//Microsoft.NET Framework
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+//Mud Designer Game Engine
using MudEngine.GameObjects.Characters;
+using MudEngine.GameManagement;
namespace MudEngine.Commands
{
- public class CommandGetTime : MudEngine.GameManagement.IGameCommand
+ ///
+ /// The GetTime command is used to print the current in-game time to the player.
+ /// This command will print the day, month and year along with hour, minute and seconds.
+ ///
+ public class CommandGetTime : IGameCommand
{
+ ///
+ /// Used by the Command Engine to allow for overriding any other commands that contain the same name.
+ /// TODO: Does Overriding Commands still work? This is part of some old code I wrote several years back and might be broke.
+ ///
+ public Boolean Override { get; set; }
+
+ ///
+ /// The name of the command.
+ /// If Override is set to true, this command will override any other command that contains the same name.
+ ///
public String Name { get; set; }
- public Boolean Override { get; set; }
+ ///
+ /// A collection of strings that contains helpfull information for this Command.
+ /// When the user enteres 'Help Exit' the game will print the content of this collection.
+ /// This is treated like a virtual book, each entry in the collection is printed as a new line.
+ ///
public List Help { get; set; }
+ ///
+ /// Constructor for the class.
+ ///
public CommandGetTime()
{
+ //Instance the help collection and add our help information to it.
Help = new List();
Help.Add("Gives you the current time and date in the game world.");
}
+ ///
+ /// Executes the Command.
+ /// This method is called from the Command Engine, it is not recommended that you call this method directly.
+ ///
+ ///
+ ///
public void Execute(String command, BaseCharacter player)
{
+ //Send the returned String containing the World Time to the player.
player.Send(player.ActiveGame.WorldTime.GetCurrentWorldTime());
}
}
diff --git a/MudEngine/Commands/CommandLinkRoom.cs b/MudEngine/Commands/CommandLinkRoom.cs
index 3a43ee1..b3c959b 100644
--- a/MudEngine/Commands/CommandLinkRoom.cs
+++ b/MudEngine/Commands/CommandLinkRoom.cs
@@ -1,9 +1,11 @@
-using System;
+//Microsoft.NET Framework
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
+//Mud Designer Game Engine
using MudEngine.FileSystem;
using MudEngine.GameManagement;
using MudEngine.GameObjects;
@@ -12,29 +14,75 @@ using MudEngine.GameObjects.Environment;
namespace MudEngine.Commands
{
+ ///
+ /// The LinkRoom command is used to Link two previously created Rooms together.
+ /// Rooms linked together can be traversed by players.
+ /// This command is used to link Rooms dynamically during run-time by Admins, allowing environments to be created
+ /// and traversed on-the-fly without the need to modify scripts and re-start the server.
+ ///
public class CommandLinkRoom : IGameCommand
{
+ ///
+ /// Used by the Command Engine to allow for overriding any other commands that contain the same name.
+ /// TODO: Does Overriding Commands still work? This is part of some old code I wrote several years back and might be broke.
+ ///
public Boolean Override { get; set; }
+
+ ///
+ /// The name of the command.
+ /// If Override is set to true, this command will override any other command that contains the same name.
+ ///
public String Name { get; set; }
+
+ ///
+ /// A collection of strings that contains helpfull information for this Command.
+ /// When the user enteres 'Help Exit' the game will print the content of this collection.
+ /// This is treated like a virtual book, each entry in the collection is printed as a new line.
+ ///
public List Help { get; set; }
+ ///
+ /// Constructor for the class.
+ ///
public CommandLinkRoom()
{
+ //Instance the help collection and add our help information to it.
Help = new List();
- Help.Add("Use this to link two previously created Rooms together");
- Help.Add("Note that this command is not fully implemented and does not work.");
+ Help.Add("Use this to link two previously created Rooms together.");
+ //Incase Admins try to use the command, they will know that it's broken.
+ //Don't convert this class into a Script until it is fully completed.
+ Help.Add("NOTE: This command is not fully implemented and does not work.");
}
+ ///
+ /// Executes the command.
+ /// This method is called from the Command Engine, it is not recommended that you call this method directly.
+ ///
+ ///
+ ///
public void Execute(String command, BaseCharacter player)
{
+ //Check if the Player has the correct privileges to Link Rooms together.
+ //If they are not a Admin or GM then the command will bail.
+ //This creates the illusion that this command possibly doesn't exist.
+ if ((player.Role != SecurityRoles.Admin) && (player.Role != SecurityRoles.GM))
+ {
+ player.Send("Invalid Command.");
+ return;
+ }
+
+ //Build the Menu system that will be displayed to Admins.
player.Send("Room linkage tool");
player.Send("Please select an option.");
player.Send("1: Link Room");
player.Send("2: Exit");
+ //Read the input from the Admin.
string input = player.ReadInput();
Int32 value = 0;
+ //Attempt to convert their input from a String into a numerical value.
+ //If they entered a non-numerical value, then the method will exit
try
{
value = Convert.ToInt32(input);
@@ -45,122 +93,204 @@ namespace MudEngine.Commands
return;
}
+ //Ask what Room the Admin wants to use as the Departing Room.
+ //Departing Rooms will be where the travel direction originates from.
+ //meaning if the Admin selects West as the traveling direction, then traveling West will exit the
+ //Departing Room and enter the Arrival Room.
player.Send("");
player.Send("Please select which Realm your departing Room resides within:");
player.Send("");
+ //Instance a new Realm that we can use to reference an existing Realm so that we can find the
+ //Rooms within it that the Admin is looking for.
Boolean isValidRealm = false;
Realm realm = new Realm(player.ActiveGame);
+ //Create a Loop incase the Admin enters an invalid Realm, we can just loop
+ //back and re-ask the Admin the enter a valid Realm name.
while (!isValidRealm)
{
- isValidRealm = true;//Default to true, assume the user entered a valid name.
- foreach (Realm r in player.ActiveGame.World.RealmCollection)
- {
- player.Send(r.Filename + " | ", false);
- }
+ //Now that we are in the loop, set the isValidRealm to true, as we will assume that
+ //the user will enter a valid Realm name on the first shot. If we can't find a matching
+ //Realm, then this will get set to false once iterating through Realms is completed.
+ isValidRealm = true;
+ //Print each Realm out to the Admin so they may see a complete list to choose from.
+ //This is the Realm that their first Room will reside within.
+ //TODO: Currently only linking Rooms within the same Realm/Zone is supported. Need to fix that.
+ foreach (Realm r in player.ActiveGame.World.RealmCollection)
+ player.Send(r.Filename + " | ", false);
+
+ //As for the Admins selection, we will place the Admins input on the same line
+ //as the last message sent to the Admin by setting the newLine parameter to false.
player.Send("");
player.Send("Selection: ", false);
-
+
+ //Get the Admins input that should specify what Realm they are wanting.
input = player.ReadInput();
+ //Check if the Admin entered 'Cancel'. If so, then cancel the Link process.
if (input.ToLower() == "cancel")
{
player.Send("Room Linking aborted.");
return;
}
- //Ensure it's a valid name, if not then loop back and try again.
- foreach (Realm r in player.ActiveGame.World.RealmCollection)
- {
- if (r.Filename.ToLower() == input.ToLower())
- {
- isValidRealm = true;
- realm = r;
- break;
- }
- else
- {
- isValidRealm = false;
- }
- }
+ //Query the Active Games world collection, finding Realms that match the filename entered by the Admin
+ var realmQuery =
+ from r in player.ActiveGame.World.RealmCollection
+ where r.Filename.ToLower() == input.ToLower()
+ select r;
- if (!isValidRealm)
+ //Check if the query contains a Realm.
+ if (realmQuery.FirstOrDefault() != null)
+ {
+ //The query does in-fact contain a valid Realm. Assign it to our realm field for use later.
+ realm = realmQuery.FirstOrDefault();
+ //We can set this to true, allowing us to exit out of the loop.
+ isValidRealm = true;
+ }
+ //If the query does not contain a Realm, then we ensure that the loop will continue by forcing
+ //isValidRealm back to false.
+ else
+ {
+ isValidRealm = false;
+ //Let the Admin know that they entered an invalid Realm name and that they need to try again.
player.Send("That Realm does not exist! Please try again.");
+ }
}
+ //Let the Admin know that they need to now select which Zone the Room they are wanting to link resides within.
player.Send("");
player.Send("Please select which Zone your departing Room resides within:");
player.Send("");
+ //Instance a new Zone that we can use to reference an existing Zone so that we can find the
+ //Rooms within it that the Admin is looking for.
Boolean isValidZone = false;
Zone zone = new Zone(player.ActiveGame);
+ //Create a Loop incase the Admin enters an invalid Zone, we can just loop
+ //back and re-ask the Admin the enter a valid Zone name.
while (!isValidZone)
{
- isValidZone = true;//Default to true, assume the user entered a valid name.
+ //Now that we are in the loop, set the isValidZone to true, as we will assume that
+ //the user will enter a valid Zone name on the first shot. If we can't find a matching
+ //Zone, then this will get set to false once iterating through Zone is completed.
+ isValidZone = true;
+
+ //Print each Zone out to the Admin so they may see a complete list to choose from.
+ //This is the Zone that their first Room will reside within.
+ //TODO: Currently only linking Rooms within the same Realm/Zone is supported. Need to fix that.
foreach (Zone z in realm.ZoneCollection)
{
player.Send(z.Filename + " | ", false);
}
+ //As for the Admins selection, we will place the Admins input on the same line
+ //as the last message sent to the Admin by setting the newLine parameter to false.
player.Send("");
player.Send("Selection: ", false);
+ //Get the Admins input that should specify what Zone they are wanting.
input = player.ReadInput();
+ //Check if the Admin entered 'Cancel'. If so, then cancel the Link process.
if (input.ToLower() == "cancel")
{
player.Send("Room Linking aborted.");
return;
}
- //Ensure it's a valid name, if not then loop back and try again.
- foreach (Zone z in realm.ZoneCollection)
- {
- if (z.Filename.ToLower() == input.ToLower())
- {
- isValidZone = true;
- zone = z;
- break;
- }
- else
- {
- isValidZone = false;
- }
- }
+ //Query the stored Realm's Zone collection, finding Zones that match the filename entered by the Admin
+ var zoneQuery =
+ from z in realm.ZoneCollection
+ where z.Filename.ToLower() == input.ToLower()
+ select z;
- if (!isValidZone)
+ //Check if the query contains a Zone.
+ if (zoneQuery.FirstOrDefault() != null)
+ {
+ //The query does in-fact contain a valid Zone. Assign it to our zone field for use later.
+ zone = zoneQuery.FirstOrDefault();
+ //We can set this to true, allowing us to exit out of the loop.
+ isValidZone = true;
+ }
+ //If the query does not contain a Zone, then we ensure that the loop will continue by forcing
+ //isValidZone back to false.
+ else
+ {
+ isValidZone = false;
+ //Let the Admin know that they entered an invalid Zone name and that they need to try again.
player.Send("That Zone does not exist! Please try again.");
+ }
}
+ //Let the Admin know that they need to now select Room they are wanting to link as the departure Room
player.Send("");
player.Send("Please select which Room that you wish to be the departing Room:");
player.Send("");
+ //Instance a new Room that we can store a reference to a existing Room.
+ //We will use this reference to link the departure and arrival Rooms together.
Boolean isValidRoom = false;
Room departingRoom = new Room(player.ActiveGame);
+ //Create a Loop incase the Admin enters an invalid Room, we can just loop
+ //back and re-ask the Admin the enter a valid Room name.
while (!isValidRoom)
{
- isValidRoom = true;//Default to true, assume the user entered a valid name.
+ //Now that we are in the loop, set the isValidRoom to true, as we will assume that
+ //the user will enter a valid Room name on the first shot. If we can't find a matching
+ //Room, then this will get set to false once iterating through Room is completed.
+ isValidRoom = true;
+
+ //Print each Room out to the Admin so they may see a complete list to choose from.
+ //This will be their departing Room.
+ //TODO: Currently only linking Rooms within the same Realm/Zone is supported. Need to fix that.
foreach (Room r in zone.RoomCollection)
{
player.Send(r.Filename + " | ", false);
}
+ //As for the Admins selection, we will place the Admins input on the same line
+ //as the last message sent to the Admin by setting the newLine parameter to false.
player.Send("");
player.Send("Selection: ", false);
+ //Get the Admins input that should specify what Room they are wanting.
input = player.ReadInput();
+ //Check if the Admin entered 'Cancel'. If so, then cancel the Link process.
if (input.ToLower() == "cancel")
{
player.Send("Room Linking aborted.");
return;
}
+ //Query the referenced zone's Room collection, finding Rooms that match the filename entered by the Admin
+ var roomQuery =
+ from r in zone.RoomCollection
+ where r.Filename.ToLower() == input.ToLower()
+ select r;
+
+ //Check if the query contains a Room.
+ if (roomQuery.FirstOrDefault() != null)
+ {
+ //The query does in-fact contain a valid Room. Assign it to our departingRoom field for use later.
+ departingRoom = roomQuery.FirstOrDefault();
+ //We can set this to true, allowing us to exit out of the loop.
+ isValidRoom = true;
+ }
+ //If the query does not contain a Room, then we ensure that the loop will continue by forcing
+ //isValidRoom back to false.
+ else
+ {
+ isValidRoom = false;
+ //Let the Admin know that they entered an invalid Room name and that they need to try again.
+ player.Send("That Room does not exist! Please try again.");
+ }
+
//Ensure it's a valid name, if not then loop back and try again.
foreach (Room r in zone.RoomCollection)
{
diff --git a/MudEngine/GameObjects/Characters/BaseAI.cs b/MudEngine/GameObjects/Characters/BaseAI.cs
deleted file mode 100644
index f3c4e80..0000000
--- a/MudEngine/GameObjects/Characters/BaseAI.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using MudEngine.GameManagement;
-
-namespace MudEngine.GameObjects.Characters
-{
- public class BaseAI : BaseCharacter
- {
- public BaseAI(Game game) : base(game)
- {
- }
- }
-}
diff --git a/MudEngine/GameObjects/Characters/BaseCharacter.cs b/MudEngine/GameObjects/Characters/BaseCharacter.cs
index 40ee6b0..180db58 100644
--- a/MudEngine/GameObjects/Characters/BaseCharacter.cs
+++ b/MudEngine/GameObjects/Characters/BaseCharacter.cs
@@ -26,10 +26,33 @@
///
public Room CurrentRoom { get; set; }
+ public String CurrentWorldLocation
+ {
+ get
+ {
+ return CurrentRoom.Realm + "." + CurrentRoom.Zone + "." + CurrentRoom.Filename;
+ }
+ }
+
///
/// Gets or Sets if this Character is controlled by the user. If not user controlled then it will be AI controlled.
///
- public Boolean IsControlled { get; set; }
+ public Boolean IsControlled
+ {
+ get
+ {
+ return _IsControlled;
+ }
+ set
+ {
+ if (value)
+ {
+ //TODO: Begin AI initialization
+ }
+ _IsControlled = value;
+ }
+ }
+ private Boolean _IsControlled;
///
/// Gets if this user has Admin privileges or not.
diff --git a/MudEngine/GameObjects/Characters/BaseStats.cs b/MudEngine/GameObjects/Characters/BaseStats.cs
new file mode 100644
index 0000000..48eade9
--- /dev/null
+++ b/MudEngine/GameObjects/Characters/BaseStats.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MudEngine.GameObjects.Characters
+{
+ ///
+ /// This class is the base class that handles the managing of a Characters stats.
+ /// It was decided to place stats within their own class, to allow for developers to easily add additional
+ /// stats or adjust how stats are used within their MUD's without having to modify the Character code themselves.
+ ///
+ public class BaseStats
+ {
+ ///
+ /// Strength is a measure of muscle, endurance and stamina combined.
+ /// Strength affects the ability of characters to lift and carry weights, melee attack rolls,
+ /// damage rolls (for both melee and ranged weapons,) the Jump, Climb, and Swim skills,
+ /// several combat actions, and general checks involving moving or breaking stubborn objects.
+ ///
+ public Int32 Strength { get; set; }
+
+ ///
+ /// Dexterity encompasses a number of physical attributes including hand-eye coordination, agility,
+ /// reflexes, fine motor skills, balance and speed of movement; a high dexterity score indicates
+ /// superiority in all these attributes. Dexterity affects characters with regard to initiative in combat,
+ /// ranged attack rolls, Armor Class, Reflex saves, and the Balance, Escape Artist, Hide, Move Silently,
+ /// Open Lock, Ride, Sleight of Hand, Tumble, and Use Rope skills. It also affects the number of additional
+ /// attacks of opportunity granted by the Combat Reflexes feat. Dexterity is the ability most influenced by
+ /// outside influences (such as armor).
+ ///
+ public Int32 Dexterity { get; set; }
+
+ ///
+ /// Constitution is a term which encompasses the character's physique, toughness, health and resistance to disease and poison.
+ /// The higher a character's Constitution, the more hit points that character will have.
+ /// Constitution also is important for Fortitude saves, the Concentration skill, and fatigue-based general checks.
+ /// Constitution also determines the duration of a barbarian's rage.
+ /// Unlike the other ability scores, which render the character unconscious or immobile when they hit 0,
+ /// having 0 Constitution is fatal.
+ ///
+ public Int32 Constitution { get; set; }
+
+ ///
+ /// Intelligence is similar to IQ, but also includes mnemonic ability, reasoning and learning ability outside
+ /// those measured by the written word. Intelligence dictates the number of languages a character can learn,
+ /// and it influences the number of spells a preparation-based arcane spellcaster (like a Wizard) may cast per
+ /// day, and the effectiveness of said spells. It also affects how many skill points a character gains per level,
+ /// the Appraise, Craft, Decipher Script, Disable Device, Forgery, Knowledge, Search, and Spellcraft skills,
+ /// and bardic knowledge checks.
+ ///
+ public Int32 Intelligence { get; set; }
+
+ ///
+ /// Wisdom is a composite term for the characters enlightenment, judgement, wile, willpower and intuitiveness.
+ /// Wisdom influences the number of spells a divine spellcaster (like clerics, druids, paladins, and rangers)
+ /// can cast per day, and the effectiveness of said spells. It also affects Will saving throws, the Heal, Listen,
+ /// Profession, Sense Motive, Spot, and Survival skills, the effectiveness of the Stunning Fist feat, and a
+ /// monk's quivering palm attack.
+ ///
+ public Int32 Wisdom { get; set; }
+
+ ///
+ /// Charisma is the measure of the character's combined physical attractiveness, persuasiveness, and personal magnetism.
+ /// A generally non-beautiful character can have a very high charisma due to strong measures of the other two aspects of charisma.
+ /// Charisma influences how many spells spontaneous arcane spellcasters (like sorcerers and bards) can cast per day, and the
+ /// effectiveness of said spells. It also affects Bluff, Diplomacy, Disguise, Gather Information, Handle Animal,
+ /// Intimidate, Perform, and Use Magic Device checks, how often and how effectively clerics and paladins can turn
+ /// undead, the wild empathy of druids and rangers, and a paladin's lay on hands ability.
+ ///
+ public Int32 Charisma { get; set; }
+
+ }
+}
diff --git a/MudEngine/MudEngine.csproj b/MudEngine/MudEngine.csproj
index bfbcc53..2b12138 100644
--- a/MudEngine/MudEngine.csproj
+++ b/MudEngine/MudEngine.csproj
@@ -74,8 +74,8 @@
-
+