ServUO Version
Publish 57
Ultima Expansion
Endless Journey
So I am still horrible at serialization, I am trying to add in an option to reduce weight on a container but trying to add in the serialization I receive the following on world load:
C#:
Process is terminated due to StackOverflowException.
Here is the code for the item I am trying to modify:
C#:
/*
 created by:
     /\            888                   888     .d8888b.   .d8888b.
____/_ \____       888                   888    d88P  Y88b d88P  Y88b
\  ___\ \  /       888                   888    888    888 888    888
 \/ /  \/ /    .d88888  8888b.   8888b.  888888 Y88b. d888 Y88b. d888
 / /\__/_/\   d88" 888     "88b     "88b 888     "Y888P888  "Y888P888
/__\ \_____\  888  888 .d888888 .d888888 888           888        888
    \  /      Y88b 888 888  888 888  888 Y88b.  Y88b  d88P Y88b  d88P
     \/        "Y88888 "Y888888 "Y888888  "Y888  "Y8888P"   "Y8888P"
*/
//comment the USE_TOKENS line if you don't have daat99 tokens system (1.0) or daat99 OWLTR system
#define USE_TOKENS
//comment the USE_OWLTR3 line if you don't have OWLTR 2.0+
#define USE_OWLTR3

using Server;
using Server.Mobiles;
using Server.Items;
using Server.Accounting;
using System;
using Server.ContextMenus;
using System.Collections.Generic;
using System.Collections;
using daat99;


namespace Daat99MasterLooterSystem
{
    public sealed class MasterLooterBackpack : MasterStorage
    {
        public MasterLooterBackpack(Serial serial)
            : base(serial)
        {
        }
        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
        }
        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
        }
    }
}
namespace daat99
{
    public class MasterStorage : Backpack
    {
        [CommandProperty(AccessLevel.GameMaster)]
        public double WeightReductionAmount
        {
            get
            {
                return WeightReductionAmount;
            }
            set
            {
                WeightReductionAmount = value;
            }
        }

        //Change this to set the default loot settings for your players
        public void RestoreDefaultSettings()
        {
            RestoreDefaultList();
            lootSettings = LootSettingsEnum.From_List; //players loot items from their list only
            DeleteAllCorpses = false; //deletes all the corpses or just empty ones
#if USE_OWLTR3
            LootType = OWLTROptionsManager.IsEnabled(OWLTROptionsManager.OPTIONS_ENUM.BLESSED_STORAGE) ? LootType.Blessed : Server.LootType.Regular;
#else
            LootType = LootType.Blessed;
#endif
            GoldLedger = true; //enables the gold ledger
            TokenLedger = true; //enables the token ledger
            KeepItemsOnDeath = false;
        }
       
        public void RestoreDefaultList()
        {
            activeBaseTypes = new List<Type>(MasterStorageUtils.DefaultBaseTypes); //see and/or change list in Utils file
            activeLootTypes = new List<Type>(MasterStorageUtils.DefaultItemTypes); //see and/or change list in Utils file
        }

        public enum LootSettingsEnum { Everything, From_List, Currency_Only };
        private LootSettingsEnum lootsettings = LootSettingsEnum.From_List;
        public LootSettingsEnum lootSettings { get { return lootsettings; } set { lootsettings = value; InvalidateProperties(); } }

        public string LootSettingsString
        {
            get
            {
                return lootSettings.ToString().Replace("_", " ");
            }
        }
       
        private static readonly string DefaultLooterName = "Master Storage";

        private PlayerMobile owner;
        [CommandProperty(AccessLevel.GameMaster)]
        public PlayerMobile Owner { get { return owner; } set { owner = value; InvalidateProperties(); } }
       
        private bool goldLedger;
        [CommandProperty(AccessLevel.GameMaster)]
        public bool GoldLedger
        {
            get
            {
#if USE_OWLTR3
                return goldLedger && OWLTROptionsManager.Manager.Options[OWLTROptionsManager.OPTIONS_ENUM.GOLD_STORAGE].Setting;
#else
                return goldLedger;
#endif
            }
            set
            {
                goldLedger = value;
                InvalidateProperties();
            }
        }
       
