Go Back   RunUO - Ultima Online Emulation > RunUO > Core Modifications > Other

Other Cant find a category above, use this one! Core mods not listed above go here!

Reply
 
Thread Tools Display Modes
Old 08-17-2005, 02:53 PM   #1 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default Intercepting Mobile Packets - Hallucination Effect Redeaux

Hi all, this started off on another topic from Starbucks but tought I'd post it here since it's more of a coding support topic:

Essentially what I'm doing is coding a sanity system for a gothic/lovecraftian themed shard. One of the side effect of sanity loss are phobias and hallucinations. So for instance if your character has a fear of spiders and they fail a sanity check they should start seeing all human mobiles as spiders for a fixed period of time.

Now I've pretty much done my due diligence here and read through all the topics pertaining to hallucination effects with little to know resolution - it was determined it can be done but the concensus was that in order to do it right it would require a modification to the core.

So I got the source code and started digging through it. I have a lot of programming background so I'm not afraid to mess around with the core. However, since there's no documentation for the source (and nor am I asking for any - the core team has enough on their plates) I'm not sure WHERE I'll need to make the necessary changes to implement the sanity hallucination effects. I know HOW to do it, just not WHERE to do it.

On the script side I have flags in a custommobile script for different phobias and a sanity amount. In addition I have two properties: SeeMobilesAsBody and SeeMobilesAsHue.

So, when a phobia kicks in the two above values are set to non-zero values (setting hue to a -1 to generate a random hue).

Then on the core side I would look at these two values before sending out mobile packets. If SeeMobileAsBody is set to a value > 0 then all mobile packets destined to the infected player's client would have the body and hue set accordingly before the packet goes out.

The process is pretty straight forward. I just can't figure out where I need to code it. I've narrowed my search to the packets.cs file but I'm having difficulty decyphering which function needs to be changed. If anyone from the core team (or anyone else in the know) can just point me to the right function, I can drive from there. I'm pretty sure it's one of the functions that accepts beholder and beholdee.

The original topic on starbucks can be found here:
Halloween bag 2005

Thanks in advance for any and all help,
-TM
Terrormaster is offline   Reply With Quote
Old 08-17-2005, 06:00 PM   #2 (permalink)
Forum Novice
 
Join Date: Oct 2003
Location: Vienna, Austria
Age: 21
Posts: 127
Send a message via ICQ to Arahil
Default

well, first of all: you can not access your custom mobile script from the core, except you do it with reflection (which i absolutely do not advise you because it is really very, very slow). so in order to make this change you have to modify the mobile.cs and put your two fields there - or messing around with some interfaces.
then, to send the right packets at the right time, you have to understand the uo packet protocol. there are several sites dedicated to it, for example http://necrotoolz.sourceforge.net/ka...uide/index.htm, http://gonzo.kiev.ua/guide/guide.html or http://uopackets.emuresource.com/packets.php?style= (not complete, but a good start). you have to take a look where the body id and hue is sended and replace the correct values with your halluzination stuff. there will be several places to change this, i think.
maybe an easy way to find those code pieces is to follow the way the server goes if the body or the hue is changed, but you won't learn that much about the uo protocol that way
Arahil is offline   Reply With Quote
Old 08-18-2005, 02:50 AM   #3 (permalink)
Forum Expert
 
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
Red face

you dont need to deal with uo protocols to do such a thing.

here is a starting point for you:

a) add a variable to Mobile/PlayerMobile for hallucination. (implement getter/setter)
b) in Mobile.cs (core), there is a method called ProcessDelta. This is where the packets are sent to the clients. First it updates the client itself, then sends new packets the other clients around.

some code from core:
Code:
IPooledEnumerable eable = m.Map.GetClientsInRange( m.m_Location );
Mobile beholder;
foreach ( NetState state in eable )
{
  beholder = state.Mobile;
  if ( beholder != m && beholder.CanSee( m ) )
  {
      //it sends some packets to clients
     //this is where you need to check whether if 
     //beholder is hallucinating. 
  }
 }
there are some packets that is sent to the clients: RemovePacket, MobileIncoming,MobileMoving etc..

you need to change some of these packets' constructors.
ex)
from
public MobileIncoming( Mobile beholder, Mobile beheld ) : base( 0x78 )
to
public MobileIncoming( Mobile beholder, Mobile beheld, bool hallucination ) : base( 0x78 )

or just add another constructor..

