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!

Sphere-like Hallucination System

fwiffo

Sorceror
ADVISORY: you have to know the system where you are working, you have to modify CORE parts and you have to modify something I'm sure I've forgotten! So be advised, It's not easy and I will not be your help-desk...

In Mobile.cs you will need this (also be advised, you have to find any method of whom I changed the overloads)
Code:
        public virtual bool IsHallucinated{get{return false;}}
 
        public virtual short GetBody(Mobile toSend)
        {
            return (short)toSend.Body;
        }
       
        public virtual int GetHue(Mobile toSend)
        {
            return toSend.Hue;
        }
       
        private static Packet[][] m_MovingPacketCache = new Packet[4][]
            {
                new Packet[8],
                new Packet[8],
                new Packet[8],
                new Packet[8]
            };
           
        ALSO FIND THE MOVE METHOD AND CHANGE
        Packet[][] cache = m_MovingPacketCache;
 
 
                for( int i = 0; i < cache.Length; ++i )
                    for( int j = 0; j < cache[i].Length; ++j )
                        Packet.Release( ref cache[i][j] );
 
 
                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 ) )
                        {
                            Packet p = null;
 
 
                            if ( ns.StygianAbyss ) {
                                int noto = Notoriety.Compute( m, this );
                                if(m.IsHallucinated)
                                {
                                    p = cache[2][noto];
                                    if( p == null )
                                    cache[2][noto] = p = Packet.Acquire( new MobileMoving( this, noto, m ) );
                                }
                                else
                                {
                                    p = cache[0][noto];
                                    if( p == null )
                                    cache[0][noto] = p = Packet.Acquire( new MobileMoving( this, noto, m ) );
                                }
                            } else {
                                int noto = Notoriety.Compute( m, this );
                                if(m.IsHallucinated)
                                {
                                    p = cache[3][noto];
                                    if( p == null )
                                    cache[3][noto] = p = Packet.Acquire( new MobileMovingOld( this, noto, m ) );
                                }
                                else
                                {
                                    p = cache[1][noto];
                                    if( p == null )
                                    cache[1][noto] = p = Packet.Acquire( new MobileMovingOld( this, noto, m ) );
                                }
                            }
 
 
                            ns.Send( p );
                        }
 
 
                        m.OnMovement( this, oldLocation );
                    }
                    else if( o is Item )
                    {
                        ((Item)o).OnMovement( this, oldLocation );
                    }
                }