        private bool tokenLedger;
        [CommandProperty(AccessLevel.GameMaster)]
        public bool TokenLedger
        {
            get
            {
#if USE_OWLTR3
                return tokenLedger && OWLTROptionsManager.Manager.Options[OWLTROptionsManager.OPTIONS_ENUM.TOKEN_STORAGE].Setting;
#elif USE_TOKENS
                return tokenLedger;
#else
                return false;
#endif
            }
            set
            {
                tokenLedger = value; InvalidateProperties();
            }
        }
       
        private bool deleteAllCorpses;
        [CommandProperty(AccessLevel.GameMaster)]
        public bool DeleteAllCorpses { get { return deleteAllCorpses; } set { deleteAllCorpses = value; InvalidateProperties(); } }

        private ulong goldAmount;
        [CommandProperty(AccessLevel.GameMaster)]
        public ulong GoldAmount
        {
            get { return goldAmount; }
            set
            {
                if (value > ulong.MaxValue || value < ulong.MinValue)
                    return;
                goldAmount = value;
                InvalidateProperties();
            }
        }

        private ulong tokensAmount;
        [CommandProperty(AccessLevel.GameMaster)]
        public ulong TokensAmount
        {
            get { return tokensAmount; }
            set
            {
                if (value > ulong.MaxValue || value < ulong.MinValue)
                    return;
                tokensAmount = value;
                InvalidateProperties();
            }
        }

        private List<Type> baseTypesA, baseTypesB;
        private List<Type> lootTypesA, lootTypesB;
        private List<Type> activeBaseTypes
        {
            get
            {
                return (activeListA ? baseTypesA : baseTypesB);
            }
            set
            {
                if ( activeListA )
                    baseTypesA = value;
                else
                    baseTypesB = value;
            }
        }
        private List<Type> activeLootTypes
        {
            get
            {
                return (activeListA ? lootTypesA : lootTypesB);
            }
            set
            {
                if ( activeListA )
                    lootTypesA = value;
                else
                    lootTypesB = value;
            }
        }

        private bool keepItemsOnDeath;
        [CommandProperty(AccessLevel.GameMaster)]
        public bool KeepItemsOnDeath
        {
            get
            {
#if USE_OWLTR3
                return keepItemsOnDeath && OWLTROptionsManager.Manager.Options[OWLTROptionsManager.OPTIONS_ENUM.STORAGE_KEEP_ITEMS_DEATH].Setting;
#else
                return keepItemsOnDeath;
#endif
            }
            set
            {
                keepItemsOnDeath = value;
                InvalidateProperties();
            }
        }
       
        private bool activeListA;
        public string ActiveListName { get { return ( activeListA ? "Primary" : "Secondary"); } }
        public void SwitchActiveList()
        {
            activeListA = !activeListA;
            InvalidateProperties();
        }

        public int LootableTypesCount
        {
            get
            {
                return (activeBaseTypes == null ? 0 : activeBaseTypes.Count) + (activeLootTypes == null ? 0 : activeLootTypes.Count);
            }
        }

        [Constructable]
        public MasterStorage()
            : base()
        {
            Weight = 0.0;
            Hue = 1169;
            ItemID = 0x9b2;
            Name = DefaultLooterName;
            Owner = null;

            WeightReductionAmount = 0.0;

            //resets list B to default
            activeListA = false;
            RestoreDefaultList();
           
            //resets list A and loot settings to default
            SwitchActiveList();
            RestoreDefaultSettings();
            StoredItems = new Dictionary<Type, ulong>();
            StorageList = new List<BaseStorage>();
        }

        public MasterStorage( Serial serial ) : base( serial ) { }

