Hi! I tried to make NPC who can be hired like mercenaries now, but for free, so you don't need to give them anything, but I couldn't come up with idea how to do it? Maybe somebody has done it before already?
 
I take 'zero' credit for this. I did not write it and in fact I do not use it on my shard. It was written by Haazen and It was given to me by . . hmm . . cannot remember by who. It is quite old and was written for RunUO.

Anyway maybe you can tinker with it for your shard so he works for 'no pay' or for only a very small amount. Take a look and good luck with it.

Code:
//Written by Haazen Jul 2005
using System; 
using Server; 
using System.Collections; 
using System.Collections.Generic;
using Server.Items; 
using Server.Spells;
using Server.Spells.First;
using Server.Spells.Second;
using Server.Spells.Sixth;
using Server.ContextMenus; 
using Server.Misc; 
using Server.Mobiles; 
using Server.Network; 

namespace Server.Mobiles 
{ 
    [CorpseName( "corpse of a medical worker" )]
    public class Medic : BaseCreature 
    { 
        private int m_Pay = 32; 
        private bool m_IsHired; 
        private int m_HoldGold = 8; 
        private Timer m_PayTimer; 
        private DateTime m_TimeEnd;

        [CommandProperty( AccessLevel.GameMaster )]
        public DateTime TimeEnd
        {
            get{ return m_TimeEnd; }
            set{ m_TimeEnd = value; }
        }
        
        [Constructable]
        public Medic(): base( AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.1, 4.0 ) 
        { 
                    Name = NameList.RandomName( "female" );
            Title = " the Medic";
            Body = 0x191;
            Female = true;
            Hue = 0x83EF;
            Blessed = true;
            ControlSlots = 3;
        //    SpeechHue = 72;

            SetStr( 400 );
            SetDex( 200 );
            SetInt( 400 );

            SetHits( 2500 );
            SetDamage( 25, 35 );

            SetSkill( SkillName.EvalInt, 200.0 );
            SetSkill( SkillName.Magery, 200.0 );
            SetSkill( SkillName.Meditation, 200.0 );
            SetSkill( SkillName.Anatomy, 300.0 );
            SetSkill( SkillName.Fencing, 200.0 );
            SetSkill( SkillName.MagicResist, 200.0 );
            SetSkill( SkillName.Tactics, 200.0 );

            HairItemID = 0x203D;
            HairHue = Utility.RandomHairHue();
            int hue = Utility.RandomList ( 1153, 1167, 1154, 1168, 1278, 1378, 91, 86, 121, 146, 156, 176,191 );

            AddItem( new PlainDress( hue ) ); 


            AddItem( new ThighBoots() );

            AddItem( new Obi( 132 ) );
            AddItem( new TricorneHat( hue ) );
            m_TimeEnd = DateTime.Now + TimeSpan.FromMinutes( 120.0 );
        } 

//aa time
        public override bool HandlesOnSpeech(Mobile from)
        {
            base.HandlesOnSpeech( from );
            return true;
        }
 
        public override bool DeleteOnRelease{ get{ return true; } }  //aa

        public override void OnThink()
                {
            foreach ( Mobile m in this.GetMobilesInRange( 10 ) ) 
            {                                                   
                if ( this.ControlMaster == m )
                {
                    if ( m.InRange( this, 10 ) ) 
                    { 

                        if ( m.Hits < (m.HitsMax - 15) )
                        {
                            if ( !new AgilitySpell( this, null ).Cast() )
                            {
                                new AgilitySpell( this, null ).Cast();
                                m.Hits += 12; // increase here if you want more healing
                            }
                        }
                    
                        if ( m.Poisoned )
                        {
                            if ( !new AgilitySpell( this, null ).Cast() )
                            {
                                new AgilitySpell( this, null ).Cast();
                                if ( m.CurePoison( this ) )
                                {
                                    m.SendLocalizedMessage( 1010059 ); // You have been cured of all poisons.
                                }
                            }
                        }
                    }
                }
            }
        }

        public Medic( Serial serial ) : base( serial ) 
        { 
        } 

        public override void Serialize( GenericWriter writer ) 
        { 
            base.Serialize( writer ); 

            writer.Write( (int) 0 ); // version 
          
            writer.Write( (bool)m_IsHired ); 
            writer.Write( (int)m_HoldGold ); 
            writer.Write( m_TimeEnd );
        } 

