- 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:
Here is the code for the item I am trying to modify:
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..
C#:
Process is terminated due to StackOverflowException.
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();
}
}