        public override int GetTotal(TotalType type)
        {
            if (type != TotalType.Weight)
                return base.GetTotal(type);
            else
            {
                if (WeightReductionAmount == 1.0)
                    return 0;
                else
                    return (int)(TotalItemWeights() * (1.0 - WeightReductionAmount));
            }
        }
        public override void UpdateTotal(Item sender, TotalType type, int delta)
        {
            if (type != TotalType.Weight)
                base.UpdateTotal(sender, type, delta);
            else
                base.UpdateTotal(sender, type, WeightReductionAmount == 1.0 ? 0 : (int)(delta * (1.0 - WeightReductionAmount)));
        }
        private double TotalItemWeights()
        {
            double weight = 0.0;

            foreach (Item item in Items)
                weight += (item.Weight * (double)(item.Amount));

            return weight;
        }

        public override void GetProperties(ObjectPropertyList list)
        {
            base.GetProperties(list);
            if (WeightReductionAmount > 0)
                list.Add(String.Format("{0}% Weight Reduction", WeightReductionAmount * 100));
            //if (!KeepItemsOnDeath)
            //    list.Add("<basefont color=#FF0000><center>Dropping Items on Death");
            //else
            //    list.Add("<basefont color=#00FF00><center>Keeping Items on Death");
            if (owner != null && !owner.Deleted)
            {
                //PlayerMobile pm = (PlayerMobile)owner;
                Account acct = owner.Account as Account;

                list.Add(" ");
                list.Add(1060660, "Gold\t" + (GoldLedger ? acct.TotalGold.ToString("#,0"):"Inactive"));
                list.Add(1060661, "Platinum\t" + (GoldLedger ? acct.TotalPlat.ToString("#,0"):"Inactive"));
            }
            //list.Add(1060659, "Gold\t" + (GoldLedger?GoldAmount.ToString():"Inactive"));
            list.Add(1060660, "Tokens\t" + (TokenLedger?TokensAmount.ToString("#,0") :"Inactive"));
            list.Add(1060661, "Looting\t" + LootSettingsString); //value: ~1_val~
            list.Add(1060662, "Deleting\t" + (DeleteAllCorpses?"All Corpses":"Empty Corpses")); //value: ~1_val~
            list.Add(1060658, "<center>On Death\t<basefont color=#" + (KeepItemsOnDeath ? "00ff00>Keeping Items" : "ff0000>Dropping Items") + "</basefont></center>"); //value: ~1_val~
        }
       
        public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
        {
            base.GetContextMenuEntries( from, list );
            PlayerMobile player = from as PlayerMobile;
            if ( !IsOwner(player) )
                return;
            if (StorageList.Count > 0)
                list.Add(new MasterStorageStorageContextMenu(player, this));
            if (GoldLedger || TokenLedger)
                list.Add( new MasterStorageLedgerContextMenu( player, this ) );
            list.Add( new MasterStorageSetupContextMenu( player, this ) );
            if ( GoldLedger || TokenLedger )
                list.Add( new MasterStorageFillContextMenu( player, this ) );
               
        }
       
        public void Loot( PlayerMobile player )
        {
            if ( !IsOwner(player) )
                return;
            List<Item> items = new List<Item>();
            List<Corpse> corpses = new List<Corpse>();

            foreach ( Item item in player.GetItemsInRange(3) )
            {
                if ( item is Corpse )
                {
                    Corpse corpse = item as Corpse;
                    if ( isCorpseLootable(player, corpse) )
                        corpses.Add(corpse);
                }
                else if ( item.Movable && item.IsAccessibleTo(player) && isItemLootable(item) )
                    items.Add(item);
             }

            foreach ( Item item in items )
                TryDropItem(player, item, false);

               
            bool lootedAll = true;
            int totalTokens = 0;
            int retries = 3;
            foreach ( Corpse corpse in corpses )
            {
                if ( lootContainer(player, corpse) )
                {

                    if ( DeleteAllCorpses || corpse.GetAmount(typeof(Item), false) == 0 )
                    {

                        int reward = getCorpseReward(corpse);

                        if ( reward > 0 )
                        {

                            totalTokens += reward;
                            AddTokensAmount((ulong)reward);
                            AddGoldAmount((ulong)(reward*2));
                        }

                        corpse.Delete();
                    }

                }
                else
                {
                    lootedAll = false;
                    if ( --retries == 0 )
                        break;
                }
            }

            if ( totalTokens > 0 )
            {
                player.SendMessage(1173, "You gained " + totalTokens + " tokens for cleaning the shard.");
            }
            else
                player.SendMessage(1173, "You didn't gain a single token...");
            if ( !lootedAll )
                player.SendMessage(1173, "You can't loot all the items.");
        }
       