        public override void Deserialize( GenericReader reader ) 
        { 
            base.Deserialize( reader );

            int version = reader.ReadInt(); 
          
            m_IsHired = reader.ReadBool(); 
            m_HoldGold = reader.ReadInt(); 
            m_TimeEnd = reader.ReadDateTime();
          
            m_PayTimer = new PayTimer( this ); 
            m_PayTimer.Start(); 
        } 

        private static Hashtable m_HireTable = new Hashtable(); 

        public static Hashtable HireTable 
        { 
            get{ return m_HireTable; } 
        } 

        public override bool KeepsItemsOnDeath{ get{ return true; } } 
        private int m_GoldOnDeath = 0; 
        public override bool OnBeforeDeath() 
        { 
            // Stop the pay timer if its running 
            if( m_PayTimer != null ) 
            m_PayTimer.Stop(); 

            m_PayTimer = null; 

            // Get all of the gold on the hireling and add up the total amount 
            if( this.Backpack != null ) 
            { 
                Item[] AllGold = this.Backpack.FindItemsByType( typeof(Gold), true ); 
                if( AllGold != null ) 
                { 
                    foreach( Gold g in AllGold ) 
                        this.m_GoldOnDeath += g.Amount; 
                } 
            } 

            return base.OnBeforeDeath(); 

        } 

        public override void OnDeath( Container c ) 
        { 

            if( this.m_GoldOnDeath > 0 ) 
                c.DropItem( new Gold( this.m_GoldOnDeath ) ); 
            base.OnDeath( c ); 
        } 

        [CommandProperty( AccessLevel.Administrator )] 
        public bool IsHired 
        { 
            get 
            { 
                return m_IsHired; 
            } 
            set 
            { 
                if ( m_IsHired== value ) 
                    return; 

                m_IsHired= value; 
                Delta( MobileDelta.Noto ); 
                InvalidateProperties(); 
            } 
        } 

        public virtual Mobile GetOwner() 
        { 
            if( !Controlled ) 
                return null; 
            Mobile Owner = ControlMaster; 
          
            m_IsHired = true; 
          
            if( Owner == null ) 
                return null; 
          
            if( Owner.Deleted || Owner.Map != this.Map || !Owner.InRange( Location, 30 ) ) 
            { 
                Say( 1005653 ); // Hmmm.  I seem to have lost my master. 
                Medic.HireTable.Remove( Owner ); 
                SetControlMaster( null ); 
                this.Delete();
                return null; 
            } 

            return Owner; 
        } 
 
        public virtual bool AddHire( Mobile m ) 
        { 
            Mobile owner = GetOwner(); 

            if( owner != null ) 
            { 
                m.SendLocalizedMessage( 1043283, owner.Name ); // I am following ~1_NAME~. 
                return false; 
            } 

            if( SetControlMaster( m ) ) 
            { 
                m_IsHired = true; 
                return true; 
            } 
          
            return false; 
        } 

        public virtual bool Payday( Medic m ) 
        { 

            m_Pay = 32;
            return true; 
        } 
 
        public override bool OnDragDrop( Mobile from, Item item ) 
        { 
            if ( from is PlayerMobile )
            {
                PlayerMobile pm = from as PlayerMobile;
                if ( !pm.Young )
                {
                    from.SendMessage("I can only help Young players.");
                    return false;
                }
            }


            if( m_Pay != 0 ) 
            { 
                if( Controlled == false ) 
                { 
                    if( item is Gold ) 
                    { 
                        if( item.Amount == m_Pay || item.Amount == m_Pay * 2) //aa  was >=
                        { 
                            int span = item.Amount / 32;
                            Medic hire = (Medic)m_HireTable[from]; 

                            if( hire != null && !hire.Deleted && hire.GetOwner() == from ) 
                            { 
                                SayTo( from, 500896 ); // I see you already have an escort. 
                                return false; 
                            } 

                            if( AddHire(from) == true ) 
                            { 
                                Say( string.Format( "I thank thee for paying me. I will heal thee for {0} hour{1}.", span == 1 ? "one" : "two", span == 1 ? "" : "s")); 
                                m_TimeEnd = DateTime.Now + TimeSpan.FromMinutes( span * 60 );
                                m_HireTable[from] = this; 
                            //    m_HoldGold += m_Pay; //item.Amount; 
                                m_PayTimer = new PayTimer( this ); 
                                m_PayTimer.Start(); 
                                item.Delete(); //aa
                                return true; 
                            } 
                            else 
                                return false; 
                        } 
                        else 
                        { 
                            this.SayHireCost(); 
                            return false;
                        } 
                    } 
                    else 
                    { 
                        SayTo( from, 1043268 ); // Tis crass of me, but I want gold 
                    } 
                } 
                else 
                { 
                    Say( 1042495 );// I have already been hired. 
                } 
            } 
            else 
            { 
                SayTo( from, 500200 ); // I have no need for that. 
                return false; //aa
            } 

            return base.OnDragDrop( from, item ); 
        } 

