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!

SpeedHandling System

Kons.snoK

Sorceror
SpeedHandling System

Doing testings - making things ready for my beta, i found a problem in the mobiles speed handling:
Server handles in a poor way changing of Maluses on a Player-Mobile, just overriding the current Speed sending the SpeedControl Packet.
This can cause serious problems if you are, for example, flying and get under sleep effect.
Normal runuo does this :
- SpeedControl.Mount - Set flying
- SpeedControl.Walk - Set sleeping
- SpeedControl.Disable - Sleep expires -> NO MORE MOUNTSPEED.
I know runuo does not supports SA, But i think this can be reproduced with the other things that use SpeedControl packet.

Notice: this solution can be used only by people who know what they are doing

Here's my solution to the problem:
In Mobile.cs
Code:
		#region SA
		private RunningFlags m_RunningFlags = RunningFlags.None;
		protected bool GetRunningFlag(RunningFlags flag)
		{
			return ((m_RunningFlags & flag) != 0);
		}
		protected void SetRunningFlag(RunningFlags flag, bool on)
		{
			m_RunningFlags = (on ? m_RunningFlags | flag : m_RunningFlags & ~flag);
		}

		public void SwitchSpeedControl(RunningFlags flag, bool active)
		{
			if (GetRunningFlag(flag) == active)
				return;//Flag is already at that status, no mod needed

			SetRunningFlag(flag, active);

			if (active)
			{
				Packet p = SpeedHandler.GetSpeedType(flag);//Override current SpeedControl
				if (p == null)
					return;
				if (p == SpeedControl.MountSpeed && GetWalkingFlag())//We cannot override any WALKING Malus
				{
					//Console.WriteLine("Malus not overridden");
					return;
				}
				else
					Send(p);
				return;
			}
			else
			{
				bool restore = false;

				RunningFlags torestore = RunningFlags.None;
				foreach (RunningFlags f in Enum.GetValues(typeof(RunningFlags)))
				{
					if (f == RunningFlags.None)
						continue;
					if (GetRunningFlag(f))
					{
						torestore = f;
						//Console.WriteLine(f.ToString());
						restore = true;
						break;
					}
				}

				if (restore)
				{
					//Console.WriteLine("Passive restoring");
					Packet p = SpeedHandler.GetSpeedType(torestore);//Restore any overridden SpeedControl
					if (p != null)
					{
						if (p == SpeedControl.MountSpeed && GetWalkingFlag())//Check if there are Malus Controls
							Send(SpeedControl.WalkSpeed);
						else
							Send(p);
					}
				}
				else
					Send(SpeedControl.Disable);
			}
		}

		public bool GetWalkingFlag()
		{
			foreach (RunningFlags f in Enum.GetValues(typeof(RunningFlags)))
			{
				if (f == RunningFlags.None)
					continue;
				if (GetRunningFlag(f) && SpeedHandler.GetSpeedType(f) == SpeedControl.WalkSpeed)
					return true;
			}
			return false;
		}
		#endregion


And in another file i called SpeedHandler.cs
Code:
using Server.Network;
using System;

namespace Server
{
	[Flags]
	public enum RunningFlags
	{
		None = 0x00000000,
		Flying = 0x00000001,
		Sleep = 0x00000002,
		ReaperForm = 0x00000004,
		//WalkAnimalForm = 0x00000008,
		StoneForm = 0x00000010,
		TwistedWeald = 0x00000020,
		Grizzle = 0x00000040,
		SpeedBoost = 0x00000080,
		AnimalForm = 0x00000100,
		//Requiem - CUSTOM
		Bola = 0x00000200,
		TPBlocked = 0x00000400,
		GuerrieroStile = 0x00000800,
	}

	public class SpeedHandler
	{
		public static Packet GetSpeedType(RunningFlags flag)
		{
			RunningFlags fl = flag;
			Packet modspeed = null;
			switch (fl)
			{
				case RunningFlags.Flying:
				case RunningFlags.AnimalForm:
				case RunningFlags.SpeedBoost:
					modspeed = SpeedControl.MountSpeed; break;
				case RunningFlags.Grizzle:
				case RunningFlags.ReaperForm:
				case RunningFlags.Sleep:
				case RunningFlags.StoneForm:
				case RunningFlags.TwistedWeald:
				//case RunningFlags.WalkAnimalForm:
				//Requiem
				case RunningFlags.Bola:
				case RunningFlags.GuerrieroStile:
				case RunningFlags.TPBlocked:
					modspeed = SpeedControl.WalkSpeed; break;
				default: break;
			}
			return modspeed;
		}
	}
}

then just simply change any
Code:
pm.Send(SpeedControl.Something)
to
Code:
pm.SwitchSpeedControl(RunningFlags.CurrentFlag, AmIActivatingTheFlag?)

Any suggestion would be welcome
 

Thilgon

Sorceror
Advanced SpeedControl Handling

