MudEngine:

- Re-worked the command system. All commands now only need 2 arguments rather than 4. The actual command string and the Player
 - All commands updated to work with the new command system
 - Look command now works in the example MudGame 
 - Realm now contains InitialZone for the starting Zone within that Realm.
 - Zone now contains InitialRoom for the starting Room within that Zone.
 - All Environment objects now contains a Initial property and Add() method for adding child objects.
 - BaseCharacter now contains a copy of Game
 - Revised Realm.GetZone()
 - Revised Zone.GetRoom()
 - Removed Zone.RebuildRoomCollection as content is currently no longer stored using physical files.
 - Added GameManagement.Log for logging errors and warnings to file. Use Log.Write().
This commit is contained in:
Scionwest_cp 2010-07-25 16:56:15 -07:00
parent 0587b4a475
commit 486efa4fed
16 changed files with 213 additions and 114 deletions

View file

@ -1,3 +1,6 @@
public class Player : MudEngine.GameObjects.Characters.Controlled.PlayerBasic public class Player : MudEngine.GameObjects.Characters.Controlled.PlayerBasic
{
public Player()
{ {
} }
}

View file

@ -10,6 +10,13 @@ namespace MUDGame.Environments
{ {
class Zeroth class Zeroth
{ {
Game game;
internal Zeroth(Game game)
{
this.game = game;
}
internal Realm BuildZeroth() internal Realm BuildZeroth()
{ {
Realm realm = new Realm(); Realm realm = new Realm();
@ -23,15 +30,15 @@ namespace MUDGame.Environments
zone.Description = "Your home is small and does not contain many items, but it's still your home and someplace you can relax after your battles."; zone.Description = "Your home is small and does not contain many items, but it's still your home and someplace you can relax after your battles.";
zone.IsSafe = true; zone.IsSafe = true;
zone.StatDrain = false; zone.StatDrain = false;
zone.IsStartingZone = true; zone.IsInitialZone = true;
//Build Rooms. //Build Rooms.
BuildHome(zone, realm); BuildHome(zone, realm);
zone.Realm = realm.Name; zone.Realm = realm.Name;
//TODO: Remove this, as Zones and Rooms contain .IsStarting properties now.
zone.EntranceRoom = "Bedroom"; realm.AddZone(zone);
realm.Zones.Add(zone); game.AddRealm(realm);
return realm; return realm;
} }
@ -43,7 +50,7 @@ namespace MUDGame.Environments
bedroom.Description = "This is your bedroom, it's small but comfortable. You have a bed, a book shelf and a rug on the floor."; bedroom.Description = "This is your bedroom, it's small but comfortable. You have a bed, a book shelf and a rug on the floor.";
bedroom.Zone = zone.Name; bedroom.Zone = zone.Name;
bedroom.Realm = realm.Name; bedroom.Realm = realm.Name;
bedroom.IsStartingRoom = true; bedroom.IsInitialRoom = true;
Room closet = new Room(); Room closet = new Room();
closet.Name = "Closet"; closet.Name = "Closet";
@ -64,8 +71,8 @@ namespace MUDGame.Environments
closet.Doorways.Add(door); closet.Doorways.Add(door);
//Todo: Should work once MUDEngine supports Types //Todo: Should work once MUDEngine supports Types
zone.Rooms.Add(bedroom); zone.AddRoom(bedroom);
zone.Rooms.Add(closet); zone.AddRoom(closet);
} }
} }
} }

View file

