Scripting for Dummies: Troubling Things That Start With "T" Part 1: Timers
As with my other tutorials, the ones you will find here are written for newer scripters. I will attempt to explain the chosen topics in enough (but not too much) detail for a good basic understanding. Please DO NOT post support questions in this thread as they will simply be removed.
I highly recommend that you have some knowledge of C# before beginning any RunUO script, and I recommend the thread “Scripting for Dummies: Creating an Item” if you have not yet written your first successful RunUO script. This series of lessons assumes you understand the key C# concepts such as Classes and Methods, as well as a familiarity with RunUO.
In this lesson we will cover the basics of a Timer by building one step by step. Since it will be easier to explain without any extraneous code, this timer will be in a class by itself. Often you will see a timer embedded in another script which we will get too later or added to the end of another script. There is no real difference between a stand-alone script with a timer class and a timer class added to the end of another script. The second simply makes keeping the script and the timer it uses easier to keep together.
Our timer will serve a somewhat useful purpose for those building quest npc’s or such. It will delete a given Mobile after a certain amount of time and optionally cause the Mobile to say something first. Not only will we explore timers, but we will delve into Overloading—a way to have more than one entry point into a given method or procedure.
Let’s get started.
First off, as with any good RunUO script we need to reference the System and Server namespaces. It is hard to write a script that does not use something from those two.
Next we need to declare a namespace for our class. Since the timer deals specifically with Mobiles, the easiest thing to do is to put it in the Mobile namespace. It could go elsewhere but you would need to add “using Server.Mobiles;” to the above directives.
Note the opening brace, it must have exactly one matching closing brace at the end of the code denoting that everything in between is in the namespace declaration we just made. I cannot stress enough that every opening brace must have exactly one closing brace.
Now we will declare the class itself, it will be public so we can use it from elsewhere, and it will be derived from the base class “Timer.”
So at this point our code is:
Just as when we create an Item or a Mobile, there are certain variables we need at the class level so that we have access to them in any of the class’s methods. To start with, we will need to know what Mobile we are acting on. We will declare it as private since we do not need it outside of this class, and we will call it “mob.”
We will come back to this point after the script evolves a bit.
Next we need the constructor for our timer. This is called when the timer is created—when it is called with the “new” keyword. If we look in the Docs, we will see there are three Timer constructors (ctor) we can call our base class with, the one we will use is Timer( TimeSpan delay ) which you see takes one TimeSpan which is the delay before the timer “ticks.” For now I am going to hard code it to 10 seconds. We will make that adjustable later.
Now when we are creating our timer, there are a few things we need to do. First we need to fetch the reference to the Mobile that was passed and store it in our variable we defined at the class level so we can use it later. Next we are going to set the timer’s “priority.”
Priority is a property of the base timer class and accepts one of the TimerPriority enumerations (enum.) Those enums are
Our complete constructor is
Next we will Override the OnTick() method of the base Timer class. The OnTick() method is called every time the timer fires (or ticks.) When you override a method, you may not change the signature of the method in any way. Meaning you cannot use a different number or type of parameters, and it must be declared in the same way as in the base class, with one required exception… a method which can be overridden is declared virtual a method which is doing the overriding is declared override. So we have
Now, and this becomes more important when dealing with timers, the very first thing we should do is make sure our target still exists. Remember it is now 10 seconds later than when the timer was created, a lot can happen. We will check to see if the Mobile is gone completely, (is null) and if it is deleted but still in the cleanup stage. If either is the case, we will stop the timer and exit.
Now, since we are comfortable that our Mobile exists, it is a simple matter to make it no longer exist. We simply add one more line to our OnTick() code.
The complete class at this point (with closing braces in place) is:
This script does the basic job of deleting a Mobile 10 seconds after it is called. To use it from another script you would “instantiate” or create a MobileDeleteTimer with the reference to the Mobile you want to delete, then start the timer. For example
Tomorrow we will add some features to make the timer more useful.
As with my other tutorials, the ones you will find here are written for newer scripters. I will attempt to explain the chosen topics in enough (but not too much) detail for a good basic understanding. Please DO NOT post support questions in this thread as they will simply be removed.
I highly recommend that you have some knowledge of C# before beginning any RunUO script, and I recommend the thread “Scripting for Dummies: Creating an Item” if you have not yet written your first successful RunUO script. This series of lessons assumes you understand the key C# concepts such as Classes and Methods, as well as a familiarity with RunUO.
In this lesson we will cover the basics of a Timer by building one step by step. Since it will be easier to explain without any extraneous code, this timer will be in a class by itself. Often you will see a timer embedded in another script which we will get too later or added to the end of another script. There is no real difference between a stand-alone script with a timer class and a timer class added to the end of another script. The second simply makes keeping the script and the timer it uses easier to keep together.
Our timer will serve a somewhat useful purpose for those building quest npc’s or such. It will delete a given Mobile after a certain amount of time and optionally cause the Mobile to say something first. Not only will we explore timers, but we will delve into Overloading—a way to have more than one entry point into a given method or procedure.
Let’s get started.
First off, as with any good RunUO script we need to reference the System and Server namespaces. It is hard to write a script that does not use something from those two.
Code:
using System;
using Server;
Code:
namespace Server.Mobiles
{
Now we will declare the class itself, it will be public so we can use it from elsewhere, and it will be derived from the base class “Timer.”
Code:
public class MobileDeleteTimer : Timer
{
Code:
using System;
using Server;
namespace Server.Mobiles
{
public class MobileDeleteTimer : Timer
{
Code:
private Mobile mob;
Next we need the constructor for our timer. This is called when the timer is created—when it is called with the “new” keyword. If we look in the Docs, we will see there are three Timer constructors (ctor) we can call our base class with, the one we will use is Timer( TimeSpan delay ) which you see takes one TimeSpan which is the delay before the timer “ticks.” For now I am going to hard code it to 10 seconds. We will make that adjustable later.
Code:
public MobileDeleteTimer( Mobile m ) : base( TimeSpan.FromSeconds( 10 ) )
{
Code:
mob = m;
Priority = TimerPriority.OneSecond;
- EveryTick
- TenMS
- TwentyFiveMS
- FiftyMS
- TwoFiftyMS
- OneSecond
- FiveSeconds
- OneMinute
Our complete constructor is
Code:
public MobileDeleteTimer( Mobile m ) : base( TimeSpan.FromSeconds( 10 ) )
{
mob = m;
Priority = TimerPriority.OneSecond;
}
Next we will Override the OnTick() method of the base Timer class. The OnTick() method is called every time the timer fires (or ticks.) When you override a method, you may not change the signature of the method in any way. Meaning you cannot use a different number or type of parameters, and it must be declared in the same way as in the base class, with one required exception… a method which can be overridden is declared virtual a method which is doing the overriding is declared override. So we have
Code:
protected override void OnTick()
{
Code:
if( mob == null || mob.Deleted )
{
this.Stop();
return;
}
Code:
mob.Delete();
The complete class at this point (with closing braces in place) is:
Code:
using System;
using Server;
namespace Server.Mobiles
{
public class MobileDeleteTimer : Timer
{
private Mobile mob;
public MobileDeleteTimer( Mobile m ) : base( TimeSpan.FromSeconds( 10 ) )
{
mob = m;
Priority = TimerPriority.OneSecond;
}
protected override void OnTick()
{
if( mob == null || mob.Deleted )
{
Stop();
return;
}
mob.Delete();
}
}
}
Code:
Timer m_timer = new MobileDeleteTimer( this );
m_timer.Start();
Tomorrow we will add some features to make the timer more useful.