if the boolean variable is true, then you need to pick a random hue for each item.
see the whole code for MobileIncoming, you will get the idea. you might wanna choose a random hue range first, then pick a random hue for each item if you want colors not to be so much different.

you might not need to modify every packet in there.
noobie is offline   Reply With Quote
Old 08-18-2005, 11:52 AM   #4 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default

Thanks Noobie, thats exactly what I was looking for - the WHERE. Gonna hit this evening.

Quote:
you need to change some of these packets' constructors.
ex)
from
public MobileIncoming( Mobile beholder, Mobile beheld ) : base( 0x78 )
to
public MobileIncoming( Mobile beholder, Mobile beheld, bool hallucination ) : base( 0x78 )
Might do that a little different. since I don't want to have to deal with Reflections. Gonna add m_SeeBodyAs into mobile.cs with its get/set. Then change the logic in

public MobileIncoming( Mobile beholder, Mobile beheld ) : base( 0x78 )

to something like

Code:
if ( beholder.SeeBodyAs == 0 )
    m_Stream.Write( (short) beheld.Body );
else
    m_Stream.Write( (short) beholder.SeeBodyAs );
I'll try that and see how that works out.

Thanks Noobie,
-TM
Terrormaster is offline   Reply With Quote
Old 08-18-2005, 12:10 PM   #5 (permalink)
Forum Expert
 
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
Default

hehe, thats not reflection, its overloading (defining extra constructor/method)

btw, you could use some kind of your own method to pick a random hue.
lets say ProcessDelta method is called 5 times in a second.
for each call, you dont want to pick a new hue for the same player. so you could use a random "seed" for some period (use a seed for randomization), and change it after a while. otherwise, client would see some kind of chameleon which changes its color so rapidly
noobie is offline   Reply With Quote
Old 08-18-2005, 01:35 PM   #6 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default

Quote:
hehe, thats not reflection, its overloading (defining extra constructor/method)
Sorry, my reply was a bit confusing - was in a rush to pick up my vidcam, was a guy outside the office cutting a car in half Knoxville style to demonstrate Lennox tools.

But yeah, I knew what you mean by overloading. What I meant by Reflection was the defining of props in the scripts and trying to access them from the core. Haven't done any reflections stuff yet but I know at a high-level what it is kinda. So, I want to put the SeeBodyAs and SeeHueAs in the core instead of the scripts.

Anyways, since I stopped in at home fer lunch (to get the vidcam) I decided to do a recompile on clean unaltered core code... Compiles fine but won't run - gets to verifying and throws an exception. I always test original source compile before making any changes to make sure I have a good point of reference for debugging. I'll post the specifics of the exception when I get back home. But anyone know why a fresh core recompile would crap out when ran?

-TM
Terrormaster is offline   Reply With Quote
Old 08-18-2005, 01:41 PM   #7 (permalink)
Forum Expert
 
Join Date: Dec 2002
Posts: 730
Default

Some times when I compile the core with a differently named .exe I get, this, try to rename the .exe or the project to the same name as the default one (Server.exe)
Atomic is offline   Reply With Quote
Old 08-18-2005, 04:00 PM   #8 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default

Quote:
Originally Posted by Atomic
Some times when I compile the core with a differently named .exe I get, this, try to rename the .exe or the project to the same name as the default one (Server.exe)
BINGO - Renamed the executable to server.exe and it worked like a charm - thanks Atomic! I'll start implementing tonight now that I know any problems resulting will be because of code I introduce. Once I get it working, I'll put together a tutorial to share here.

-TM
Terrormaster is offline   Reply With Quote
Old 08-19-2005, 12:38 AM   #9 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default

WOOHOO! Got this to work, yehah! Had some interesting hickups on the way. For some reason the first iteration behaved rather bizaar - everyone within range of the affected player saw the effects as well.

After commenting out a particular piece of core code in two spots I got the sucker to work. However, I'm not 100% certain as to why it created the above behavior nor do I completely understand the logic behind its inclusion. The code in question is as follows:

Code:
if ( p == null )
    p = cache[noto] = new MobileMoving( m, noto );
What is the reasoning behind caching preset packets sorted by notoriety? I'd be eternally greatful if someone could explain this one - I hate commenting out original code without knowing why I'm doing so.

-TM
Terrormaster is offline   Reply With Quote
Old 08-19-2005, 01:20 AM   #10 (permalink)
Forum Expert
 
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
Default

