Go Back   RunUO - Ultima Online Emulation > RunUO > Script Support

Script Support Get support for modifying RunUO Scripts, or writing your own!

Reply
 
Thread Tools Display Modes
Old 09-28-2008, 01:19 PM   #1 (permalink)
Newbie
 
Join Date: Apr 2007
Posts: 47
Red face Explosion potion issue

I have purple potions almost fully functional to the way I want them to run on my RunUO 1.0 server. There is a random countdown timer that functions properly, and a delay timer between each use of a purple potion. My problem is that because of the delay timer between each use, if the target is cancelled, the original potion cannot be selected again because it is still a purple potion. Please understand that my coding skill is basically nill as I just started to learn it when I decided to try out making a server about 3 days ago. Here is a copy of the code:

Code:
using System;
using System.Collections;
using Server;
using Server.Network;
using Server.Targeting;
using Server.Spells;

namespace Server.Items
{
	public abstract class BaseExplosionPotion : BasePotion
	{
		public abstract int MinDamage { get; }
		public abstract int MaxDamage { get; }
		public virtual double Delay { get { return 5.0; } }


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

		private static bool LeveledExplosion = false; // Should explosion potions explode other nearby potions?
		private static bool InstantExplosion = false; // Should explosion potions explode on impact?
		private const int   ExplosionRange   = 2;     // How long is the blast radius?

		public BaseExplosionPotion( PotionEffect effect ) : base( 0xF0D, effect )
		{
		}

		public BaseExplosionPotion( 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();
		}

		public virtual object FindParent( Mobile from )
		{
			Mobile m = this.HeldBy;

			if ( m != null && m.Holding == this )
				return m;

			object obj = this.RootParent;

			if ( obj != null )
				return obj;

			if ( Map == Map.Internal )
				return from;

			return this;
		}

		private Timer m_Timer;

		private ArrayList m_Users;