        private bool lootContainer( PlayerMobile player, Container container )
        {
            if ( !IsOwner(player) )
                return false;
            List<Item> items = new List<Item>( container.Items.Count );
            foreach ( Item item in container.Items )
                if ( item != null && isItemLootable( item ) )
                    items.Add( item );

            foreach ( Item item in items )
                if ( !this.TryDropItem(player, item, false) )
                    return false;
            return true;
        }
       
        private int getCorpseReward( Corpse c )
        {

            if (c == null || c.Owner == null)
                return 0;

            BaseCreature owner = c.Owner as BaseCreature;
            if ( owner == null )
                return 0;

            double resists = ((owner.PhysicalResistance + owner.FireResistance + owner.ColdResistance + owner.PoisonResistance + owner.EnergyResistance)/50); //set the amount of resists the monster have
            if (resists < 1.0) //if it have less then total on 100 resists set to 1
                resists = 1.0;
            int hits = (owner.HitsMax/10); //set the amount of max hp the creature had.
            double tempReward = (hits + ((hits * resists)/10) ); //set the temp reward
                       
            int fameKarma = Math.Abs(owner.Fame) + Math.Abs(owner.Karma); //set fame\karma reward bonus
            fameKarma /= 250;
            tempReward += fameKarma; //add the fame\karma reward to the temp reward

            if (owner.AI == AIType.AI_Mage) //if it's mage add some tokens, it have spells
            {
                double mage = ((owner.Skills[SkillName.Meditation].Value + owner.Skills[SkillName.Magery].Value + owner.Skills[SkillName.EvalInt].Value)/8);
                tempReward += mage;
            }
                           
            if (owner.HasAbility(SpecialAbility.DragonBreath)) //give bonus for creatures that have fire breath
            {
                double fireBreath = (owner.HitsMax/25);
                tempReward += fireBreath; //add the firebreath bonus to temp reward
            }    
                           
            int reward = ((int)tempReward);
            reward = Utility.RandomMinMax((int)(reward*0.3), (int)(reward*0.6));

            if (reward < 1)
                reward = 1; //set minimum reward to 1

            return reward;
        }
       
        public bool isItemLootable( Item item )
        {
            if ( item == null || item.Deleted || !item.Movable )
                return false;
            return isTypeLootable(item.GetType());
        }
       
        internal bool isTypeLootable(Type itemType)
        {
            if ( itemType == null )
                return false;

            if ( lootSettings == LootSettingsEnum.Everything )
                return true;

            if ( MasterStorageUtils.IsCurrencyType(itemType) )
                return true;
           
            if ( lootSettings == LootSettingsEnum.Currency_Only )
                return false;

            if ( activeLootTypes != null && activeLootTypes.Contains(itemType) )
                return true;

            if ( activeBaseTypes != null )
                foreach ( Type type in activeBaseTypes )
                    if ((type.IsInterface && type.IsAssignableFrom(itemType)) ||
                        itemType.IsSubclassOf(type) )
                        return true;
            return false;
        }

        internal bool AddLootableItemType(Type type)
        {
            if ( type == null )
                return false;
            if ( isTypeLootable(type) )
                return false;
            activeLootTypes.Add(type);
            return true;
        }
       
