RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Function overriding

Killamus

Knight
Function overriding

Just a quick question, is something like this at all possible? I did a bit of searching, but turned up nothing:

Code:
public class class1
{
  public virtual void A()
  {
     Console.WriteLine("A");
  }
}

public static class classO
{
public override void class1.A()
  {
     Console.WriteLine("B");
  } 
}

So, something like having a regular class (Must be a regular class) and not inheriting it, but having another class override the function?
 

Killamus

Knight
Code:
using System;
using Server.Mobiles;
using Server.Items:

namespace Server.Mobiles
{
public static class PlayerOverride
{
public override void PlayerMobile.OnResurrection()
{
//Overriden! No PM edits.
}
}
}
No more playermobile edits :]
 

daat99

Moderator
Staff member
Killamus;750697 said:
Just a quick question, is something like this at all possible? I did a bit of searching, but turned up nothing:

Code:
public class class1
{
  public virtual void A()
  {
     Console.WriteLine("A");
  }
}

public static class classO
{
public override void class1.A()
  {
     Console.WriteLine("B");
  } 
}

So, something like having a regular class (Must be a regular class) and not inheriting it, but having another class override the function?
In order to "override" a method you must inherit the original class.
Personally I understand the motive of avoiding changes to distro classes but in my opinion, this is an example for when you should modify it.

If you want an easy way you can always do:
Code:
public class PlayerMobile
{
  public virtual type function(parameters)
  {
    if (MyStaticClass.MyStaticMethod(my_parameters)) return type;
    //distro code
  }
}
This way you need to add only one line to player mobile.
 

roadmaster

Sorceror
If your not wanting to make edits to the Distro PlayerMobile you could use a custom derived playermobile.

this is an old one i used to use, this is just an example for you:

Code:
using System;
using System.Collections;
using Server;
using Server.Gumps;
using Server.Items;
using Server.Network;
using Server.Accounting; 
 
namespace Server.Mobiles
{
	public class MyPlayerMobile : PlayerMobile
	{
		private Item m_InternalMount;
		
		private bool m_OrcFriend = false;
    	private bool m_DrowFriend = false;
		
		private RaceType m_Race = RaceType.None;
		
		public int m_StrCap = 150;
		public int m_DexCap = 150;
		public int m_IntCap = 150;
		
    public enum RaceType
    {
      None, Human, Dwarf, Drow, Centaur, Elf, Orc, Deamon, Vampire, Undead 
    }
    
    public Item InternalMount
	{
		get{ return m_InternalMount; }
		set{ m_InternalMount = value; }
	}

    [CommandProperty( AccessLevel.GameMaster )]
    public bool OrcFriend
    {
      get{ return m_OrcFriend; }
      set{ m_OrcFriend = value; }
    }

    [CommandProperty( AccessLevel.GameMaster )]
    public bool DrowFriend
    {
      get{ return m_DrowFriend; }
      set{ m_DrowFriend = value; }
    }

   [CommandProperty( AccessLevel.GameMaster )]
    public RaceType Race
    {
      get{ return m_Race; }
      set{ m_Race = value; InvalidateProperties(); }
    }

		[CommandProperty( AccessLevel.GameMaster )] 
		public int StrCap // Maximum value of STR stat
		{
			get {return m_StrCap;}
			set {m_StrCap = value;}
		}

		[CommandProperty( AccessLevel.GameMaster )] 
		public int IntCap // Maximum value of INT stat
		{
			get {return m_IntCap;}
			set {m_IntCap = value;}
		}

		[CommandProperty( AccessLevel.GameMaster )] 
		public int DexCap // Maximum value of DEX stat
		{
			get {return m_DexCap;}
			set {m_DexCap = value;}
		}

    new public static void Initialize()
		{
			EventSink.Login += new LoginEventHandler( OnLogin );
		}

 		private static void OnLogin( LoginEventArgs e )
		{
			if ( e.Mobile is MyPlayerMobile )
			{
				MyPlayerMobile m = (MyPlayerMobile)e.Mobile;
				
				MyPlayerMobile.MaxPlayerResistance = 85;

				if(m.Race == RaceType.None)
				{
					m.CloseGump( typeof( RaceGump ) );
					m.SendGump( new RaceGump( m, RacePage.Info) );
				}
			}
		}

/*
		public override void AddNameProperties( ObjectPropertyList list )
		{
			if(this.Race != RaceType.None)
			list.Add( 1042971, "{0}", m_Race==RaceType.None ? " " : m_Race.ToString() );

			base.AddNameProperties( list );
		}
*/
		public override void OnDeath( Container c )
		{
			if ( m_InternalMount != null )
			{
				m_InternalMount.Delete();
				m_InternalMount = null;
			}
			base.OnDeath( c );
		}