@ -14,7 +14,7 @@ namespace MUDGame
//Setup our Fields //Setup our Fields
static MudEngine.GameManagement.Game game; static MudEngine.GameManagement.Game game;
static MudEngine.GameManagement.CommandEngine commands; static MudEngine.GameManagement.CommandEngine commands;
static MudEngine.GameObjects.Characters.Controlled.PlayerAdmin user; static MudEngine.GameObjects.Characters.BaseCharacter player;
static List<MudEngine.GameObjects.Environment.Realm> realmCollection; static List<MudEngine.GameObjects.Environment.Realm> realmCollection;
@ -24,7 +24,6 @@ namespace MUDGame
game = new MudEngine.GameManagement.Game(); game = new MudEngine.GameManagement.Game();
commands = new MudEngine.GameManagement.CommandEngine(); commands = new MudEngine.GameManagement.CommandEngine();
realmCollection = new List<MudEngine.GameObjects.Environment.Realm>(); realmCollection = new List<MudEngine.GameObjects.Environment.Realm>();
user = new MudEngine.GameObjects.Characters.Controlled.PlayerAdmin();
//Setup the game //Setup the game
game.AutoSave = true; game.AutoSave = true;
@ -47,34 +46,32 @@ namespace MUDGame
//Create the world //Create the world
BuildRealms(); BuildRealms();
//Setup our starting location
foreach (MudEngine.GameObjects.Environment.Realm realm in realmCollection)
{
if (realm.IsInitialRealm)
{
game.SetInitialRealm(realm);
break;
}
}
if (game.InitialRealm == null)
Console.WriteLine("Critical Error: No Initial Realm defined!");
game.PlayerCollection = new List<MudEngine.GameObjects.Characters.Controlled.PlayerBasic>();
//Start the game. //Start the game.
MudEngine.GameManagement.CommandEngine.LoadAllCommands(); MudEngine.GameManagement.CommandEngine.LoadAllCommands();
//Player must be instanced AFTER BuildRealms as it needs Game.InitialRealm.InitialZone.InitialRoom
//property so that it can set it's starting room correctly.
player = new MudEngine.GameObjects.Characters.BaseCharacter(game);
// Start the server thread. // Start the server thread.
game.Start(); if (!game.Start())
Console.WriteLine("Error starting game!\nReview Log file for details.");
game.IsRunning = true; game.IsRunning = true;
game.PlayerCollection.Add(player);
while (game.IsRunning) while (game.IsRunning)
{ {
Console.Write("Command: "); Console.Write("Command: ");
string command = Console.ReadLine(); string command = Console.ReadLine();
user.ExecuteCommand(command, user, game, null); object[] result = player.ExecuteCommand(command).Result;
foreach (object o in result)
{
if (o is string)
Console.WriteLine(o.ToString());
}
} }
Console.WriteLine("Press Enter to exit."); Console.WriteLine("Press Enter to exit.");
@ -83,8 +80,8 @@ namespace MUDGame
static private void BuildRealms() static private void BuildRealms()
{ {
Zeroth zeroth = new Zeroth(); Zeroth zeroth = new Zeroth(game);
realmCollection.Add(zeroth.BuildZeroth()); zeroth.BuildZeroth();
} }
} }
} }

View file

@ -15,9 +15,9 @@ namespace MudEngine.Commands
public bool Override { get; set; } public bool Override { get; set; }
public string Name { get; set; } public string Name { get; set; }
public CommandResults Execute(string command, BaseCharacter player, Game game, Room room) public CommandResults Execute(string command, BaseCharacter player)
{ {
game.IsRunning = false; player.Game.IsRunning = false;
return new CommandResults(); return new CommandResults();
} }

View file