        internal void SayHireCost() 
        { 
            Say( string.Format( "I am available to hire for {0} gold coins an hour for max of two hours. If thou dost give me gold, I will heal thee.", m_Pay ) ); 
        } 

        public override void OnSpeech( SpeechEventArgs e ) 
        {    
            if( !e.Handled && e.Mobile.InRange( this, 6 ) ) 
            { 
                int[] keywords = e.Keywords; 
                string speech = e.Speech; 

                if( ( e.HasKeyword( 0x003B ) == true ) || ( e.HasKeyword( 0x0162 ) == true ) ) 
                { 
                    e.Handled = Payday( this ); 
                    this.SayHireCost(); 
                } 
            } 
//aa time
                Mobile from = e.Mobile;
                    string keyword5 = this.Name +" time";

                    if ( keyword5 != null && e.Speech.ToLower().IndexOf( keyword5.ToLower() ) >= 0 ) 
             { // time
 
    
                           if ( ControlMaster != from )
                               return;
TimeSpan ts = this.TimeEnd - DateTime.Now;

string gt = String.Format( "{0:D2}:{1:D2}", ts.Hours % 24, ts.Minutes % 60 );            

        //    from.SendMessage ( "Time End {0} ", this.TimeEnd );
        //    Say( string.Format( "I will be leaveing {0}.", this.TimeEnd ) );
            Say( string.Format( "I will be leaveing in {0}.", gt ) );
                           e.Handled = true;
            }
//aa

            base.OnSpeech( e ); 
        }

        public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list ) 
        { 
            Mobile Owner = GetOwner(); 
          
            if( Owner == null ) 
            { 
                base.GetContextMenuEntries( from, list ); 
                list.Add( new HireEntry( from, this ) ); 
            } 
            else 
                base.GetContextMenuEntries( from, list ); 
        } 

        private class PayTimer : Timer 
        { 
            private Medic di; 
          
            public PayTimer( Medic vend ) : base( TimeSpan.FromMinutes( 5.0 ), TimeSpan.FromMinutes( 5.0 ) ) //aa was 30
            { 
                di = vend; 
                Priority = TimerPriority.OneMinute; 
            } 
          
            protected override void OnTick() 
            { 
                try {
                if ( di.Deleted )
                {
                    Stop();
                    return;
                }

                if ( DateTime.Now >= di.m_TimeEnd )
                {
                    di.Say ("Good Bye!");
                    Stop();
                    di.ControlMaster.PlaySound( 259 );
            Effects.SendLocationEffect( new Point3D( di.X + 1, di.Y + 1, di.Z + 11 ), di.Map, 0x3728, 13, 93, 0 );
            Effects.SendLocationEffect( new Point3D( di.X + 1, di.Y + 1, di.Z + 7 ), di.Map, 0x3728, 13, 93, 0 );
        //    Effects.SendLocationEffect( new Point3D( di.X + 1, di.Y + 1, di.Z + 3 ), di.Map, 0x3728, 13 );
        //    Effects.SendLocationEffect( new Point3D( di.X + 1, di.Y + 1, di.Z - 1 ), di.Map, 0x3728, 13 );
                    di.Delete();
                }

                else if ( DateTime.Now + TimeSpan.FromMinutes( 5.0 ) >= di.m_TimeEnd )
                {
                    di.SpeechHue = 32;
                    di.ControlMaster.PlaySound( 784 );
                    di.Say ("I have only a few more minutes to serve you!");
                }
                else if ( DateTime.Now + TimeSpan.FromMinutes( 10.0 ) >= di.m_TimeEnd )
                {
                    di.SpeechHue = 71;
                    di.Say ("I must be leaving you soon!");
                }
                }
                catch{}
            } 
        } 

        public class HireEntry : ContextMenuEntry 
        { 
            private Mobile m_Mobile; 
            private Medic m_Hire; 

            public HireEntry( Mobile from, Medic hire ) : base( 6120, 3 )    
            { 
                m_Hire = hire; 
                m_Mobile = from; 
            } 
          
