P
php-junkie
Guest
Smart Programming (tutorial)
I've noticed when allot of us C# newbies want to script something most of us are constantly trying to modify (edit) the RunUO script package so I thought I would share my some of new found knowledge with the rest of the C# newbies here.
Class inheritance in RunUO
The script I hate updating the most every time the dev's release a new beta is the PlayerMobile.cs. This script also takes the most abuse from programmers on the script submission forum so for this example I'm going to create a new class using PlayerMobile as a parent class. In this class we'll create titles for your staff members. Some examples of other things that could be put inside this new class are the properties, methods, etc of the PlayerMobile.cs in Archeronne's faction system. Also, remember you can do this with any object in the RunUO script package.
I started by creating a new file under \Scripts\Custom\Mobiles. You can name this file what ever you want and put it where ever you want as long as it's inside the scripts folder. I named mine IntrepidMobile.cs because Intrepid is the name of my shard. It means, without fear.
First thing we need are the using directives and namespace.
Now lets create our new class. Make sure you take note of how I use the PlayerMobile as the parent class.
Did you noticed how I used the PlayerMobile as a parent class? This is the most important part of my tutorial and it is also the reason why I'm writing this tutorial so make sure you understand what it is I did here before you continue. Also, you can name the class what ever you want. I named mine IntrepidMobile for the same reason I named the file IntrepidMobile.cs.
Ok, my point for doing this is to show you that you don't need to edit any of the script files inside the RunUO Distro so I'm going to skip over the rest of it and finish the script so you can see what it is I'm doing.
Now that we've finished the script. There is two other things we need to do here before we can use our new class on our players. The first is in \Scripts\Misc\CharacterCreation.cs. In order for this new class to be attached to newly created Characters we need to edit line 429 from PlayerMobile() to IntrepidMobile() so change line 429 from this;
to this;
Or change it to what ever you named your new Mobile class.
The next step is to convert all of your players to the new class. This is rather simple to do considering there is a script in the RunUO package that converts players to the PlayerMobile class. I'm not going to go into details on how to mod this script. Instead I'll provide you with my modified version of the script. Remember the hole point of this is not to edit the RunUO package so do not copy this over the original ConvertPlayers.cs. Put it in a new file. I named mine simply ConvertPlayer.cs. I also change the command from ConvertPlayers to ConvertPlayer.
Congratulation, you just added a new property to your players without editing the PlayerMobile.cs file. I tried to make this as simple as I possibly could so if you still don't understand don't worry because I'm going to post a couple more examples of class inheritance in RunUO.
I've noticed when allot of us C# newbies want to script something most of us are constantly trying to modify (edit) the RunUO script package so I thought I would share my some of new found knowledge with the rest of the C# newbies here.
Class inheritance in RunUO
The script I hate updating the most every time the dev's release a new beta is the PlayerMobile.cs. This script also takes the most abuse from programmers on the script submission forum so for this example I'm going to create a new class using PlayerMobile as a parent class. In this class we'll create titles for your staff members. Some examples of other things that could be put inside this new class are the properties, methods, etc of the PlayerMobile.cs in Archeronne's faction system. Also, remember you can do this with any object in the RunUO script package.
I started by creating a new file under \Scripts\Custom\Mobiles. You can name this file what ever you want and put it where ever you want as long as it's inside the scripts folder. I named mine IntrepidMobile.cs because Intrepid is the name of my shard. It means, without fear.
First thing we need are the using directives and namespace.
Code:
using Server;
using Server.Network;
namespace Server.Mobiles
{
}
Code:
using Server;
using Server.Network;
namespace Server.Mobiles
{
public class IntrepidMobile : PlayerMobile
{
}
}
Did you noticed how I used the PlayerMobile as a parent class? This is the most important part of my tutorial and it is also the reason why I'm writing this tutorial so make sure you understand what it is I did here before you continue. Also, you can name the class what ever you want. I named mine IntrepidMobile for the same reason I named the file IntrepidMobile.cs.
Ok, my point for doing this is to show you that you don't need to edit any of the script files inside the RunUO Distro so I'm going to skip over the rest of it and finish the script so you can see what it is I'm doing.
Code:
using Server;
using Server.Network;
namespace Server.Mobiles
{
public class IntrepidMobile : PlayerMobile
{
private string m_StaffTitle;
[CommandProperty( AccessLevel.GameMaster )]
public string StaffTitle
{
get{ return m_StaffTitle; }
set{ m_StaffTitle = value }
}
public IntrepidMobile()
{
m_StaffTitle = null;
}
public override void OnSingleClick( Mobile from )
{
if ( from.AccessLevel > AccessLevel.Player && m_StaffTitle != null )
PrivateOverheadMessage( MessageType.Label, this.SpeachHue, true,"["+ m_StaffTitle +"]" , from.NetState );
}
public IntrepidMobile( Serial serial ) : base( serial )
{
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_StaffTitle = reader.ReadString();
break;
}
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.Write( m_StaffTitle );
}
}
}
Now that we've finished the script. There is two other things we need to do here before we can use our new class on our players. The first is in \Scripts\Misc\CharacterCreation.cs. In order for this new class to be attached to newly created Characters we need to edit line 429 from PlayerMobile() to IntrepidMobile() so change line 429 from this;
Code:
return (a[i] = new PlayerMobile());
Code:
return (a[i] = new IntrpidMobile());
The next step is to convert all of your players to the new class. This is rather simple to do considering there is a script in the RunUO package that converts players to the PlayerMobile class. I'm not going to go into details on how to mod this script. Instead I'll provide you with my modified version of the script. Remember the hole point of this is not to edit the RunUO package so do not copy this over the original ConvertPlayers.cs. Put it in a new file. I named mine simply ConvertPlayer.cs. I also change the command from ConvertPlayers to ConvertPlayer.
Code:
using System;
using System.Collections;
using System.Reflection;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Accounting;
namespace Server.Scripts.Commands
{
public class ConvertPlayer
{
public static void Initialize()
{
Server.Commands.Register( "ConvertPlayer", AccessLevel.Administrator, new CommandEventHandler( ConvertPlayer_OnCommand ) );
}
public static void ConvertPlayer_OnCommand( CommandEventArgs e )
{
e.Mobile.SendMessage( "Converting all players to IntrepidMobile. You will be disconnected. Please Restart the server after the world has finished saving." );
ArrayList mobs = new ArrayList( World.Mobiles.Values );
int count = 0;
foreach ( Mobile m in mobs )
{
if ( m.Player && !(m is IntrepidMobile ) )
{
count++;
if ( m.NetState != null )
m.NetState.Dispose();
IntrepidMobile im = new IntrepidMobile( m.Serial );
im.DefaultMobileInit();
ArrayList copy = new ArrayList( m.Items );
for (int i=0;i<copy.Count;i++)
im.AddItem( (Item)copy[i] );
CopyProps( im, m );
for (int i=0;i<m.Skills.Length;i++)
{
im.Skills[i].Base = m.Skills[i].Base;
im.Skills[i].SetLockNoRelay( m.Skills[i].Lock );
}
Account acct = m.Account as Account;
PlayerMobile pm = m as PlayerMobile;
for ( int i = 0; i < 5; ++i )
if ( acct[i] == pm )
{
acct[i].Delete();
acct[i] = im;
}
}
}
if ( count > 0 )
{
NetState.ProcessDisposedQueue();
World.Save();
Console.WriteLine( "{0} players have been converted to IntrepidMobile. Please restart the server.", count );
while ( true )
Console.ReadLine();
}
else
{
e.Mobile.SendMessage( "Couldn't find any Players to convert." );
}
}
private static void CopyProps( Mobile to, Mobile from )
{
Type pmtype = typeof( PlayerMobile );
PropertyInfo[] pmprops = pmtype.GetProperties( BindingFlags.Public | BindingFlags.Instance );
for (int p=0;p<pmprops.Length;p++)
{
PropertyInfo prop = pmprops[p];
if ( prop.CanRead && prop.CanWrite )
{
try
{
prop.SetValue( to, prop.GetValue( from, null ), null );
}
catch
{
}
}
}
Type mtype = typeof( Mobile );
PropertyInfo[] mprops = mtype.GetProperties( BindingFlags.Public | BindingFlags.Instance );
for (int p=0;p<mprops.Length;p++)
{
PropertyInfo prop = mprops[p];
if ( prop.CanRead && prop.CanWrite )
{
try
{
prop.SetValue( to, prop.GetValue( from, null ), null );
}
catch
{
}
}
}
}
}
}
Congratulation, you just added a new property to your players without editing the PlayerMobile.cs file. I tried to make this as simple as I possibly could so if you still don't understand don't worry because I'm going to post a couple more examples of class inheritance in RunUO.