@ -17,17 +17,17 @@ namespace MudEngine.Commands
public string Name { get; set; } public string Name { get; set; }
public bool Override { get; set; } public bool Override { get; set; }
public CommandResults Execute(string command, BaseCharacter player, Game project, Room room) public CommandResults Execute(string command, BaseCharacter player)
{ {
StringBuilder desc = new StringBuilder(); StringBuilder desc = new StringBuilder();
if (room == null) if (player.CurrentRoom == null)
{ {
return new CommandResults("Not within a created Room."); return new CommandResults("Not within a created Room.");
} }
desc.AppendLine(room.Description); desc.AppendLine(player.CurrentRoom.Description);
foreach (Door door in room.Doorways) foreach (Door door in player.CurrentRoom.Doorways)
{ {
if (door.TravelDirection != MudEngine.GameObjects.AvailableTravelDirections.Down && door.TravelDirection != MudEngine.GameObjects.AvailableTravelDirections.Up) if (door.TravelDirection != MudEngine.GameObjects.AvailableTravelDirections.Down && door.TravelDirection != MudEngine.GameObjects.AvailableTravelDirections.Up)
{ {

View file

@ -21,17 +21,17 @@ namespace MudEngine.Commands
public string Name { get; set; } public string Name { get; set; }
public bool Override { get; set; } public bool Override { get; set; }
public CommandResults Execute(string command, BaseCharacter player, Game project, Room room) public CommandResults Execute(string command, BaseCharacter player)
{ {
if (player.IsAdmin) if (player.IsAdmin)
{ {
for (int i = 0; i < project.PlayerCollection.Count; i++) for (int i = 0; i < player.Game.PlayerCollection.Count; i++)
project.PlayerCollection[i].Save(project.PlayerCollection[i].Name + ".dat"); player.Game.PlayerCollection[i].Save(player.Game.PlayerCollection[i].Name + ".dat");
project.server.EndServer(); player.Game.Server.EndServer();
if (project.ServerType == ProtocolType.Tcp) if (player.Game.ServerType == ProtocolType.Tcp)
project.server.InitializeTCP(555, ref project.PlayerCollection); player.Game.Server.InitializeTCP(555, ref player.Game.PlayerCollection);
else else
project.server.InitializeUDP(555, ref project.PlayerCollection); player.Game.Server.InitializeUDP(555, ref player.Game.PlayerCollection);
return new CommandResults("Server Restarted."); return new CommandResults("Server Restarted.");
} }
return new CommandResults("Access Denied."); return new CommandResults("Access Denied.");

View file

@ -17,7 +17,7 @@ namespace MudEngine.Commands
public string Name { get; set; } public string Name { get; set; }
public bool Override { get; set; } public bool Override { get; set; }
public CommandResults Execute(string command, BaseCharacter player, Game project, Room room) public CommandResults Execute(string command, BaseCharacter player)
{ {
string[] words = command.Split(' '); string[] words = command.Split(' ');
List<string> directions = new List<string>(); List<string> directions = new List<string>();
@ -26,21 +26,22 @@ namespace MudEngine.Commands
return new CommandResults("No direction supplied"); return new CommandResults("No direction supplied");
else else
{ {
foreach (Door door in room.Doorways) foreach (Door door in player.CurrentRoom.Doorways)
{ {
AvailableTravelDirections direction = TravelDirections.GetTravelDirectionValue(words[1]); AvailableTravelDirections direction = TravelDirections.GetTravelDirectionValue(words[1]);
if (door.TravelDirection == direction) if (door.TravelDirection == direction)
{ {
room = (Room)room.Load(door.ConnectedRoom); //TODO: Player.Move() method needed so room loading is handled by player code.
player.CurrentRoom = (Room)player.CurrentRoom.Load(door.ConnectedRoom);
CommandResults cmd = CommandEngine.ExecuteCommand("Look", player, project, room); CommandResults cmd = CommandEngine.ExecuteCommand("Look", player);
string lookValue = ""; string lookValue = "";
if (cmd.Result.Length != 0) if (cmd.Result.Length != 0)
lookValue = cmd.Result[0].ToString(); lookValue = cmd.Result[0].ToString();
return new CommandResults(new object[] { lookValue, room }); return new CommandResults(new object[] { lookValue, player.CurrentRoom });
} }
} }
} }

View file

@ -46,14 +46,14 @@ namespace MudEngine.GameManagement
/// <param name="Name"></param> /// <param name="Name"></param>
/// <param name="Parameter"></param> /// <param name="Parameter"></param>
/// <returns></returns> /// <returns></returns>
public static CommandResults ExecuteCommand(string command, BaseCharacter player, Game project, Room room) public static CommandResults ExecuteCommand(string command, BaseCharacter player)
{ {
string commandKey = command.Insert(0, "Command"); string commandKey = command.Insert(0, "Command");
foreach (string key in Commands.Keys) foreach (string key in Commands.Keys)
{ {
if (commandKey.ToLower().Contains(key.ToLower())) if (commandKey.ToLower().Contains(key.ToLower()))
{ {
return Commands[key.ToLower()].Execute(command, player, project, room); return Commands[key.ToLower()].Execute(command, player);
} }
} }

View file

@ -147,6 +147,10 @@ namespace MudEngine.GameManagement
get; get;
private set; private set;
} }
/// <summary>
/// Gets the collection of Realms currently stored in the Game.
/// </summary>
public List<Realm> RealmCollection { get; private set; }
[Browsable(false)] [Browsable(false)]
public string Story public string Story
@ -168,27 +172,27 @@ namespace MudEngine.GameManagement
public Game() public Game()
{ {
CurrencyList = new List<Currency>(); CurrencyList = new List<Currency>();
scriptEngine = new Scripting.ScriptEngine();
RealmCollection = new List<Realm>();
PlayerCollection = new List<BaseCharacter>();
GameTitle = "New Game"; GameTitle = "New Game";
_Filename = "Game.xml"; _Filename = "Game.xml";
BaseCurrencyAmount = 1; BaseCurrencyAmount = 1;
BaseCurrencyName = "Copper"; BaseCurrencyName = "Copper";
scriptEngine.Initialize();
//Get the new
} }
/// <summary> /// <summary>
/// Starts the game. /// Starts the game.
/// </summary> /// </summary>
public void Start() public bool Start()
{ {
this.StartServer(); //Setup the scripting engine
scriptEngine = new Scripting.ScriptEngine();
scriptEngine.Initialize(); scriptEngine.Initialize();
scriptEngine.ScriptPath = "Scripts"; scriptEngine.ScriptPath = "Scripts";
scriptEngine.ScriptExtension = ".mud"; scriptEngine.ScriptExtension = ".mud";
//Load our scripts library
if (System.IO.File.Exists("Scripts.dll")) if (System.IO.File.Exists("Scripts.dll"))
{ {
Assembly assem = Assembly.LoadFile("Scripts.dll"); Assembly assem = Assembly.LoadFile("Scripts.dll");
@ -203,6 +207,27 @@ namespace MudEngine.GameManagement
} }
} }
} }
//See if we have an Initial Realm set
foreach (Realm r in RealmCollection)
{
if (r.IsInitialRealm)
{
InitialRealm = r;
break;
}
}
if (InitialRealm == null)
{
Log.Write("ERROR: No initial realm set, un-able to finish starting of Game");
return false;
}
//Start the Telnet server
this.StartServer();
return true;
} }
public void Save(string filename) public void Save(string filename)
@ -226,15 +251,29 @@ namespace MudEngine.GameManagement
return FileManager.Load(fileName, this); return FileManager.Load(fileName, this);
} }
public void SetInitialRealm(Realm realm) public void AddRealm(Realm realm)
{ {
if (realm.IsInitialRealm)
{
foreach (Realm r in RealmCollection)
{
if (r.IsInitialRealm)
{
r.IsInitialRealm = false;
break;
}
}
}
//TODO: Check for duplicate Realms.
RealmCollection.Add(realm);
InitialRealm = realm; InitialRealm = realm;
} }
//TODO: This should be internal only; C# property using get; internal set; so only MudEngine.dll may edit this collection
public List<BaseCharacter> PlayerCollection; public List<BaseCharacter> PlayerCollection;
public MudEngine.Networking.Server server = new MudEngine.Networking.Server(); public MudEngine.Networking.Server Server { get; internal set; }
public ProtocolType ServerType = ProtocolType.Tcp; public ProtocolType ServerType = ProtocolType.Tcp;
public int ServerPort = 555; public int ServerPort = 555;
public int MaximumPlayers = 1000; public int MaximumPlayers = 1000;
@ -243,8 +282,9 @@ namespace MudEngine.GameManagement
private void StartServer() private void StartServer()
{ {
server.InitializeTCP(ServerPort, ref PlayerCollection); Server = new Networking.Server();
server.Start(); Server.InitializeTCP(ServerPort, ref PlayerCollection);
Server.Start();
} }
} }
} }