		public override void OnAfterResurrect()
		{
			RestoreBody();
			base.OnAfterResurrect();
		}
		
		public void CreateInternalMount()
		{
			if ( m_InternalMount == null )
			{
				m_InternalMount = new Item( 0x3EAA );
				m_InternalMount.Layer = Layer.Mount;
				m_InternalMount.Movable = false;
				m_InternalMount.Visible = false;
				AddItem( m_InternalMount );
			}
		}

		
		public void RestoreBody()
		{
			if(this.Female)
				this.BodyValue = 401;// if error change back to BodyMod instead of BodyValue
			else
				this.BodyValue = 400;// if error change back to BodyMod instead of BodyValue
			
			RaceType race = this.Race;

			switch( race )
			{
				case RaceType.Centaur:
				{
					this.BodyMod = 101;
					CreateInternalMount();
					break;
				}
				//case RaceType.Ogre: this.BodyMod = 1; break;
				case RaceType.Orc: 
				{
					this.BodyMod = 7;
					CreateInternalMount();
					break;
				}
				case RaceType.Deamon: 
				{
					this.BodyMod = 43;
					CreateInternalMount();
					break;
				}
			}
		}
/*
		public override TimeSpan ComputeMovementSpeed( Direction dir )
		{
			if ( (dir & Direction.Mask) != (this.Direction & Direction.Mask) )
				return TimeSpan.Zero;

			bool running = ( (dir & Direction.Running) != 0 );

			bool onHorse = ( this.Mount != null );

			if ( onHorse )
			{
				if(this.Race == RaceType.Centaur)
					return ( running ? TimeSpan.FromSeconds( 0.1 ) : TimeSpan.FromSeconds( 0.2 ) );
				else if(this.Race == RaceType.Deamon)
					return ( running ? TimeSpan.FromSeconds( 0.1 ) : TimeSpan.FromSeconds( 0.2 ) );
				else if(this.Race == RaceType.Orc)
					return ( running ? TimeSpan.FromSeconds( 0.3 ) : TimeSpan.FromSeconds( 0.6 ) );
				else
					return ( running ? TimeSpan.FromSeconds( 0.2 ) : TimeSpan.FromSeconds( 0.2 ) );
			}
			else
				return ( running ? TimeSpan.FromSeconds( 0.9 ) : TimeSpan.FromSeconds( 1.4 ) ); //changed to assist centaur and orc speeds: turin
			//return ( running ? TimeSpan.FromSeconds( 0.15 ) : TimeSpan.FromSeconds( 0.3 ) );
		}
*/
		//the default constructor called at creation
		public MyPlayerMobile()
		{
			try
			{
				m_Race = this.Race;
			}
			catch(Exception e)
			{
				Console.WriteLine(e);
			}
		}
 
		//the serial constructor called at world load
		public MyPlayerMobile( Serial s ) : base( s )
		{
		}
            
		//called at every world save
		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
            
			writer.Write( (int) 3 ); 
			
			writer.Write( m_InternalMount );
 
      		writer.Write( (bool)m_OrcFriend );
			writer.Write( (bool)m_DrowFriend );
			
			writer.Write( (int)m_Race );
 
			writer.Write( (int) m_StrCap );
			writer.Write( (int) m_DexCap );
			writer.Write( (int) m_IntCap ); 
		}
 
		//called by serial constructor at world load
		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
 
			int version = reader.ReadInt();
 
			switch ( version )
			{
				case 3:
				{
					m_InternalMount = reader.ReadItem();
					goto case 2;
				}
				case 2:
				{
         			m_OrcFriend = (bool)reader.ReadBool();
          			m_DrowFriend = (bool)reader.ReadBool();
					goto case 1;
				}
				case 1:
				{
					m_Race = (RaceType)reader.ReadInt();
					goto case 0;
				}
				case 0: 
				{
					m_StrCap = reader.ReadInt();
					m_DexCap = reader.ReadInt();
					m_IntCap = reader.ReadInt();
					
					break;
				}
			}
			RestoreBody();
		}
/*
		public override void Resurrect()
		{
//			bool wasAlive = this.Alive;
// Races stuff
			RaceType Race = this.Race;
// EO Races stuff
			base.Resurrect();
		}
*/
	}
}

of course you'd still have to set it up in CharacterCreation.cs to use the Custom PlayerMobile instead of the Distro when creating a new character.

and of course whether or not you would want to use a Custom would depend on what your trying to do.
 

daat99

Moderator
Staff member
roadmaster;750859 said:
If your not wanting to make edits to the Distro PlayerMobile you could use a custom derived playermobile.
Based on killamus track record, the reason he doesn't want to have any playermobile edits is because he want to release a script without them.