thats a cache mechanism. instead of re-evaluate and creating the same packet, it sends same value from the cache.

that should has nothing to do with the error.
noobie is offline   Reply With Quote
Old 08-19-2005, 09:10 AM   #11 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default

Is it possible that the cache[] array is not localized? Because when I comment out the conditional and just force a value into it and P the error goes away. Here's the full extent of the code I modified in mobile.cs:

move() method:
Code:
		public virtual bool Move( Direction d )
		{
			if ( m_Deleted )
				return false;

			BankBox box = FindBankNoCreate();

			if ( box != null && box.Opened )
				box.Close();

			Point3D newLocation = Location;
			Point3D oldLocation = newLocation;

			if ( (m_Direction & Direction.Mask) == (d & Direction.Mask) )
			{
				// We are actually moving (not just a direction change)

				if ( m_Spell != null && !m_Spell.OnCasterMoving( d ) )
					return false;

				if ( m_Paralyzed || m_Frozen )
				{
					SendLocalizedMessage( 500111 ); // You are frozen and can not move.

					return false;
				}

				int newZ;

				if ( CheckMovement( d, out newZ ) )
				{
					int x = m_Location.m_X, y = m_Location.m_Y;
					int oldX = x, oldY = y;
					int oldZ = m_Location.m_Z;

					switch ( d & Direction.Mask )
					{
						case Direction.North:      --y; break;
						case Direction.Right: ++x; --y; break;
						case Direction.East:  ++x;      break;
						case Direction.Down:  ++x; ++y; break;
						case Direction.South:      ++y; break;
						case Direction.Left:  --x; ++y; break;
						case Direction.West:  --x;      break;
						case Direction.Up:    --x; --y; break;
					}

					m_Pushing = false;

					Map map = m_Map;

					if ( map != null )
					{
						Sector oldSector = map.GetSector( oldX, oldY );
						Sector newSector = map.GetSector( x, y );
						ArrayList list;

						if ( oldSector != newSector )
						{
							list = oldSector.Mobiles;

							for ( int i = 0; i < list.Count; ++i )
							{
								Mobile m = (Mobile)list[i];

								if ( m != this && m.X == oldX && m.Y == oldY && (m.Z + 15) > oldZ && (oldZ + 15) > m.Z && !m.OnMoveOff( this ) )
									return false;
							}

							list = oldSector.Items;

							for ( int i = 0; i < list.Count; ++i )
							{
								Item item = (Item)list[i];

								if ( item.AtWorldPoint( oldX, oldY ) && (item.Z == oldZ || ((item.Z + item.ItemData.Height) > oldZ && (oldZ + 15) > item.Z)) && !item.OnMoveOff( this ) )
									return false;
							}

							list = newSector.Mobiles;

							for ( int i = 0; i < list.Count; ++i )
							{
								Mobile m = (Mobile)list[i];

								if ( m.X == x && m.Y == y && (m.Z + 15) > newZ && (newZ + 15) > m.Z && !m.OnMoveOver( this ) )
									return false;
							}

							list = newSector.Items;

							for ( int i = 0; i < list.Count; ++i )
							{
								Item item = (Item)list[i];

								if ( item.AtWorldPoint( x, y ) && (item.Z == newZ || ((item.Z + item.ItemData.Height) > newZ && (newZ + 15) > item.Z)) && !item.OnMoveOver( this ) )
									return false;
							}
						}
						else
						{
							list = oldSector.Mobiles;

							for ( int i = 0; i < list.Count; ++i )
							{
								Mobile m = (Mobile)list[i];

								if ( m != this && m.X == oldX && m.Y == oldY && (m.Z + 15) > oldZ && (oldZ + 15) > m.Z && !m.OnMoveOff( this ) )
									return false;
								else if ( m.X == x && m.Y == y && (m.Z + 15) > newZ && (newZ + 15) > m.Z && !m.OnMoveOver( this ) )
									return false;
							}

							list = oldSector.Items;

							for ( int i = 0; i < list.Count; ++i )
							{
								Item item = (Item)list[i];

								if ( item.AtWorldPoint( oldX, oldY ) && (item.Z == oldZ || ((item.Z + item.ItemData.Height) > oldZ && (oldZ + 15) > item.Z)) && !item.OnMoveOff( this ) )
									return false;
								else if ( item.AtWorldPoint( x, y ) && (item.Z == newZ || ((item.Z + item.ItemData.Height) > newZ && (newZ + 15) > item.Z)) && !item.OnMoveOver( this ) )
									return false;
							}
						}

						Region region = Region.Find( new Point3D( x, y, newZ ), m_Map );

						if ( region != null && !region.OnMoveInto( this, d, new Point3D( x, y, newZ ), oldLocation ) )
							return false;
					}
					else
					{
						return false;
					}

					if ( !InternalOnMove( d ) )
						return false;

					if ( m_FwdEnabled && m_NetState != null && m_AccessLevel < m_FwdAccessOverride && (!m_FwdUOTDOverride || (m_NetState.Version != null && m_NetState.Version.Type != ClientType.UOTD)) )
					{
						if ( m_MoveRecords == null )
							m_MoveRecords = new Queue( 6 );

						while ( m_MoveRecords.Count > 0 )
						{
							MovementRecord r = (MovementRecord)m_MoveRecords.Peek();

							if ( r.Expired() )
								m_MoveRecords.Dequeue();
							else
								break;
						}

						if ( m_MoveRecords.Count >= m_FwdMaxSteps )
						{
							FastWalkEventArgs fw = new FastWalkEventArgs( m_NetState );
							EventSink.InvokeFastWalk( fw );

							if ( fw.Blocked )
								return false;
						}

						TimeSpan delay;

						if ( Mounted )
							delay = (d & Direction.Running) != 0 ? m_RunMount : m_WalkMount;
						else
							delay = (d & Direction.Running) != 0 ? m_RunFoot : m_WalkFoot;

						DateTime end;

						if ( m_MoveRecords.Count > 0 )
							end = m_EndQueue + delay;
						else
							end = DateTime.Now + delay;

						m_MoveRecords.Enqueue( MovementRecord.NewInstance( end ) );

						m_EndQueue = end;
					}

					m_LastMoveTime = DateTime.Now;
					newLocation = new Point3D( x, y, newZ );
				}
				else
				{
					return false;
				}

				DisruptiveAction();
			}

			if ( m_NetState != null )
				m_NetState.Send( MovementAck.Instantiate( m_NetState.Sequence, this ) );//new MovementAck( m_NetState.Sequence, this ) );

			SetLocation( newLocation, false );
			SetDirection( d );

			if ( m_Map != null )
			{
				MobileMoving[] cache = m_MovingPacketCache;

				for ( int i = 0; i < cache.Length; ++i )
					cache[i] = null;

				IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange );

				foreach ( object o in eable )
				{
					if ( o == this )
						continue;

					if ( o is Mobile )
					{
						m_MoveList.Add( o );
					}
					else if ( o is Item )
					{
						Item item = (Item)o;

						if ( item.HandlesOnMovement )
							m_MoveList.Add( item );
					}
				}

				eable.Free();

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

					if ( o is Mobile )
					{
						Mobile m = (Mobile)m_MoveList[i];
						NetState ns = m.NetState;

						if ( ns != null && Utility.InUpdateRange( m_Location, m.m_Location ) && m.CanSee( this ) )
						{
							int noto = Notoriety.Compute( m, this );
							MobileMoving p = cache[noto];

							/// NECROPOLIS: removed cache conditional to correct bug with hallucination code - TM, 08-19-05
							//if ( p == null ) //** ORIGINAL CORE **//
							//	p = cache[noto] = new MobileMoving( m, noto ); //** ORIGINAL CORE **//
							p = cache[noto] = new MobileMoving( this, noto, m );

							ns.Send( p );
						}

						m.OnMovement( this, oldLocation );
					}
					else if ( o is Item )
					{
						((Item)o).OnMovement( this, oldLocation );
					}
				}

				if ( m_MoveList.Count > 0 )
					m_MoveList.Clear();
			}

			return true;
		}