View file

@ -19,6 +19,6 @@ namespace MudEngine.GameManagement
//Used to override commands with the same name //Used to override commands with the same name
bool Override { get; set; } bool Override { get; set; }
//Executes the command. //Executes the command.
CommandResults Execute(string command, BaseCharacter player, Game project, Room room); CommandResults Execute(string command, BaseCharacter player);
} }
} }

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MudEngine.FileSystem;
namespace MudEngine.GameManagement
{
public static class Log
{
public static void Write(string message)
{
string filename = Path.Combine(FileManager.GetDataPath(SaveDataTypes.Root), "Log.txt");
StreamWriter sw;
if (File.Exists(filename))
sw = File.AppendText(filename);
else
sw = File.CreateText(filename);
sw.WriteLine(message);
sw.Close();
}
}
}

View file

@ -31,6 +31,17 @@ namespace MudEngine.GameObjects.Characters
/// </summary> /// </summary>
public Boolean IsAdmin { get; private set; } public Boolean IsAdmin { get; private set; }
/// <summary>
/// Gets a reference to the currently running game.
/// </summary>
public Game Game { get; private set; }
public BaseCharacter(Game game)
{
Game = game;
CurrentRoom = game.InitialRealm.InitialZone.InitialRoom;
}
public virtual void OnTravel(AvailableTravelDirections travelDirection) public virtual void OnTravel(AvailableTravelDirections travelDirection)
{ {
if (CurrentRoom.DoorwayExist(travelDirection.ToString())) if (CurrentRoom.DoorwayExist(travelDirection.ToString()))
@ -40,15 +51,16 @@ namespace MudEngine.GameObjects.Characters
} }
} }
public CommandResults ExecuteCommand(string command, BaseCharacter character, Game game, Room room) public CommandResults ExecuteCommand(string command)
{ {
//TODO: Character class can handle a lot of the command management here, checking various things prior to sending //TODO: Character class can handle a lot of the command management here, checking various things prior to sending
//the command off to the command engine for execution. //the command off to the command engine for execution.
return CommandEngine.ExecuteCommand(command, character, game, room); return CommandEngine.ExecuteCommand(command, this);
} }
public void Initialize(ref MudEngine.Networking.ClientSocket rcs) public void Initialize(ref MudEngine.Networking.ClientSocket rcs)
{ {
CurrentRoom = Game.InitialRealm.InitialZone.InitialRoom;
sock = rcs; sock = rcs;
} }