If that's the case then making a derived class will be a bit problematic.

Personally speaking, I never liked the idea of "derived class" just to avoid editing the original class, but that's just simple me :D

Thanks for your input though.
 

Greystar

Wanderer
daat99;750933 said:
Based on killamus track record, the reason he doesn't want to have any playermobile edits is because he want to release a script without them.

If that's the case then making a derived class will be a bit problematic.

Personally speaking, I never liked the idea of "derived class" just to avoid editing the original class, but that's just simple me :D

Thanks for your input though.

I'm not big on the derived thing either, however at one point I had made a "baseMobile" that inherited from Mobile then both PlayerMobile and BaseCreature inherited from it, that way I could add things to that, that affected both NPCs and PCs, however now that I'm doing core compiling on my own I just modify Mobile in the core and recompile.
 

Killamus

Knight
daat99;750933 said:
Based on killamus track record, the reason he doesn't want to have any playermobile edits is because he want to release a script without them.

I have a track record? Now I'm scared :(
anyways, Thanks for the help. That's helped a lot, plus your posts in the whole static class thread.
Don't worry, you won't see this script released for a while, so be prepared to answer many more questions I can't find answers to in the MSDN library.
 

daat99

Moderator
Staff member
Killamus;750983 said:
I have a track record? Now I'm scared :(
anyways, Thanks for the help. That's helped a lot, plus your posts in the whole static class thread.
Don't worry, you won't see this script released for a while, so be prepared to answer many more questions I can't find answers to in the MSDN library.

Looks like I was right, you do work on another script for a release ;)

Good luck with it and if I'll have thoughts to share on your questions I'll let you know.
 

Killamus

Knight
mordero;751170 said:
I havent tried this at all, so I dont know how hard it would be to implement, but you could always try this:

Type: System.Reflection.Emit.MethodRental

It uses reflection to replace a method in an object.

*twitch* *twitch* *Brain explodes*

Ouch.
It looks simple enough, but I'm curious as to how I'd find the values for some of the requirements (Like the size of the method in bytes). Is there an int for that, or is it copy/paste into a text file?

Also, how exactly does one do a pointer in C#? I remember learning about it in C++, but I haven't seen it in C# yet.
 

Killamus

Knight
So a pointer to a function would be something like
Code:
public virtual void* MethodName(params)
{
Methods();
return;
}

Also, why is it unsafe to do pointers in C#?
 

Killamus

Knight
Ok. So, that is how you'd do a pointer method in C#? So, if I wanted to write a pointer to a playermobile function, I'd have to do something like this:

Code:
public virtual void* OnResurrection(PlayerMobile player)
{
player.OnResurrection();
}
and that would be a pointer to the PlayerMobile OnResurrection function? Or would something like this have to be in the PlayerMobile class?

Also: lol@Microsoft still trying to tell programmers what to do... At least this is easy enough to get past.
 

mordero

Knight
Umm the whole point isnt to tell programmers what to do, but make it easier for them. Its much easier for a programmer to ignore the whole memory thing and let it happen automatically.
 

Killamus

Knight
mordero;751409 said:
Umm the whole point isnt to tell programmers what to do, but make it easier for them. Its much easier for a programmer to ignore the whole memory thing and let it happen automatically.

I know, I just think it's funny.
I'm also rather greatful for it, as I suck at remembering what to delete and what not to delete.
Anyways, moot point.
But, while talking to my C++ instructor, it seems that everything in C# is a pointer, and managed that way. To me, there are very few differences between (ex) a regular integer in C# and a pointer integer in C++. Anyone care to explain?
 

Jeff

Lord
A pointer to a method in C# is a bitch, but it ends up being a IntPtr in the end if you keep everything safe. YOu have to use tons of MarshalAs bullshit. TBH its not worth it.
 

daat99

Moderator
Staff member
Jeff;751560 said:
A pointer to a method in C# is a bitch, but it ends up being a IntPtr in the end if you keep everything safe. YOu have to use tons of MarshalAs bullshit. TBH its not worth it.

I totally agree :)

In any case c# integer is basically an object that knows basic integer math while c++ pointer to integer is only a memory address for a memory block that represent an integer number.
For the average user there's no difference between c# integer and c++ normal integer (due to the fact that most people doesn't use the integer class methods).

Keep in mind that every object in c# is basically a pointer to a memory block that contains that objects internal data.

Like people said before me, c# just hides all the pointer headache from the programmer while c++ let the programmer bang his head against the table (and maybe jump off the roof) in order to use pointers without nasty hard to detect memory leaks.
 
Top