public void HandlePacket(GameClient client, GSPacketIn packet)
        {
            string accountName = packet.ReadString(24);

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("CharacterCreateRequestHandler for account {0} using version {1}", accountName, client.Version);
            }

            if (!accountName.StartsWith(client.Account.Name))            // TODO more correctly check, client send accountName as account-S, -N, -H (if it not fit in 20, then only account)
            {
                if (ServerProperties.Properties.BAN_HACKERS)
                {
                    client.BanAccount(string.Format("Autoban wrong Account '{0}'", accountName));
                }

                client.Disconnect();
                return;
            }

            // Realm
            eRealm currentRealm = eRealm.None;

            if (accountName.EndsWith("-S"))
            {
                currentRealm = eRealm.Albion;
            }
            else if (accountName.EndsWith("-N"))
            {
                currentRealm = eRealm.Midgard;
            }
            else if (accountName.EndsWith("-H"))
            {
                currentRealm = eRealm.Hibernia;
            }


            // Client character count support
            int  charsCount  = client.Version < GameClient.eClientVersion.Version173 ? 8 : 10;
            bool needRefresh = false;

            for (int i = 0; i < charsCount; i++)
            {
                var pakdata = new CreationCharacterData(packet, client);

                // Graveen: changed the following to allow GMs to have special chars in their names (_,-, etc..)
                var nameCheck = new Regex("^[A-Z][a-zA-Z]");
                if (!string.IsNullOrEmpty(pakdata.CharName) && (pakdata.CharName.Length < 3 || !nameCheck.IsMatch(pakdata.CharName)))
                {
                    if ((ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
                    {
                        if (ServerProperties.Properties.BAN_HACKERS)
                        {
                            client.BanAccount(string.Format("Autoban bad CharName '{0}'", pakdata.CharName));
                        }

                        client.Disconnect();
                        return;
                    }
                }

                switch ((eOperation)pakdata.Operation)
                {
                case eOperation.Delete:
                    if (string.IsNullOrEmpty(pakdata.CharName))
                    {
                        // Deletion in 1.104+ check for removed character.
                        needRefresh |= CheckForDeletedCharacter(accountName, client, i);
                    }
                    break;

                case eOperation.Customize:
                    if (!string.IsNullOrEmpty(pakdata.CharName))
                    {
                        // Candidate for Customizing ?
                        var character = client.Account.Characters != null?client.Account.Characters.FirstOrDefault(ch => ch.Name.Equals(pakdata.CharName, StringComparison.OrdinalIgnoreCase)) : null;

                        if (character != null)
                        {
                            needRefresh |= CheckCharacterForUpdates(pakdata, client, character);
                        }
                    }
                    break;

                case eOperation.Create:
                    if (!string.IsNullOrEmpty(pakdata.CharName))
                    {
                        // Candidate for Creation ?
                        var character = client.Account.Characters != null?client.Account.Characters.FirstOrDefault(ch => ch.Name.Equals(pakdata.CharName, StringComparison.OrdinalIgnoreCase)) : null;

                        if (character == null)
                        {
                            needRefresh |= CreateCharacter(pakdata, client, i);
                        }
                    }
                    break;

                default:
                    break;
                }
            }

            if (needRefresh)
            {
                client.Out.SendCharacterOverview(currentRealm);
            }
        }
        /// <summary>
        /// Check if a Character Needs update based to packet data
        /// </summary>
        /// <param name="pdata">packet data</param>
        /// <param name="client">client</param>
        /// <param name="character">db character</param>
        /// <returns>True if character need refreshment false if no refresh needed.</returns>
        private bool CheckCharacterForUpdates(CreationCharacterData pdata, GameClient client, DOLCharacters character)
        {
            int newModel = character.CurrentModel;

            if (pdata.CustomMode == 1 || pdata.CustomMode == 2 || pdata.CustomMode == 3)
            {
                bool flagChangedStats = false;

                if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION)
                {
                    character.EyeSize   = (byte)pdata.EyeSize;
                    character.LipSize   = (byte)pdata.LipSize;
                    character.EyeColor  = (byte)pdata.EyeColor;
                    character.HairColor = (byte)pdata.HairColor;
                    character.FaceType  = (byte)pdata.FaceType;
                    character.HairStyle = (byte)pdata.HairStyle;
                    character.MoodType  = (byte)pdata.MoodType;
                }

                if (pdata.CustomMode != 3 && client.Version >= GameClient.eClientVersion.Version189)
                {
                    var stats = new Dictionary <eStat, int>();
                    stats[eStat.STR] = pdata.Strength;                  // Strength
                    stats[eStat.DEX] = pdata.Dexterity;                 // Dexterity
                    stats[eStat.CON] = pdata.NewConstitution;           // New Constitution
                    stats[eStat.QUI] = pdata.Quickness;                 // Quickness
                    stats[eStat.INT] = pdata.Intelligence;              // Intelligence
                    stats[eStat.PIE] = pdata.Piety;                     // Piety
                    stats[eStat.EMP] = pdata.Empathy;                   // Empathy
                    stats[eStat.CHR] = pdata.Charisma;                  // Charisma

                    // check for changed stats.
                    flagChangedStats |= stats[eStat.STR] != character.Strength;
                    flagChangedStats |= stats[eStat.CON] != character.Constitution;
                    flagChangedStats |= stats[eStat.DEX] != character.Dexterity;
                    flagChangedStats |= stats[eStat.QUI] != character.Quickness;
                    flagChangedStats |= stats[eStat.INT] != character.Intelligence;
                    flagChangedStats |= stats[eStat.PIE] != character.Piety;
                    flagChangedStats |= stats[eStat.EMP] != character.Empathy;
                    flagChangedStats |= stats[eStat.CHR] != character.Charisma;

                    if (flagChangedStats)
                    {
                        ICharacterClass charClass = ScriptMgr.FindCharacterClass(character.Class);

                        if (charClass != null)
                        {
                            int  points;
                            bool valid = IsCustomPointsDistributionValid(character, stats, out points);

                            // Hacking attemp ?
                            if (points > MAX_STARTING_BONUS_POINTS)
                            {
                                if ((ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
                                {
                                    if (ServerProperties.Properties.BAN_HACKERS)
                                    {
                                        client.BanAccount(string.Format("Autoban Hack char update : Wrong allowed points:{0}", points));
                                    }

                                    client.Disconnect();
                                    return(false);
                                }
                            }

                            // Error in setting points
                            if (!valid)
                            {
                                return(true);
                            }

                            if (Properties.ALLOW_CUSTOMIZE_STATS_AFTER_CREATION)
                            {
                                // Set Stats, valid is ok.
                                character.Strength     = stats[eStat.STR];
                                character.Constitution = stats[eStat.CON];
                                character.Dexterity    = stats[eStat.DEX];
                                character.Quickness    = stats[eStat.QUI];
                                character.Intelligence = stats[eStat.INT];
                                character.Piety        = stats[eStat.PIE];
                                character.Empathy      = stats[eStat.EMP];
                                character.Charisma     = stats[eStat.CHR];

                                if (log.IsInfoEnabled)
                                {
                                    log.InfoFormat("Character {0} Stats updated in cache!", character.Name);
                                }

                                if (client.Player != null)
                                {
                                    foreach (var stat in stats.Keys)
                                    {
                                        client.Player.ChangeBaseStat(stat, (short)(stats[stat] - client.Player.GetBaseStat(stat)));
                                    }

                                    if (log.IsInfoEnabled)
                                    {
                                        log.InfoFormat("Character {0} Player Stats updated in cache!", character.Name);
                                    }
                                }
                            }
                        }
                        else if (log.IsErrorEnabled)
                        {
                            log.ErrorFormat("No CharacterClass with ID {0} found", character.Class);
                        }
                    }
                }


                if (pdata.CustomMode == 2)                 // change player customization
                {
                    if (client.Account.PrivLevel == 1 && ((pdata.CreationModel >> 11) & 3) == 0)
                    {
                        if (ServerProperties.Properties.BAN_HACKERS)                         // Player size must be > 0 (from 1 to 3)
                        {
                            client.BanAccount(string.Format("Autoban Hack char update : zero character size in model:{0}", newModel));
                            client.Disconnect();
                            return(false);
                        }
                        return(true);
                    }

                    character.CustomisationStep = 2;                     // disable config button

                    if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION)
                    {
                        if (pdata.CreationModel != character.CreationModel)
                        {
                            character.CurrentModel = newModel;
                        }

                        if (log.IsInfoEnabled)
                        {
                            log.InfoFormat("Character {0} face properties configured by account {1}!", character.Name, client.Account.Name);
                        }
                    }
                }
                else if (pdata.CustomMode == 3)                 //auto config -- seems someone thinks this is not possible?
                {
                    character.CustomisationStep = 3;            // enable config button to player
                }

                //Save the character in the database
                GameServer.Database.SaveObject(character);
            }

            return(false);
        }
        private bool CreateCharacter(CreationCharacterData pdata, GameClient client, int accountSlot)
        {
            Account account = client.Account;
            var     ch      = new DOLCharacters();

            ch.AccountName = account.Name;
            ch.Name        = pdata.CharName;

            if (pdata.CustomMode == 0x01)
            {
                ch.EyeSize           = (byte)pdata.EyeSize;
                ch.LipSize           = (byte)pdata.LipSize;
                ch.EyeColor          = (byte)pdata.EyeColor;
                ch.HairColor         = (byte)pdata.HairColor;
                ch.FaceType          = (byte)pdata.FaceType;
                ch.HairStyle         = (byte)pdata.HairStyle;
                ch.MoodType          = (byte)pdata.MoodType;
                ch.CustomisationStep = 2;                 // disable config button

                if (log.IsDebugEnabled)
                {
                    log.Debug("Disable Config Button");
                }
            }

            ch.Level = 1;
            // Set Realm and Class
            ch.Realm = pdata.Realm;
            ch.Class = pdata.Class;

            // Set Account Slot, Gender
            ch.AccountSlot = accountSlot + ch.Realm * 100;
            ch.Gender      = pdata.Gender;

            // Set Race
            ch.Race = pdata.Race;

            ch.CreationModel = pdata.CreationModel;
            ch.CurrentModel  = ch.CreationModel;
            ch.Region        = pdata.Region;

            ch.Strength     = pdata.Strength;
            ch.Dexterity    = pdata.Dexterity;
            ch.Constitution = pdata.Constitution;
            ch.Quickness    = pdata.Quickness;
            ch.Intelligence = pdata.Intelligence;
            ch.Piety        = pdata.Piety;
            ch.Empathy      = pdata.Empathy;
            ch.Charisma     = pdata.Charisma;

            // defaults
            ch.CreationDate = DateTime.Now;

            ch.Endurance     = 100;
            ch.MaxEndurance  = 100;
            ch.Concentration = 100;
            ch.MaxSpeed      = GamePlayer.PLAYER_BASE_SPEED;

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("Creation {0} character, class:{1}, realm:{2}", client.Version, ch.Class, ch.Realm);
            }

            // Is class disabled ?
            int           occurences       = 0;
            List <string> disabled_classes = Properties.DISABLED_CLASSES.SplitCSV(true);

            occurences = (from j in disabled_classes
                          where j == ch.Class.ToString()
                          select j).Count();

            if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
            {
                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("Client {0} tried to create a disabled classe: {1}", client.Account.Name, (eCharacterClass)ch.Class);
                }

                return(true);
            }

            // check if race disabled
            List <string> disabled_races = Properties.DISABLED_RACES.SplitCSV(true);

            occurences = (from j in disabled_races
                          where j == ch.Race.ToString()
                          select j).Count();

            if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
            {
                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("Client {0} tried to create a disabled race: {1}", client.Account.Name, (eRace)ch.Race);
                }

                return(true);
            }


            // If sending invalid Class ID
            if (!Enum.IsDefined(typeof(eCharacterClass), (eCharacterClass)ch.Class))
            {
                if (log.IsErrorEnabled)
                {
                    log.ErrorFormat("{0} tried to create a character with wrong class ID: {1}, realm:{2}", client.Account.Name, ch.Class, ch.Realm);
                }

                if (ServerProperties.Properties.BAN_HACKERS)
                {
                    client.BanAccount(string.Format("Autoban character create class: id:{0} realm:{1} name:{2} account:{3}", ch.Class, ch.Realm, ch.Name, account.Name));
                    client.Disconnect();
                    return(false);
                }
                return(true);
            }

            // check if client tried to create invalid char
            if (!IsCharacterValid(ch))
            {
                if (log.IsWarnEnabled)
                {
                    log.WarnFormat("{0} tried to create invalid character:\nchar name={1}, gender={2}, race={3}, realm={4}, class={5}, region={6}" +
                                   "\nstr={7}, con={8}, dex={9}, qui={10}, int={11}, pie={12}, emp={13}, chr={14}", ch.AccountName, ch.Name, ch.Gender,
                                   ch.Race, ch.Realm, ch.Class, ch.Region, ch.Strength, ch.Constitution, ch.Dexterity, ch.Quickness, ch.Intelligence, ch.Piety, ch.Empathy, ch.Charisma);
                }
                return(true);
            }

            //Save the character in the database
            GameServer.Database.AddObject(ch);

            // Fire the character creation event
            // This is Where Most Creation Script should take over to update any data they would like !
            GameEventMgr.Notify(DatabaseEvent.CharacterCreated, null, new CharacterEventArgs(ch, client));

            //write changes
            GameServer.Database.SaveObject(ch);

            // Log creation
            AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.CharacterCreate, "", pdata.CharName);

            client.Account.Characters = null;

            if (log.IsInfoEnabled)
            {
                log.InfoFormat("Character {0} created on Account {1}!", pdata.CharName, account);
            }

            // Reload Account Relations
            GameServer.Database.FillObjectRelations(client.Account);

            return(true);
        }
		public void HandlePacket(GameClient client, GSPacketIn packet)
		{
			string accountName = packet.ReadString(24);

			if (log.IsDebugEnabled)
				log.DebugFormat("CharacterCreateRequestHandler for account {0} using version {1}", accountName, client.Version);

			if (!accountName.StartsWith(client.Account.Name))// TODO more correctly check, client send accountName as account-S, -N, -H (if it not fit in 20, then only account)
			{
				if (ServerProperties.Properties.BAN_HACKERS)
					client.BanAccount(string.Format("Autoban wrong Account '{0}'", accountName));

				client.Disconnect();
				return;
			}
			
			// Realm
			eRealm currentRealm = eRealm.None;
			if (accountName.EndsWith("-S")) currentRealm = eRealm.Albion;
			else if (accountName.EndsWith("-N")) currentRealm = eRealm.Midgard;
			else if (accountName.EndsWith("-H")) currentRealm = eRealm.Hibernia;

			
			// Client character count support
			int charsCount = client.Version < GameClient.eClientVersion.Version173 ? 8 : 10;
			bool needRefresh = false;
			
			for (int i = 0; i < charsCount; i++)
			{
				var pakdata = new CreationCharacterData(packet, client);
				
				// Graveen: changed the following to allow GMs to have special chars in their names (_,-, etc..)
				var nameCheck = new Regex("^[A-Z][a-zA-Z]");
				if (!string.IsNullOrEmpty(pakdata.CharName) && (pakdata.CharName.Length < 3 || !nameCheck.IsMatch(pakdata.CharName)))
				{
					if ((ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
					{
						if (ServerProperties.Properties.BAN_HACKERS)
							client.BanAccount(string.Format("Autoban bad CharName '{0}'", pakdata.CharName));

						client.Disconnect();
						return;
					}
				}
					
				switch ((eOperation)pakdata.Operation)
				{
					case eOperation.Delete:
						if (string.IsNullOrEmpty(pakdata.CharName))
						{
							// Deletion in 1.104+ check for removed character.
							needRefresh |= CheckForDeletedCharacter(accountName, client, i);
						}
						break;
					case eOperation.Customize:
						if (!string.IsNullOrEmpty(pakdata.CharName))
						{
							// Candidate for Customizing ?
							var character = client.Account.Characters != null ? client.Account.Characters.FirstOrDefault(ch => ch.Name.Equals(pakdata.CharName, StringComparison.OrdinalIgnoreCase)) : null;
							if (character != null)
								needRefresh |= CheckCharacterForUpdates(pakdata, client, character);
						}
						break;
					case eOperation.Create:
						if (!string.IsNullOrEmpty(pakdata.CharName))
						{
							// Candidate for Creation ?
							var character = client.Account.Characters != null ? client.Account.Characters.FirstOrDefault(ch => ch.Name.Equals(pakdata.CharName, StringComparison.OrdinalIgnoreCase)) : null;
							if (character == null)
								needRefresh |= CreateCharacter(pakdata, client, i);
						}
						break;
					default:
						break;
				}
			}
			
			if(needRefresh)
			{
				client.Out.SendCharacterOverview(currentRealm);
			}
		}
		/// <summary>
		/// Check if a Character Needs update based to packet data
		/// </summary>
		/// <param name="pdata">packet data</param>
		/// <param name="client">client</param>
		/// <param name="character">db character</param>
		/// <returns>True if character need refreshment false if no refresh needed.</returns>
		private bool CheckCharacterForUpdates(CreationCharacterData pdata, GameClient client, DOLCharacters character)
		{
			int newModel = character.CurrentModel;

			if (pdata.CustomMode == 1 || pdata.CustomMode == 2 || pdata.CustomMode == 3)
			{
				bool flagChangedStats = false;
				
				if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION)
				{
					character.EyeSize = (byte)pdata.EyeSize;
					character.LipSize = (byte)pdata.LipSize;
					character.EyeColor = (byte)pdata.EyeColor;
					character.HairColor = (byte)pdata.HairColor;
					character.FaceType = (byte)pdata.FaceType;
					character.HairStyle = (byte)pdata.HairStyle;
					character.MoodType = (byte)pdata.MoodType;
				}
				
				if (pdata.CustomMode != 3 && client.Version >= GameClient.eClientVersion.Version189)
				{
					var stats = new Dictionary<eStat, int>();
					stats[eStat.STR] = pdata.Strength; // Strength
					stats[eStat.DEX] = pdata.Dexterity; // Dexterity
					stats[eStat.CON] = pdata.NewConstitution; // New Constitution
					stats[eStat.QUI] = pdata.Quickness; // Quickness
					stats[eStat.INT] = pdata.Intelligence; // Intelligence
					stats[eStat.PIE] = pdata.Piety; // Piety
					stats[eStat.EMP] = pdata.Empathy; // Empathy
					stats[eStat.CHR] = pdata.Charisma; // Charisma

					// check for changed stats.
					flagChangedStats |= stats[eStat.STR] != character.Strength;
					flagChangedStats |= stats[eStat.CON] != character.Constitution;
					flagChangedStats |= stats[eStat.DEX] != character.Dexterity;
					flagChangedStats |= stats[eStat.QUI] != character.Quickness;
					flagChangedStats |= stats[eStat.INT] != character.Intelligence;
					flagChangedStats |= stats[eStat.PIE] != character.Piety;
					flagChangedStats |= stats[eStat.EMP] != character.Empathy;
					flagChangedStats |= stats[eStat.CHR] != character.Charisma;

					if (flagChangedStats)
					{
						ICharacterClass charClass = ScriptMgr.FindCharacterClass(character.Class);

						if (charClass != null)
						{
							int points;							
							bool valid = IsCustomPointsDistributionValid(character, stats, out points);

							// Hacking attemp ?
							if (points > MAX_STARTING_BONUS_POINTS)
							{
								if ((ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
								{
									if (ServerProperties.Properties.BAN_HACKERS)
										client.BanAccount(string.Format("Autoban Hack char update : Wrong allowed points:{0}", points));

									client.Disconnect();
									return false;
								}
							}
							
							// Error in setting points
							if (!valid)
							{
							    return true;
							}
							
							if (Properties.ALLOW_CUSTOMIZE_STATS_AFTER_CREATION)
							{
								// Set Stats, valid is ok.
								character.Strength = stats[eStat.STR];
								character.Constitution = stats[eStat.CON];
								character.Dexterity = stats[eStat.DEX];
								character.Quickness = stats[eStat.QUI];
								character.Intelligence = stats[eStat.INT];
								character.Piety = stats[eStat.PIE];
								character.Empathy = stats[eStat.EMP];
								character.Charisma = stats[eStat.CHR];
	
								if (log.IsInfoEnabled)
									log.InfoFormat("Character {0} Stats updated in cache!", character.Name);
	
								if (client.Player != null)
								{
									foreach(var stat in stats.Keys)
										client.Player.ChangeBaseStat(stat, (short)(stats[stat] - client.Player.GetBaseStat(stat)));
									
									if (log.IsInfoEnabled)
										log.InfoFormat("Character {0} Player Stats updated in cache!", character.Name);
								}
							}
						}
						else if (log.IsErrorEnabled)
							log.ErrorFormat("No CharacterClass with ID {0} found", character.Class);
					}
				}


				if (pdata.CustomMode == 2) // change player customization
				{
					if (client.Account.PrivLevel == 1 && ((pdata.CreationModel >> 11) & 3) == 0)
					{
						if (ServerProperties.Properties.BAN_HACKERS) // Player size must be > 0 (from 1 to 3)
						{
							client.BanAccount(string.Format("Autoban Hack char update : zero character size in model:{0}", newModel));
							client.Disconnect();
							return false;
						}
						return true;
					}
					
					character.CustomisationStep = 2; // disable config button

					if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION)
					{
						if (pdata.CreationModel != character.CreationModel)
							character.CurrentModel = newModel;
	
						if (log.IsInfoEnabled)
							log.InfoFormat("Character {0} face properties configured by account {1}!", character.Name, client.Account.Name);
					}
				}
				else if (pdata.CustomMode == 3) //auto config -- seems someone thinks this is not possible?
				{
					character.CustomisationStep = 3; // enable config button to player
				}
				
				//Save the character in the database
				GameServer.Database.SaveObject(character);
			}
			
			return false;
		}
		private bool CreateCharacter(CreationCharacterData pdata, GameClient client, int accountSlot)
		{
			Account account = client.Account;
			var ch = new DOLCharacters();
			ch.AccountName = account.Name;
			ch.Name = pdata.CharName;
			
			if (pdata.CustomMode == 0x01)
			{
				ch.EyeSize = (byte)pdata.EyeSize;
				ch.LipSize = (byte)pdata.LipSize;
				ch.EyeColor = (byte)pdata.EyeColor;
				ch.HairColor = (byte)pdata.HairColor;
				ch.FaceType = (byte)pdata.FaceType;
				ch.HairStyle = (byte)pdata.HairStyle;
				ch.MoodType = (byte)pdata.MoodType;
				ch.CustomisationStep = 2; // disable config button
				
				if (log.IsDebugEnabled)
					log.Debug("Disable Config Button");
			}
			
			ch.Level = 1;
			// Set Realm and Class
			ch.Realm = pdata.Realm;
			ch.Class = pdata.Class;
			
			// Set Account Slot, Gender
			ch.AccountSlot = accountSlot + ch.Realm * 100;
			ch.Gender = pdata.Gender;

			// Set Race
			ch.Race = pdata.Race;
			
			ch.CreationModel = pdata.CreationModel;
			ch.CurrentModel = ch.CreationModel;
			ch.Region = pdata.Region;

			ch.Strength = pdata.Strength;
			ch.Dexterity = pdata.Dexterity;
			ch.Constitution = pdata.Constitution;
			ch.Quickness = pdata.Quickness;
			ch.Intelligence = pdata.Intelligence;
			ch.Piety = pdata.Piety;
			ch.Empathy = pdata.Empathy;
			ch.Charisma = pdata.Charisma;
			
			// defaults
			ch.CreationDate = DateTime.Now;

			ch.Endurance = 100;
			ch.MaxEndurance = 100;
			ch.Concentration = 100;
			ch.MaxSpeed = GamePlayer.PLAYER_BASE_SPEED;
			
			if (log.IsDebugEnabled)
				log.DebugFormat("Creation {0} character, class:{1}, realm:{2}", client.Version, ch.Class, ch.Realm);
			
			// Is class disabled ?
			int occurences = 0;
			List<string> disabled_classes = Properties.DISABLED_CLASSES.SplitCSV(true);
			occurences = (from j in disabled_classes
			              where j == ch.Class.ToString()
			              select j).Count();

			if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
			{
				if (log.IsDebugEnabled)
					log.DebugFormat("Client {0} tried to create a disabled classe: {1}", client.Account.Name, (eCharacterClass)ch.Class);
				
			    return true;
			}
			
			// check if race disabled
			List<string> disabled_races = Properties.DISABLED_RACES.SplitCSV(true);
			occurences = (from j in disabled_races
			              where j == ch.Race.ToString()
			              select j).Count();
			
			if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
			{
				if (log.IsDebugEnabled)
					log.DebugFormat("Client {0} tried to create a disabled race: {1}", client.Account.Name, (eRace)ch.Race);

				return true;
			}

			
			// If sending invalid Class ID
			if (!Enum.IsDefined(typeof(eCharacterClass), (eCharacterClass)ch.Class))
			{
				if (log.IsErrorEnabled)
					log.ErrorFormat("{0} tried to create a character with wrong class ID: {1}, realm:{2}", client.Account.Name, ch.Class, ch.Realm);
				
				if (ServerProperties.Properties.BAN_HACKERS)
				{
					client.BanAccount(string.Format("Autoban character create class: id:{0} realm:{1} name:{2} account:{3}", ch.Class, ch.Realm, ch.Name, account.Name));
					client.Disconnect();
					return false;
				}
			    return true;
			}

			// check if client tried to create invalid char
			if (!IsCharacterValid(ch))
			{
				if (log.IsWarnEnabled)
				{
					log.WarnFormat("{0} tried to create invalid character:\nchar name={1}, gender={2}, race={3}, realm={4}, class={5}, region={6}" +
					               "\nstr={7}, con={8}, dex={9}, qui={10}, int={11}, pie={12}, emp={13}, chr={14}", ch.AccountName, ch.Name, ch.Gender,
					              ch.Race, ch.Realm, ch.Class, ch.Region, ch.Strength, ch.Constitution, ch.Dexterity, ch.Quickness, ch.Intelligence, ch.Piety, ch.Empathy, ch.Charisma);
				}
			    return true;
			}

			//Save the character in the database
			GameServer.Database.AddObject(ch);
			
			// Fire the character creation event
			// This is Where Most Creation Script should take over to update any data they would like !
			GameEventMgr.Notify(DatabaseEvent.CharacterCreated, null, new CharacterEventArgs(ch, client));
			
			//write changes
			GameServer.Database.SaveObject(ch);

			// Log creation
			AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.CharacterCreate, "", pdata.CharName);

			client.Account.Characters = null;

			if (log.IsInfoEnabled)
				log.InfoFormat("Character {0} created on Account {1}!", pdata.CharName, account);

			// Reload Account Relations
			GameServer.Database.FillObjectRelations(client.Account);

		    return true;
		}