495 lines
No EOL
12 KiB
C#
495 lines
No EOL
12 KiB
C#
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();
|
|
}
|
|
}
|
|
} |