        internal bool AddLootableBaseType(Type type)
        {
            if ( type == null )
                return false;
            if ( isTypeLootable(type) )
                return false;
           
            List<Type> contained = new List<Type>();
            foreach ( Type t in activeBaseTypes )
                if ( t.IsSubclassOf(type) )
                    contained.Add(t);
            foreach ( Type t in contained )
                activeBaseTypes.Remove(t);
            foreach ( Type t in activeLootTypes )
                if ( t.IsSubclassOf(type) )
                    contained.Add(t);
            foreach ( Type t in contained )
                activeLootTypes.Remove(t);
            activeBaseTypes.Add(type);
            return true;
        }

        internal void RemoveLootableType(Type type)
        {
            if ( type == null )
                return;

            if ( activeLootTypes.Contains(type) )
                activeLootTypes.Remove(type);
            else if ( activeBaseTypes.Contains(type) )
                activeBaseTypes.Remove(type);
        }

        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );

            writer.Write( (int) 9 ); // version

            //version 8
            writer.Write((double)WeightReductionAmount);

            //version 7
            writer.Write(StoragePage);
            writer.Write(StorageFilter != null);
            if ( StorageFilter != null )
                StorageFilter.Serialize(writer);

            //version 6
            writer.Write(StoredItems.Count);
           
            foreach (Type key in StoredItems.Keys)
            {
                writer.Write(key.FullName);
                writer.Write(StoredItems[key]);

               // Vii edit
                if (key.IsSubclassOf(typeof(BaseInstrument)))
                {
                    if (ItemInfoByType.ContainsKey(key) && ItemInfoByType[key].Count == (int)StoredItems[key])
                    {

                        writer.Write((bool)true); // This is to stop a possible loading crash

                        foreach (ItemInformation info in ItemInfoByType[key])
                        {
                            info.Serialize(writer);
                        }
                    }
                    else
                        writer.Write((bool)false);  // Fix possible loading crash
                }
                // end Vii edit

            }
           
            //version 5
            writer.Write(KeepItemsOnDeath);
           
            //version 4
            writer.Write(activeListA);
           
            //version 6 change start
            SerializeTypeList(writer, baseTypesA);
            SerializeTypeList(writer, lootTypesA);
            SerializeTypeList(writer, baseTypesB);
            SerializeTypeList(writer, lootTypesB);
            //version 6 change end

            writer.Write( GoldLedger );
            writer.Write( TokenLedger );
            writer.Write( (int)lootSettings );
            writer.Write( GoldAmount );
            writer.Write( TokensAmount );
            writer.Write( Owner ); //version 8 changed from int to PlayerMobile
            // Version 2
            writer.Write( DeleteAllCorpses );