ProcessDelta() method
Code:
		public virtual void ProcessDelta()
		{
			Mobile m = this;
			MobileDelta delta;
			MobileDelta attrs;

			delta = m.m_DeltaFlags;

			if ( delta == MobileDelta.None )
				return;

			attrs = delta & MobileDelta.Attributes;

			m.m_DeltaFlags = MobileDelta.None;
			m.m_InDeltaQueue = false;

			bool sendHits = false, sendStam = false, sendMana = false, sendAll = false, sendAny = false;
			bool sendIncoming = false, sendNonlocalIncoming = false;
			bool sendUpdate = false, sendRemove = false;
			bool sendPublicStats = false, sendPrivateStats = false;
			bool sendMoving = false, sendNonlocalMoving = false;
			bool sendOPLUpdate = Core.AOS && (delta & MobileDelta.Properties) != 0;

			if ( attrs != MobileDelta.None )
			{
				sendAny = true;

				if ( attrs == MobileDelta.Attributes )
				{
					sendAll = true;
				}
				else
				{
					sendHits = ( (attrs & MobileDelta.Hits) != 0 );
					sendStam = ( (attrs & MobileDelta.Stam) != 0 );
					sendMana = ( (attrs & MobileDelta.Mana) != 0 );
				}
			}

			if ( (delta & MobileDelta.GhostUpdate) != 0 )
			{
				sendNonlocalIncoming = true;
			}

			if ( (delta & MobileDelta.Hue) != 0 )
			{
				sendNonlocalIncoming = true;
				sendUpdate = true;
				sendRemove = true;
			}

			if ( (delta & MobileDelta.Direction) != 0 )
			{
				sendNonlocalMoving = true;
				sendUpdate = true;
			}

			if ( (delta & MobileDelta.Body) != 0 )
			{
				sendUpdate = true;
				sendIncoming = true;
			}

			/*if ( (delta & MobileDelta.Hue) != 0 )
				{
					sendNonlocalIncoming = true;
					sendUpdate = true;
				}
				else if ( (delta & (MobileDelta.Direction | MobileDelta.Body)) != 0 )
				{
					sendNonlocalMoving = true;
					sendUpdate = true;
				}
				else*/ if ( (delta & (MobileDelta.Flags | MobileDelta.Noto)) != 0 )
					   {
						   sendMoving = true;
					   }

			if ( (delta & MobileDelta.Name) != 0 )
			{
				sendAll = false;
				sendHits = false;
				sendAny = sendStam || sendMana;
				sendPublicStats = true;
			}

			if ( (delta & (MobileDelta.WeaponDamage | MobileDelta.Resistances | MobileDelta.Stat | MobileDelta.Weight | MobileDelta.Gold | MobileDelta.Armor | MobileDelta.StatCap | MobileDelta.Followers | MobileDelta.TithingPoints)) != 0 )
			{
				sendPrivateStats = true;
			}

			MobileMoving[] cache = m_MovingPacketCache;

			if ( sendMoving || sendNonlocalMoving )
			{
				for ( int i = 0; i < cache.Length; ++i )
					cache[i] = null;
			}

			NetState ourState = m.m_NetState;

			if ( ourState != null )
			{
				if ( sendUpdate )
				{
					ourState.Sequence = 0;
					ourState.Send( new MobileUpdate( m ) );
					ClearFastwalkStack();
				}

				if ( sendIncoming )
					ourState.Send( new MobileIncoming( m, m ) );

				if ( sendMoving )
				{
					int noto = Notoriety.Compute( m, m );

					ourState.Send( cache[noto] = new MobileMoving( m, noto ) );
				}

				if ( sendPublicStats || sendPrivateStats )
				{
					ourState.Send( new MobileStatusExtended( m ) );
				}
				else if ( sendAll )
				{
					ourState.Send( new MobileAttributes( m ) );
				}
				else if ( sendAny )
				{
					if ( sendHits )
						ourState.Send( new MobileHits( m ) );

					if ( sendStam )
						ourState.Send( new MobileStam( m ) );

					if ( sendMana )
						ourState.Send( new MobileMana( m ) );
				}

				if ( sendStam || sendMana )
				{
					IParty ip = m_Party as IParty;

					if ( ip != null && sendStam )
						ip.OnStamChanged( this );

					if ( ip != null && sendMana )
						ip.OnManaChanged( this );
				}

				if ( sendOPLUpdate )
					ourState.Send( OPLPacket );
			}

			sendMoving = sendMoving || sendNonlocalMoving;
			sendIncoming = sendIncoming || sendNonlocalIncoming;
			sendHits = sendHits || sendAll;

			if ( m.m_Map != null && (sendRemove || sendIncoming || sendPublicStats || sendHits || sendMoving || sendOPLUpdate) )
			{
				Mobile beholder;

				IPooledEnumerable eable = m.Map.GetClientsInRange( m.m_Location );

				Packet hitsPacket = null;
				Packet statPacketTrue = null, statPacketFalse = null;
				Packet deadPacket = null;

				foreach ( NetState state in eable )
				{
					beholder = state.Mobile;

					if ( beholder != m && beholder.CanSee( m ) )
					{
						if ( sendRemove )
							state.Send( m.RemovePacket );

						if ( sendIncoming )
						{
							state.Send( new MobileIncoming( beholder, m ) );

							if ( m.IsDeadBondedPet )
							{
								if ( deadPacket == null )
									deadPacket = new BondedStatus( 0, m.m_Serial, 1 );

								state.Send( deadPacket );
							}
						}

						if ( sendMoving )
						{
							int noto = Notoriety.Compute( beholder, m );

							MobileMoving p = cache[noto];


					/// NECROPOLIS: removed cache conditional to correct bug with hallucination code - TM, 08-19-05
							//if ( p == null ) //** ORIGINAL CORE **//
							//	cache[noto] = p = new MobileMoving( m, noto ); //** ORIGINAL CORE **//
							cache[noto] = p = new MobileMoving( m, noto, beholder );

							state.Send( p );
						}

						if ( sendPublicStats )
						{
							if ( m.CanBeRenamedBy( beholder ) )
							{
								if ( statPacketTrue == null )
									statPacketTrue = new MobileStatusCompact( true, m );

								state.Send( statPacketTrue );
							}
							else
							{
								if ( statPacketFalse == null )
									statPacketFalse = new MobileStatusCompact( false, m );

								state.Send( statPacketFalse );
							}
						}
						else if ( sendHits )
						{
							if ( hitsPacket == null )
								hitsPacket = new MobileHitsN( m );

							state.Send( hitsPacket );
						}

						if ( sendOPLUpdate )
							state.Send( OPLPacket );
					}
				}

				eable.Free();
			}
		}