In Packets.cs (IN THE CORE!) YOU NEED THIS!
Code:
    public sealed class MobileUpdate : Packet    {
        public MobileUpdate( Mobile m ) : base( 0x20, 19 )
        {
            int hue = m.GetHue(m);
 
 
            if ( m.SolidHueOverride >= 0 )
                hue = m.SolidHueOverride;
 
 
            m_Stream.Write( (int) m.Serial );
            m_Stream.Write( m.GetBody(m) );
            m_Stream.Write( (byte) 0 );
            m_Stream.Write( (short) hue );
            m_Stream.Write( (byte) m.GetPacketFlags() );
            m_Stream.Write( (short) m.X );
            m_Stream.Write( (short) m.Y );
            m_Stream.Write( (short) 0 );
            m_Stream.Write( (byte) m.Direction );
            m_Stream.Write( (sbyte) m.Z );
        }
    }
 
 
    // Pre-7.0.0.0 Mobile Update
    public sealed class MobileUpdateOld : Packet
    {
        public MobileUpdateOld( Mobile m ) : base( 0x20, 19 )
        {
            int hue = m.GetHue(m);
 
 
            if ( m.SolidHueOverride >= 0 )
                hue = m.SolidHueOverride;
 
 
            m_Stream.Write( (int) m.Serial );
            m_Stream.Write( m.GetBody(m) );
            m_Stream.Write( (byte) 0 );
            m_Stream.Write( (short) hue );
            m_Stream.Write( (byte) m.GetOldPacketFlags() );
            m_Stream.Write( (short) m.X );
            m_Stream.Write( (short) m.Y );
            m_Stream.Write( (short) 0 );
            m_Stream.Write( (byte) m.Direction );
            m_Stream.Write( (sbyte) m.Z );
        }
    }
 
 
    public sealed class MobileIncoming : Packet
    {
        private static int[] m_DupedLayers = new int[256];
        private static int m_Version;
 
 
        public MobileIncoming( Mobile beholder, Mobile beheld ) : base( 0x78 )
        {
            ++m_Version;
 
 
            List<Item> eq = beheld.Items;
            int count = eq.Count;
 
 
            if( beheld.HairItemID > 0 )
                count++;
            if( beheld.FacialHairItemID > 0 )
                count++;
 
 
            this.EnsureCapacity( 23 + (count * 9) );
 
 
            int hue = beholder.GetHue(beheld);
            //int hue = beheld.Hue;
 
 
            if ( beheld.SolidHueOverride >= 0 )
                hue = beheld.SolidHueOverride;
 
 
            m_Stream.Write( (int) beheld.Serial );
            m_Stream.Write( beholder.GetBody(beheld) );
            //m_Stream.Write( (short) beheld.Body );
            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 < eq.Count; ++i )
            {
                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 & 0x7FFF;
                    bool writeHue = ( hue != 0 );
 
 
                    if ( writeHue )
                        itemID |= 0x8000;
 
 
                    m_Stream.Write( (int) item.Serial );
                    m_Stream.Write( (ushort) itemID );
                    m_Stream.Write( (byte) layer );
 
 
                    if ( writeHue )
                        m_Stream.Write( (short) hue );
                }
            }
 
 
            if( beheld.HairItemID > 0 )
            {
                if( m_DupedLayers[(int)Layer.Hair] != m_Version )
                {
                    m_DupedLayers[(int)Layer.Hair] = m_Version;
                    hue = beheld.HairHue;
 
 
                    if( beheld.SolidHueOverride >= 0 )
                        hue = beheld.SolidHueOverride;
 
 
                    int itemID = beheld.HairItemID & 0x7FFF;
 
 
                    bool writeHue = (hue != 0);
 
 
                    if( writeHue )
                        itemID |= 0x8000;
 
 
                    m_Stream.Write( (int)HairInfo.FakeSerial( beheld ) );
                    m_Stream.Write( (ushort)itemID );
                    m_Stream.Write( (byte)Layer.Hair );
 
 
                    if( writeHue )
                        m_Stream.Write( (short)hue );
                }
            }
 
 
            if( beheld.FacialHairItemID > 0 )
            {
                if( m_DupedLayers[(int)Layer.FacialHair] != m_Version )
                {
                    m_DupedLayers[(int)Layer.FacialHair] = m_Version;
                    hue = beheld.FacialHairHue;
 
 
                    if( beheld.SolidHueOverride >= 0 )
                        hue = beheld.SolidHueOverride;
 
 
                    int itemID = beheld.FacialHairItemID & 0x7FFF;
 
 
                    bool writeHue = (hue != 0);
 
 
                    if( writeHue )
                        itemID |= 0x8000;
 
 
                    m_Stream.Write( (int)FacialHairInfo.FakeSerial( beheld ) );
                    m_Stream.Write( (ushort)itemID );
                    m_Stream.Write( (byte)Layer.FacialHair );
 
 
                    if( writeHue )
                        m_Stream.Write( (short)hue );
                }
            }
 
 
            m_Stream.Write( (int) 0 ); // terminate
        }
    }
 
 
    // Pre-7.0.0.0 Mobile Incoming
    public sealed class MobileIncomingOld : Packet
    {
        private static int[] m_DupedLayers = new int[256];
        private static int m_Version;
 
 
        public MobileIncomingOld( Mobile beholder, Mobile beheld ) : base( 0x78 )
        {
            ++m_Version;
 
 
            List<Item> eq = beheld.Items;
            int count = eq.Count;
 
 
            if( beheld.HairItemID > 0 )
                count++;
            if( beheld.FacialHairItemID > 0 )
                count++;
 
 
            this.EnsureCapacity( 23 + (count * 9) );
 
 
            int hue = beholder.GetHue(beheld); //int hue = beheld.Hue;
 
 
            if ( beheld.SolidHueOverride >= 0 )
                hue = beheld.SolidHueOverride;
 
 
            m_Stream.Write( (int) beheld.Serial );
            m_Stream.Write( beholder.GetBody(beheld) ); //m_Stream.Write( (short) beheld.Body );
            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.GetOldPacketFlags() );
            m_Stream.Write( (byte) Notoriety.Compute( beholder, beheld ) );
 
 
            for ( int i = 0; i < eq.Count; ++i )
            {
                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 & 0x7FFF;
                    bool writeHue = ( hue != 0 );
 
 
                    if ( writeHue )
                        itemID |= 0x8000;
 
 
                    m_Stream.Write( (int) item.Serial );
                    m_Stream.Write( (ushort) itemID );
                    m_Stream.Write( (byte) layer );
 
 
                    if ( writeHue )
                        m_Stream.Write( (short) hue );
                }
            }
 
 
            if( beheld.HairItemID > 0 )
            {
                if( m_DupedLayers[(int)Layer.Hair] != m_Version )
                {
                    m_DupedLayers[(int)Layer.Hair] = m_Version;
                    hue = beheld.HairHue;
 
 
                    if( beheld.SolidHueOverride >= 0 )
                        hue = beheld.SolidHueOverride;
 
 
                    int itemID = beheld.HairItemID & 0x7FFF;
 
 
                    bool writeHue = (hue != 0);
 
 
                    if( writeHue )
                        itemID |= 0x8000;
 
 
                    m_Stream.Write( (int)HairInfo.FakeSerial( beheld ) );
                    m_Stream.Write( (ushort)itemID );
                    m_Stream.Write( (byte)Layer.Hair );
 
 
                    if( writeHue )
                        m_Stream.Write( (short)hue );
                }
            }
 
 
            if( beheld.FacialHairItemID > 0 )
            {
                if( m_DupedLayers[(int)Layer.FacialHair] != m_Version )
                {
                    m_DupedLayers[(int)Layer.FacialHair] = m_Version;
                    hue = beheld.FacialHairHue;
 
 
                    if( beheld.SolidHueOverride >= 0 )
                        hue = beheld.SolidHueOverride;
 
 
                    int itemID = beheld.FacialHairItemID & 0x7FFF;
 
 
                    bool writeHue = (hue != 0);
 
 
                    if( writeHue )
                        itemID |= 0x8000;
 
 
                    m_Stream.Write( (int)FacialHairInfo.FakeSerial( beheld ) );
                    m_Stream.Write( (ushort)itemID );
                    m_Stream.Write( (byte)Layer.FacialHair );
 
 
                    if( writeHue )
                        m_Stream.Write( (short)hue );
                }
            }
 
 
            m_Stream.Write( (int) 0 ); // terminate
        }
    }
 
 
    public sealed class MobileMoving : Packet
    {
        public MobileMoving( Mobile m, int noto, Mobile receiver ) : base( 0x77, 17 )
        {
            Point3D loc = m.Location;
 
 
            int hue = receiver.GetHue(m);
 
 
            if ( m.SolidHueOverride >= 0 )
                hue = m.SolidHueOverride;
 
 
            m_Stream.Write( (int) m.Serial );
            m_Stream.Write( receiver.GetBody(m) );
            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 );
        }
    }
 
 
    // Pre-7.0.0.0 Mobile Moving
    public sealed class MobileMovingOld : Packet
    {
        public MobileMovingOld( Mobile m, int noto, Mobile receiver ) : base( 0x77, 17 )
        {
            Point3D loc = m.Location;
 
 
            int hue = receiver.GetHue(m);
 
 
            if ( m.SolidHueOverride >= 0 )
                hue = m.SolidHueOverride;
 
 
            m_Stream.Write( (int) m.Serial );
            m_Stream.Write( receiver.GetBody(m) );
            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.GetOldPacketFlags() );
            m_Stream.Write( (byte) noto );
        }
    }