            //version 6 addition
            writer.Write(StorageList.Count);
            foreach (BaseStorage storage in StorageList)
            {
                //force delete in version 8 without upgrading to 9 intentionally!
                writer.Write(storage.GetType().FullName);
                storage.Serialize(writer);
            }
        }

        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );

            int version = reader.ReadInt();

            if (version >= 9)
            {
                WeightReductionAmount = reader.ReadDouble();
            }

            if ( version >= 7 )
            {
                StoragePage = reader.ReadInt();
                bool hasStorageFilter = reader.ReadBool();
                if (hasStorageFilter)
                    StorageFilter = new BaseStorage(reader);

            }
            if (version >= 6)
            {
                int count = reader.ReadInt();
                StoredItems = new Dictionary<Type, ulong>(count);
               
                for (int i = 0; i < count; ++i)
                {
                    try
                    {
                        Type key = Type.GetType(reader.ReadString());
                        ulong amount = reader.ReadULong();
                        if (key != null)
                        {
                            StoredItems.Add(key, amount);

                            // Vii edit
                            if (key.IsSubclassOf(typeof(BaseInstrument)))
                            {
                                if (reader.ReadBool()) // For stopping load crash
                                {
                                    m_ItemInfoByType = new Dictionary<Type, List<ItemInformation>>();
                                    List<ItemInformation> info = new List<ItemInformation>();
                                    for (int j = 0; j < (int)amount; j++)
                                    {
                                        ItemInformation iteminfo = new ItemInformation(reader);
                                        info.Add(iteminfo);
                                    }
                                    ItemInfoByType.Add(key, info);
                                }
                            }
                            // end Vii edit
                        }
                    }
                    catch { }
                }
               
                KeepItemsOnDeath = reader.ReadBool();
                activeListA = reader.ReadBool();
                baseTypesA = DeserializeTypeList(reader, true);
                lootTypesA = DeserializeTypeList(reader, true);
                baseTypesB = DeserializeTypeList(reader, true);
                lootTypesB = DeserializeTypeList(reader, true);
                GoldLedger = reader.ReadBool();
                TokenLedger = reader.ReadBool();
                try { lootSettings = (LootSettingsEnum)reader.ReadInt(); }
                catch { lootSettings = LootSettingsEnum.From_List; }
                GoldAmount = reader.ReadULong();
                TokensAmount = reader.ReadULong();
                if (version >= 8)
                    Owner = reader.ReadMobile() as PlayerMobile;
                else
                {
                    int serial = reader.ReadInt();
                    Owner = World.FindMobile(serial) as PlayerMobile;
                }
                DeleteAllCorpses = reader.ReadBool();

                count = reader.ReadInt();
                StorageList = new List<BaseStorage>(count);
                while (count-- > 0)
                {
                    try
                    {
                        BaseStorage storage;
                        if (version >= 8)
                        {
                            Type storageType = Type.GetType(reader.ReadString());
                            if ( storageType != typeof(BaseStorage) )
                                storage = Activator.CreateInstance(storageType, new object[] { reader }) as BaseStorage;
                            else
                                storage = new BaseStorage(reader);
                        }
                        else
                            storage = new BaseStorage(reader);
                        if (!StorageList.Contains(storage))
                            StorageList.Add(storage);
                    } catch { }
                }
            }
            else
            {
                StorageList = new List<BaseStorage>();
                StoredItems = new Dictionary<Type, ulong>();
                if (version >= 5)
                    KeepItemsOnDeath = reader.ReadBool();
                if (version >= 4)
                {
                    activeListA = reader.ReadBool();
                    DeserializeList(reader, true);
                    DeserializeList(reader, false);
                }
                else
                {
                    activeListA = false;
                    RestoreDefaultList();
                    activeListA = true;
                    DeserializeList(reader, true);
                }

                GoldLedger = reader.ReadBool();
                TokenLedger = reader.ReadBool();
                if (version >= 3)
                {
                    try { lootSettings = (LootSettingsEnum)reader.ReadInt(); }
                    catch { lootSettings = LootSettingsEnum.From_List; }
                }
                else
                    lootSettings = reader.ReadBool() ? LootSettingsEnum.Currency_Only : LootSettingsEnum.From_List;
                GoldAmount = reader.ReadULong();
                TokensAmount = reader.ReadULong();
                int serial = reader.ReadInt();
                Owner = World.FindMobile(serial) as PlayerMobile;
                if (version > 1)
                    DeleteAllCorpses = reader.ReadBool();
            }
        }
I increased the write by 1, added my change, then followed same step to increase by one in the reader.. but probably doing it wrong haha..
 
1670876945078.png1670876956974.png
serialize says you wanted 8, you just read at 9 or higher though?
Did you maybe use 8 befor for your WeightReductionAmount? Ran the server and saved?
 
I tried 8 and got the same error, if you look further down in the des there is already an 8 so I wasn't sure and tried 9 anyways.. I removed the ser/des changes and tried with just the weight reduction bits in and it still gave me an overflow exception so I think it's something to do with the way I added in the weight reduction portion of the code?