Maybe something like that can be useful to you, even if does not directly involves packets, nor SA things about speed...

I haven't understood exactly what's the mess with speedcontrol, flying and sleep, could you be more specific? It could also help fixing some not-yet discovered issues with the SA project on Orbsydia :)
 

Kons.snoK

Sorceror
Thilgon;831693 said:
Advanced SpeedControl Handling

Maybe something like that can be useful to you, even if does not directly involves packets, nor SA things about speed...

I haven't understood exactly what's the mess with speedcontrol, flying and sleep, could you be more specific? It could also help fixing some not-yet discovered issues with the SA project on Orbsydia :)

The link you sent me seems to do the same thing using a Dictionary instead of flags.
I really can't see why someone should use a TimeSpan for speedhandling :confused:

Btw i think this does not handle in a correct way speeds:

Code:
        public static SpeedState ComputeSpeed(Mobile m)
        {
            int speed = 0;

            foreach (SpeedContext c in m_Table[m])
            {
               [COLOR="red"] speed += (int)c.Speed;[/COLOR]
                //Console.WriteLine("Speed of {0} changed by {1}. It is now {2}.", m.RawName, (int)c.Speed, speed);
            }

            if (speed > 1)
                speed = 1;
            else if (speed < -1)
                speed = -1;

            return (SpeedState)speed;
        }
Let's say you have 2 flags running and 2 walking, you have has result Disable, instead you probably have some malus applied.
Na it doesn't work.
 

Thilgon

Sorceror
Kons.snoK;831750 said:
The link you sent me seems to do the same thing using a Dictionary instead of flags.
I really can't see why someone should use a TimeSpan for speedhandling :confused:

Btw i think this does not handle in a correct way speeds:

Code:
        public static SpeedState ComputeSpeed(Mobile m)
        {
            int speed = 0;

            foreach (SpeedContext c in m_Table[m])
            {
               [COLOR="red"] speed += (int)c.Speed;[/COLOR]
                //Console.WriteLine("Speed of {0} changed by {1}. It is now {2}.", m.RawName, (int)c.Speed, speed);
            }

            if (speed > 1)
                speed = 1;
            else if (speed < -1)
                speed = -1;

            return (SpeedState)speed;
        }
Let's say you have 2 flags running and 2 walking, you have has result Disable, instead you probably have some malus applied.
Na it doesn't work.

Timespan is probably used to handle custom effects involving speedhandling, like, as he stated there, for a speed potion, that enhances your speed for a short time.
I've never investigated how to manage speed till now, so i do not have it clear...
SpeedControl.Mount is sent when you are mounted or flying
SpeedControl.Walk is the normal, not-mounted speed, right?
SpeedControl.Disable makes the character walk only, he cannot run anymore, so even if he later becames mounted or flying, he is slowed down?

As far as i can tell, you inverted the "sleep expires" and "set sleeping" effect, should be
SpeedControl.Disable - set sleeping
SpeedControl.Walk - sleep expires, with a check if mounted or flying

Maybe i'm totally wrong, but this is all i could assume right now
 

Kons.snoK

Sorceror
Thilgon;831766 said:
Timespan is probably used to handle custom effects involving speedhandling, like, as he stated there, for a speed potion, that enhances your speed for a short time.

This is stupid because speedhandling is always related to some status-malus or other things, and don't need a duration, because already the status has one.

Thilgon;831766 said:
Maybe i'm totally wrong, but this is all i could assume right now

Yeah you're wrong, it's exactly as i wrote ;)
 

M_0_h

Page
Kons.snoK;831782 said:
This is stupid because speedhandling is always related to some status-malus or other things, and don't need a duration, because already the status has one.

Well the timespan is just another aspect of my system you could use, but actually you can do it somewhere else in the scripts as well. Of course, if you don't need the timespan you don't have to use it as a consequence ;)

But oh well, I don't want to compete with anyone in here. :)

Greetings
 

Kons.snoK

Sorceror
M_0_h;831843 said:
Well the timespan is just another aspect of my system you could use, but actually you can do it somewhere else in the scripts as well. Of course, if you don't need the timespan you don't have to use it as a consequence ;)

But oh well, I don't want to compete with anyone in here. :)

Greetings

i just thought on how systems are right now :)
Btw i didn't know about your system till Thilgon posted it here.
 

Thilgon

Sorceror
Kons.snoK;831782 said:
This is stupid because speedhandling is always related to some status-malus or other things, and don't need a duration, because already the status has one.
It is always related on OSI, but you never know what custom effects might include, like, just to say one, an effect that makes you SpeedControl.Mount and some stat loss: the speed effect might last within 1 minute, leaving the stat loss for a longer period...


Kons.snoK;831782 said:
Yeah you're wrong, it's exactly as i wrote ;)
After some kind explanation from M_0_h, now i know i was wrong and why. And i can tell the diffence between the 2 systems.
 
Top