SeeBodyAs(get|set) property <-- appended to the end of the mobile class
Code:

		/// NECROPOLIS: ==============================================================
		/// Begin modifications for Necropolis Sanity system
		/// ==========================================================================

		private short m_SeeBodyAs = 0;

		[CommandProperty( AccessLevel.GameMaster )]
		public short SeeBodyAs
		{
			get{ return m_SeeBodyAs; }
			set{ m_SeeBodyAs = value; }
		}
		/// ==========================================================================
The following are the changes I made to the packets.cs file:

MobileIncoming() class
Code:
	public sealed class MobileIncoming : Packet
	{
		private static int[] m_DupedLayers = new int[256];
		private static int m_Version;

		public Mobile m_Beheld;

		public MobileIncoming( Mobile beholder, Mobile beheld ) : base( 0x78 )
		{
			m_Beheld = beheld;
			++m_Version;

			ArrayList eq = beheld.Items;
			int count = eq.Count;

			this.EnsureCapacity( 23 + (count * 9) );

			int hue = beheld.Hue;

			if ( beheld.SolidHueOverride >= 0 )
				hue = beheld.SolidHueOverride;

			m_Stream.Write( (int) beheld.Serial );

			/// NECROPOLIS: Added conditional for Hallucination support - TM, 08-19-05
			if ( beholder.SeeBodyAs == 0 || beholder == beheld )
				m_Stream.Write( (short) beheld.Body );
			else
				m_Stream.Write( (short) beholder.SeeBodyAs );
			/// NECROPOLIS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
			m_Stream.Write( (short) beheld.X );
			m_Stream.Write( (short) beheld.Y );
			m_Stream.Write( (sbyte) beheld.Z );
			m_Stream.Write( (byte) beheld.Direction );
			m_Stream.Write( (short) hue );
			m_Stream.Write( (byte) beheld.GetPacketFlags() );
			m_Stream.Write( (byte) Notoriety.Compute( beholder, beheld ) );

			for ( int i = 0; i < count; ++i )
			{
				Item item = (Item)eq[i];

				byte layer = (byte) item.Layer;

				if ( !item.Deleted && beholder.CanSee( item ) && m_DupedLayers[layer] != m_Version )
				{
					m_DupedLayers[layer] = m_Version;

					hue = item.Hue;

					if ( beheld.SolidHueOverride >= 0 )
						hue = beheld.SolidHueOverride;

					int itemID = item.ItemID & 0x3FFF;
					bool writeHue = ( hue != 0 );

					if ( writeHue )
						itemID |= 0x8000;

					m_Stream.Write( (int) item.Serial );
					m_Stream.Write( (short) itemID );
					m_Stream.Write( (byte) layer );

					if ( writeHue )
						m_Stream.Write( (short) hue );
				}
			}

			m_Stream.Write( (int) 0 ); // terminate
		}
	}
