Tallow released a script in the script submission section and it works great but I am having one issue. I tried posting in that threat weeks ago with no help so now I come here. :)

It's a auto res potion, it has an optional delay timer from when it will resurrect the player after they have died. I tried changing this timer to zero but it still takes about 30 seconds to resurrect the player after they die (which is what the default timer was). I can't find any other timer to change so I am a bit lost. Any help is appreciated. Thanks. Here is the script.

Code:
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Prompts;
using Server.Network;
using System.Collections;
using System.Collections.Generic;
namespace Server.Items
{
    public class AutoResPotion : Item
    {
		private static Dictionary<Mobile, AutoResPotion> m_ResList;
		
        private int m_Charges;

        [CommandProperty( AccessLevel.GameMaster )]
        public int Charges
        {
            get { return m_Charges; }
            set { m_Charges = value; InvalidateProperties(); }
        }

        private Timer m_Timer;
        private static TimeSpan m_Delay = TimeSpan.Zero; // TimeSpan.FromSeconds( 2.0 ); /*TimeSpan.Zero*/

        [CommandProperty(AccessLevel.GameMaster)]
        public TimeSpan Delay { get { return m_Delay; } set { m_Delay = value; } }
	
        public static void Initialize()
        {
            EventSink.PlayerDeath += new PlayerDeathEventHandler(EventSink_Death);
        }
		
        [Constructable]
        public AutoResPotion() : this( 3 )
        { }

        [Constructable]
        public AutoResPotion(int charges) : base(0xF04) 
        {
            m_Charges = charges;

            Name = "Potion Of Rebirth";
            LootType = LootType.Blessed;
           
            /*Stackable = true;*/
            Weight = 1.0;
            /*Amount = amount;*/
        }

        public AutoResPotion(Serial serial)
            : base(serial)
        { }
		
		public override void OnDoubleClick( Mobile from )
		{
			if(!from.Alive)
				return;
			if(m_ResList == null)
				m_ResList = new Dictionary<Mobile, AutoResPotion>();
			
			if( !m_ResList.ContainsKey(from))
			{
				if(!m_ResList.ContainsValue(this))
				{
					m_ResList.Add(from, this);
					from.SendMessage("You feel the spirits watching you, awaiting to send you back to your body.");
				}
				else
					from.SendMessage("The spirits of this potion are watching another");
			}
			else
				from.SendMessage("The spirits watch you already.");
		}
		
		private static void EventSink_Death(PlayerDeathEventArgs e)
        {
            PlayerMobile owner = e.Mobile as PlayerMobile;

            if (owner != null && !owner.Deleted)
            {
                if (owner.Alive)
                    return;
				
				if(m_ResList != null && m_ResList.ContainsKey(owner))
				{
					AutoResPotion arp = m_ResList[owner];
					if(arp == null || arp.Deleted)
					{
						m_ResList.Remove(owner);
						return;
					}
					arp.m_Timer = Timer.DelayCall(m_Delay, new TimerStateCallback(Resurrect_OnTick), new object[] { owner, arp });
					m_ResList.Remove(owner);
				}
            }
        }

        private static void Resurrect_OnTick(object state)
        {
            object[] states = (object[])state;
            PlayerMobile owner = (PlayerMobile)states[0];
			AutoResPotion arp = (AutoResPotion)states[1];
            if (owner != null && !owner.Deleted && arp != null && !arp.Deleted)
            {
                if (owner.Alive || arp.m_Charges < 1)
                    return;

                owner.SendMessage("You died under the watch of the spirits, they have offered you another chance at life.");
                owner.Resurrect();

                arp.m_Charges--;

                arp.InvalidateProperties();

                if (arp.m_Charges < 1)
                    arp.Delete();
            }
        }

        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties( list );

            list.Add(String.Format("{0} Charges", m_Charges));
        }

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

            writer.Write( (int) 0 ); // version

            writer.Write( (TimeSpan) m_Delay );
            writer.Write( (int) m_Charges );            
        }

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

            int version = reader.ReadInt();

            switch (version)
            {
                case 0: 
                {
                     m_Delay = reader.ReadTimeSpan();
                     m_Charges = reader.ReadInt();
                } break;
            }
        }
    }
}

As you can see I have the time setting to be zero.

private static TimeSpan m_Delay = TimeSpan.Zero;

But it still takes a good 30 seconds before they are resurrected and I can't find any other timer that is causing that.
 
m_Delay is serialized, so your changes won't affect already existing potions, only new ones.

You can correct this with a serialize tweak;

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

            writer.Write( (int) 1 ); // version

            writer.Write( (TimeSpan) m_Delay );
            writer.Write( (int) m_Charges );         
        }

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

            int version = reader.ReadInt();

            switch (version)
            {
                case 1:
                case 0:
                {
                     m_Delay = reader.ReadTimeSpan();
                     m_Charges = reader.ReadInt();
                } break;
            }

            if(version < 1)
            {
                 m_Delay = TimeSpan.Zero;
            }
        }

Other possible cause is the potion is created in code and then the Delay property is set, overriding your default, EG;
C#:
var pot = new AutoResPotion( );

pot.Delay = TimeSpan.FromSeconds(30.0);
 