In PlayerMobile.CS you will need of course this:
Code:
        private bool m_hallucinate;
 
        [CommandProperty(AccessLevel.GameMaster)]
        public bool Hallucinating
        {
            get { return m_hallucinate; }
            set
            {
                if (m_hallucinate == value)
                    return;
 
 
                if(value) //PRIMA INIZIALIZZIAMO
                {
                    m_hallucinate = value; // e poi settiamo la var..
                    this.SendEverything();
                }
                else //DEINIZIALIZZAZIONE
                {
                    m_hallucinate = value; // settiamo subito la var
                    this.SendEverything();
                }
 
 
                InvalidateProperties();
            }
        }
       
        public override bool IsHallucinated
        {
            get { return m_hallucinate; }
        }
 
 
        public override short GetBody(Mobile toSend)
        {
            if(m_hallucinate)
            {
                return (short) m_BodyArray[new Random(HalluRandomSeed+toSend.Serial.Value).Next( 0, 59 )];
            }
 
 
            return (short)toSend.Body;
        }
 
 
        public override int GetHue(Mobile toSend)
        {
            if(m_hallucinate)
            {
                return new Random(HalluRandomSeed+toSend.Serial.Value).Next( 2, 1200 );
            }
 
 
            return toSend.Hue;
        }
 
 
        private static int HalluRandomSeed=Utility.Random(1073741822);
 
 
        private class ReseedTimer : Timer
        {
            public ReseedTimer() : base( TimeSpan.FromSeconds( 40 ), TimeSpan.FromSeconds( 20 ) )
            {
                Priority = TimerPriority.FiveSeconds;
            }
 
 
            protected override void OnTick()
            {
                PlayerMobile.HalluRandomSeed=Utility.Random(1073741822);
            }
        }
 
 
        private static readonly int[] m_BodyArray = new int[60]{1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15, 16, 21, 22, 24, 26, 28, 29, 30, 31, 33, 39, 42, 46, 47, 48, 50, 51, 52, 53, 58, 62, 64, 70, 72, 75, 80, 81, 85, 86, 88, 90, 97, 101, 104, 123, 134, 145, 149, 150, 151, 152, 154, 157, 400, 401, 605, 606};