MobileMoving() class <- basically added an overload to pass in beholder
Code:
	public sealed class MobileMoving : Packet
	{
		public MobileMoving( Mobile m, int noto/*Mobile beholder, Mobile beheld*/ ) : base( 0x77, 17 )
		{
			Point3D loc = m.Location;

			int hue = m.Hue;

			if ( m.SolidHueOverride >= 0 )
				hue = m.SolidHueOverride;

			m_Stream.Write( (int) m.Serial );
			m_Stream.Write( (short) m.Body );
			m_Stream.Write( (short) loc.m_X );
			m_Stream.Write( (short) loc.m_Y );
			m_Stream.Write( (sbyte) loc.m_Z );
			m_Stream.Write( (byte) m.Direction );
			m_Stream.Write( (short) hue );
			m_Stream.Write( (byte) m.GetPacketFlags() );
			m_Stream.Write( (byte) noto );//Notoriety.Compute( beholder, beheld ) );
		}

		/// NECROPOLIS: Added overload for Hallucination support - TM, 08-19-05
		public MobileMoving( Mobile m, int noto, Mobile beholder ) : base( 0x77, 17 )
		{
			Point3D loc = m.Location;

			int hue = m.Hue;

			if ( m.SolidHueOverride >= 0 )
				hue = m.SolidHueOverride;

			m_Stream.Write( (int) m.Serial );
			if ( beholder.SeeBodyAs == 0 || m == beholder )
				m_Stream.Write( (short) m.Body );
			else
				m_Stream.Write( (short) beholder.SeeBodyAs );
			m_Stream.Write( (short) loc.m_X );
			m_Stream.Write( (short) loc.m_Y );
			m_Stream.Write( (sbyte) loc.m_Z );
			m_Stream.Write( (byte) m.Direction );
			m_Stream.Write( (short) hue );
			m_Stream.Write( (byte) m.GetPacketFlags() );
			m_Stream.Write( (byte) noto );
		}
	}