            public override void OnClick()    
            {    
                m_Hire.Payday(m_Hire); 
                m_Hire.SayHireCost(); 
            } 
        } 
    }    
}
 
Ty PyrO for the response. I tried that by replacing Gold with Kudos (Exchangeable Game Time Reward Tokens). Got this.
Errors:
+ Mobiles/Medic.cs:
CS0246: Line 167: The type or namespace name 'Kudos' could not be found (are you missing a using directive or an assembly reference?)
I clearly have Kudos but, it says could not be found... hmm:D
C#:
[/QUOTE]
//   ___|========================|___
//   \  |  Written by Felladrin  |  /   [Kudos - Exchangeable Game Time Reward] - Current version: 1.3 (September 10, 2013)
//    > |       July 2013        | <
//   /__|========================|__\   Description: An item given to players for each period of time they stay online.

using System;
using Server.Mobiles;
using Server.Network;

namespace Server.Custom.GameTimeReward
{
    public class KudosTimer : Timer
    {
        public static class Config
        {
            public static int MinutesOnline = 30;                            // Every X minutes we give kudos to all players online.
            public static bool DropOnBank = true;                           // Should we place the kudos on character's bankbox (true) or backpack (false)?
            public static AccessLevel MaxAccessLevel = AccessLevel.Player;  // Any character with this access and below receives kudos.
        }

        public static void Initialize()
        {
            new KudosTimer().Start();
        }

        public KudosTimer() : base(TimeSpan.Zero, TimeSpan.FromMinutes(Config.MinutesOnline))
        {
            Priority = TimerPriority.OneMinute;
        }

        protected override void OnTick()
        {
            foreach (NetState state in NetState.Instances)
            {
                Mobile m = state.Mobile;
                
                if (m == null || m.AccessLevel > Config.MaxAccessLevel) continue;

                if (m.Player)
                {
                    if (Config.DropOnBank && m.Backpack != null)
                    {
                        m.Backpack.DropItem(new KudosRewardDeed());
                    }
                    else if (m.BankBox != null)
                    {
                        m.BankBox.DropItem(new KudosRewardDeed());
                    }
                }
            }
        }
    }
    public class KudosRewardDeed : Item
    {

        [Constructable]
        public KudosRewardDeed() : this( null )
        {
        }

        [Constructable]
        public KudosRewardDeed(string name) : base(5360)
           
        {
            Name = "A Kudos Reward Deed for a random amount of Kudos";
            Hue = 1150;
            Stackable = false;            
        }

        public KudosRewardDeed ( Serial serial ) : base ( serial )
        {
        }

              public override void OnDoubleClick( Mobile from ) 
              {
            if ( !IsChildOf( from.Backpack ) )
            {
                from.SendLocalizedMessage(1042001);
            }
            else
            {
                    //from.AddToBackpack(new Kudos( Utility.Random( 13, 20 )));
        
                            switch ( Utility.Random( 1 ) )
                            {
                                
                                case  0: from.AddToBackpack( new Kudos ( Utility.Random( 18, 25 ))); break;
                            
                            }
                this.Delete();
            }

        }
    
        public override void Serialize ( GenericWriter writer)
        {
            base.Serialize ( writer );

            writer.Write ( (int) 0);
        }

        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize ( reader );

            int version = reader.ReadInt();
        }
    }

    public class Kudos : Item
    {
        [Constructable]
        public Kudos(int amount)
        {
            Name = "Kudos";
            ItemID = 0xF11;
            Hue = 0x47E;
            Stackable = true;
            Amount = amount;
            Weight = 0;
        }

        [Constructable]
        public Kudos() : this(1) { }

        public override void GetProperties(ObjectPropertyList list)
        {
            base.GetProperties(list);
            list.Add("Exchangeable Game Time Reward");
        }

        public override bool DisplayWeight { get { return false; } }

        public Kudos(Serial serial) : base(serial) { }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write((int)0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();
        }
    }
}

[QUOTE]
 
As in the using daat99; statement? Thanks for the help. Not sure how to word it though so,I tried this:
using System;
using Server;
using System.Collections;
using System.Collections.Generic;
using Server.Items;
using Kudos;
using Server.Spells;
using Server.Spells.First;
using Server.Spells.Second;
using Server.Spells.Sixth;
using Server.ContextMenus;
using Server.Misc;
using Server.Mobiles;
using Server.Network;

Same result:(
 
Last edited:
Well at the top it will say namespace .....
inside the Kudos script.

You will need to use whats haver namespace inside the Merc script and add that to the using statements
 
Back