Ok I understand what your saying. I'll be testing it as soon as I get home tonight. Thanks a lot :)
 
Last edited:
No problem :)

I would recommend against using a flat zero delay though, being killed and resurrecting instantly greatly increases the potential for a client crash or freeze. I would recommend 1 second at the lowest, which shouldn't be a noticeable difference.

A lot of the time, the client crashes are caused by the Death Shroud item that is equipped to all players when they die, if they die with a blessed item on the OuterTorso layer; when the player resurrects, they have two items on the OuterTorso layer (temporarily) and if an update is sent to the client while both are equipped, it crashes. The crash is more likely to happen if you are observing the player who was killed and resurrected - if they die while on your screen and you walk off screen enough for the client to release them from its cache, when you walk back on screen and they resurrect, you crash.

I was able to reproduce this almost every time, but my shard is heavily customized, so it might just be my bad luck :p
 
  • Like
Reactions: ExX
So this may be a dumb question, but I made the changes you suggested. I thought I put the

var pot = new AutoResPotion( );
pot.Delay = TimeSpan.FromSeconds( 2.0 );

in the right location but clearly I did not. Everytime I try creating the item the server crashes. Lol Where do I place that code? I'm sorry for being so new. I've learned so much but still very new. This is the script I have currently.

Code:
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Prompts;
using Server.Network;
using System.Collections;
using System.Collections.Generic;
namespace Server.Items
{
    public class AutoResPotion : Item
    {
		private static Dictionary<Mobile, AutoResPotion> m_ResList;
		
        private int m_Charges;

        [CommandProperty( AccessLevel.GameMaster )]
        public int Charges
        {
            get { return m_Charges; }
            set { m_Charges = value; InvalidateProperties(); }
        }

        private Timer m_Timer;
        private static TimeSpan m_Delay =  TimeSpan.FromSeconds( 2.0 ); // TimeSpan.Zero;

        [CommandProperty(AccessLevel.GameMaster)]
        public TimeSpan Delay { get { return m_Delay; } set { m_Delay = value; } }
	
        public static void Initialize()
        {
            EventSink.PlayerDeath += new PlayerDeathEventHandler(EventSink_Death);
        }
		
        [Constructable]
        public AutoResPotion() : this( 3 )
        { }

        [Constructable]
        public AutoResPotion(int charges) : base(0xF04) 
        {
            m_Charges = charges;

            Name = "Potion Of Rebirth";
            LootType = LootType.Blessed;
           
            /*Stackable = true;*/
            Weight = 1.0;
            /*Amount = amount;*/
			
			var pot = new AutoResPotion( );
			pot.Delay = TimeSpan.FromSeconds( 2.0 );
        }

        public AutoResPotion(Serial serial)
            : base(serial)
        { }
		
		public override void OnDoubleClick( Mobile from )
		{
			if(!from.Alive)
				return;
			if(m_ResList == null)
				m_ResList = new Dictionary<Mobile, AutoResPotion>();
			
			if( !m_ResList.ContainsKey(from))
			{
				if(!m_ResList.ContainsValue(this))
				{
					m_ResList.Add(from, this);
					from.SendMessage("You feel the spirits watching you, awaiting to send you back to your body.");
				}
				else
					from.SendMessage("The spirits of this potion are watching another");
			}
			else
				from.SendMessage("The spirits watch you already.");
		}
		
		private static void EventSink_Death(PlayerDeathEventArgs e)
        {
            PlayerMobile owner = e.Mobile as PlayerMobile;

            if (owner != null && !owner.Deleted)
            {
                if (owner.Alive)
                    return;
				
				if(m_ResList != null && m_ResList.ContainsKey(owner))
				{
					AutoResPotion arp = m_ResList[owner];
					if(arp == null || arp.Deleted)
					{
						m_ResList.Remove(owner);
						return;
					}
					arp.m_Timer = Timer.DelayCall(m_Delay, new TimerStateCallback(Resurrect_OnTick), new object[] { owner, arp });
					m_ResList.Remove(owner);
				}
            }
        }

        private static void Resurrect_OnTick(object state)
        {
            object[] states = (object[])state;
            PlayerMobile owner = (PlayerMobile)states[0];
			AutoResPotion arp = (AutoResPotion)states[1];
            if (owner != null && !owner.Deleted && arp != null && !arp.Deleted)
            {
                if (owner.Alive || arp.m_Charges < 1)
                    return;

                owner.SendMessage("You died under the watch of the spirits, they have offered you another chance at life.");
                owner.Resurrect();

                arp.m_Charges--;

                arp.InvalidateProperties();

                if (arp.m_Charges < 1)
                    arp.Delete();
            }
        }

        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties( list );

            list.Add(String.Format("{0} Charges", m_Charges));
        }

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

            writer.Write( (int) 1 ); // version

            writer.Write( (TimeSpan) m_Delay );
            writer.Write( (int) m_Charges );        
        }

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

            int version = reader.ReadInt();

            switch (version)
            {
                case 1:
                case 0:
                {
                     m_Delay = reader.ReadTimeSpan();
                     m_Charges = reader.ReadInt();
                } break;
            }

            if(version < 1)
            {
                 m_Delay = TimeSpan.Zero;
            }
        }
    }
}
 
Back