OP
Thes
ServUO Version
Publish Unknown
Ultima Expansion
High Seas
Hi everyone!

I'm relatively new to writing / editing ServUO files, so this may be a bit more of an undertaking than I'm imagining here. I attempted to search for something similar, but couldn't seem to find anything. Most threads seem to mention editing properties for items.

I am attempting to add new properties / values to the Mobile.cs class for use with a few items within the server. The first and perhaps most simple concept is to have a value of "MagicUser". This value would be accessed from SpellScroll OnDoubleClick() and similar items to check if a Player or Mobile is able to use magic.

So far I've added the following to Mobile.cs:
Mobile.cs changes:
public class Mobile : IEntity, IHued, IComparable<Mobile>, ISerializable, ISpawnable, IDamageable

    {

        // My understanding is this would allow calls to MagicUser for Mobile types.

        private bool _magic_user;

    

        [CommandProperty(AccessLevel.GameMaster)]

        public bool MagicUser{ get { return _magic_user; } set { _magic_user= value; } }


        // ... normal Mobile.cs things here

    

        // This is attempting to get MagicUser to show up in [Props

        public virtual void AddCustomProperties(ObjectPropertyList list)

        {

            // Adding Properties Specific to Imperius

            list.Add("MagicUser", _magic_user);

        }

    }

Then in my SpellScroll.cs file I added a check for MagicUser

SpellScroll.cs OnDoubleClick:
        public override void OnDoubleClick(Mobile from)

        {

            if (!Multis.DesignContext.Check(from))

                return; // They are customizing

            if (!this.IsChildOf(from.Backpack))

            {

                from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.

                return;

            }


            // If the user is unable to use magic, notify and exit

            if (!from.MagicUser)

            {

                from.SendMessage("You aren't quite sure what to do with this.");

                return;

            }

            #region SA

            else if (from.Flying && from is PlayerMobile && BaseMount.OnFlightPath(from))

            {

                from.SendLocalizedMessage(1113749); // You may not use that while flying over such precarious terrain.

                return;

            }

            #endregion

            Spell spell = SpellRegistry.NewSpell(this.m_SpellID, from, this);

            if (spell != null)

                spell.Cast();

            else

                from.SendLocalizedMessage(502345); // This spell has been temporarily disabled.

        }

    }

}

The two issues that are being had are:
The MagicUser property doesn't show up in [Props, which the GMs should be able to see / edit to enable it for players.
On compile, SpellScroll.cs is stating that from.MagicUser doesn't exist.

Thank you for any help!

[Edited to fix the code blocks for easier reading]
 
Last edited:
Ok lets start ;)
What you need to make a property appear in [props is just the following line, above the property itself
Additonally since you just want to read and write the property, there is no need for an private
field as well. Therefor we can use the shorter version, a auto property.

C#:
[CommandProperty(AccessLevel.GameMaster)]
public bool MagicUser{ get; set; }

this would be enough to appear fully working in the [props menu.


This part, while ne name suggests though, is not related to [props.
If you encounter similar named methods that all take a ObjectPropertyList for example, then that is the spot
where the properties for mouse over appear. As in the Name of the Mobile for example.

C#:
public virtual void AddCustomProperties(ObjectPropertyList list)
{
// Adding Properties Specific to Imperius
list.Add("MagicUser", _magic_user);
}

Your SpellScroll.cs edit seems fine so you are good there, it does what you want to, it cancels the use with the return and gives textual feedback.

Now, since you said on compile the SpellScroll.cs is stating the property doesnt exist, we have the other issue.
To me it seems like you use a version of ServUO that still supports the auto recompile on start.

If you do, then in this case you actually still need to use the compile bat of your choice again.

The reason for that is as following. Mobile.cs is inside the Server structure / folder. This is not getting an auto recompile.
Since SpellScroll then tries to look at the old state of the Mobile, it wond find the property.


Lastly, is MagicUser something you unlock? Or is it ment to be like "MagicUser should be true when the Player / Mobile has x amount of skill in magery"?

If it is something you unlock you also need to serialize and deserialize the property properly ;)
 
C#:
Code:
[CommandProperty(AccessLevel.GameMaster)]
public bool MagicUser{ get; set; }

this would be enough to appear fully working in the [props menu.
Great! It seemed like this tag above the property was all it required, but after attempting to "re-compile" it didn't show up which is what informed the ObjectPropertyList editing. Now I know only the /Scripts/ were being compiled.

Now, since you said on compile the SpellScroll.cs is stating the property doesnt exist, we have the other issue.
To me it seems like you use a version of ServUO that still supports the auto recompile on start.

If you do, then in this case you actually still need to use the compile bat of your choice again.

The reason for that is as following. Mobile.cs is inside the Server structure / folder. This is not getting an auto recompile.
Since SpellScroll then tries to look at the old state of the Mobile, it wond find the property.
Aha! Yes, that does appear to be the case. I will take a look to see if there are any recommendations for what to use to do this on the forums.

Lastly, is MagicUser something you unlock? Or is it ment to be like "MagicUser should be true when the Player / Mobile has x amount of skill in magery"?

If it is something you unlock you also need to serialize and deserialize the property properly
This will be something that is unlocked. I plan to create a "Tome of Knowledge" or maybe just a GM command to update this for the player.

For serializing and deserializing I have added the following to the respective functions:

Serialize _magic_user:
        public virtual void Serialize(GenericWriter writer)
        {
            // Many lines of standard Serialize
            writer.Write((byte)m_StrLock);
            writer.Write((byte)m_DexLock);
            writer.Write((byte)m_IntLock);

            // Added Section
            writer.Write(_magic_user);
            // Serialize continues
        }

Deserialize _magic_user:
        public virtual void Deserialize(GenericReader reader)
        {
            // Many lines of standard Deserialize...
            case 0:
            {
                        m_StrLock = (StatLockType)reader.ReadByte();
                        m_DexLock = (StatLockType)reader.ReadByte();
                        m_IntLock = (StatLockType)reader.ReadByte();

                        // Added Section
                        _magic_user = reader.ReadBool();              
            }
            // Deserialize continues...
        }

My understanding is the write/read order should be preserved, so I have placed them after the same m_IntLock value in both.

Thank you very much for your help, PyrO!
 
Inside your ServUO folder you should have a compile bat, either for debug or for release. Depending on what you want.

For your serialize and deserialize, well this will not work with existing Mobiles.

You need a version check there, since else the read looks for data that isnt there, since the whole save is just plain byte code, it cant process it asking you if you want to remove them all.

What you need to do in this case is to increase the version number in the Serialize (since we only want to read the old version 1 more time)
and then use a if or in this case a case with the new version number and read magic_user
 
Okay, and then I see now that the case statements flow through all the way back to the case 0 where I was originally adding it. Revised, where the previous version was 37.

C#:
public virtual void Serialize(GenericWriter writer)
{
    writer.Write(38); // version
    
    // 38, added section
    writer.Write(_magic_user);
    
    // Serialize continues...
}

Deserialize with version revise:
        public virtual void Deserialize(GenericReader reader)
        {
            int version = reader.ReadInt();

            switch (version)
            {
                case 38:
                    {
                        // Added Section
                        _magic_user = reader.ReadBool();
                        goto case 37;
                    }
                    
            // Continues for previous versions...
        }
 
Back