Okay I was able to get it to compile and launch with the following changes which work in game and no longer gives a stack overflow, but I still can't figure out the ser/des for it.. I have atached the full script this time as is working right now.
C#:
        private double m_WeightReductionAmount = 0.0;

        [CommandProperty(AccessLevel.GameMaster)]
        public double WeightReductionAmount
        {
            get
            {
                return m_WeightReductionAmount;
            }
            set
            {
                m_WeightReductionAmount = value;
            }
        }
 
Last edited:
wow should have looked properly.

yes
C#:
        [CommandProperty(AccessLevel.GameMaster)]
        public double WeightReductionAmount
        {
            get
            {
                return WeightReductionAmount;
            }
            set
            {
                WeightReductionAmount = value;
            }
        }
is faulty.

since you dont need another function besides storing and reading the variable, you can use auto properties.

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

but the main reason why your code threw that error?
You are setting the property to the value, inside the code that sets the value of the property. That is an endless loop.
 
Yeah I took another look now that I'm awake and not in a rush to get to work haha, I redid it and it did work but your way is much easier.. thank you..

I am however still stuck on the serialization though I can't seem to figure it out.. I was at least able to get it to ask me to delete them all rather than a stack overflow though haha :) the writer was already at 8 so I increased it to 9.

Never mind, think I got it.. testing it now..
Looks like it's saving and reading correctly now.. this is what I got:
C#:
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );

            writer.Write( (int) 9 ); // version

            writer.Write((double)WeightReductionAmount);

            //version 7
            writer.Write(StoragePage);
            writer.Write(StorageFilter != null);
            if ( StorageFilter != null )
                StorageFilter.Serialize(writer);

            //version 6
            writer.Write(StoredItems.Count);
            
            foreach (Type key in StoredItems.Keys)
            {
                writer.Write(key.FullName);
                writer.Write(StoredItems[key]);

               // Vii edit
                if (key.IsSubclassOf(typeof(BaseInstrument)))
                {
                    if (ItemInfoByType.ContainsKey(key) && ItemInfoByType[key].Count == (int)StoredItems[key])
                    {

                        writer.Write((bool)true); // This is to stop a possible loading crash

                        foreach (ItemInformation info in ItemInfoByType[key])
                        {
                            info.Serialize(writer);
                        }
                    }
                    else
                        writer.Write((bool)false);  // Fix possible loading crash
                }
                // end Vii edit

            }
            
            //version 5
            writer.Write(KeepItemsOnDeath);
            
            //version 4
            writer.Write(activeListA);
            
            //version 6 change start
            SerializeTypeList(writer, baseTypesA);
            SerializeTypeList(writer, lootTypesA);
            SerializeTypeList(writer, baseTypesB);
            SerializeTypeList(writer, lootTypesB);
            //version 6 change end

            writer.Write( GoldLedger );
            writer.Write( TokenLedger );
            writer.Write( (int)lootSettings );
            writer.Write( GoldAmount );
            writer.Write( TokensAmount );
            writer.Write( Owner ); //version 8 changed from int to PlayerMobile
            // Version 2
            writer.Write( DeleteAllCorpses );

            //version 6 addition
            writer.Write(StorageList.Count);
            foreach (BaseStorage storage in StorageList)
            {
                //force delete in version 8 without upgrading to 9 intentionally!
                writer.Write(storage.GetType().FullName);
                storage.Serialize(writer);
            }
        }

        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );

            int version = reader.ReadInt();

            if (version >= 9)
            {
                WeightReductionAmount = reader.ReadDouble();
            }

            if ( version >= 7 )
            {
                StoragePage = reader.ReadInt();
                bool hasStorageFilter = reader.ReadBool();
                if (hasStorageFilter)
                    StorageFilter = new BaseStorage(reader);

            }
            if (version >= 6)
            {
                int count = reader.ReadInt();
                StoredItems = new Dictionary<Type, ulong>(count);
                
                for (int i = 0; i < count; ++i)
                {
                    try
                    {
                        Type key = Type.GetType(reader.ReadString());
                        ulong amount = reader.ReadULong();
                        if (key != null)
                        {
                            StoredItems.Add(key, amount);

                            // Vii edit
                            if (key.IsSubclassOf(typeof(BaseInstrument)))
                            {
                                if (reader.ReadBool()) // For stopping load crash
                                {
                                    m_ItemInfoByType = new Dictionary<Type, List<ItemInformation>>();
                                    List<ItemInformation> info = new List<ItemInformation>();
                                    for (int j = 0; j < (int)amount; j++)
                                    {
                                        ItemInformation iteminfo = new ItemInformation(reader);
                                        info.Add(iteminfo);
                                    }
                                    ItemInfoByType.Add(key, info);
                                }
                            }
                            // end Vii edit
                        }
                    }
                    catch { }
                }
                
                KeepItemsOnDeath = reader.ReadBool();
                activeListA = reader.ReadBool();
                baseTypesA = DeserializeTypeList(reader, true);
                lootTypesA = DeserializeTypeList(reader, true);
                baseTypesB = DeserializeTypeList(reader, true);
                lootTypesB = DeserializeTypeList(reader, true);
                GoldLedger = reader.ReadBool();
                TokenLedger = reader.ReadBool();
                try { lootSettings = (LootSettingsEnum)reader.ReadInt(); }
                catch { lootSettings = LootSettingsEnum.From_List; }
                GoldAmount = reader.ReadULong();
                TokensAmount = reader.ReadULong();
                if (version >= 8)
                    Owner = reader.ReadMobile() as PlayerMobile;
                else
                {
                    int serial = reader.ReadInt();
                    Owner = World.FindMobile(serial) as PlayerMobile;
                }
                DeleteAllCorpses = reader.ReadBool();

                count = reader.ReadInt();
                StorageList = new List<BaseStorage>(count);
                while (count-- > 0)
                {
                    try
                    {
                        BaseStorage storage;
                        if (version >= 8)
                        {
                            Type storageType = Type.GetType(reader.ReadString());
                            if ( storageType != typeof(BaseStorage) )
                                storage = Activator.CreateInstance(storageType, new object[] { reader }) as BaseStorage;
                            else
                                storage = new BaseStorage(reader);
                        }
                        else
                            storage = new BaseStorage(reader);
                        if (!StorageList.Contains(storage))
                            StorageList.Add(storage);
                    } catch { }
                }
            }
            else
            {
                StorageList = new List<BaseStorage>();
                StoredItems = new Dictionary<Type, ulong>();
                if (version >= 5)
                    KeepItemsOnDeath = reader.ReadBool();
                if (version >= 4)
                {
                    activeListA = reader.ReadBool();
                    DeserializeList(reader, true);
                    DeserializeList(reader, false);
                }
                else
                {
                    activeListA = false;
                    RestoreDefaultList();
                    activeListA = true;
                    DeserializeList(reader, true);
                }

                GoldLedger = reader.ReadBool();
                TokenLedger = reader.ReadBool();
                if (version >= 3)
                {
                    try { lootSettings = (LootSettingsEnum)reader.ReadInt(); }
                    catch { lootSettings = LootSettingsEnum.From_List; }
                }
                else
                    lootSettings = reader.ReadBool() ? LootSettingsEnum.Currency_Only : LootSettingsEnum.From_List;
                GoldAmount = reader.ReadULong();
                TokensAmount = reader.ReadULong();
                int serial = reader.ReadInt();
                Owner = World.FindMobile(serial) as PlayerMobile;
                if (version > 1)
                    DeleteAllCorpses = reader.ReadBool();
            }
        }
 
Last edited:
serialize and deserialize look fine, are you sure you didnt save with 9 already in place and not the write for the weight there?
 
serialize and deserialize look fine, are you sure you didnt save with 9 already in place and not the write for the weight there?
No it was already at 8, pretty sure I know why there were some other changes made to the pack ages ago.
I changed it to 9 and redid the ser/des and everything seems to be working fine now. The double is saving as expected can be changed in game and I've saved and restarted and seems to be working as expected. Thank you for your help :)
 
Back