View file

@ -18,13 +18,21 @@ namespace MudEngine.GameObjects.Environment
[Category("Environment Information")] [Category("Environment Information")]
[Description("A collection of Zones that are contained within this Realm. Players can traverse the world be traveling through Rooms that are contained within Zones. Note that it is not required to place a Zone into a Realm.")] [Description("A collection of Zones that are contained within this Realm. Players can traverse the world be traveling through Rooms that are contained within Zones. Note that it is not required to place a Zone into a Realm.")]
//[EditorAttribute(typeof(UIRealmEditor), typeof(System.Drawing.Design.UITypeEditor))] //[EditorAttribute(typeof(UIRealmEditor), typeof(System.Drawing.Design.UITypeEditor))]
public List<Zone> Zones { get; set; } public List<Zone> ZoneCollection { get; private set; }
/// <summary>
/// Gets or Sets if this Realm is the starting realm for the game.
/// </summary>
public bool IsInitialRealm { get; set; } public bool IsInitialRealm { get; set; }
/// <summary>
/// The Initial Starting Zone for this Realm.
/// </summary>
public Zone InitialZone { get; private set; }
public Realm() public Realm()
{ {
Zones = new List<Zone>(); ZoneCollection = new List<Zone>();
} }
/// <summary> /// <summary>
@ -34,16 +42,31 @@ namespace MudEngine.GameObjects.Environment
/// <returns></returns> /// <returns></returns>
public Zone GetZone(string filename) public Zone GetZone(string filename)
{ {
var filterQuery = foreach (Zone zone in ZoneCollection)
from zone in Zones {
where zone.Filename == filename if (zone.Filename == filename)
select zone; return zone;
}
Zone z = new Zone();
foreach (var zone in filterQuery)
return (Zone)z.Load(zone.Filename);
return null; return null;
} }
public void AddZone(Zone zone)
{
if (zone.IsInitialZone)
{
foreach (Zone z in ZoneCollection)
{
if (z.IsInitialZone)
{
z.IsInitialZone = false;
break;
}
}
}
InitialZone = zone;
ZoneCollection.Add(zone);
}
} }
} }

View file