I changed some overloads, so recheck your scripts!
 

Scriptiz

Sorceror
It works but on my side I'm still using MobileMoving if ns.StygianAbyss instead of your changes (you are using MobileMovingOld in both cases).
 

fwiffo

Sorceror
corrected, thanks for pointing it out...If you're asking why that error, I disabled new client packets on my server until I can use the newmobile anims and something else I'm still finishing with my friends...we are still sticky on 6.ish client.

Oh, just to point it out, You'll have to stick the hallu with some sort of timer (the old hallutimer can be of use, you just need to change it and remove all the unnecessary things)...since it will never go off, but I suppose you can see it by yourself.

for changeing the hue of items it's a bit complicated, there is the need to build another cache for items, and the final expense/overall performance of the system may not be worth the result if I don't find a way to make it really lightweight...
 

mumuboy

Sorceror
To make it lightweight, do the following:
Make a timer. Keep track of the last "hallucination" by DateTime. Use that DateTime + Item/Mobile Hash + Player Hash (this insures the same hue despite the item being moved in/ and out of the update range, and its unique per player) to seed a randomizer to generate a random hue. Hue items/mobiles accordingly when packets are being transmitted. When timer ticks, update the DateTime, and re-hue everything within an 18 tile radius (the update range).

For WorldPacket, and GetWorldLocation, I updated the required functions to also accept the NetState (or Mobile is fine) as a parameter, so that various aspects of those packets could be updated on a per Mobile basis. Once you recode the packets accordingly, coupled with the hash for a randomizer seed, you don't need to keep track of packet/item caches. :)

Good luck!
 

fwiffo

Sorceror
Erhm...It's already like this, mumuboy...

What I want for item is a parallel cache without overload modify to items...the item property is sent to cache without taking into account the mobile whom is requesting it, so it need quite a modify to make use of the system, or maybe packet mangling to mod the hue on-the-fly only when the mobile is hallucinated...The mobile thing is already ok this way, since it's light and the seed is regenerated accordingly with a random number+mobile.serial.value ("return (short) m_BodyArray[new Random(HalluRandomSeed+toSend.Serial.Value).Next( 0, 59 )];" an index of the array, whom I use statically numbered, since using .Lenght calls another method and is using more power than needed...the array is static and readonly, so it's easy to mod this way) or for colors (return new Random(HalluRandomSeed+toSend.Serial.Value).Next( 2, 1200 );)
the value remains ALWAYS the same since the seed is regenerated globally once every 20 seconds. More lightweight, at least for mobiles, than this, it's another thing, maybe possible, but everything set like so is already doing the best.

Items are the only thing remaining, after I find a way to do it without to much compromises I'll update the mod, untile then, anyone is free to try this one O_O
 

mumuboy

Sorceror
The easiest thing is to modify GetWorldPacketFor to check the netstate.mobile and if they are hallucinating, use a non-static packet, otherwise default.
Then you have to override EquipUpdate and other packets that also send hue, which will all be in ProcessDelta(). Since those packets are only sent via that function which loops through each netstate, then it should be easy to send an EquipUpdateHallucinated packet or something.

If you have already done it this way, then I don't see any issues.
 

Vorspire

Knight
Actually the easiest thing to do would be to rip the OutgoingPacketOverrides code from my VNc project, then create an outgoing handler for the required packets that can re-write the packet buffer before it's sent to the client.

This means no distro edits, no core edits, nothing.

It also means you can achieve the *true* Sphere-style hallucination that also includes the shifting of body values and item id's, as well as their hues.

You can use the VNc code without the need to use the entire VNc project, feel free to redistribute it with your system if you do use it.
I'm not certain at this point whether doing so will cause problems for VNc users, but I doubt it will as the overrides framework is designed to store succession chains for parent callbacks should anyone have already overridden the NetState.PacketEncoder instance.

Jeff wrote the overrides framework for VNc, so any credit/thanks should go to him :) -I can help you by showing you how to use it, but it's really very easy!
 

fwiffo

Sorceror
Anyway I've already done core changes, I'm still in the middle of a million mods for my shard, it's nearly impossible to even keep an eye on this, when It will be finished as suggested by vorspire, It will be pubblished, I like the packet mod on the fly with overrides...But I have really no time to follow it now.
 
Top