		public override void Drink( Mobile from )
		{
			if ( from.BeginAction( typeof( BaseExplosionPotion ) ) )
				{
				Timer.DelayCall( TimeSpan.FromSeconds( Delay ), new TimerStateCallback( ReleaseExplosionLock ), from );
				}else{
				from.SendMessage("You must wait before throwing another explosion potion!" );
				return;
				}

			if ( Core.AOS && (from.Paralyzed || from.Frozen || (from.Spell != null && from.Spell.IsCasting)) )
			{
				from.SendLocalizedMessage( 1062725 ); // You can not use a purple potion while paralyzed.
				return;
			}

			ThrowTarget targ = from.Target as ThrowTarget;
			
			if (targ == null)
				from.Target = new ThrowTarget( this );

			if ( targ != null && targ.Potion == this )
				return;

			from.RevealingAction();

			if ( m_Users == null )
				m_Users = new ArrayList();

			if ( !m_Users.Contains( from ) )
				m_Users.Add( from );

			if ( m_Timer == null )
			{
				from.SendLocalizedMessage( 500236 ); // You should throw it now!
				m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 0.75 ), TimeSpan.FromSeconds( 1.0 ), 5, new TimerStateCallback( Detonate_OnTick ), new object[]{ from, Utility.RandomMinMax(3, 4) } );
			}
		}

		private void Detonate_OnTick( object state )
		{
			if ( Deleted )
				return;

			object[] states = (object[])state;
			Mobile from = (Mobile)states[0];
			int timer = (int)states[1];

			object parent = FindParent( from );

			if ( timer == 0 )
			{
				Point3D loc;
				Map map;

				if ( parent is Item )
				{
					Item item = (Item)parent;

					loc = item.GetWorldLocation();
					map = item.Map;
				}
				else if ( parent is Mobile )
				{
					Mobile m = (Mobile)parent;

					loc = m.Location;
					map = m.Map;
				}
				else
				{
					return;
				}

				Explode( from, true, loc, map );
			}
			else
			{
				if ( parent is Item )
					((Item)parent).PublicOverheadMessage( MessageType.Regular, 0x22, false, timer.ToString() );
				else if ( parent is Mobile )
					((Mobile)parent).PublicOverheadMessage( MessageType.Regular, 0x22, false, timer.ToString() );

				states[1] = timer - 1;
			}
		}

		private void Reposition_OnTick( object state )
		{
			if ( Deleted )
				return;

			object[] states = (object[])state;
			Mobile from = (Mobile)states[0];
			IPoint3D p = (IPoint3D)states[1];
			Map map = (Map)states[2];

			Point3D loc = new Point3D( p );

			if ( InstantExplosion )
				Explode( from, true, loc, map );
			else
				MoveToWorld( loc, map );
		}

		private class ThrowTarget : Target
		{
			private BaseExplosionPotion m_Potion;

			public BaseExplosionPotion Potion
			{
				get{ return m_Potion; }
			}

			public ThrowTarget( BaseExplosionPotion potion ) : base( 12, true, TargetFlags.None )
			{
				m_Potion = potion;
			}

			protected override void OnTarget( Mobile from, object targeted )
			{
				if ( m_Potion.Deleted || m_Potion.Map == Map.Internal )
					return;

				IPoint3D p = targeted as IPoint3D;

				if ( p == null )
					return;

				Map map = from.Map;

				if ( map == null )
					return;

				SpellHelper.GetSurfaceTop( ref p );

				from.RevealingAction();

				IEntity to;

				if ( p is Mobile )
					to = (Mobile)p;
				else
					to = new Entity( Serial.Zero, new Point3D( p ), map );

				Effects.SendMovingEffect( from, to, m_Potion.ItemID & 0x3FFF, 7, 0, false, false, m_Potion.Hue, 0 );

				m_Potion.Internalize();
				Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerStateCallback( m_Potion.Reposition_OnTick ), new object[]{ from, p, map } );
			}
		}

		public void Explode( Mobile from, bool direct, Point3D loc, Map map )
		{
			if ( Deleted )
				return;

			Delete();

			for ( int i = 0; m_Users != null && i < m_Users.Count; ++i )
			{
				Mobile m = (Mobile)m_Users[i];
				ThrowTarget targ = m.Target as ThrowTarget;

				if ( targ != null && targ.Potion == this )
					Target.Cancel( m );
			}

			if ( map == null )
				return;

			Effects.PlaySound( loc, map, 0x207 );
			Effects.SendLocationEffect( loc, map, 0x36BD, 20 );

			int alchemyBonus = 0;

			if ( direct )
				alchemyBonus = (int)(from.Skills.Alchemy.Value / (Core.AOS ? 5 : 10));

			IPooledEnumerable eable = LeveledExplosion ? map.GetObjectsInRange( loc, ExplosionRange ) : map.GetMobilesInRange( loc, ExplosionRange );
			ArrayList toExplode = new ArrayList();

			int toDamage = 0;

			foreach ( object o in eable )
			{
				if ( o is Mobile )
				{
					toExplode.Add( o );
					++toDamage;
				}
				else if ( o is BaseExplosionPotion && o != this )
				{
					toExplode.Add( o );
				}
			}

			eable.Free();

			int min = Scale( from, MinDamage );
			int max = Scale( from, MaxDamage );

			for ( int i = 0; i < toExplode.Count; ++i )
			{
				object o = toExplode[i];

				if ( o is Mobile )
				{
					Mobile m = (Mobile)o;

					if ( from == null || (SpellHelper.ValidIndirectTarget( from, m ) && from.CanBeHarmful( m, false )) )
					{
						if ( from != null )
							from.DoHarmful( m );

						int damage = Utility.RandomMinMax( min, max );

						damage += alchemyBonus;

						if ( !Core.AOS && damage > 40 )
							damage = 40;
						else if ( Core.AOS && toDamage > 2 )
							damage /= toDamage - 1;

						AOS.Damage( m, from, damage, 0, 100, 0, 0, 0 );
					}
				}
				else if ( o is BaseExplosionPotion )
				{
					BaseExplosionPotion pot = (BaseExplosionPotion)o;

					pot.Explode( from, false, pot.GetWorldLocation(), pot.Map );
				}
			}
		}
				private static void ReleaseExplosionLock( object state )
		{
			((Mobile)state).EndAction( typeof( BaseExplosionPotion ) );
		}
			}

}
My understanding is that there should be a way to select this (as in the currently cooking potion) for a new ThrowTarget in a way that overrides the timer delay in some fashion but I have no idea how this needs to be written. If anyone could help I would appreciate both an example and an explaination of what you're doing (I'm trying to teach myself C#). Also, if it helps, my purple potions will be functioning similar to UOHybrids.

