|
||
|
|||||||
| Script Support Get support for modifying RunUO Scripts, or writing your own! |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 (permalink) |
|
Guest
Posts: n/a
|
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
{
}
}
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 );
}
}
}
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
{
}
}
}
}
}
}
Last edited by daat99; 01-12-2006 at 05:58 PM. |
|
|
|
#2 (permalink) |
|
Guest
Posts: n/a
|
In this example of class inheritance we are going to add a player accessible pack to the Nightmare just like what the Beetle has. This time we're going to use the Nightmare as the parent class.
Code:
using System;
using Server;
using Server.Items;
using Server.Mobiles;
namespace Server.Mobiles
{
public class PackMare : Nightmare
{
[Constructable]
public PackMare()
{
}
}
}
Code:
using System;
using Server;
using Server.Items;
using Server.Mobiles;
namespace Server.Mobiles
{
public class PackMare : Nightmare
{
[Constructable]
public PackMare()
{
Container pack = Backpack;
if ( pack != null )
pack.Delete();
pack = new StrongBackpack();
pack.Movable = false;
AddItem( pack );
}
public PackMare( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}
Here is what you should have thus far. Code:
using System;
using Server;
using Server.Items;
using Server.Mobiles;
namespace Server.Mobiles
{
public class PackMare : Nightmare
{
[Constructable]
public PackMare()
{
Container pack = Backpack;
if ( pack != null )
pack.Delete();
pack = new StrongBackpack();
pack.Movable = false;
AddItem( pack );
PackGem();
PackGold( 250, 350 );
PackItem( new SulfurousAsh( Utility.RandomMinMax( 3, 5 ) ) );
PackScroll( 1, 5 );
PackPotion();
PackNecroScroll( 1 ); // Blood Oath
PackNecroScroll( 10 ); // Strangle
PackNecroScroll( 5 ); // Horrific Beast
PackNecroScroll( 13 ); // Vengeful Spirit
}
public PackMare( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}
Code:
using System;
using Server;
using Server.Items;
using Server.Mobiles;
namespace Server.Mobiles
{
public class PackMare : Nightmare
{
[Constructable]
public PackMare()
{
Container pack = Backpack;
if ( pack != null )
pack.Delete();
pack = new StrongBackpack();
pack.Movable = false;
AddItem( pack );
PackGem();
PackGold( 250, 350 );
PackItem( new SulfurousAsh( Utility.RandomMinMax( 3, 5 ) ) );
PackScroll( 1, 5 );
PackPotion();
PackNecroScroll( 1 ); // Blood Oath
PackNecroScroll( 10 ); // Strangle
PackNecroScroll( 5 ); // Horrific Beast
PackNecroScroll( 13 ); // Vengeful Spirit
}
public PackMare( Serial serial ) : base( serial )
{
}
#region Pack Animal Methods
public override bool OnBeforeDeath()
{
if ( !base.OnBeforeDeath() )
return false;
PackAnimal.CombineBackpacks( this );
return true;
}
public override bool IsSnoop( Mobile from )
{
if ( PackAnimal.CheckAccess( this, from ) )
return false;
return base.IsSnoop( from );
}
public override bool OnDragDrop( Mobile from, Item item )
{
if ( CheckFeed( from, item ) )
return true;
if ( PackAnimal.CheckAccess( this, from ) )
{
AddToBackpack( item );
return true;
}
return base.OnDragDrop( from, item );
}
public override bool CheckNonlocalDrop( Mobile from, Item item, Item target )
{
return PackAnimal.CheckAccess( this, from );
}
public override bool CheckNonlocalLift( Mobile from, Item item )
{
return PackAnimal.CheckAccess( this, from );
}
public override void GetContextMenuEntries( Mobile from, System.Collections.ArrayList list )
{
base.GetContextMenuEntries( from, list );
PackAnimal.GetContextMenuEntries( this, from, list );
}
#endregion
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}
Last edited by daat99; 01-12-2006 at 05:57 PM. |
|
|
|
#3 (permalink) |
|
Administrator
Join Date: Aug 2002
Location: Baltimore, MD
Age: 25
Posts: 4,870
|
One VERY important error in junkie's new convertplayer.cs:
Code:
IntrepidMobile im = new IntrepidMobile(); Code:
IntrepidMobile im = new IntrepidMobile( m.Serial );
__________________
Zippy, Razor Creator and RunUO Core Developer The RunUO Software Team "Intuition, like a flash of lightning, lasts only for a second. It generally comes when one is tormented by a difficult decipherment and when one reviews in his mind the fruitless experiments already tried. Suddenly the light breaks through and one finds after a few minutes what previous days of labor were unable to reveal." ~The Cryptonomicon Last edited by daat99; 01-12-2006 at 05:58 PM. |
|
|
|
|
|
#5 (permalink) |
|
Administrator
Join Date: Aug 2002
Location: Baltimore, MD
Age: 25
Posts: 4,870
|
Yes it makes them the same serial, this is VERY important for keeping compatability with exisiting houses and items and such.
__________________
Zippy, Razor Creator and RunUO Core Developer The RunUO Software Team "Intuition, like a flash of lightning, lasts only for a second. It generally comes when one is tormented by a difficult decipherment and when one reviews in his mind the fruitless experiments already tried. Suddenly the light breaks through and one finds after a few minutes what previous days of labor were unable to reveal." ~The Cryptonomicon |
|
|
|
|
|
#7 (permalink) |
|
Administrator
Join Date: Aug 2002
Location: Baltimore, MD
Age: 25
Posts: 4,870
|
Correct, you want them both to have the same serial, so the next time the world loads, the corect mobile is loaded for all of their houses and things.
__________________
Zippy, Razor Creator and RunUO Core Developer The RunUO Software Team "Intuition, like a flash of lightning, lasts only for a second. It generally comes when one is tormented by a difficult decipherment and when one reviews in his mind the fruitless experiments already tried. Suddenly the light breaks through and one finds after a few minutes what previous days of labor were unable to reveal." ~The Cryptonomicon |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|