using System; using Server; using Server.Items; using Server.Mobiles; using Server.Network; using Server.Accounting; namespace Server.Misc { public class CharacterCreation { public static void Initialize() { // Register our event handler EventSink.CharacterCreated += new CharacterCreatedEventHandler( EventSink_CharacterCreated ); } private static void AddBackpack( Mobile m ) { Container pack = m.Backpack; if ( pack == null ) { pack = new Backpack(); pack.Movable = false; m.AddItem( pack ); } PackItem( new RedBook( "a book", m.Name, 20, true ) ); PackItem( new Gold( Server.Misc.Settings.StartGold() ) ); PackItem( new Dagger() ); PackItem( new Candle() ); } private static void AddShirt( Mobile m ) { switch ( Utility.Random( 5 ) ) { case 0: EquipItem( new FancyShirt( Utility.RandomHue() ), true ); break; case 1: EquipItem( new Doublet( Utility.RandomHue() ), true ); break; case 2: EquipItem( new Shirt( Utility.RandomHue() ), true ); break; case 3: EquipItem( new Tunic( Utility.RandomHue() ), true ); break; case 4: EquipItem( new Surcoat( Utility.RandomHue() ), true ); break; } } private static void AddPants( Mobile m ) { if ( m.Female ) { switch ( Utility.Random( 4 ) ) { case 0: EquipItem( new Skirt( Utility.RandomHue() ), true ); break; case 1: EquipItem( new Kilt( Utility.RandomHue() ), true ); break; case 2: EquipItem( new LongPants( Utility.RandomHue() ), true ); break; case 3: EquipItem( new ShortPants( Utility.RandomHue() ), true ); break; } } else { switch ( Utility.Random( 3 ) ) { case 0: EquipItem( new LongPants( Utility.RandomHue() ), true ); break; case 1: EquipItem( new ShortPants( Utility.RandomHue() ), true ); break; case 2: EquipItem( new Kilt( Utility.RandomHue() ), true ); break; } } } private static void AddShoes( Mobile m ) { switch ( Utility.Random( 4 ) ) { case 0: EquipItem( new Shoes( Utility.RandomNeutralHue() ), true ); break; case 1: EquipItem( new Boots( Utility.RandomNeutralHue() ), true ); break; case 2: EquipItem( new Sandals( Utility.RandomNeutralHue() ), true ); break; case 3: EquipItem( new ThighBoots( Utility.RandomNeutralHue() ), true ); break; } } private static void AddHat( Mobile m, int color ) { switch ( Utility.Random( 7 ) ) { case 0: EquipItem( new FloppyHat( Utility.RandomHue() ), true ); break; case 1: EquipItem( new Hood( color ), true ); break; case 2: EquipItem( new WideBrimHat( Utility.RandomHue() ), true ); break; case 3: EquipItem( new Cap( Utility.RandomHue() ), true ); break; case 4: EquipItem( new SkullCap( Utility.RandomHue() ), true ); break; case 5: EquipItem( new Bandana( Utility.RandomHue() ), true ); break; case 6: EquipItem( new FeatheredHat( Utility.RandomHue() ), true ); break; } } private static Mobile CreateMobile( Account a ) { if ( a.Count >= a.Limit ) return null; for ( int i = 0; i < a.Length; ++i ) { if ( a[i] == null ) return (a[i] = new PlayerMobile()); } return null; } private static void EventSink_CharacterCreated( CharacterCreatedEventArgs args ) { if ( !VerifyProfession( args.Profession ) ) args.Profession = 0; NetState state = args.State; if ( state == null ) return; Mobile newChar = CreateMobile( args.Account as Account ); if ( newChar == null ) { Console.WriteLine( "Login: {0}: Character creation failed, account full", state ); return; } args.Mobile = newChar; m_Mobile = newChar; newChar.Player = true; newChar.StatCap = 200; newChar.Skills.Cap = 7000; newChar.AccessLevel = args.Account.AccessLevel; newChar.Female = args.Female; newChar.Race = Race.Human; newChar.Hue = newChar.Race.ClipSkinHue( args.Hue & 0x3FFF ) | 0x8000; newChar.Hunger = 20; newChar.Thirst = 20; if ( newChar is PlayerMobile ) { PlayerMobile pm = (PlayerMobile) newChar; pm.Profession = args.Profession; } SetName( newChar, args.Name ); AddBackpack( newChar ); SetStats( newChar, state, args.Str, args.Dex, args.Int, args.Profession ); SetSkills( newChar, args.Skills, args.Profession ); newChar.HairItemID = args.HairID; newChar.HairHue = ClipHairHue( args.HairHue & 0x3FFF ); newChar.FacialHairItemID = args.BeardID; newChar.FacialHairHue = ClipHairHue( args.BeardHue & 0x3FFF ); newChar.RecordHair = newChar.HairItemID;; newChar.RecordBeard = newChar.FacialHairItemID;; AddShirt( newChar ); AddPants( newChar ); AddShoes( newChar ); int hatColor = 0; int robeColor = 0; if ( Utility.RandomBool() ) { hatColor = Utility.RandomHue(); EquipItem( new Cloak( hatColor ), true ); } if ( Utility.RandomBool() ) { robeColor = Utility.RandomHue(); EquipItem( new Robe( robeColor ), true ); if ( hatColor > 0 && Utility.RandomBool() ){ hatColor = robeColor; } else if ( hatColor == 0 ){ hatColor = robeColor; } } if ( Utility.RandomBool() ){ AddHat( newChar, hatColor ); } CityInfo city = GetStartLocation( args ); newChar.MoveToWorld( city.Location, city.Map ); Console.WriteLine( "Login: {0}: New character being created (account={1})", state, args.Account.Username ); Console.WriteLine( " - Character: {0} (serial={1})", newChar.Name, newChar.Serial ); Console.WriteLine( " - Started: {0} {1} in {2}", city.City, city.Location, city.Map.ToString() ); new WelcomeTimer( newChar ).Start(); } public static int ClipHairHue( int hue ) { if( hue < 1102 ) return 1102; else if( hue > 1149 ) return 1149; else return hue; } public static bool VerifyProfession( int profession ) { if ( profession < 8 ) return true; else return false; } private class BadStartMessage : Timer { Mobile m_Mobile; int m_Message; public BadStartMessage( Mobile m, int message ) : base( TimeSpan.FromSeconds ( 3.5 ) ) { m_Mobile = m; m_Message = message; this.Start(); } protected override void OnTick() { m_Mobile.SendLocalizedMessage( m_Message ); } } private static CityInfo GetStartLocation( CharacterCreatedEventArgs args ) { return args.City; } private static void FixStats( ref int str, ref int dex, ref int intel, int max ) { int vMax = max - 30; int vStr = str - 10; int vDex = dex - 10; int vInt = intel - 10; if ( vStr < 0 ) vStr = 0; if ( vDex < 0 ) vDex = 0; if ( vInt < 0 ) vInt = 0; int total = vStr + vDex + vInt; if ( total == 0 || total == vMax ) return; double scalar = vMax / (double)total; vStr = (int)(vStr * scalar); vDex = (int)(vDex * scalar); vInt = (int)(vInt * scalar); FixStat( ref vStr, (vStr + vDex + vInt) - vMax, vMax ); FixStat( ref vDex, (vStr + vDex + vInt) - vMax, vMax ); FixStat( ref vInt, (vStr + vDex + vInt) - vMax, vMax ); str = vStr + 10; dex = vDex + 10; intel = vInt + 10; } private static void FixStat( ref int stat, int diff, int max ) { stat += diff; if ( stat < 0 ) stat = 0; else if ( stat > max ) stat = max; } private static void SetStats( Mobile m, NetState state, int str, int dex, int intel, int prof ) { int max = state.NewCharacterCreation ? 90 : 80; FixStats( ref str, ref dex, ref intel, max ); if ( str < 10 || str > 60 || dex < 10 || dex > 60 || intel < 10 || intel > 60 || (str + dex + intel) != max ) { str = 10; dex = 10; intel = 10; } if ( prof > 0 ) { switch ( prof ) { case 1: // Swordsman { m.InitStats( 45, 25, 10 ); break; } case 2: // Magician { m.InitStats( 15, 20, 45 ); break; } case 3: // Thief { m.InitStats( 20, 45, 15 ); break; } case 4: // Fencer { m.InitStats( 30, 40, 10 ); break; } case 5: // Mace Fighter { m.InitStats( 45, 25, 10 ); break; } case 6: // Archer { m.InitStats( 25, 45, 10 ); break; } case 7: // Bard { m.InitStats( 25, 35, 20 ); break; } } } else m.InitStats( str, dex, intel ); } private static void SetName( Mobile m, string name ) { name = name.Trim(); if ( !NameVerification.Validate( name, 2, 16, true, false, true, 1, NameVerification.SpaceDashPeriodQuote ) ) name = "Generic Player"; m.Name = name; } private static bool ValidSkills( SkillNameValue[] skills ) { int total = 0; for ( int i = 0; i < skills.Length; ++i ) { if ( skills[i].Value < 0 || skills[i].Value > 50 ) return false; total += skills[i].Value; for ( int j = i + 1; j < skills.Length; ++j ) { if ( skills[j].Value > 0 && skills[j].Name == skills[i].Name ) return false; } } return ( total == 100 || total == 120 ); } private static Mobile m_Mobile; private static void SetSkills( Mobile m, SkillNameValue[] skills, int prof ) { switch ( prof ) { case 1: // Swordsman { skills = new SkillNameValue[] { new SkillNameValue( SkillName.Healing, 30 ), new SkillNameValue( SkillName.Swords, 40 ), new SkillNameValue( SkillName.Tactics, 30 ) }; break; } case 2: // Magician { skills = new SkillNameValue[] { new SkillNameValue( SkillName.Magery, 50 ), new SkillNameValue( SkillName.Meditation, 50 ) }; break; } case 3: // Thief { skills = new SkillNameValue[] { new SkillNameValue( SkillName.Hiding, 50 ), new SkillNameValue( SkillName.Stealing, 50 ) }; break; } case 4: // Fencer { skills = new SkillNameValue[] { new SkillNameValue( SkillName.Healing, 30 ), new SkillNameValue( SkillName.Fencing, 40 ), new SkillNameValue( SkillName.Tactics, 30 ) }; break; } case 5: // Mace Fighter { skills = new SkillNameValue[] { new SkillNameValue( SkillName.Healing, 30 ), new SkillNameValue( SkillName.Bludgeoning, 40 ), new SkillNameValue( SkillName.Tactics, 30 ) }; break; } case 6: // Archer { skills = new SkillNameValue[] { new SkillNameValue( SkillName.Archery, 50 ), new SkillNameValue( SkillName.Tactics, 50 ) }; break; } case 7: // Bard { skills = new SkillNameValue[] { new SkillNameValue( SkillName.Musicianship, 40 ), new SkillNameValue( SkillName.Discordance, 30 ), new SkillNameValue( SkillName.Peacemaking, 30 ) }; break; } default: { if ( !ValidSkills( skills ) ) return; break; } } for ( int i = 0; i < skills.Length; ++i ) { SkillNameValue snv = skills[i]; if ( snv.Value > 0 ) { Skill skill = m.Skills[snv.Name]; if ( skill != null ) { skill.BaseFixedPoint = snv.Value * 10; } } } } private static void EquipItem( Item item ) { EquipItem( item, false ); } private static void EquipItem( Item item, bool mustEquip ) { if ( m_Mobile != null && m_Mobile.EquipItem( item ) ) return; Container pack = m_Mobile.Backpack; if ( !mustEquip && pack != null ) pack.DropItem( item ); else item.Delete(); } private static void PackItem( Item item ) { Container pack = m_Mobile.Backpack; if ( pack != null ) pack.DropItem( item ); else item.Delete(); } } }