Thats pretty much the extent of everything I changed or added at this point. Then I loaded up two clients with two different accounts as well as having a friend login to test. Then I used [set seebodyas 28 (spider) and target only ONE of the three players.

The SeeBodyAs will be managed script side from the sanity system to keep all the sanity rules out of the core.

Also, I had to mod both Move() and ProcessDelta() for this to work - modding ProcessDelta() only resulted in bizaar flickering effects where the mobile would occasionally toggle back to their normal state.

-TM

FYI: ALPHA VERSION / PROOF OF CONCEPT
This core modification is alpha only as proof of concept. Install into the core at your own risk. Once I have finished testing, and am confident the code is pretty solid I will release it for public consumption with support and detailed installation instructions.
Terrormaster is offline   Reply With Quote
Old 08-19-2005, 12:00 PM   #12 (permalink)
Forum Expert
 
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
Default

btw, customized MobileIncoming packet is not called in your code..
noobie is offline   Reply With Quote
Old 08-19-2005, 12:10 PM   #13 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default

I didn't overload on MobileIncoming() as it already accepted Beholder and Beheld, just added logic around the stream for Body. As a result I didn't need to modify any of the existing calls.

-TM
Terrormaster is offline   Reply With Quote
Old 08-19-2005, 01:37 PM   #14 (permalink)
Forum Expert
 
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
Default

upss, my bad sry
noobie is offline   Reply With Quote
Old 08-19-2005, 03:21 PM   #15 (permalink)
 
Join Date: Jul 2005
Location: New England
Age: 39
Posts: 29
Send a message via AIM to Terrormaster
Default

Quote:
Originally Posted by noobie
upss, my bad sry
NP

Now all is left is to find out what the reprecussions of commenting out those IFs are and I'll be set to roll forward. Gonna wrap up the remainder of the design for the sanity system and begin implementation.

Thanks again for all the help everyone,
-TM
Terrormaster is offline   Reply With Quote
Old 04-17-2006, 11:48 AM   #16 (permalink)
 
Join Date: Jan 2006
Posts: 1
Default

You can mantain the caching system for non-Hallucinated mobile.

when the code send the Mobilemoving packet you can check if the beholding mobile are hallucinated or not. Then you can sent the cached packet (if the mob aren't hallucinated), or a new one for the hallucination.
NicoTM 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