@ -103,7 +103,7 @@ namespace MudEngine.GameObjects.Environment
/// </summary> /// </summary>
[Browsable(true)] [Browsable(true)]
[Description("Sets if this is the starting room for the Zone that contains it.")] [Description("Sets if this is the starting room for the Zone that contains it.")]
public bool IsStartingRoom public bool IsInitialRoom
{ {
get; get;
set; set;

View file

@ -58,7 +58,7 @@ namespace MudEngine.GameObjects.Environment
[Category("Environment Information")] [Category("Environment Information")]
[Description("Sets that this Zone is a starting Zone for the game.")] [Description("Sets that this Zone is a starting Zone for the game.")]
[DefaultValue(false)] [DefaultValue(false)]
public bool IsStartingZone public bool IsInitialZone
{ {
get; get;
set; set;
@ -67,14 +67,17 @@ namespace MudEngine.GameObjects.Environment
[Category("Environment Information")] [Category("Environment Information")]
//[EditorAttribute(typeof(UIRoomEditor), typeof(UITypeEditor))] //[EditorAttribute(typeof(UIRoomEditor), typeof(UITypeEditor))]
[Description("Collection of Rooms that have been created. Editing the Rooms Collection lets you manage the Zones rooms.")] [Description("Collection of Rooms that have been created. Editing the Rooms Collection lets you manage the Zones rooms.")]
public List<Room> Rooms { get; set; } public List<Room> RoomCollection { get; private set; }
/// <summary>
/// Gets the initial Room for this Zone.
/// </summary>
[Category("Environment Information")] [Category("Environment Information")]
public string EntranceRoom { get; set; } public Room InitialRoom { get; private set; }
public Zone() public Zone()
{ {
Rooms = new List<Room>(); RoomCollection = new List<Room>();
IsSafe = false; IsSafe = false;
Realm = "No Realm Associated."; Realm = "No Realm Associated.";
} }
@ -84,53 +87,38 @@ namespace MudEngine.GameObjects.Environment
/// </summary> /// </summary>
/// <param name="RoomName"></param> /// <param name="RoomName"></param>
/// <returns></returns> /// <returns></returns>
public Room GetRoomByName(string name) public Room GetRoom(string name)
{ {
var filterQuery = foreach (Room room in RoomCollection)
from room in Rooms
where room.Name == name
select room;
foreach (Room room in filterQuery)
{ {
Room r = new Room(); if (room.Name == name)
return (Room)r.Load(room.Name, this.Name); return room;
} }
return null; return null;
} }
/// <summary> /// <summary>
/// Clears out the Zones room collection and re-builds it. /// Adds the supplied room into the Zones Room collection.
/// This is a time consuming process if there are a large amount of
/// of rooms, use sparingly.
/// </summary> /// </summary>
public void RebuildRoomCollection() /// <param name="room"></param>
public void AddRoom(Room room)
{ {
Rooms = new List<Room>(); if (room.IsInitialRoom)
//Create our collection of Rooms.
string realmPath = Path.Combine(FileManager.GetDataPath(SaveDataTypes.Realms), this.Realm);
string zonePath = Path.Combine(realmPath, this.Name);
//incase the zone hasn't been saved yet.
if (!Directory.Exists(zonePath))
return;
//Zone exists, so it's already been saved.
string[] rooms = Directory.GetFiles(zonePath, "*.room");
//Clear the existing collection of Rooms
this.Rooms.Clear();
//Build a new one based off of the files
foreach (string file in rooms)
{ {
Room r = new Room(); //Look if we already have a initial room. If so change it. Only 1 InitialRoom per Zone permitted.
r = (Room)r.Load(Path.GetFileNameWithoutExtension(file)); foreach (Room r in RoomCollection)
//r = (Room)FileManager.Load(file, r); {
this.Rooms.Add(r); if (r.IsInitialRoom)
{
r.IsInitialRoom = false;
break;
}
}
} }
//Save the re-built Room collection RoomCollection.Add(room);
this.Save(Path.Combine(zonePath, this.Filename)); if (room.IsInitialRoom)
InitialRoom = room;
} }
} }
} }

View file

@ -60,6 +60,7 @@
<Compile Include="FileSystem\SaveDataTypes.cs" /> <Compile Include="FileSystem\SaveDataTypes.cs" />
<Compile Include="FileSystem\XmlSerialization.cs" /> <Compile Include="FileSystem\XmlSerialization.cs" />
<Compile Include="GameManagement\Game.cs" /> <Compile Include="GameManagement\Game.cs" />
<Compile Include="GameManagement\Log.cs" />
<Compile Include="GameObjects\Bag.cs" /> <Compile Include="GameObjects\Bag.cs" />
<Compile Include="GameObjects\BaseObject.cs" /> <Compile Include="GameObjects\BaseObject.cs" />
<Compile Include="GameObjects\Characters\BaseCharacter.cs" /> <Compile Include="GameObjects\Characters\BaseCharacter.cs" />