Last edited by Hyfigh; 09-29-2008 at 09:53 AM.
Hyfigh is offline   Reply With Quote
Old 09-28-2008, 05:37 PM   #2 (permalink)
Master of the Internet
 
Join Date: Mar 2006
Location: Germany
Age: 17
Posts: 14,817
Send a message via AIM to Suil Ban Send a message via MSN to Suil Ban
Default

This is how I did it in my Hybrid-style BaseExplosionPotion.cs:
Code:
if (from is PlayerMobile)
            {
                PlayerMobile pm = from as PlayerMobile;
                if (DateTime.Now - pm.LastExplo < TimeSpan.FromSeconds(5.0))
                {
                    if (m_Timer != null)
                    {
                        from.Target = new ThrowTarget(this);
                        return;
                    }

                    pm.LocalOverheadMessage(0, 0x22, false, "You must wait 5 before using another explosion potion.");
                    return;
                }

                pm.LastExplo = DateTime.Now;
            }
__________________
go fish
Suil Ban is offline   Reply With Quote
Old 09-29-2008, 09:52 AM   #3 (permalink)
Newbie
 
Join Date: Apr 2007
Posts: 47
Default

OK, I changed my script to remove my old timer (I did back it up though) and added yours. I get a bunch of errors though.

Quote:
Originally Posted by Errors Message
The type or namespace name 'PlayerMobile' could not be found (are you missing a using directive or an assembly referrence?)
This along with the same message about 'pm'.

Now I am running RunUO 1.0, and something tells me that line of coding is for 2.0 as I do not see a namespace of Server.PlayerMobile in namespaces folder.

Edit: Added the fact that its 1.0 to the OP.
Hyfigh is offline   Reply With Quote
Old 09-29-2008, 03:09 PM   #4 (permalink)
Forum Novice
 
Soteric's Avatar
 
Join Date: Aug 2006
Location: Russia, Rostov-on-Don
Posts: 772
Send a message via ICQ to Soteric
Default

Code:
using Server.Mobiles;
Soteric is offline   Reply With Quote
Old 09-29-2008, 09:58 PM   #5 (permalink)
Newbie
 
Join Date: Apr 2007
Posts: 47
Default

Understood.

Now it provides me an Error for LastExplo.

Quote:
Originally Posted by Error Message
'Server.Mobiles.PlayerMobile' does not contain a definition for 'LastExplo'
Can someone please explain how to define that? Please remember I am new at this and I do apologize for my ignorance.
Hyfigh is offline   Reply With Quote
Old 09-30-2008, 04:53 AM   #6 (permalink)
Master of the Internet
 
Join Date: Mar 2006
Location: Germany
Age: 17
Posts: 14,817
Send a message via AIM to Suil Ban Send a message via MSN to Suil Ban
Default

You weren't supposed to use my whole block of code. I handle my explosion potion lock differently than you do. I highlighted the important bit in red and pasted the rest so you could get an idea of where to place it.
__________________
go fish
Suil Ban is offline   Reply With Quote
Old 09-30-2008, 09:57 AM   #7 (permalink)
Newbie
 
Join Date: Apr 2007
Posts: 47
Default

Awesome. I appreciate the help. I found where to put the line. Since I couldn't find the fix through my searches, here's what I did:

Code:
		public override void Drink( Mobile from )
		{
			if ( from.BeginAction( typeof ( BaseExplosionPotion ) ) )
			{
				Timer.DelayCall( TimeSpan.FromSeconds( Delay ), new TimerStateCallback( ReleaseExplosionLock ), from );
				}else{
					if ( m_Timer != null )
					{
						from.Target = new ThrowTarget ( this );
						return;
					}
					from.SendMessage("You must wait before throwing another explosion potion!" );
					return;
				}
Sorry that it took me a bit to figure out what exactly I was doing wrong... Again, thanks!
Hyfigh is offline   Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off



Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0 RC5