ServUO Version
Publish 57
Ultima Expansion
Endless Journey
I'm trying to add 9 skills with bonuses to an item however it will only recognize the first 5, is this hard coded or am I doing something wrong?

C#:
            SkillBonuses.SetValues(0, SkillName.ArmsLore, 25.0);
            SkillBonuses.SetValues(1, SkillName.Blacksmith, 25.0);
            SkillBonuses.SetValues(2, SkillName.Carpentry, 25.0);
            SkillBonuses.SetValues(3, SkillName.Cooking, 25.0);
            SkillBonuses.SetValues(4, SkillName.Fishing, 25.0);
            SkillBonuses.SetValues(5, SkillName.Fletching, 25.0);
            SkillBonuses.SetValues(6, SkillName.Mining, 25.0);
            SkillBonuses.SetValues(7, SkillName.Tailoring, 25.0);
            SkillBonuses.SetValues(8, SkillName.Tinkering, 25.0);

**UPDATE**
After fiddling with some things I was able to at least get it to display and read all 9 skills, however it is neither showing on the item or applying the stats when equipped.
1652839798418.png
 
Last edited:
Have you added the skill mods in OnAdded() and OnRemoved() as well as listing them all in the properties? I'd recommend taking a look at the ancient smith hammer and adapting that code to your own.

Can't really say for sure what the issue might be without seeing all of or at least more of the items code.
 
Have you added the skill mods in OnAdded() and OnRemoved() as well as listing them all in the properties? I'd recommend taking a look at the ancient smith hammer and adapting that code to your own.

Can't really say for sure what the issue might be without seeing all of or at least more of the items code.
It's just a ring to add skills, I have not done it that way though no.. let me try that now.. if that works then I'm okay with that I can add the skill list in the name properties..
C#:
using System;
using Server;

namespace Server.Items
{
    public class RingOfCrafts : GoldRing
    {
        
         public override int ArtifactRarity{ get{ return 50; } }

        [Constructable]
        public RingOfCrafts()
        {
            Weight = 1.0;
            Name = "Ring Of Crafts";
            Hue = 1150;

            SkillBonuses.SetValues(0, SkillName.ArmsLore, 25.0);
            SkillBonuses.SetValues(1, SkillName.Blacksmith, 25.0);
            SkillBonuses.SetValues(2, SkillName.Carpentry, 25.0);
            SkillBonuses.SetValues(3, SkillName.Cooking, 25.0);
            SkillBonuses.SetValues(4, SkillName.Fishing, 25.0);
            SkillBonuses.SetValues(5, SkillName.Fletching, 25.0);
            SkillBonuses.SetValues(6, SkillName.Mining, 25.0);
            SkillBonuses.SetValues(7, SkillName.Tailoring, 25.0);
            SkillBonuses.SetValues(8, SkillName.Tinkering, 25.0);

        }

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

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

            writer.Write( (int) 0 );
        }
        
        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize( reader );

            int version = reader.ReadInt();
        }
    }
}
 
Ahh, if you're not wanting it to show the skill bonus then you don't have to list it in the properties. I think I misunderstood you.

Also, apparently it has changed a bit since the last time I messed with skill bonuses or mods. I typically code for pre-AoS servers and haven't messed with them in a while.

Are you still gaining the first 5 skill bonuses? Arms lore - Fishing?

**Edit**
Actually an easy fix. In AOS.cs change this:
C#:
        public void AddTo(Mobile m)
        {
            if (Discordance.UnderPVPEffects(m))
            {
                return;
            }

            Remove();

            for (int i = 0; i < 5; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                if (m_Mods == null)
                    m_Mods = new List<SkillMod>();

                SkillMod sk = new DefaultSkillMod(skill, true, bonus);
                sk.ObeyCap = true;
                m.AddSkillMod(sk);
                m_Mods.Add(sk);
            }
        }
To this:
C#:
        public void AddTo(Mobile m)
        {
            if (Discordance.UnderPVPEffects(m))
            {
                return;
            }

            Remove();

            for (int i = 0; i < 9; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                if (m_Mods == null)
                    m_Mods = new List<SkillMod>();

                SkillMod sk = new DefaultSkillMod(skill, true, bonus);
                sk.ObeyCap = true;
                m.AddSkillMod(sk);
                m_Mods.Add(sk);
            }
        }

You will need to change the GetProperties in order to list the additional 4 skills on the item if that is something you'd be interested in anyway.

**Edit 2**
I took the liberty of getting the other 4 skills to show on the OPL. In AOS.cs change GetProperties to look like this:
C#:
        public void GetProperties(ObjectPropertyList list)
        {
            for (int i = 0; i < 9; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                if (i < 5)
                {
                    list.Add(1060451 + i, "#{0}\t{1}", GetLabel(skill), bonus);
                }
                else if (i == 5)
                {
                    list.Add(1063468, "#{0}\t{1}", GetLabel(skill), bonus);
                }
                else if (i == 6)
                {
                    list.Add(1151413, "#{0}\t{1}", GetLabel(skill), bonus);
                }
                else if (i == 7)
                {
                    list.Add(1060658, "#{0}\t{1}", GetLabel(skill), bonus);
                }
                else if (i == 8)
                {
                    list.Add(1060659, "#{0}\t{1}", GetLabel(skill), bonus);
                }
            }
        }

RingOfCrafts.png
 
Last edited:
Yeah the first 5 work fine with no issues, but you gave me an idea on what to look for so I ended up going a different route and got it to work, similar to the onadded/remove then I just had to list the skills in the properties to show what it was. But was able to get it working :)

1652848177102.png
 
Happy to hear it :D Your way of displaying the properties is better than mine as well since the last two skills show
SkillName: Value
instead of
SkillName +Value
 
A very good trait to have, especially when it comes to coding :p
Also just saw your edit, I completely missed that number! I had modded it to show the stats I posted in the first image but completely overlooked that one little number! Well at least now we know for the future :)
 
Also just saw your edit, I completely missed that number! I had modded it to show the stats I posted in the first image but completely overlooked that one little number! Well at least now we know for the future :)
Did you do it the SkillMod way in OnAdded and OnRemoved like how the Ancient Smithy Hammer is done? It's the same thing either way really, just with your original way in the Constructable is less you have to do overall on future items with the small edit to AddTo in AOS.cs.
 
C#:
namespace Server.Items
{
    public class RingOfCrafts : GoldRing
    {
        private SkillMod m_SkillMod0;
        private SkillMod m_SkillMod1;
        private SkillMod m_SkillMod2;
        private SkillMod m_SkillMod3;
        private SkillMod m_SkillMod4;
        private SkillMod m_SkillMod5;
        private SkillMod m_SkillMod6;
        private SkillMod m_SkillMod7;
        private SkillMod m_SkillMod8;

        [Constructable]
        public RingOfCrafts() : base()
        {
            Weight = 1.0;
            Name = "Ring Of Crafts";
            Hue = 1150;
            DefineMods();
        }

        private void DefineMods()
        {
            m_SkillMod0 = new DefaultSkillMod(SkillName.ArmsLore, true, 15.0);
            m_SkillMod1 = new DefaultSkillMod(SkillName.Blacksmith, true, 15.0);
            m_SkillMod2 = new DefaultSkillMod(SkillName.Carpentry, true, 15.0);
            m_SkillMod3 = new DefaultSkillMod(SkillName.Cooking, true, 15.0);
            m_SkillMod4 = new DefaultSkillMod(SkillName.Fishing, true, 15.0);
            m_SkillMod5 = new DefaultSkillMod(SkillName.Fletching, true, 15.0);
            m_SkillMod6 = new DefaultSkillMod(SkillName.Mining, true, 15.0);
            m_SkillMod7 = new DefaultSkillMod(SkillName.Tailoring, true, 15.0);
            m_SkillMod8 = new DefaultSkillMod(SkillName.Tinkering, true, 15.0);
        }

        private void SetMods(Mobile wearer)
        {
            wearer.AddSkillMod(m_SkillMod0);
            wearer.AddSkillMod(m_SkillMod1);
            wearer.AddSkillMod(m_SkillMod2);
            wearer.AddSkillMod(m_SkillMod3);
            wearer.AddSkillMod(m_SkillMod4);
            wearer.AddSkillMod(m_SkillMod5);
            wearer.AddSkillMod(m_SkillMod6);
            wearer.AddSkillMod(m_SkillMod7);
            wearer.AddSkillMod(m_SkillMod8);
        }

        public override bool OnEquip(Mobile from)
        {
            SetMods(from);
            return true;
        }


        public override void OnRemoved(object parent)
        {
            if (parent is Mobile)
            {
                Mobile m = (Mobile)parent;

                if (m_SkillMod0 != null)
                    m_SkillMod0.Remove();

                if (m_SkillMod1 != null)
                    m_SkillMod1.Remove();

                if (m_SkillMod2 != null)
                    m_SkillMod2.Remove();

                if (m_SkillMod3 != null)
                    m_SkillMod3.Remove();

                if (m_SkillMod4 != null)
                    m_SkillMod4.Remove();

                if (m_SkillMod5 != null)
                    m_SkillMod5.Remove();

                if (m_SkillMod6 != null)
                    m_SkillMod6.Remove();

                if (m_SkillMod7 != null)
                    m_SkillMod7.Remove();

                if (m_SkillMod8 != null)
                    m_SkillMod8.Remove();
            }
        }

        public override void OnSingleClick(Mobile from)
        {
            this.LabelTo(from, Name);
        }

        public RingOfCrafts(Serial serial) : base(serial)
        {
            DefineMods();

            if (Parent != null && this.Parent is Mobile)
                SetMods((Mobile)Parent);
        }

        public override void GetProperties(ObjectPropertyList list)
        {
            base.GetProperties(list);
            {
                list.Add("Arms Lore +15");
                list.Add("Blacksmith +15");
                list.Add("Carpentry +15");
                list.Add("Cooking +15");
                list.Add("Fishing +15");
                list.Add("Fletching +15");
                list.Add("Mining +15");
                list.Add("Tailoring +15");
                list.Add("Tinkering +15");
            }
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write((int)0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();
        }
    }
}

Used an old cloak I found floating around on the forums for starter.
 
C#:
namespace Server.Items
{
    public class RingOfCrafts : GoldRing
    {
        private SkillMod m_SkillMod0;
        private SkillMod m_SkillMod1;
        private SkillMod m_SkillMod2;
        private SkillMod m_SkillMod3;
        private SkillMod m_SkillMod4;
        private SkillMod m_SkillMod5;
        private SkillMod m_SkillMod6;
        private SkillMod m_SkillMod7;
        private SkillMod m_SkillMod8;

        [Constructable]
        public RingOfCrafts() : base()
        {
            Weight = 1.0;
            Name = "Ring Of Crafts";
            Hue = 1150;
            DefineMods();
        }

        private void DefineMods()
        {
            m_SkillMod0 = new DefaultSkillMod(SkillName.ArmsLore, true, 15.0);
            m_SkillMod1 = new DefaultSkillMod(SkillName.Blacksmith, true, 15.0);
            m_SkillMod2 = new DefaultSkillMod(SkillName.Carpentry, true, 15.0);
            m_SkillMod3 = new DefaultSkillMod(SkillName.Cooking, true, 15.0);
            m_SkillMod4 = new DefaultSkillMod(SkillName.Fishing, true, 15.0);
            m_SkillMod5 = new DefaultSkillMod(SkillName.Fletching, true, 15.0);
            m_SkillMod6 = new DefaultSkillMod(SkillName.Mining, true, 15.0);
            m_SkillMod7 = new DefaultSkillMod(SkillName.Tailoring, true, 15.0);
            m_SkillMod8 = new DefaultSkillMod(SkillName.Tinkering, true, 15.0);
        }

        private void SetMods(Mobile wearer)
        {
            wearer.AddSkillMod(m_SkillMod0);
            wearer.AddSkillMod(m_SkillMod1);
            wearer.AddSkillMod(m_SkillMod2);
            wearer.AddSkillMod(m_SkillMod3);
            wearer.AddSkillMod(m_SkillMod4);
            wearer.AddSkillMod(m_SkillMod5);
            wearer.AddSkillMod(m_SkillMod6);
            wearer.AddSkillMod(m_SkillMod7);
            wearer.AddSkillMod(m_SkillMod8);
        }

        public override bool OnEquip(Mobile from)
        {
            SetMods(from);
            return true;
        }


        public override void OnRemoved(object parent)
        {
            if (parent is Mobile)
            {
                Mobile m = (Mobile)parent;

                if (m_SkillMod0 != null)
                    m_SkillMod0.Remove();

                if (m_SkillMod1 != null)
                    m_SkillMod1.Remove();

                if (m_SkillMod2 != null)
                    m_SkillMod2.Remove();

                if (m_SkillMod3 != null)
                    m_SkillMod3.Remove();

                if (m_SkillMod4 != null)
                    m_SkillMod4.Remove();

                if (m_SkillMod5 != null)
                    m_SkillMod5.Remove();

                if (m_SkillMod6 != null)
                    m_SkillMod6.Remove();

                if (m_SkillMod7 != null)
                    m_SkillMod7.Remove();

                if (m_SkillMod8 != null)
                    m_SkillMod8.Remove();
            }
        }

        public override void OnSingleClick(Mobile from)
        {
            this.LabelTo(from, Name);
        }

        public RingOfCrafts(Serial serial) : base(serial)
        {
            DefineMods();

            if (Parent != null && this.Parent is Mobile)
                SetMods((Mobile)Parent);
        }

        public override void GetProperties(ObjectPropertyList list)
        {
            base.GetProperties(list);
            {
                list.Add("Arms Lore +15");
                list.Add("Blacksmith +15");
                list.Add("Carpentry +15");
                list.Add("Cooking +15");
                list.Add("Fishing +15");
                list.Add("Fletching +15");
                list.Add("Mining +15");
                list.Add("Tailoring +15");
                list.Add("Tinkering +15");
            }
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write((int)0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();
        }
    }
}
Haha yeah, see, a lot more you have to write doing it that way. As I said, I typically always did it this way as well since I am used to coding for pre-AOS servers and if in the future I write an item like this again for a pre-AOS server, I'll be sure to adapt it's code to make it easier haha.
 
Yeah for sure, using the AOS is a lot less coding I have to do, I'll make sure to remember this for the future :)

It is weird that your last 2 skills got a : though..
 
It is weird that your last 2 skills got a : though..
It's because I wanted to keep them as a cliloc in case it mattered to you. There are 7 clilocs with ~1_skillname~ +~2_val~ you can use, the last two I had to use were ~1_val~: ~2_val~ otherwise I would've simply made it into a string like so:
C#:
list.Add(skill.ToString() + " +" + bonus.ToString());
Increasing the number in GetProperties and leaving it alone wouldn't have worked since there are only 5 that are 1 digit higher before it turns into an irrelevant cliloc. The other two are by themselves as well, which is why I did the < 5, == 5, == 6, etc.

However one issue with doing it by string and not by GetLabel (other than different translations for clilocs) is that skills such as Arms Lore in this case will appear as ArmsLore, so you would need to use a method of separating strings by capital letters unless you don't mind the words being together.

**Edit**
Which incase it matters to anyone, you can add something like this to separate them:
C#:
        public static string SeparateCapitals(string msg)
        {
            StringBuilder builder = new StringBuilder();
            foreach (char c in msg)
            {
                if (Char.IsUpper(c) && builder.Length > 0) builder.Append(' ');
                builder.Append(c);
            }
            return msg = builder.ToString();
        }

Then in GetProperties you'd need to make it look like this:
C#:
        public void GetProperties(ObjectPropertyList list)
        {
            for (int i = 0; i < 9; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                list.Add(SeparateCapitals(skill.ToString()) + " +" + bonus.ToString());
            }
        }

You will also need to add the reference for StringBuilder at the top of the file by adding:
using System.Text;

Before and After:
Separate1.pngSeparate2.png
 
Last edited:
Hmm I think I may have done something wrong lol, ignore the fact that I made it 60 :) but it lists the whole list twice.. looking it over now but was just curious if you see anything wrong.

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Server.Engines.SphynxFortune;
using Server.Engines.XmlSpawner2;
using Server.Items;
using Server.Misc;
using Server.Mobiles;
using Server.Spells;
using Server.Spells.Second;
using Server.Spells.Fifth;
using Server.Spells.Bushido;
using Server.Spells.Ninjitsu;
using Server.Spells.Seventh;
using Server.Spells.Chivalry;
using Server.Spells.Necromancy;
using Server.Spells.Spellweaving;
using Server.SkillHandlers;
using Server.Engines.CityLoyalty;
using Server.Services.Virtues;
using Server.Spells.SkillMasteries;

namespace Server
{
    public enum DamageType
    {
        Melee,
        Ranged,
        Spell,
        SpellAOE
    }

    public class AOS
    {
        public static void DisableStatInfluences()
        {
            for (int i = 0; i < SkillInfo.Table.Length; ++i)
            {
                SkillInfo info = SkillInfo.Table[i];

                info.StrScale = 0.0;
                info.DexScale = 0.0;
                info.IntScale = 0.0;
                info.StatTotal = 0.0;
            }
        }

        public static int Damage(IDamageable m, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, null, damage, ignoreArmor, phys, fire, cold, pois, nrgy);
        }

        public static int Damage(IDamageable m, int damage, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, null, damage, phys, fire, cold, pois, nrgy);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, 0, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, from, damage, ignoreArmor, phys, fire, cold, pois, nrgy, 0, 0, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, bool keepAlive)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, keepAlive);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, bool keepAlive, bool archer, bool deathStrike)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, keepAlive, archer ? DamageType.Ranged : DamageType.Melee); // old deathStrike damage, kept for compatibility
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, DamageType type)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, false, type);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, DamageType type)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, false, type);
        }

        public static int Damage(IDamageable damageable, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, bool keepAlive, DamageType type = DamageType.Melee)
        {
            Mobile m = damageable as Mobile;

            #region Iomega0318 Player Damage Cap for Pets, Prevent use in PvP
            if (damageable is PlayerMobile && from is BaseCreature && ((BaseCreature)from).Controlled)
            {
                damage = Math.Min(damage, 40); // Pet Dmg Cap to players
                phys = Math.Min(phys, 40); // Pet phys Cap to players
                fire = Math.Min(fire, 40); // Pet fire Cap to players
                cold = Math.Min(cold, 40); // Pet cold Cap to players
                pois = Math.Min(pois, 40); // Pet pois Cap to players
                nrgy = Math.Min(nrgy, 40); // Pet nrgy Cap to players
                chaos = Math.Min(chaos, 40); // Pet chaos Cap to players
                direct = Math.Min(direct, 40); // Pet direct Cap to players
            }
            #endregion

            if (damageable == null || damageable.Deleted || !damageable.Alive || damage <= 0)
                return 0;

            if (m != null && phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0)
                Mobiles.MeerMage.StopEffect(m, true);

            if (!Core.AOS)
            {
                if(m != null)
                    m.Damage(damage, from);

                return damage;
            }

            #region Mondain's Legacy
            if (m != null)
            {
                m.Items.ForEach(i =>
                {
                    ITalismanProtection prot = i as ITalismanProtection;

                    if (prot != null)
                        damage = prot.Protection.ScaleDamage(from, damage);
                });
            }
            #endregion

            Fix(ref phys);
            Fix(ref fire);
            Fix(ref cold);
            Fix(ref pois);
            Fix(ref nrgy);
            Fix(ref chaos);
            Fix(ref direct);

            if (Core.ML && chaos > 0)
            {
                switch (Utility.Random(5))
                {
                    case 0:
                        phys += chaos;
                        break;
                    case 1:
                        fire += chaos;
                        break;
                    case 2:
                        cold += chaos;
                        break;
                    case 3:
                        pois += chaos;
                        break;
                    case 4:
                        nrgy += chaos;
                        break;
                }
            }

            bool ranged = type == DamageType.Ranged;
            BaseQuiver quiver = null;

            if (ranged && from.Race != Race.Gargoyle)
                quiver = from.FindItemOnLayer(Layer.Cloak) as BaseQuiver;

            int totalDamage;

            if (!ignoreArmor)
            {
                int physDamage = damage * phys * (100 - damageable.PhysicalResistance);
                int fireDamage = damage * fire * (100 - damageable.FireResistance);
                int coldDamage = damage * cold * (100 - damageable.ColdResistance);
                int poisonDamage = damage * pois * (100 - damageable.PoisonResistance);
                int energyDamage = damage * nrgy * (100 - damageable.EnergyResistance);

                totalDamage = physDamage + fireDamage + coldDamage + poisonDamage + energyDamage;
                totalDamage /= 10000;

                if (Core.ML)
                {
                    totalDamage += damage * direct / 100;

                    if (quiver != null)
                        totalDamage += totalDamage * quiver.DamageIncrease / 100;
                }

                if (m != null)
                    BaseFishPie.ScaleDamage(from, m, ref totalDamage, phys, fire, cold, pois, nrgy, direct);

                if (Core.HS && ArmorPierce.IsUnderEffects(m))
                {
                    totalDamage += (int)((double)totalDamage * .1);
                }

                if (totalDamage < 1)
                    totalDamage = 1;         
            }
            else if (Core.ML && m is PlayerMobile)
            {
                if (quiver != null)
                    damage += damage * quiver.DamageIncrease / 100;

                totalDamage = Math.Min(damage, Core.TOL && ranged ? 30 : 35);    // Direct Damage cap of 30/35
            }
            else
            {
                totalDamage = damage;

                if (Core.ML && quiver != null)
                    totalDamage += totalDamage * quiver.DamageIncrease / 100;
            }

            // object being damaged is not a mobile, so we will end here
            if (damageable is Item)
            {
                return damageable.Damage(totalDamage, from);
            }

            #region Evil Omen, Blood Oath and reflect physical
            if (EvilOmenSpell.TryEndEffect(m))
            {
                totalDamage = (int)(totalDamage * 1.25);
            }

            if (from != null && !from.Deleted && from.Alive && !from.IsDeadBondedPet)
            {
                Mobile oath = BloodOathSpell.GetBloodOath(from);

                /* Per EA's UO Herald Pub48 (ML):
                * ((resist spellsx10)/20 + 10=percentage of damage resisted)
                *
                * Tested 12/29/2017-
                * No cap, also, above forumula is only in effect vs. creatures
                */

                if (oath == m)
                {
                    int originalDamage = totalDamage;
                    totalDamage = (int)(totalDamage * 1.2);

                    if (!Core.TOL && totalDamage > 35 && from is PlayerMobile) /* capped @ 35, seems no expansion */
                    {
                        totalDamage = 35;
                    }

                    if (Core.ML && m is BaseCreature)
                    {
                        from.Damage((int)(originalDamage * (1 - (((from.Skills.MagicResist.Value * .5) + 10) / 100))), m);
                    }
                    else
                    {
                        from.Damage(originalDamage, m);
                    }
                }
                else if (!ignoreArmor && from != m)
                {
                    int reflectPhys = Math.Min(105, AosAttributes.GetValue(m, AosAttribute.ReflectPhysical));

                    if (reflectPhys != 0)
                    {
                        if (from is ExodusMinion && ((ExodusMinion)from).FieldActive || from is ExodusOverseer && ((ExodusOverseer)from).FieldActive)
                        {
                            from.FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist);
                            from.PlaySound(0x2F4);
                            m.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier");
                        }
                        else
                        {
                            from.Damage(Scale((damage * phys * (100 - (ignoreArmor ? 0 : m.PhysicalResistance))) / 10000, reflectPhys), m);
                        }
                    }
                }
            }
            #endregion

            #region Stygian Abyss
            //SHould this go in after or before dragon barding absorb?
            if (ignoreArmor)
                DamageEaterContext.CheckDamage(m, totalDamage, 0, 0, 0, 0, 0, 100);
            else
                DamageEaterContext.CheckDamage(m, totalDamage, phys, fire, cold, pois, nrgy, direct);

            if (fire > 0 && totalDamage > 0)
                SwarmContext.CheckRemove(m);
            #endregion

            SpiritualityVirtue.GetDamageReduction(m, ref totalDamage);

            #region Berserk
            BestialSetHelper.OnDamage(m, from, ref totalDamage);
            #endregion

            #region Epiphany Set
            EpiphanyHelper.OnHit(m, totalDamage);
            #endregion

            if (type == DamageType.Spell && m != null && Feint.Registry.ContainsKey(m) && Feint.Registry[m].Enemy == from)
                totalDamage -= (int)((double)damage * ((double)Feint.Registry[m].DamageReduction / 100));

            if (m.Hidden && Core.ML && type >= DamageType.Spell)
            {
                int chance = (int)Math.Min(33, 100 - (Server.Spells.SkillMasteries.ShadowSpell.GetDifficultyFactor(m) * 100));

                if (Utility.Random(100) < chance)
                {
                    m.RevealingAction();
                    m.NextSkillTime = Core.TickCount + (12000 - ((int)m.Skills[SkillName.Hiding].Value) * 100);
                }
            }

            #region Skill Mastery
            SkillMasterySpell.OnDamage(m, from, type, ref totalDamage);
            #endregion

            #region Pet Training
            if (from is BaseCreature || m is BaseCreature)
            {
                SpecialAbility.CheckCombatTrigger(from, m, ref totalDamage, type);

                if (PetTrainingHelper.Enabled)
                {
                    if (from is BaseCreature && m is BaseCreature)
                    {
                        var profile = PetTrainingHelper.GetTrainingProfile((BaseCreature)from);

                        if (profile != null)
                        {
                            profile.CheckProgress((BaseCreature)m);
                        }

                        profile = PetTrainingHelper.GetTrainingProfile((BaseCreature)m);

                        if (profile != null && 0.3 > Utility.RandomDouble())
                        {
                            profile.CheckProgress((BaseCreature)from);
                        }
                    }

                    if (from is BaseCreature && ((BaseCreature)from).Controlled && m.Player)
                    {
                        totalDamage /= 2;
                    }
                }
            }
            #endregion

            if (type <= DamageType.Ranged)
            {
                AttuneWeaponSpell.TryAbsorb(m, ref totalDamage);
            }

            if (keepAlive && totalDamage > m.Hits)
            {
                totalDamage = m.Hits;
            }

            if (from is BaseCreature && type <= DamageType.Ranged)
            {
                ((BaseCreature)from).AlterMeleeDamageTo(m, ref totalDamage);
            }

            if (m is BaseCreature && type <= DamageType.Ranged)
            {
                ((BaseCreature)m).AlterMeleeDamageFrom(from, ref totalDamage);
            }

            if (m is BaseCreature)
            {
                ((BaseCreature)m).OnBeforeDamage(from, ref totalDamage, type);
            }

            if (totalDamage <= 0)
            {
                return 0;
            }

            if (from != null)
            {
                DoLeech(totalDamage, from, m);
            }

            totalDamage = m.Damage(totalDamage, from, true, false);

            if (Core.SA && type == DamageType.Melee && from is BaseCreature &&
                (m is PlayerMobile || (m is BaseCreature && !((BaseCreature)m).IsMonster)))
            {
                from.RegisterDamage(totalDamage / 4, m);
            }

            SpiritSpeak.CheckDisrupt(m);

            #region Stygian Abyss
            if (m.Spell != null)
                ((Spell)m.Spell).CheckCasterDisruption(true, phys, fire, cold, pois, nrgy);

            BattleLust.IncreaseBattleLust(m, totalDamage);

            if (ManaPhasingOrb.IsInManaPhase(m))
                ManaPhasingOrb.RemoveFromTable(m);

            SoulChargeContext.CheckHit(from, m, totalDamage);

            Spells.Mysticism.SleepSpell.OnDamage(m);
            Spells.Mysticism.PurgeMagicSpell.OnMobileDoDamage(from);
            #endregion

            BaseCostume.OnDamaged(m);

            return totalDamage;
        }

        public static void Fix(ref int val)
        {
            if (val < 0)
                val = 0;
        }

        public static int Scale(int input, int percent)
        {
            return (input * percent) / 100;
        }

        public static void DoLeech(int damageGiven, Mobile from, Mobile target)
        {
            TransformContext context = TransformationSpellHelper.GetContext(from);

            if (context != null)
            {
                if (context.Type == typeof(WraithFormSpell))
                {
                    int manaLeech = AOS.Scale(damageGiven, Math.Min(target.Mana, (int)from.Skills.SpiritSpeak.Value / 5)); // Wraith form gives 5-20% mana leech

                    if (manaLeech != 0)
                    {
                        from.Mana += manaLeech;
                        from.PlaySound(0x44D);

                        target.Mana -= manaLeech;
                    }
                }
                else if (context.Type == typeof(VampiricEmbraceSpell))
                {
                    #region High Seas
                    if (target is BaseCreature && ((BaseCreature)target).TaintedLifeAura)
                    {
                        AOS.Damage(from, target, AOS.Scale(damageGiven, 20), false, 0, 0, 0, 0, 0, 0, 100, false, false, false);
                        from.SendLocalizedMessage(1116778); //The tainted life force energy damages you as your body tries to absorb it.
                    }
                    #endregion
                    else
                    {
                        from.Hits += AOS.Scale(damageGiven, 20);
                        from.PlaySound(0x44D);
                    }
                }
            }
        }

        #region AOS Status Bar
        public static int GetStatus( Mobile from, int index )
        {
            switch ( index )
            {
                case 0: return from.GetMaxResistance( ResistanceType.Physical );
                case 1: return from.GetMaxResistance( ResistanceType.Fire );
                case 2: return from.GetMaxResistance( ResistanceType.Cold );
                case 3: return from.GetMaxResistance( ResistanceType.Poison );
                case 4: return from.GetMaxResistance( ResistanceType.Energy );
                case 5: return Math.Min(45 + BaseArmor.GetRefinedDefenseChance(from), AosAttributes.GetValue(from, AosAttribute.DefendChance));
                case 6: return 45 + BaseArmor.GetRefinedDefenseChance(from);
                case 7: return Math.Min(from.Race == Race.Gargoyle ? 50 : 45, AosAttributes.GetValue(from, AosAttribute.AttackChance));
                case 8: return Math.Min(60, AosAttributes.GetValue(from, AosAttribute.WeaponSpeed));
                case 9: return Math.Min(100, AosAttributes.GetValue(from, AosAttribute.WeaponDamage));
                case 10: return Math.Min(100, AosAttributes.GetValue(from, AosAttribute.LowerRegCost));
                case 11: return AosAttributes.GetValue(from, AosAttribute.SpellDamage);
                case 12: return Math.Min(6, AosAttributes.GetValue(from, AosAttribute.CastRecovery));
                case 13: return Math.Min(4, AosAttributes.GetValue(from, AosAttribute.CastSpeed));
                case 14: return Math.Min(40, AosAttributes.GetValue(from, AosAttribute.LowerManaCost)) + BaseArmor.GetInherentLowerManaCost(from);
              
                case 15: return (int)RegenRates.HitPointRegen(from); // HP   REGEN
                case 16: return (int)RegenRates.StamRegen(from); // Stam REGEN
                case 17: return (int)RegenRates.ManaRegen(from); // MANA REGEN
                case 18: return Math.Min(105, AosAttributes.GetValue(from, AosAttribute.ReflectPhysical)); // reflect phys
                case 19: return Math.Min(50, AosAttributes.GetValue(from, AosAttribute.EnhancePotions)); // enhance pots

                case 20: return AosAttributes.GetValue(from, AosAttribute.BonusStr) + from.GetStatOffset(StatType.Str); // str inc
                case 21: return AosAttributes.GetValue(from, AosAttribute.BonusDex) + from.GetStatOffset(StatType.Dex); ; // dex inc
                case 22: return AosAttributes.GetValue(from, AosAttribute.BonusInt) + from.GetStatOffset(StatType.Int); ; // int inc

                case 23: return 0; // hits neg
                case 24: return 0; // stam neg
                case 25: return 0; // mana neg

                case 26: return AosAttributes.GetValue(from, AosAttribute.BonusHits); // hits inc
                case 27: return AosAttributes.GetValue(from, AosAttribute.BonusStam); // stam inc
                case 28: return AosAttributes.GetValue(from, AosAttribute.BonusMana); // mana inc
                default: return 0;
            }
        }
        #endregion
    }

    [Flags]
    public enum AosAttribute
    {
        RegenHits = 0x00000001,
        RegenStam = 0x00000002,
        RegenMana = 0x00000004,
        DefendChance = 0x00000008,
        AttackChance = 0x00000010,
        BonusStr = 0x00000020,
        BonusDex = 0x00000040,
        BonusInt = 0x00000080,
        BonusHits = 0x00000100,
        BonusStam = 0x00000200,
        BonusMana = 0x00000400,
        WeaponDamage = 0x00000800,
        WeaponSpeed = 0x00001000,
        SpellDamage = 0x00002000,
        CastRecovery = 0x00004000,
        CastSpeed = 0x00008000,
        LowerManaCost = 0x00010000,
        LowerRegCost = 0x00020000,
        ReflectPhysical = 0x00040000,
        EnhancePotions = 0x00080000,
        Luck = 0x00100000,
        SpellChanneling = 0x00200000,
        NightSight = 0x00400000,
        IncreasedKarmaLoss = 0x00800000,
        Brittle = 0x01000000,
        LowerAmmoCost = 0x02000000,
        BalancedWeapon = 0x04000000
    }

    public sealed class AosAttributes : BaseAttributes
    {
        public static bool IsValid(AosAttribute attribute)
        {
            if (!Core.AOS)
            {
                return false;
            }

            if (!Core.ML && attribute == AosAttribute.IncreasedKarmaLoss)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params AosAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<AosAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<AosAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, AosAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            if (attribute == AosAttribute.Luck || attribute == AosAttribute.RegenMana || attribute == AosAttribute.DefendChance || attribute == AosAttribute.EnhancePotions)
                value += SphynxFortune.GetAosAttributeBonus(m, attribute);

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                Item obj = m.Items[i];

                AosAttributes attrs = RunicReforging.GetAosAttributes(obj);

                if (attrs != null)
                    value += attrs[attribute];

                if (attribute == AosAttribute.Luck)
                {
                    if (obj is BaseWeapon)
                        value += ((BaseWeapon)obj).GetLuckBonus();

                    if (obj is BaseArmor)
                        value += ((BaseArmor)obj).GetLuckBonus();
                }

                if (obj is ISetItem)
                {
                    ISetItem item = (ISetItem)obj;

                    attrs = item.SetAttributes;

                    if (attrs != null && item.LastEquipped)
                        value += attrs[attribute];
                }
            }

            #region Malus/Buff Handler

            #region Skill Mastery
            value += SkillMasterySpell.GetAttributeBonus(m, attribute);
            #endregion

            if (attribute == AosAttribute.WeaponDamage)
            {
                if (BaseMagicalFood.IsUnderInfluence(m, MagicalFood.GrapesOfWrath))
                    value += 35;

                // attacker gets 10% bonus when they're under divine fury
                if (DivineFurySpell.UnderEffect(m))
                    value += DivineFurySpell.GetDamageBonus(m);

                // Horrific Beast transformation gives a +25% bonus to damage.
                if (TransformationSpellHelper.UnderTransformation(m, typeof(HorrificBeastSpell)))
                    value += 25;

                int defenseMasteryMalus = 0;
                int discordanceEffect = 0;

                // Defense Mastery gives a -50%/-80% malus to damage.
                if (Server.Items.DefenseMastery.GetMalus(m, ref defenseMasteryMalus))
                    value -= defenseMasteryMalus;

                // Discordance gives a -2%/-48% malus to damage.
                if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
                    value -= discordanceEffect * 2;

                if (Block.IsBlocking(m))
                    value -= 30;

                #region SA
                if (m is PlayerMobile && m.Race == Race.Gargoyle)
                {
                    value += ((PlayerMobile)m).GetRacialBerserkBuff(false);
                }
                #endregion

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.WeaponDam))
                    value += 5;
                #endregion
            }
            else if (attribute == AosAttribute.SpellDamage)
            {
                if (BaseMagicalFood.IsUnderInfluence(m, MagicalFood.GrapesOfWrath))
                    value += 15;

                if (PsychicAttack.Registry.ContainsKey(m))
                    value -= PsychicAttack.Registry[m].SpellDamageMalus;

                TransformContext context = TransformationSpellHelper.GetContext(m);

                if (context != null && context.Spell is ReaperFormSpell)
                    value += ((ReaperFormSpell)context.Spell).SpellDamageBonus;

                value += ArcaneEmpowermentSpell.GetSpellBonus(m, true);

                #region SA
                if (m is PlayerMobile && m.Race == Race.Gargoyle)
                {
                    value += ((PlayerMobile)m).GetRacialBerserkBuff(true);
                }
                #endregion

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.GuildOfArcaneArts))
                    value += 5;
                #endregion

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.SpellDamage))
                    value += 5;
                #endregion
            }
            else if (attribute == AosAttribute.CastSpeed)
            {
                if (HowlOfCacophony.IsUnderEffects(m) || AuraOfNausea.UnderNausea(m))
                    value -= 5;

                if (EssenceOfWindSpell.IsDebuffed(m))
                    value -= EssenceOfWindSpell.GetFCMalus(m);

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.BardicCollegium))
                    value += 1;
                #endregion

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 2;

                if (TransformationSpellHelper.UnderTransformation(m, typeof(Spells.Mysticism.StoneFormSpell)))
                    value -= 2;
                #endregion
            }
            else if (attribute == AosAttribute.CastRecovery)
            {
                if (HowlOfCacophony.IsUnderEffects(m))
                    value -= 5;

                value -= ThunderstormSpell.GetCastRecoveryMalus(m);

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 3;
                #endregion
            }
            else if (attribute == AosAttribute.WeaponSpeed)
            {
                if (HowlOfCacophony.IsUnderEffects(m) || AuraOfNausea.UnderNausea(m))
                    value -= 60;

                if (DivineFurySpell.UnderEffect(m))
                    value += DivineFurySpell.GetWeaponSpeedBonus(m);

                value += HonorableExecution.GetSwingBonus(m);

                TransformContext context = TransformationSpellHelper.GetContext(m);

                if (context != null && context.Spell is ReaperFormSpell)
                    value += ((ReaperFormSpell)context.Spell).SwingSpeedBonus;

                int discordanceEffect = 0;

                // Discordance gives a malus of -0/-28% to swing speed.
                if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
                    value -= discordanceEffect;

                if (EssenceOfWindSpell.IsDebuffed(m))
                    value -= EssenceOfWindSpell.GetSSIMalus(m);

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.GuildOfAssassins))
                    value += 5;
                #endregion

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 45;

                if (TransformationSpellHelper.UnderTransformation(m, typeof(Spells.Mysticism.StoneFormSpell)))
                    value -= 10;

                if (StickySkin.IsUnderEffects(m))
                    value -= 30;
                #endregion
            }
            else if (attribute == AosAttribute.AttackChance)
            {
                if (AuraOfNausea.UnderNausea(m))
                    value -= 60;

                if (DivineFurySpell.UnderEffect(m))
                    value += DivineFurySpell.GetAttackBonus(m);                 

                if (BaseWeapon.CheckAnimal(m, typeof(GreyWolf)) || BaseWeapon.CheckAnimal(m, typeof(BakeKitsune)))
                    value += 20; // attacker gets 20% bonus when under Wolf or Bake Kitsune form

                if (HitLower.IsUnderAttackEffect(m))
                    value -= 25; // Under Hit Lower Attack effect -> 25% malus

                WeaponAbility ability = WeaponAbility.GetCurrentAbility(m);

                if (ability != null)
                    value += ability.AccuracyBonus;

                SpecialMove move = SpecialMove.GetCurrentMove(m);

                if (move != null)
                    value += move.GetAccuracyBonus(m);

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.WarriorsGuild))
                    value += 5;
                #endregion

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 45;

                if (m.Race == Race.Gargoyle)
                    value += 5;  //Gargoyles get a +5 HCI
                #endregion

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.HitChance))
                    value += 8;
                #endregion
            }
            else if (attribute == AosAttribute.DefendChance)
            {
                if (AuraOfNausea.UnderNausea(m))
                    value -= 60;

                if (DivineFurySpell.UnderEffect(m))
                    value -= DivineFurySpell.GetDefendMalus(m);

                value -= HitLower.GetDefenseMalus(m);

                int discordanceEffect = 0;
                int surpriseMalus = 0;

                value += Block.GetBonus(m);

                if (SurpriseAttack.GetMalus(m, ref surpriseMalus))
                    value -= surpriseMalus;

                // Defender loses -0/-28% if under the effect of Discordance.
                if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
                    value -= discordanceEffect;

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.DefChance))
                    value += 8;
                #endregion
            }
            else if (attribute == AosAttribute.RegenHits)
            {
                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.MaritimeGuild))
                    value += 2;
                #endregion

                #region High Seas
                if (m is PlayerMobile && BaseFishPie.IsUnderEffects(m, FishPieEffect.HitsRegen))
                    value += 3;

                if (SurgeShield.IsUnderEffects(m, SurgeType.Hits))
                    value += 10;

                if (SearingWeaponContext.HasContext(m))
                    value -= m is PlayerMobile ? 20 : 60;
                #endregion

                //Virtue Artifacts
                value += AnkhPendant.GetHitsRegenModifier(m);
            }
            else if (attribute == AosAttribute.RegenStam)
            {
                #region High Seas
                if (m is PlayerMobile && BaseFishPie.IsUnderEffects(m, FishPieEffect.StamRegen))
                    value += 3;

                if (SurgeShield.IsUnderEffects(m, SurgeType.Stam))
                    value += 10;
                #endregion

                //Virtue Artifacts
                value += AnkhPendant.GetStamRegenModifier(m);
            }
            else if (attribute == AosAttribute.RegenMana)
            {
                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.MerchantsAssociation))
                    value += 1;
                #endregion

                #region High Seas
                if (m is PlayerMobile && BaseFishPie.IsUnderEffects(m, FishPieEffect.ManaRegen))
                    value += 3;

                if (SurgeShield.IsUnderEffects(m, SurgeType.Mana))
                    value += 10;
                #endregion

                //Virtue Artifacts
                value += AnkhPendant.GetManaRegenModifier(m);
            }
            #endregion

            return value;
        }

        public override void SetValue(int bitmask, int value)
        {
            if (Core.SA && bitmask == (int)AosAttribute.WeaponSpeed && Owner is BaseWeapon)
            {
                ((BaseWeapon)Owner).WeaponAttributes.ScaleLeech(value);
            }

            base.SetValue(bitmask, value);
        }

        public AosAttributes(Item owner)
            : base(owner)
        {
        }

        public AosAttributes(Item owner, AosAttributes other)
            : base(owner, other)
        {
        }

        public AosAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }


        public int this[AosAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public override string ToString()
        {
            return "...";
        }

        public void AddStatBonuses(Mobile to)
        {
            int strBonus = BonusStr;
            int dexBonus = BonusDex;
            int intBonus = BonusInt;

            if (strBonus != 0 || dexBonus != 0 || intBonus != 0)
            {
                string modName = Owner.Serial.ToString();

                if (strBonus != 0)
                    to.AddStatMod(new StatMod(StatType.Str, modName + "Str", strBonus, TimeSpan.Zero));

                if (dexBonus != 0)
                    to.AddStatMod(new StatMod(StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero));

                if (intBonus != 0)
                    to.AddStatMod(new StatMod(StatType.Int, modName + "Int", intBonus, TimeSpan.Zero));
            }

            to.CheckStatTimers();
        }

        public void RemoveStatBonuses(Mobile from)
        {
            string modName = Owner.Serial.ToString();

            from.RemoveStatMod(modName + "Str");
            from.RemoveStatMod(modName + "Dex");
            from.RemoveStatMod(modName + "Int");

            from.CheckStatTimers();
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int RegenHits
        {
            get
            {
                return this[AosAttribute.RegenHits];
            }
            set
            {
                this[AosAttribute.RegenHits] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int RegenStam
        {
            get
            {
                return this[AosAttribute.RegenStam];
            }
            set
            {
                this[AosAttribute.RegenStam] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int RegenMana
        {
            get
            {
                return this[AosAttribute.RegenMana];
            }
            set
            {
                this[AosAttribute.RegenMana] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int DefendChance
        {
            get
            {
                return this[AosAttribute.DefendChance];
            }
            set
            {
                this[AosAttribute.DefendChance] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int AttackChance
        {
            get
            {
                return this[AosAttribute.AttackChance];
            }
            set
            {
                this[AosAttribute.AttackChance] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusStr
        {
            get
            {
                return this[AosAttribute.BonusStr];
            }
            set
            {
                this[AosAttribute.BonusStr] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusDex
        {
            get
            {
                return this[AosAttribute.BonusDex];
            }
            set
            {
                this[AosAttribute.BonusDex] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusInt
        {
            get
            {
                return this[AosAttribute.BonusInt];
            }
            set
            {
                this[AosAttribute.BonusInt] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusHits
        {
            get
            {
                return this[AosAttribute.BonusHits];
            }
            set
            {
                this[AosAttribute.BonusHits] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusStam
        {
            get
            {
                return this[AosAttribute.BonusStam];
            }
            set
            {
                this[AosAttribute.BonusStam] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusMana
        {
            get
            {
                return this[AosAttribute.BonusMana];
            }
            set
            {
                this[AosAttribute.BonusMana] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int WeaponDamage
        {
            get
            {
                return this[AosAttribute.WeaponDamage];
            }
            set
            {
                this[AosAttribute.WeaponDamage] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int WeaponSpeed
        {
            get
            {
                return this[AosAttribute.WeaponSpeed];
            }
            set
            {
                this[AosAttribute.WeaponSpeed] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SpellDamage
        {
            get
            {
                return this[AosAttribute.SpellDamage];
            }
            set
            {
                this[AosAttribute.SpellDamage] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int CastRecovery
        {
            get
            {
                return this[AosAttribute.CastRecovery];
            }
            set
            {
                this[AosAttribute.CastRecovery] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int CastSpeed
        {
            get
            {
                return this[AosAttribute.CastSpeed];
            }
            set
            {
                this[AosAttribute.CastSpeed] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerManaCost
        {
            get
            {
                return this[AosAttribute.LowerManaCost];
            }
            set
            {
                this[AosAttribute.LowerManaCost] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerRegCost
        {
            get
            {
                return this[AosAttribute.LowerRegCost];
            }
            set
            {
                this[AosAttribute.LowerRegCost] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ReflectPhysical
        {
            get
            {
                return this[AosAttribute.ReflectPhysical];
            }
            set
            {
                this[AosAttribute.ReflectPhysical] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EnhancePotions
        {
            get
            {
                return this[AosAttribute.EnhancePotions];
            }
            set
            {
                this[AosAttribute.EnhancePotions] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Luck
        {
            get
            {
                return this[AosAttribute.Luck];
            }
            set
            {
                this[AosAttribute.Luck] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SpellChanneling
        {
            get
            {
                return this[AosAttribute.SpellChanneling];
            }
            set
            {
                this[AosAttribute.SpellChanneling] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int NightSight
        {
            get
            {
                return this[AosAttribute.NightSight];
            }
            set
            {
                this[AosAttribute.NightSight] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int IncreasedKarmaLoss
        {
            get
            {
                return this[AosAttribute.IncreasedKarmaLoss];
            }
            set
            {
                this[AosAttribute.IncreasedKarmaLoss] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Brittle
        {
            get
            {
                return this[AosAttribute.Brittle];
            }
            set
            {
                this[AosAttribute.Brittle] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerAmmoCost
        {
            get
            {
                return this[AosAttribute.LowerAmmoCost];
            }
            set
            {
                this[AosAttribute.LowerAmmoCost] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BalancedWeapon
        {
            get
            {
                return this[AosAttribute.BalancedWeapon];
            }
            set
            {
                this[AosAttribute.BalancedWeapon] = value;
            }
        }
    }

    [Flags]
    public enum AosWeaponAttribute : long
    {
        LowerStatReq = 0x00000001,
        SelfRepair = 0x00000002,
        HitLeechHits = 0x00000004,
        HitLeechStam = 0x00000008,
        HitLeechMana = 0x00000010,
        HitLowerAttack = 0x00000020,
        HitLowerDefend = 0x00000040,
        HitMagicArrow = 0x00000080,
        HitHarm = 0x00000100,
        HitFireball = 0x00000200,
        HitLightning = 0x00000400,
        HitDispel = 0x00000800,
        HitColdArea = 0x00001000,
        HitFireArea = 0x00002000,
        HitPoisonArea = 0x00004000,
        HitEnergyArea = 0x00008000,
        HitPhysicalArea = 0x00010000,
        ResistPhysicalBonus = 0x00020000,
        ResistFireBonus = 0x00040000,
        ResistColdBonus = 0x00080000,
        ResistPoisonBonus = 0x00100000,
        ResistEnergyBonus = 0x00200000,
        UseBestSkill = 0x00400000,
        MageWeapon = 0x00800000,
        DurabilityBonus = 0x01000000,
        BloodDrinker = 0x02000000,
        BattleLust = 0x04000000,
        HitCurse = 0x08000000,
        HitFatigue = 0x10000000,
        HitManaDrain = 0x20000000,
        SplinteringWeapon = 0x40000000,
        ReactiveParalyze =  0x80000000,
    }

    public sealed class AosWeaponAttributes : BaseAttributes
    {
        public static bool IsValid(AosWeaponAttribute attribute)
        {
            if (!Core.AOS)
            {
                return false;
            }

            if (!Core.SA && attribute >= AosWeaponAttribute.BloodDrinker)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params AosWeaponAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<AosWeaponAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<AosWeaponAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, AosWeaponAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                AosWeaponAttributes attrs = RunicReforging.GetAosWeaponAttributes(m.Items[i]);

                if (attrs != null)
                    value += attrs[attribute];
            }

            return value;
        }

        public override void SetValue(int bitmask, int value)
        {
            if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && Owner is BaseWeapon)
            {
                ((BaseWeapon)Owner).UnscaleDurability();
            }

            base.SetValue(bitmask, value);

            if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && Owner is BaseWeapon)
            {
                ((BaseWeapon)Owner).ScaleDurability();
            }
        }

        public AosWeaponAttributes(Item owner)
            : base(owner)
        {
        }

        public AosWeaponAttributes(Item owner, AosWeaponAttributes other)
            : base(owner, other)
        {
        }

        public AosWeaponAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public int this[AosWeaponAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public void ScaleLeech(int weaponSpeed)
        {
            BaseWeapon wep = Owner as BaseWeapon;

            if (wep == null || wep.IsArtifact)
                return;

            if (HitLeechHits > 0)
            {
                double postcap = (double)HitLeechHits / (double)ItemPropertyInfo.GetMaxIntensity(wep, AosWeaponAttribute.HitLeechHits);
                if (postcap < 1.0) postcap = 1.0;

                int newhits = (int)((wep.MlSpeed * 2500 / (100 + weaponSpeed)) * postcap);

                if (wep is BaseRanged)
                    newhits /= 2;

                if(HitLeechHits > newhits)
                    HitLeechHits = newhits;
            }

            if (HitLeechMana > 0)
            {
                double postcap = (double)HitLeechMana / (double)ItemPropertyInfo.GetMaxIntensity(wep, AosWeaponAttribute.HitLeechMana);
                if (postcap < 1.0) postcap = 1.0;

                int newmana = (int)((wep.MlSpeed * 2500 / (100 + weaponSpeed)) * postcap);

                if (wep is BaseRanged)
                    newmana /= 2;

                if(HitLeechMana > newmana)
                    HitLeechMana = newmana;
            }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerStatReq
        {
            get
            {
                return this[AosWeaponAttribute.LowerStatReq];
            }
            set
            {
                this[AosWeaponAttribute.LowerStatReq] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SelfRepair
        {
            get
            {
                return this[AosWeaponAttribute.SelfRepair];
            }
            set
            {
                this[AosWeaponAttribute.SelfRepair] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLeechHits
        {
            get
            {
                return this[AosWeaponAttribute.HitLeechHits];
            }
            set
            {
                this[AosWeaponAttribute.HitLeechHits] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLeechStam
        {
            get
            {
                return this[AosWeaponAttribute.HitLeechStam];
            }
            set
            {
                this[AosWeaponAttribute.HitLeechStam] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLeechMana
        {
            get
            {
                return this[AosWeaponAttribute.HitLeechMana];
            }
            set
            {
                this[AosWeaponAttribute.HitLeechMana] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLowerAttack
        {
            get
            {
                return this[AosWeaponAttribute.HitLowerAttack];
            }
            set
            {
                this[AosWeaponAttribute.HitLowerAttack] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLowerDefend
        {
            get
            {
                return this[AosWeaponAttribute.HitLowerDefend];
            }
            set
            {
                this[AosWeaponAttribute.HitLowerDefend] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitMagicArrow
        {
            get
            {
                return this[AosWeaponAttribute.HitMagicArrow];
            }
            set
            {
                this[AosWeaponAttribute.HitMagicArrow] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitHarm
        {
            get
            {
                return this[AosWeaponAttribute.HitHarm];
            }
            set
            {
                this[AosWeaponAttribute.HitHarm] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitFireball
        {
            get
            {
                return this[AosWeaponAttribute.HitFireball];
            }
            set
            {
                this[AosWeaponAttribute.HitFireball] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLightning
        {
            get
            {
                return this[AosWeaponAttribute.HitLightning];
            }
            set
            {
                this[AosWeaponAttribute.HitLightning] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitDispel
        {
            get
            {
                return this[AosWeaponAttribute.HitDispel];
            }
            set
            {
                this[AosWeaponAttribute.HitDispel] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitColdArea
        {
            get
            {
                return this[AosWeaponAttribute.HitColdArea];
            }
            set
            {
                this[AosWeaponAttribute.HitColdArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitFireArea
        {
            get
            {
                return this[AosWeaponAttribute.HitFireArea];
            }
            set
            {
                this[AosWeaponAttribute.HitFireArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitPoisonArea
        {
            get
            {
                return this[AosWeaponAttribute.HitPoisonArea];
            }
            set
            {
                this[AosWeaponAttribute.HitPoisonArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitEnergyArea
        {
            get
            {
                return this[AosWeaponAttribute.HitEnergyArea];
            }
            set
            {
                this[AosWeaponAttribute.HitEnergyArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitPhysicalArea
        {
            get
            {
                return this[AosWeaponAttribute.HitPhysicalArea];
            }
            set
            {
                this[AosWeaponAttribute.HitPhysicalArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistPhysicalBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistPhysicalBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistPhysicalBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistFireBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistFireBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistFireBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistColdBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistColdBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistColdBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistPoisonBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistPoisonBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistPoisonBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistEnergyBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistEnergyBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistEnergyBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int UseBestSkill
        {
            get
            {
                return this[AosWeaponAttribute.UseBestSkill];
            }
            set
            {
                this[AosWeaponAttribute.UseBestSkill] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MageWeapon
        {
            get
            {
                return this[AosWeaponAttribute.MageWeapon];
            }
            set
            {
                this[AosWeaponAttribute.MageWeapon] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int DurabilityBonus
        {
            get
            {
                return this[AosWeaponAttribute.DurabilityBonus];
            }
            set
            {
                this[AosWeaponAttribute.DurabilityBonus] = value;
            }
        }

        #region SA
        [CommandProperty(AccessLevel.GameMaster)]
        public int BloodDrinker
        {
            get
            {
                return this[AosWeaponAttribute.BloodDrinker];
            }
            set
            {
                this[AosWeaponAttribute.BloodDrinker] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BattleLust
        {
            get
            {
                return this[AosWeaponAttribute.BattleLust];
            }
            set
            {
                this[AosWeaponAttribute.BattleLust] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitCurse
        {
            get
            {
                return this[AosWeaponAttribute.HitCurse];
            }
            set
            {
                this[AosWeaponAttribute.HitCurse] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitFatigue
        {
            get
            {
                return this[AosWeaponAttribute.HitFatigue];
            }
            set
            {
                this[AosWeaponAttribute.HitFatigue] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitManaDrain
        {
            get
            {
                return this[AosWeaponAttribute.HitManaDrain];
            }
            set
            {
                this[AosWeaponAttribute.HitManaDrain] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SplinteringWeapon
        {
            get
            {
                return this[AosWeaponAttribute.SplinteringWeapon];
            }
            set
            {
                this[AosWeaponAttribute.SplinteringWeapon] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ReactiveParalyze
        {
            get
            {
                return this[AosWeaponAttribute.ReactiveParalyze];
            }
            set
            {
                this[AosWeaponAttribute.ReactiveParalyze] = value;
            }
        }
        #endregion
    }

    [Flags]
    public enum ExtendedWeaponAttribute
    {
        BoneBreaker     = 0x00000001,
        HitSwarm        = 0x00000002,
        HitSparks       = 0x00000004,
        Bane            = 0x00000008,
        MysticWeapon    = 0x00000010,
        AssassinHoned   = 0x00000020,
        Focus           = 0x00000040,
        HitExplosion    = 0x00000080
    }

    public sealed class ExtendedWeaponAttributes : BaseAttributes
    {
        public ExtendedWeaponAttributes(Item owner)
            : base(owner)
        {
        }

        public ExtendedWeaponAttributes(Item owner, ExtendedWeaponAttributes other)
            : base(owner, other)
        {
        }

        public ExtendedWeaponAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public static int GetValue(Mobile m, ExtendedWeaponAttribute attribute)
        {
            if (!Core.AOS)
                return 0;

            int value = 0;

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                Item obj = m.Items[i];

                if (obj is BaseWeapon)
                {
                    ExtendedWeaponAttributes attrs = ((BaseWeapon)obj).ExtendedWeaponAttributes;

                    if (attrs != null)
                        value += attrs[attribute];
                }
            }

            return value;
        }

        public int this[ExtendedWeaponAttribute attribute]
        {
            get
            {
                return GetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BoneBreaker
        {
            get
            {
                return this[ExtendedWeaponAttribute.BoneBreaker];
            }
            set
            {
                this[ExtendedWeaponAttribute.BoneBreaker] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitSwarm
        {
            get
            {
                return this[ExtendedWeaponAttribute.HitSwarm];
            }
            set
            {
                this[ExtendedWeaponAttribute.HitSwarm] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitSparks
        {
            get
            {
                return this[ExtendedWeaponAttribute.HitSparks];
            }
            set
            {
                this[ExtendedWeaponAttribute.HitSparks] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Bane
        {
            get
            {
                return this[ExtendedWeaponAttribute.Bane];
            }
            set
            {
                this[ExtendedWeaponAttribute.Bane] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MysticWeapon
        {
            get
            {
                return this[ExtendedWeaponAttribute.MysticWeapon];
            }
            set
            {
                this[ExtendedWeaponAttribute.MysticWeapon] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int AssassinHoned
        {
            get
            {
                return this[ExtendedWeaponAttribute.AssassinHoned];
            }
            set
            {
                this[ExtendedWeaponAttribute.AssassinHoned] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Focus
        {
            get
            {
                return this[ExtendedWeaponAttribute.Focus];
            }
            set
            {
                this[ExtendedWeaponAttribute.Focus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitExplosion
        {
            get
            {
                return this[ExtendedWeaponAttribute.HitExplosion];
            }
            set
            {
                this[ExtendedWeaponAttribute.HitExplosion] = value;
            }
        }
    }

    [Flags]
    public enum AosArmorAttribute
    {
        LowerStatReq = 0x00000001,
        SelfRepair = 0x00000002,
        MageArmor = 0x00000004,
        DurabilityBonus = 0x00000008,
        #region Stygian Abyss
        ReactiveParalyze = 0x00000010,
        SoulCharge = 0x00000020
        #endregion
    }

    public sealed class AosArmorAttributes : BaseAttributes
    {
        public static bool IsValid(AosArmorAttribute attribute)
        {
            if (!Core.AOS)
            {
                return false;
            }

            if (!Core.SA && attribute >= AosArmorAttribute.ReactiveParalyze)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params AosArmorAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<AosArmorAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<AosArmorAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, AosArmorAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            for (int i = 0; i < m.Items.Count; ++i)
            {
                AosArmorAttributes attrs = RunicReforging.GetAosArmorAttributes(m.Items[i]);

                if (attrs != null)
                    value += attrs[attribute];
            }

            return value;
        }

        public override void SetValue(int bitmask, int value)
        {
            if (bitmask == (int)AosArmorAttribute.DurabilityBonus)
            {
                if (Owner is BaseArmor)
                {
                    ((BaseArmor)Owner).UnscaleDurability();
                }
                else if (Owner is BaseClothing)
                {
                    ((BaseClothing)Owner).UnscaleDurability();
                }
            }

            base.SetValue(bitmask, value);

            if (bitmask == (int)AosArmorAttribute.DurabilityBonus)
            {
                if (Owner is BaseArmor)
                {
                    ((BaseArmor)Owner).ScaleDurability();
                }
                else if (Owner is BaseClothing)
                {
                    ((BaseClothing)Owner).ScaleDurability();
                }
            }
        }

        public AosArmorAttributes(Item owner)
            : base(owner)
        {
        }

        public AosArmorAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public AosArmorAttributes(Item owner, AosArmorAttributes other)
            : base(owner, other)
        {
        }

        public int this[AosArmorAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerStatReq
        {
            get
            {
                return this[AosArmorAttribute.LowerStatReq];
            }
            set
            {
                this[AosArmorAttribute.LowerStatReq] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SelfRepair
        {
            get
            {
                return this[AosArmorAttribute.SelfRepair];
            }
            set
            {
                this[AosArmorAttribute.SelfRepair] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MageArmor
        {
            get
            {
                return this[AosArmorAttribute.MageArmor];
            }
            set
            {
                this[AosArmorAttribute.MageArmor] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int DurabilityBonus
        {
            get
            {
                return this[AosArmorAttribute.DurabilityBonus];
            }
            set
            {
                this[AosArmorAttribute.DurabilityBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ReactiveParalyze
        {
            get
            {
                return this[AosArmorAttribute.ReactiveParalyze];
            }
            set
            {
                this[AosArmorAttribute.ReactiveParalyze] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SoulCharge
        {
            get
            {
                return this[AosArmorAttribute.SoulCharge];
            }
            set
            {
                this[AosArmorAttribute.SoulCharge] = value;
            }
        }
    }

    public sealed class AosSkillBonuses : BaseAttributes
    {
        private List<SkillMod> m_Mods;

        public AosSkillBonuses(Item owner)
            : base(owner)
        {
        }

        public AosSkillBonuses(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public AosSkillBonuses(Item owner, AosSkillBonuses other)
            : base(owner, other)
        {
        }

        public static string SeparateCapitals(string msg)
        {
            StringBuilder builder = new StringBuilder();
            foreach (char c in msg)
            {
                if (Char.IsUpper(c) && builder.Length > 0) builder.Append(' ');
                builder.Append(c);
            }
            return msg = builder.ToString();
        }

        public void GetProperties(ObjectPropertyList list)
        {
            for (int i = 0; i < 60; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                list.Add(SeparateCapitals(skill.ToString()) + " +" + bonus.ToString());
            }
        }

        public static int GetLabel(SkillName skill)
        {
            switch (skill)
            {
                case SkillName.EvalInt:
                    return 1002070; // Evaluate Intelligence
                case SkillName.Forensics:
                    return 1002078; // Forensic Evaluation
                case SkillName.Lockpicking:
                    return 1002097; // Lockpicking
                default:
                    return 1044060 + (int)skill;
            }
        }

        public void AddTo(Mobile m)
        {
            if (Discordance.UnderPVPEffects(m))
            {
                return;
            }

            Remove();

            for (int i = 0; i < 60; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                if (m_Mods == null)
                    m_Mods = new List<SkillMod>();

                SkillMod sk = new DefaultSkillMod(skill, true, bonus);
                sk.ObeyCap = false;
                m.AddSkillMod(sk);
                m_Mods.Add(sk);
            }
        }

        public void Remove()
        {
            if (m_Mods == null)
                return;

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

                if (Core.ML)
                    CheckCancelMorph(m);
            }
            m_Mods = null;
        }

        public override void SetValue(int bitmask, int value)
        {
            base.SetValue(bitmask, value);

            if (Owner != null && Owner.Parent is Mobile)
            {
                Remove();
                AddTo((Mobile)Owner.Parent);
            }
        }

        public bool GetValues(int index, out SkillName skill, out double bonus)
        {
            int v = GetValue(1 << index);
            int vSkill = 0;
            int vBonus = 0;

            for (int i = 0; i < 16; ++i)
            {
                vSkill <<= 1;
                vSkill |= (v & 1);
                v >>= 1;

                vBonus <<= 1;
                vBonus |= (v & 1);
                v >>= 1;
            }

            skill = (SkillName)vSkill;
            bonus = (double)vBonus / 10;

            return (bonus != 0);
        }

        public void SetValues(int index, SkillName skill, double bonus)
        {
            int v = 0;
            int vSkill = (int)skill;
            int vBonus = (int)(bonus * 10);

            for (int i = 0; i < 16; ++i)
            {
                v <<= 1;
                v |= (vBonus & 1);
                vBonus >>= 1;

                v <<= 1;
                v |= (vSkill & 1);
                vSkill >>= 1;
            }

            SetValue(1 << index, v);
        }

        public SkillName GetSkill(int index)
        {
            SkillName skill;
            double bonus;

            GetValues(index, out skill, out bonus);

            return skill;
        }

        public void SetSkill(int index, SkillName skill)
        {
            SetValues(index, skill, GetBonus(index));
        }

        public double GetBonus(int index)
        {
            SkillName skill;
            double bonus;

            GetValues(index, out skill, out bonus);

            return bonus;
        }

        public void SetBonus(int index, double bonus)
        {
            SetValues(index, GetSkill(index), bonus);
        }

        public override string ToString()
        {
            return "...";
        }

        public void CheckCancelMorph(Mobile m)
        {
            if (m == null)
                return;

            double minSkill, maxSkill;

            AnimalFormContext acontext = AnimalForm.GetContext(m);
            TransformContext context = TransformationSpellHelper.GetContext(m);

            if (context != null)
            {
                Spell spell = context.Spell as Spell;
                spell.GetCastSkills(out minSkill, out maxSkill);

                if (m.Skills[spell.CastSkill].Value < minSkill)
                {
                    TransformationSpellHelper.RemoveContext(m, context, true);
                }
            }

            if (acontext != null)
            {
                if (acontext.Type == typeof(WildWhiteTiger) && m.Skills[SkillName.Ninjitsu].Value < 90)
                {
                    AnimalForm.RemoveContext(m, true);
                }
                else
                {
                    int i;

                    for (i = 0; i < AnimalForm.Entries.Length; ++i)
                    {
                        if (AnimalForm.Entries[i].Type == acontext.Type)
                            break;
                    }

                    if (i < AnimalForm.Entries.Length && m.Skills[SkillName.Ninjitsu].Value < AnimalForm.Entries[i].ReqSkill)
                    {
                        AnimalForm.RemoveContext(m, true);
                    }
                }
            }
            if (!m.CanBeginAction(typeof(PolymorphSpell)) && m.Skills[SkillName.Magery].Value < 66.1)
            {
                m.BodyMod = 0;
                m.HueMod = -1;
                m.NameMod = null;
                m.EndAction(typeof(PolymorphSpell));
                BaseArmor.ValidateMobile(m);
                BaseClothing.ValidateMobile(m);
            }
            if (!m.CanBeginAction(typeof(IncognitoSpell)) && m.Skills[SkillName.Magery].Value < 38.1)
            {
                if (m is PlayerMobile)
                    ((PlayerMobile)m).SetHairMods(-1, -1);
                m.BodyMod = 0;
                m.HueMod = -1;
                m.NameMod = null;
                m.EndAction(typeof(IncognitoSpell));
                BaseArmor.ValidateMobile(m);
                BaseClothing.ValidateMobile(m);
                BuffInfo.RemoveBuff(m, BuffIcon.Incognito);
            }
            return;
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_1_Value
        {
            get
            {
                return GetBonus(0);
            }
            set
            {
                SetBonus(0, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_1_Name
        {
            get
            {
                return GetSkill(0);
            }
            set
            {
                SetSkill(0, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_2_Value
        {
            get
            {
                return GetBonus(1);
            }
            set
            {
                SetBonus(1, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_2_Name
        {
            get
            {
                return GetSkill(1);
            }
            set
            {
                SetSkill(1, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_3_Value
        {
            get
            {
                return GetBonus(2);
            }
            set
            {
                SetBonus(2, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_3_Name
        {
            get
            {
                return GetSkill(2);
            }
            set
            {
                SetSkill(2, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_4_Value
        {
            get
            {
                return GetBonus(3);
            }
            set
            {
                SetBonus(3, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_4_Name
        {
            get
            {
                return GetSkill(3);
            }
            set
            {
                SetSkill(3, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_5_Value
        {
            get
            {
                return GetBonus(4);
            }
            set
            {
                SetBonus(4, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_5_Name
        {
            get
            {
                return GetSkill(4);
            }
            set
            {
                SetSkill(4, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_6_Value
        {
            get
            {
                return GetBonus(5);
            }
            set
            {
                SetBonus(5, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_6_Name
        {
            get
            {
                return GetSkill(5);
            }
            set
            {
                SetSkill(5, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_7_Value
        {
            get
            {
                return GetBonus(6);
            }
            set
            {
                SetBonus(6, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_7_Name
        {
            get
            {
                return GetSkill(6);
            }
            set
            {
                SetSkill(6, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_8_Value
        {
            get
            {
                return GetBonus(7);
            }
            set
            {
                SetBonus(7, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_8_Name
        {
            get
            {
                return GetSkill(7);
            }
            set
            {
                SetSkill(7, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_9_Value
        {
            get
            {
                return GetBonus(8);
            }
            set
            {
                SetBonus(8, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_9_Name
        {
            get
            {
                return GetSkill(8);
            }
            set
            {
                SetSkill(8, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_10_Value
        {
            get
            {
                return GetBonus(9);
            }
            set
            {
                SetBonus(9, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_10_Name
        {
            get
            {
                return GetSkill(9);
            }
            set
            {
                SetSkill(9, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_11_Value
        {
            get
            {
                return GetBonus(10);
            }
            set
            {
                SetBonus(10, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_11_Name
        {
            get
            {
                return GetSkill(10);
            }
            set
            {
                SetSkill(10, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_12_Value
        {
            get
            {
                return GetBonus(11);
            }
            set
            {
                SetBonus(11, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_12_Name
        {
            get
            {
                return GetSkill(11);
            }
            set
            {
                SetSkill(11, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_13_Value
        {
            get
            {
                return GetBonus(12);
            }
            set
            {
                SetBonus(12, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_13_Name
        {
            get
            {
                return GetSkill(12);
            }
            set
            {
                SetSkill(12, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_14_Value
        {
            get
            {
                return GetBonus(13);
            }
            set
            {
                SetBonus(13, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_14_Name
        {
            get
            {
                return GetSkill(13);
            }
            set
            {
                SetSkill(13, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_15_Value
        {
            get
            {
                return GetBonus(14);
            }
            set
            {
                SetBonus(14, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_15_Name
        {
            get
            {
                return GetSkill(14);
            }
            set
            {
                SetSkill(14, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_16_Value
        {
            get
            {
                return GetBonus(15);
            }
            set
            {
                SetBonus(15, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_16_Name
        {
            get
            {
                return GetSkill(15);
            }
            set
            {
                SetSkill(15, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_17_Value
        {
            get
            {
                return GetBonus(16);
            }
            set
            {
                SetBonus(16, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_17_Name
        {
            get
            {
                return GetSkill(16);
            }
            set
            {
                SetSkill(16, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_18_Value
        {
            get
            {
                return GetBonus(17);
            }
            set
            {
                SetBonus(17, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_18_Name
        {
            get
            {
                return GetSkill(17);
            }
            set
            {
                SetSkill(17, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_19_Value
        {
            get
            {
                return GetBonus(18);
            }
            set
            {
                SetBonus(18, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_19_Name
        {
            get
            {
                return GetSkill(18);
            }
            set
            {
                SetSkill(18, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_20_Value
        {
            get
            {
                return GetBonus(19);
            }
            set
            {
                SetBonus(19, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_20_Name
        {
            get
            {
                return GetSkill(19);
            }
            set
            {
                SetSkill(19, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_21_Value
        {
            get
            {
                return GetBonus(20);
            }
            set
            {
                SetBonus(20, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_21_Name
        {
            get
            {
                return GetSkill(20);
            }
            set
            {
                SetSkill(20, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_22_Value
        {
            get
            {
                return GetBonus(21);
            }
            set
            {
                SetBonus(21, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_22_Name
        {
            get
            {
                return GetSkill(21);
            }
            set
            {
                SetSkill(21, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_23_Value
        {
            get
            {
                return GetBonus(22);
            }
            set
            {
                SetBonus(22, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_23_Name
        {
            get
            {
                return GetSkill(22);
            }
            set
            {
                SetSkill(22, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_24_Value
        {
            get
            {
                return GetBonus(23);
            }
            set
            {
                SetBonus(23, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_24_Name
        {
            get
            {
                return GetSkill(23);
            }
            set
            {
                SetSkill(23, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_25_Value
        {
            get
            {
                return GetBonus(24);
            }
            set
            {
                SetBonus(24, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_25_Name
        {
            get
            {
                return GetSkill(24);
            }
            set
            {
                SetSkill(24, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_26_Value
        {
            get
            {
                return GetBonus(25);
            }
            set
            {
                SetBonus(25, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_26_Name
        {
            get
            {
                return GetSkill(25);
            }
            set
            {
                SetSkill(25, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_27_Value
        {
            get
            {
                return GetBonus(26);
            }
            set
            {
                SetBonus(26, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_27_Name
        {
            get
            {
                return GetSkill(26);
            }
            set
            {
                SetSkill(26, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_28_Value
        {
            get
            {
                return GetBonus(27);
            }
            set
            {
                SetBonus(27, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_28_Name
        {
            get
            {
                return GetSkill(27);
            }
            set
            {
                SetSkill(27, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_29_Value
        {
            get
            {
                return GetBonus(28);
            }
            set
            {
                SetBonus(28, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_29_Name
        {
            get
            {
                return GetSkill(28);
            }
            set
            {
                SetSkill(28, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_30_Value
        {
            get
            {
                return GetBonus(29);
            }
            set
            {
                SetBonus(29, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_30_Name
        {
            get
            {
                return GetSkill(29);
            }
            set
            {
                SetSkill(29, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_31_Value
        {
            get
            {
                return GetBonus(30);
            }
            set
            {
                SetBonus(30, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_31_Name
        {
            get
            {
                return GetSkill(30);
            }
            set
            {
                SetSkill(30, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_32_Value
        {
            get
            {
                return GetBonus(31);
            }
            set
            {
                SetBonus(31, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_32_Name
        {
            get
            {
                return GetSkill(31);
            }
            set
            {
                SetSkill(31, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_33_Value
        {
            get
            {
                return GetBonus(32);
            }
            set
            {
                SetBonus(32, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_33_Name
        {
            get
            {
                return GetSkill(32);
            }
            set
            {
                SetSkill(32, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_34_Value
        {
            get
            {
                return GetBonus(33);
            }
            set
            {
                SetBonus(33, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_34_Name
        {
            get
            {
                return GetSkill(33);
            }
            set
            {
                SetSkill(33, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_35_Value
        {
            get
            {
                return GetBonus(34);
            }
            set
            {
                SetBonus(34, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_35_Name
        {
            get
            {
                return GetSkill(34);
            }
            set
            {
                SetSkill(34, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_36_Value
        {
            get
            {
                return GetBonus(35);
            }
            set
            {
                SetBonus(35, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_36_Name
        {
            get
            {
                return GetSkill(35);
            }
            set
            {
                SetSkill(35, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_37_Value
        {
            get
            {
                return GetBonus(36);
            }
            set
            {
                SetBonus(36, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_37_Name
        {
            get
            {
                return GetSkill(36);
            }
            set
            {
                SetSkill(36, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_38_Value
        {
            get
            {
                return GetBonus(37);
            }
            set
            {
                SetBonus(37, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_38_Name
        {
            get
            {
                return GetSkill(37);
            }
            set
            {
                SetSkill(37, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_39_Value
        {
            get
            {
                return GetBonus(38);
            }
            set
            {
                SetBonus(38, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_39_Name
        {
            get
            {
                return GetSkill(38);
            }
            set
            {
                SetSkill(38, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_40_Value
        {
            get
            {
                return GetBonus(39);
            }
            set
            {
                SetBonus(39, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_40_Name
        {
            get
            {
                return GetSkill(39);
            }
            set
            {
                SetSkill(39, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_41_Value
        {
            get
            {
                return GetBonus(40);
            }
            set
            {
                SetBonus(40, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_41_Name
        {
            get
            {
                return GetSkill(40);
            }
            set
            {
                SetSkill(40, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_42_Value
        {
            get
            {
                return GetBonus(41);
            }
            set
            {
                SetBonus(41, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_42_Name
        {
            get
            {
                return GetSkill(41);
            }
            set
            {
                SetSkill(41, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_43_Value
        {
            get
            {
                return GetBonus(42);
            }
            set
            {
                SetBonus(42, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_43_Name
        {
            get
            {
                return GetSkill(42);
            }
            set
            {
                SetSkill(42, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_44_Value
        {
            get
            {
                return GetBonus(43);
            }
            set
            {
                SetBonus(43, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_44_Name
        {
            get
            {
                return GetSkill(43);
            }
            set
            {
                SetSkill(43, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_45_Value
        {
            get
            {
                return GetBonus(44);
            }
            set
            {
                SetBonus(44, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_45_Name
        {
            get
            {
                return GetSkill(44);
            }
            set
            {
                SetSkill(44, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_46_Value
        {
            get
            {
                return GetBonus(45);
            }
            set
            {
                SetBonus(45, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_46_Name
        {
            get
            {
                return GetSkill(45);
            }
            set
            {
                SetSkill(45, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_47_Value
        {
            get
            {
                return GetBonus(46);
            }
            set
            {
                SetBonus(46, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_47_Name
        {
            get
            {
                return GetSkill(46);
            }
            set
            {
                SetSkill(46, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_48_Value
        {
            get
            {
                return GetBonus(47);
            }
            set
            {
                SetBonus(47, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_48_Name
        {
            get
            {
                return GetSkill(47);
            }
            set
            {
                SetSkill(47, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_49_Value
        {
            get
            {
                return GetBonus(48);
            }
            set
            {
                SetBonus(48, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_49_Name
        {
            get
            {
                return GetSkill(48);
            }
            set
            {
                SetSkill(48, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_50_Value
        {
            get
            {
                return GetBonus(49);
            }
            set
            {
                SetBonus(49, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_50_Name
        {
            get
            {
                return GetSkill(49);
            }
            set
            {
                SetSkill(49, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_51_Value
        {
            get
            {
                return GetBonus(50);
            }
            set
            {
                SetBonus(50, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_51_Name
        {
            get
            {
                return GetSkill(50);
            }
            set
            {
                SetSkill(50, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_52_Value
        {
            get
            {
                return GetBonus(51);
            }
            set
            {
                SetBonus(51, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_52_Name
        {
            get
            {
                return GetSkill(51);
            }
            set
            {
                SetSkill(51, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_53_Value
        {
            get
            {
                return GetBonus(52);
            }
            set
            {
                SetBonus(52, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_53_Name
        {
            get
            {
                return GetSkill(52);
            }
            set
            {
                SetSkill(52, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_54_Value
        {
            get
            {
                return GetBonus(53);
            }
            set
            {
                SetBonus(53, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_54_Name
        {
            get
            {
                return GetSkill(53);
            }
            set
            {
                SetSkill(53, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_55_Value
        {
            get
            {
                return GetBonus(54);
            }
            set
            {
                SetBonus(54, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_55_Name
        {
            get
            {
                return GetSkill(54);
            }
            set
            {
                SetSkill(54, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_56_Value
        {
            get
            {
                return GetBonus(55);
            }
            set
            {
                SetBonus(55, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_56_Name
        {
            get
            {
                return GetSkill(55);
            }
            set
            {
                SetSkill(55, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_57_Value
        {
            get
            {
                return GetBonus(56);
            }
            set
            {
                SetBonus(56, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_57_Name
        {
            get
            {
                return GetSkill(56);
            }
            set
            {
                SetSkill(56, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_58_Value
        {
            get
            {
                return GetBonus(57);
            }
            set
            {
                SetBonus(57, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_58_Name
        {
            get
            {
                return GetSkill(57);
            }
            set
            {
                SetSkill(57, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_59_Value
        {
            get
            {
                return GetBonus(58);
            }
            set
            {
                SetBonus(58, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_59_Name
        {
            get
            {
                return GetSkill(58);
            }
            set
            {
                SetSkill(58, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_60_Value
        {
            get
            {
                return GetBonus(59);
            }
            set
            {
                SetBonus(59, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_60_Name
        {
            get
            {
                return GetSkill(59);
            }
            set
            {
                SetSkill(59, value);
            }
        }

    }

    #region Stygian Abyss
    [Flags]
    public enum SAAbsorptionAttribute
    {
        EaterFire = 0x00000001,
        EaterCold = 0x00000002,
        EaterPoison = 0x00000004,
        EaterEnergy = 0x00000008,
        EaterKinetic = 0x00000010,
        EaterDamage = 0x00000020,
        ResonanceFire = 0x00000040,
        ResonanceCold = 0x00000080,
        ResonancePoison = 0x00000100,
        ResonanceEnergy = 0x00000200,
        ResonanceKinetic = 0x00000400,
        /*Soul Charge is wrong.
         * Do not use these types.
         * Use AosArmorAttribute type only.
         * Fill these in with any new attributes.*/
        SoulChargeFire = 0x00000800,
        SoulChargeCold = 0x00001000,
        SoulChargePoison = 0x00002000,
        SoulChargeEnergy = 0x00004000,
        SoulChargeKinetic = 0x00008000,
        CastingFocus = 0x00010000
    }

    public sealed class SAAbsorptionAttributes : BaseAttributes
    {
        public static bool IsValid(SAAbsorptionAttribute attribute)
        {
            if (!Core.SA)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params SAAbsorptionAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<SAAbsorptionAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<SAAbsorptionAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, SAAbsorptionAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                SAAbsorptionAttributes attrs = RunicReforging.GetSAAbsorptionAttributes(m.Items[i]);

                if (attrs != null)
                    value += attrs[attribute];
            }

            value += SkillMasterySpell.GetAttributeBonus(m, attribute);

            return value;
        }

        public SAAbsorptionAttributes(Item owner)
            : base(owner)
        {
        }

        public SAAbsorptionAttributes(Item owner, SAAbsorptionAttributes other)
            : base(owner, other)
        {
        }

        public SAAbsorptionAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public int this[SAAbsorptionAttribute attribute]
        {
            get
            {
                return GetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterFire
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterFire];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterFire] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterCold
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterCold];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterCold] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterPoison
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterPoison];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterPoison] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterEnergy
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterEnergy];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterEnergy] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterKinetic
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterKinetic];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterKinetic] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterDamage
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterDamage];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterDamage] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceFire
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceFire];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceFire] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceCold
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceCold];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceCold] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonancePoison
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonancePoison];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonancePoison] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceEnergy
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceEnergy];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceEnergy] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceKinetic
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceKinetic];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceKinetic] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeFire
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeFire];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeFire] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeCold
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeCold];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeCold] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargePoison
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargePoison];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargePoison] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeEnergy
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeEnergy];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeEnergy] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeKinetic
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeKinetic];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeKinetic] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int CastingFocus
        {
            get
            {
                return this[SAAbsorptionAttribute.CastingFocus];
            }
            set
            {
                this[SAAbsorptionAttribute.CastingFocus] = value;
            }
        }
    }
    #endregion

    [Flags]
    public enum AosElementAttribute
    {
        Physical = 0x00000001,
        Fire = 0x00000002,
        Cold = 0x00000004,
        Poison = 0x00000008,
        Energy = 0x00000010,
        Chaos = 0x00000020,
        Direct = 0x00000040
    }

    public sealed class AosElementAttributes : BaseAttributes
    {
        public AosElementAttributes(Item owner)
            : base(owner)
        {
        }

        public AosElementAttributes(Item owner, AosElementAttributes other)
            : base(owner, other)
        {
        }

        public AosElementAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public int this[AosElementAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Physical
        {
            get
            {
                return this[AosElementAttribute.Physical];
            }
            set
            {
                this[AosElementAttribute.Physical] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Fire
        {
            get
            {
                return this[AosElementAttribute.Fire];
            }
            set
            {
                this[AosElementAttribute.Fire] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Cold
        {
            get
            {
                return this[AosElementAttribute.Cold];
            }
            set
            {
                this[AosElementAttribute.Cold] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Poison
        {
            get
            {
                return this[AosElementAttribute.Poison];
            }
            set
            {
                this[AosElementAttribute.Poison] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Energy
        {
            get
            {
                return this[AosElementAttribute.Energy];
            }
            set
            {
                this[AosElementAttribute.Energy] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Chaos
        {
            get
            {
                return this[AosElementAttribute.Chaos];
            }
            set
            {
                this[AosElementAttribute.Chaos] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Direct
        {
            get
            {
                return this[AosElementAttribute.Direct];
            }
            set
            {
                this[AosElementAttribute.Direct] = value;
            }
        }
    }

    [Flags]
    public enum NegativeAttribute
    {
        Brittle = 0x00000001,
        Prized = 0x00000002,
        Massive = 0x00000004,
        Unwieldly = 0x00000008,
        Antique = 0x00000010,
        NoRepair = 0x00000020
    }

    public sealed class NegativeAttributes : BaseAttributes
    {
        public NegativeAttributes(Item owner)
            : base(owner)
        {
        }

        public NegativeAttributes(Item owner, NegativeAttributes other)
            : base(owner, other)
        {
        }

        public NegativeAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public void GetProperties(ObjectPropertyList list, Item item)
        {
            if (NoRepair > 0)
                list.Add(1151782);

            if (Brittle > 0 ||
                item is BaseWeapon && ((BaseWeapon)item).Attributes.Brittle > 0 ||
                item is BaseArmor && ((BaseArmor)item).Attributes.Brittle > 0 ||
                item is BaseJewel && ((BaseJewel)item).Attributes.Brittle > 0 ||
                item is BaseClothing && ((BaseClothing)item).Attributes.Brittle > 0)
                list.Add(1116209);

            if (Prized > 0)
                list.Add(1154910);

            //if (Massive > 0)
            //    list.Add(1038003);

            //if (Unwieldly > 0)
            //    list.Add(1154909);

            if (Antique > 0)
                list.Add(1076187);
        }

        public const double CombatDecayChance = 0.02;

        public static void OnCombatAction(Mobile m)
        {
            if (m == null || !m.Alive)
                return;

            var list = new List<Item>();

            foreach (var item in m.Items.Where(i => i is IDurability))
            {
                NegativeAttributes attrs = RunicReforging.GetNegativeAttributes(item);

                if (attrs != null && attrs.Antique > 0 && CombatDecayChance > Utility.RandomDouble())
                {
                    list.Add(item);
                }
            }

            foreach (var item in list)
            {
                IDurability dur = item as IDurability;

                if (dur == null)
                    continue;

                if (dur.HitPoints >= 1)
                {
                    if (dur.HitPoints >= 4)
                    {
                        dur.HitPoints -= 4;
                    }
                    else
                    {
                        dur.HitPoints = 0;
                    }
                }
                else
                {
                    if (dur.MaxHitPoints > 1)
                    {
                        dur.MaxHitPoints--;

                        if (item.Parent is Mobile)
                            ((Mobile)item.Parent).LocalOverheadMessage(Server.Network.MessageType.Regular, 0x3B2, 1061121); // Your equipment is severely damaged.
                    }
                    else
                    {
                        item.Delete();
                    }
                }
            }

            ColUtility.Free(list);
        }

        public int this[NegativeAttribute attribute]
        {
            get { return GetValue((int)attribute); }
            set { SetValue((int)attribute, value); }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Brittle { get { return this[NegativeAttribute.Brittle]; } set { this[NegativeAttribute.Brittle] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Prized { get { return this[NegativeAttribute.Prized]; } set { this[NegativeAttribute.Prized] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Massive { get { return this[NegativeAttribute.Massive]; } set { this[NegativeAttribute.Massive] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Unwieldly { get { return this[NegativeAttribute.Unwieldly]; } set { this[NegativeAttribute.Unwieldly] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Antique { get { return this[NegativeAttribute.Antique]; } set { this[NegativeAttribute.Antique] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int NoRepair { get { return this[NegativeAttribute.NoRepair]; } set { this[NegativeAttribute.NoRepair] = value; } }
    }

    [PropertyObject]
    public abstract class BaseAttributes
    {
        private readonly Item m_Owner;
        private uint m_Names;
        private int[] m_Values;

        private static readonly int[] m_Empty = new int[0];

        public bool IsEmpty
        {
            get
            {
                return (m_Names == 0);
            }
        }
        public Item Owner
        {
            get
            {
                return m_Owner;
            }
        }

        public BaseAttributes(Item owner)
        {
            m_Owner = owner;
            m_Values = m_Empty;
        }

        public BaseAttributes(Item owner, BaseAttributes other)
        {
            m_Owner = owner;
            m_Values = new int[other.m_Values.Length];
            other.m_Values.CopyTo(m_Values, 0);
            m_Names = other.m_Names;
        }

        public BaseAttributes(Item owner, GenericReader reader)
        {
            m_Owner = owner;

            int version = reader.ReadByte();

            switch (version)
            {
                case 1:
                    {
                        m_Names = reader.ReadUInt();
                        m_Values = new int[reader.ReadEncodedInt()];

                        for (int i = 0; i < m_Values.Length; ++i)
                            m_Values[i] = reader.ReadEncodedInt();

                        break;
                    }
                case 0:
                    {
                        m_Names = reader.ReadUInt();
                        m_Values = new int[reader.ReadInt()];

                        for (int i = 0; i < m_Values.Length; ++i)
                            m_Values[i] = reader.ReadInt();

                        break;
                    }
            }
        }

        public void Serialize(GenericWriter writer)
        {
            writer.Write((byte)1); // version;

            writer.Write((uint)m_Names);
            writer.WriteEncodedInt((int)m_Values.Length);

            for (int i = 0; i < m_Values.Length; ++i)
                writer.WriteEncodedInt((int)m_Values[i]);
        }

        public int GetValue(int bitmask)
        {
            if (!Core.AOS)
                return 0;

            uint mask = (uint)bitmask;

            if ((m_Names & mask) == 0)
                return 0;

            int index = GetIndex(mask);

            if (index >= 0 && index < m_Values.Length)
                return m_Values[index];

            return 0;
        }

        public virtual void SetValue(int bitmask, int value)
        {
            uint mask = (uint)bitmask;

            if (value != 0)
            {
                if ((m_Names & mask) != 0)
                {
                    int index = GetIndex(mask);

                    if (index >= 0 && index < m_Values.Length)
                        m_Values[index] = value;
                }
                else
                {
                    int index = GetIndex(mask);

                    if (index >= 0 && index <= m_Values.Length)
                    {
                        int[] old = m_Values;
                        m_Values = new int[old.Length + 1];

                        for (int i = 0; i < index; ++i)
                            m_Values[i] = old[i];

                        m_Values[index] = value;

                        for (int i = index; i < old.Length; ++i)
                            m_Values[i + 1] = old[i];

                        m_Names |= mask;
                    }
                }
            }
            else if ((m_Names & mask) != 0)
            {
                int index = GetIndex(mask);

                if (index >= 0 && index < m_Values.Length)
                {
                    m_Names &= ~mask;

                    if (m_Values.Length == 1)
                    {
                        m_Values = m_Empty;
                    }
                    else
                    {
                        int[] old = m_Values;
                        m_Values = new int[old.Length - 1];

                        for (int i = 0; i < index; ++i)
                            m_Values[i] = old[i];

                        for (int i = index + 1; i < old.Length; ++i)
                            m_Values[i - 1] = old[i];
                    }
                }
            }

            if (m_Owner != null && m_Owner.Parent is Mobile)
            {
                Mobile m = (Mobile)m_Owner.Parent;

                m.CheckStatTimers();
                m.UpdateResistances();
                m.Delta(MobileDelta.Stat | MobileDelta.WeaponDamage | MobileDelta.Hits | MobileDelta.Stam | MobileDelta.Mana);
            }

            if (m_Owner != null)
                m_Owner.InvalidateProperties();
        }

        private int GetIndex(uint mask)
        {
            int index = 0;
            uint ourNames = m_Names;
            uint currentBit = 1;

            while (currentBit != mask)
            {
                if ((ourNames & currentBit) != 0)
                    ++index;

                if (currentBit == 0x80000000)
                    return -1;

                currentBit <<= 1;
            }

            return index;
        }
    }
}

**EDIT**
It doesn't like the 30's for some reason.. yeah it desn't like anything more than around 30 then it starts to duplicate in the 30ish range a little into the 40's and then it's normal again.. weird..
1652921359634.png
 
Last edited:
Hmm I think I may have done something wrong lol, ignore the fact that I made it 60 :) but it lists the whole list twice.. looking it over now but was just curious if you see anything wrong.

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Server.Engines.SphynxFortune;
using Server.Engines.XmlSpawner2;
using Server.Items;
using Server.Misc;
using Server.Mobiles;
using Server.Spells;
using Server.Spells.Second;
using Server.Spells.Fifth;
using Server.Spells.Bushido;
using Server.Spells.Ninjitsu;
using Server.Spells.Seventh;
using Server.Spells.Chivalry;
using Server.Spells.Necromancy;
using Server.Spells.Spellweaving;
using Server.SkillHandlers;
using Server.Engines.CityLoyalty;
using Server.Services.Virtues;
using Server.Spells.SkillMasteries;

namespace Server
{
    public enum DamageType
    {
        Melee,
        Ranged,
        Spell,
        SpellAOE
    }

    public class AOS
    {
        public static void DisableStatInfluences()
        {
            for (int i = 0; i < SkillInfo.Table.Length; ++i)
            {
                SkillInfo info = SkillInfo.Table[i];

                info.StrScale = 0.0;
                info.DexScale = 0.0;
                info.IntScale = 0.0;
                info.StatTotal = 0.0;
            }
        }

        public static int Damage(IDamageable m, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, null, damage, ignoreArmor, phys, fire, cold, pois, nrgy);
        }

        public static int Damage(IDamageable m, int damage, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, null, damage, phys, fire, cold, pois, nrgy);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, 0, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy)
        {
            return Damage(m, from, damage, ignoreArmor, phys, fire, cold, pois, nrgy, 0, 0, false);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, bool keepAlive)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, keepAlive);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, bool keepAlive, bool archer, bool deathStrike)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, keepAlive, archer ? DamageType.Ranged : DamageType.Melee); // old deathStrike damage, kept for compatibility
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, DamageType type)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, false, type);
        }

        public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, DamageType type)
        {
            return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, false, type);
        }

        public static int Damage(IDamageable damageable, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, bool keepAlive, DamageType type = DamageType.Melee)
        {
            Mobile m = damageable as Mobile;

            #region Iomega0318 Player Damage Cap for Pets, Prevent use in PvP
            if (damageable is PlayerMobile && from is BaseCreature && ((BaseCreature)from).Controlled)
            {
                damage = Math.Min(damage, 40); // Pet Dmg Cap to players
                phys = Math.Min(phys, 40); // Pet phys Cap to players
                fire = Math.Min(fire, 40); // Pet fire Cap to players
                cold = Math.Min(cold, 40); // Pet cold Cap to players
                pois = Math.Min(pois, 40); // Pet pois Cap to players
                nrgy = Math.Min(nrgy, 40); // Pet nrgy Cap to players
                chaos = Math.Min(chaos, 40); // Pet chaos Cap to players
                direct = Math.Min(direct, 40); // Pet direct Cap to players
            }
            #endregion

            if (damageable == null || damageable.Deleted || !damageable.Alive || damage <= 0)
                return 0;

            if (m != null && phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0)
                Mobiles.MeerMage.StopEffect(m, true);

            if (!Core.AOS)
            {
                if(m != null)
                    m.Damage(damage, from);

                return damage;
            }

            #region Mondain's Legacy
            if (m != null)
            {
                m.Items.ForEach(i =>
                {
                    ITalismanProtection prot = i as ITalismanProtection;

                    if (prot != null)
                        damage = prot.Protection.ScaleDamage(from, damage);
                });
            }
            #endregion

            Fix(ref phys);
            Fix(ref fire);
            Fix(ref cold);
            Fix(ref pois);
            Fix(ref nrgy);
            Fix(ref chaos);
            Fix(ref direct);

            if (Core.ML && chaos > 0)
            {
                switch (Utility.Random(5))
                {
                    case 0:
                        phys += chaos;
                        break;
                    case 1:
                        fire += chaos;
                        break;
                    case 2:
                        cold += chaos;
                        break;
                    case 3:
                        pois += chaos;
                        break;
                    case 4:
                        nrgy += chaos;
                        break;
                }
            }

            bool ranged = type == DamageType.Ranged;
            BaseQuiver quiver = null;

            if (ranged && from.Race != Race.Gargoyle)
                quiver = from.FindItemOnLayer(Layer.Cloak) as BaseQuiver;

            int totalDamage;

            if (!ignoreArmor)
            {
                int physDamage = damage * phys * (100 - damageable.PhysicalResistance);
                int fireDamage = damage * fire * (100 - damageable.FireResistance);
                int coldDamage = damage * cold * (100 - damageable.ColdResistance);
                int poisonDamage = damage * pois * (100 - damageable.PoisonResistance);
                int energyDamage = damage * nrgy * (100 - damageable.EnergyResistance);

                totalDamage = physDamage + fireDamage + coldDamage + poisonDamage + energyDamage;
                totalDamage /= 10000;

                if (Core.ML)
                {
                    totalDamage += damage * direct / 100;

                    if (quiver != null)
                        totalDamage += totalDamage * quiver.DamageIncrease / 100;
                }

                if (m != null)
                    BaseFishPie.ScaleDamage(from, m, ref totalDamage, phys, fire, cold, pois, nrgy, direct);

                if (Core.HS && ArmorPierce.IsUnderEffects(m))
                {
                    totalDamage += (int)((double)totalDamage * .1);
                }

                if (totalDamage < 1)
                    totalDamage = 1;        
            }
            else if (Core.ML && m is PlayerMobile)
            {
                if (quiver != null)
                    damage += damage * quiver.DamageIncrease / 100;

                totalDamage = Math.Min(damage, Core.TOL && ranged ? 30 : 35);    // Direct Damage cap of 30/35
            }
            else
            {
                totalDamage = damage;

                if (Core.ML && quiver != null)
                    totalDamage += totalDamage * quiver.DamageIncrease / 100;
            }

            // object being damaged is not a mobile, so we will end here
            if (damageable is Item)
            {
                return damageable.Damage(totalDamage, from);
            }

            #region Evil Omen, Blood Oath and reflect physical
            if (EvilOmenSpell.TryEndEffect(m))
            {
                totalDamage = (int)(totalDamage * 1.25);
            }

            if (from != null && !from.Deleted && from.Alive && !from.IsDeadBondedPet)
            {
                Mobile oath = BloodOathSpell.GetBloodOath(from);

                /* Per EA's UO Herald Pub48 (ML):
                * ((resist spellsx10)/20 + 10=percentage of damage resisted)
                *
                * Tested 12/29/2017-
                * No cap, also, above forumula is only in effect vs. creatures
                */

                if (oath == m)
                {
                    int originalDamage = totalDamage;
                    totalDamage = (int)(totalDamage * 1.2);

                    if (!Core.TOL && totalDamage > 35 && from is PlayerMobile) /* capped @ 35, seems no expansion */
                    {
                        totalDamage = 35;
                    }

                    if (Core.ML && m is BaseCreature)
                    {
                        from.Damage((int)(originalDamage * (1 - (((from.Skills.MagicResist.Value * .5) + 10) / 100))), m);
                    }
                    else
                    {
                        from.Damage(originalDamage, m);
                    }
                }
                else if (!ignoreArmor && from != m)
                {
                    int reflectPhys = Math.Min(105, AosAttributes.GetValue(m, AosAttribute.ReflectPhysical));

                    if (reflectPhys != 0)
                    {
                        if (from is ExodusMinion && ((ExodusMinion)from).FieldActive || from is ExodusOverseer && ((ExodusOverseer)from).FieldActive)
                        {
                            from.FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist);
                            from.PlaySound(0x2F4);
                            m.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier");
                        }
                        else
                        {
                            from.Damage(Scale((damage * phys * (100 - (ignoreArmor ? 0 : m.PhysicalResistance))) / 10000, reflectPhys), m);
                        }
                    }
                }
            }
            #endregion

            #region Stygian Abyss
            //SHould this go in after or before dragon barding absorb?
            if (ignoreArmor)
                DamageEaterContext.CheckDamage(m, totalDamage, 0, 0, 0, 0, 0, 100);
            else
                DamageEaterContext.CheckDamage(m, totalDamage, phys, fire, cold, pois, nrgy, direct);

            if (fire > 0 && totalDamage > 0)
                SwarmContext.CheckRemove(m);
            #endregion

            SpiritualityVirtue.GetDamageReduction(m, ref totalDamage);

            #region Berserk
            BestialSetHelper.OnDamage(m, from, ref totalDamage);
            #endregion

            #region Epiphany Set
            EpiphanyHelper.OnHit(m, totalDamage);
            #endregion

            if (type == DamageType.Spell && m != null && Feint.Registry.ContainsKey(m) && Feint.Registry[m].Enemy == from)
                totalDamage -= (int)((double)damage * ((double)Feint.Registry[m].DamageReduction / 100));

            if (m.Hidden && Core.ML && type >= DamageType.Spell)
            {
                int chance = (int)Math.Min(33, 100 - (Server.Spells.SkillMasteries.ShadowSpell.GetDifficultyFactor(m) * 100));

                if (Utility.Random(100) < chance)
                {
                    m.RevealingAction();
                    m.NextSkillTime = Core.TickCount + (12000 - ((int)m.Skills[SkillName.Hiding].Value) * 100);
                }
            }

            #region Skill Mastery
            SkillMasterySpell.OnDamage(m, from, type, ref totalDamage);
            #endregion

            #region Pet Training
            if (from is BaseCreature || m is BaseCreature)
            {
                SpecialAbility.CheckCombatTrigger(from, m, ref totalDamage, type);

                if (PetTrainingHelper.Enabled)
                {
                    if (from is BaseCreature && m is BaseCreature)
                    {
                        var profile = PetTrainingHelper.GetTrainingProfile((BaseCreature)from);

                        if (profile != null)
                        {
                            profile.CheckProgress((BaseCreature)m);
                        }

                        profile = PetTrainingHelper.GetTrainingProfile((BaseCreature)m);

                        if (profile != null && 0.3 > Utility.RandomDouble())
                        {
                            profile.CheckProgress((BaseCreature)from);
                        }
                    }

                    if (from is BaseCreature && ((BaseCreature)from).Controlled && m.Player)
                    {
                        totalDamage /= 2;
                    }
                }
            }
            #endregion

            if (type <= DamageType.Ranged)
            {
                AttuneWeaponSpell.TryAbsorb(m, ref totalDamage);
            }

            if (keepAlive && totalDamage > m.Hits)
            {
                totalDamage = m.Hits;
            }

            if (from is BaseCreature && type <= DamageType.Ranged)
            {
                ((BaseCreature)from).AlterMeleeDamageTo(m, ref totalDamage);
            }

            if (m is BaseCreature && type <= DamageType.Ranged)
            {
                ((BaseCreature)m).AlterMeleeDamageFrom(from, ref totalDamage);
            }

            if (m is BaseCreature)
            {
                ((BaseCreature)m).OnBeforeDamage(from, ref totalDamage, type);
            }

            if (totalDamage <= 0)
            {
                return 0;
            }

            if (from != null)
            {
                DoLeech(totalDamage, from, m);
            }

            totalDamage = m.Damage(totalDamage, from, true, false);

            if (Core.SA && type == DamageType.Melee && from is BaseCreature &&
                (m is PlayerMobile || (m is BaseCreature && !((BaseCreature)m).IsMonster)))
            {
                from.RegisterDamage(totalDamage / 4, m);
            }

            SpiritSpeak.CheckDisrupt(m);

            #region Stygian Abyss
            if (m.Spell != null)
                ((Spell)m.Spell).CheckCasterDisruption(true, phys, fire, cold, pois, nrgy);

            BattleLust.IncreaseBattleLust(m, totalDamage);

            if (ManaPhasingOrb.IsInManaPhase(m))
                ManaPhasingOrb.RemoveFromTable(m);

            SoulChargeContext.CheckHit(from, m, totalDamage);

            Spells.Mysticism.SleepSpell.OnDamage(m);
            Spells.Mysticism.PurgeMagicSpell.OnMobileDoDamage(from);
            #endregion

            BaseCostume.OnDamaged(m);

            return totalDamage;
        }

        public static void Fix(ref int val)
        {
            if (val < 0)
                val = 0;
        }

        public static int Scale(int input, int percent)
        {
            return (input * percent) / 100;
        }

        public static void DoLeech(int damageGiven, Mobile from, Mobile target)
        {
            TransformContext context = TransformationSpellHelper.GetContext(from);

            if (context != null)
            {
                if (context.Type == typeof(WraithFormSpell))
                {
                    int manaLeech = AOS.Scale(damageGiven, Math.Min(target.Mana, (int)from.Skills.SpiritSpeak.Value / 5)); // Wraith form gives 5-20% mana leech

                    if (manaLeech != 0)
                    {
                        from.Mana += manaLeech;
                        from.PlaySound(0x44D);

                        target.Mana -= manaLeech;
                    }
                }
                else if (context.Type == typeof(VampiricEmbraceSpell))
                {
                    #region High Seas
                    if (target is BaseCreature && ((BaseCreature)target).TaintedLifeAura)
                    {
                        AOS.Damage(from, target, AOS.Scale(damageGiven, 20), false, 0, 0, 0, 0, 0, 0, 100, false, false, false);
                        from.SendLocalizedMessage(1116778); //The tainted life force energy damages you as your body tries to absorb it.
                    }
                    #endregion
                    else
                    {
                        from.Hits += AOS.Scale(damageGiven, 20);
                        from.PlaySound(0x44D);
                    }
                }
            }
        }

        #region AOS Status Bar
        public static int GetStatus( Mobile from, int index )
        {
            switch ( index )
            {
                case 0: return from.GetMaxResistance( ResistanceType.Physical );
                case 1: return from.GetMaxResistance( ResistanceType.Fire );
                case 2: return from.GetMaxResistance( ResistanceType.Cold );
                case 3: return from.GetMaxResistance( ResistanceType.Poison );
                case 4: return from.GetMaxResistance( ResistanceType.Energy );
                case 5: return Math.Min(45 + BaseArmor.GetRefinedDefenseChance(from), AosAttributes.GetValue(from, AosAttribute.DefendChance));
                case 6: return 45 + BaseArmor.GetRefinedDefenseChance(from);
                case 7: return Math.Min(from.Race == Race.Gargoyle ? 50 : 45, AosAttributes.GetValue(from, AosAttribute.AttackChance));
                case 8: return Math.Min(60, AosAttributes.GetValue(from, AosAttribute.WeaponSpeed));
                case 9: return Math.Min(100, AosAttributes.GetValue(from, AosAttribute.WeaponDamage));
                case 10: return Math.Min(100, AosAttributes.GetValue(from, AosAttribute.LowerRegCost));
                case 11: return AosAttributes.GetValue(from, AosAttribute.SpellDamage);
                case 12: return Math.Min(6, AosAttributes.GetValue(from, AosAttribute.CastRecovery));
                case 13: return Math.Min(4, AosAttributes.GetValue(from, AosAttribute.CastSpeed));
                case 14: return Math.Min(40, AosAttributes.GetValue(from, AosAttribute.LowerManaCost)) + BaseArmor.GetInherentLowerManaCost(from);
             
                case 15: return (int)RegenRates.HitPointRegen(from); // HP   REGEN
                case 16: return (int)RegenRates.StamRegen(from); // Stam REGEN
                case 17: return (int)RegenRates.ManaRegen(from); // MANA REGEN
                case 18: return Math.Min(105, AosAttributes.GetValue(from, AosAttribute.ReflectPhysical)); // reflect phys
                case 19: return Math.Min(50, AosAttributes.GetValue(from, AosAttribute.EnhancePotions)); // enhance pots

                case 20: return AosAttributes.GetValue(from, AosAttribute.BonusStr) + from.GetStatOffset(StatType.Str); // str inc
                case 21: return AosAttributes.GetValue(from, AosAttribute.BonusDex) + from.GetStatOffset(StatType.Dex); ; // dex inc
                case 22: return AosAttributes.GetValue(from, AosAttribute.BonusInt) + from.GetStatOffset(StatType.Int); ; // int inc

                case 23: return 0; // hits neg
                case 24: return 0; // stam neg
                case 25: return 0; // mana neg

                case 26: return AosAttributes.GetValue(from, AosAttribute.BonusHits); // hits inc
                case 27: return AosAttributes.GetValue(from, AosAttribute.BonusStam); // stam inc
                case 28: return AosAttributes.GetValue(from, AosAttribute.BonusMana); // mana inc
                default: return 0;
            }
        }
        #endregion
    }

    [Flags]
    public enum AosAttribute
    {
        RegenHits = 0x00000001,
        RegenStam = 0x00000002,
        RegenMana = 0x00000004,
        DefendChance = 0x00000008,
        AttackChance = 0x00000010,
        BonusStr = 0x00000020,
        BonusDex = 0x00000040,
        BonusInt = 0x00000080,
        BonusHits = 0x00000100,
        BonusStam = 0x00000200,
        BonusMana = 0x00000400,
        WeaponDamage = 0x00000800,
        WeaponSpeed = 0x00001000,
        SpellDamage = 0x00002000,
        CastRecovery = 0x00004000,
        CastSpeed = 0x00008000,
        LowerManaCost = 0x00010000,
        LowerRegCost = 0x00020000,
        ReflectPhysical = 0x00040000,
        EnhancePotions = 0x00080000,
        Luck = 0x00100000,
        SpellChanneling = 0x00200000,
        NightSight = 0x00400000,
        IncreasedKarmaLoss = 0x00800000,
        Brittle = 0x01000000,
        LowerAmmoCost = 0x02000000,
        BalancedWeapon = 0x04000000
    }

    public sealed class AosAttributes : BaseAttributes
    {
        public static bool IsValid(AosAttribute attribute)
        {
            if (!Core.AOS)
            {
                return false;
            }

            if (!Core.ML && attribute == AosAttribute.IncreasedKarmaLoss)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params AosAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<AosAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<AosAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, AosAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            if (attribute == AosAttribute.Luck || attribute == AosAttribute.RegenMana || attribute == AosAttribute.DefendChance || attribute == AosAttribute.EnhancePotions)
                value += SphynxFortune.GetAosAttributeBonus(m, attribute);

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                Item obj = m.Items[i];

                AosAttributes attrs = RunicReforging.GetAosAttributes(obj);

                if (attrs != null)
                    value += attrs[attribute];

                if (attribute == AosAttribute.Luck)
                {
                    if (obj is BaseWeapon)
                        value += ((BaseWeapon)obj).GetLuckBonus();

                    if (obj is BaseArmor)
                        value += ((BaseArmor)obj).GetLuckBonus();
                }

                if (obj is ISetItem)
                {
                    ISetItem item = (ISetItem)obj;

                    attrs = item.SetAttributes;

                    if (attrs != null && item.LastEquipped)
                        value += attrs[attribute];
                }
            }

            #region Malus/Buff Handler

            #region Skill Mastery
            value += SkillMasterySpell.GetAttributeBonus(m, attribute);
            #endregion

            if (attribute == AosAttribute.WeaponDamage)
            {
                if (BaseMagicalFood.IsUnderInfluence(m, MagicalFood.GrapesOfWrath))
                    value += 35;

                // attacker gets 10% bonus when they're under divine fury
                if (DivineFurySpell.UnderEffect(m))
                    value += DivineFurySpell.GetDamageBonus(m);

                // Horrific Beast transformation gives a +25% bonus to damage.
                if (TransformationSpellHelper.UnderTransformation(m, typeof(HorrificBeastSpell)))
                    value += 25;

                int defenseMasteryMalus = 0;
                int discordanceEffect = 0;

                // Defense Mastery gives a -50%/-80% malus to damage.
                if (Server.Items.DefenseMastery.GetMalus(m, ref defenseMasteryMalus))
                    value -= defenseMasteryMalus;

                // Discordance gives a -2%/-48% malus to damage.
                if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
                    value -= discordanceEffect * 2;

                if (Block.IsBlocking(m))
                    value -= 30;

                #region SA
                if (m is PlayerMobile && m.Race == Race.Gargoyle)
                {
                    value += ((PlayerMobile)m).GetRacialBerserkBuff(false);
                }
                #endregion

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.WeaponDam))
                    value += 5;
                #endregion
            }
            else if (attribute == AosAttribute.SpellDamage)
            {
                if (BaseMagicalFood.IsUnderInfluence(m, MagicalFood.GrapesOfWrath))
                    value += 15;

                if (PsychicAttack.Registry.ContainsKey(m))
                    value -= PsychicAttack.Registry[m].SpellDamageMalus;

                TransformContext context = TransformationSpellHelper.GetContext(m);

                if (context != null && context.Spell is ReaperFormSpell)
                    value += ((ReaperFormSpell)context.Spell).SpellDamageBonus;

                value += ArcaneEmpowermentSpell.GetSpellBonus(m, true);

                #region SA
                if (m is PlayerMobile && m.Race == Race.Gargoyle)
                {
                    value += ((PlayerMobile)m).GetRacialBerserkBuff(true);
                }
                #endregion

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.GuildOfArcaneArts))
                    value += 5;
                #endregion

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.SpellDamage))
                    value += 5;
                #endregion
            }
            else if (attribute == AosAttribute.CastSpeed)
            {
                if (HowlOfCacophony.IsUnderEffects(m) || AuraOfNausea.UnderNausea(m))
                    value -= 5;

                if (EssenceOfWindSpell.IsDebuffed(m))
                    value -= EssenceOfWindSpell.GetFCMalus(m);

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.BardicCollegium))
                    value += 1;
                #endregion

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 2;

                if (TransformationSpellHelper.UnderTransformation(m, typeof(Spells.Mysticism.StoneFormSpell)))
                    value -= 2;
                #endregion
            }
            else if (attribute == AosAttribute.CastRecovery)
            {
                if (HowlOfCacophony.IsUnderEffects(m))
                    value -= 5;

                value -= ThunderstormSpell.GetCastRecoveryMalus(m);

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 3;
                #endregion
            }
            else if (attribute == AosAttribute.WeaponSpeed)
            {
                if (HowlOfCacophony.IsUnderEffects(m) || AuraOfNausea.UnderNausea(m))
                    value -= 60;

                if (DivineFurySpell.UnderEffect(m))
                    value += DivineFurySpell.GetWeaponSpeedBonus(m);

                value += HonorableExecution.GetSwingBonus(m);

                TransformContext context = TransformationSpellHelper.GetContext(m);

                if (context != null && context.Spell is ReaperFormSpell)
                    value += ((ReaperFormSpell)context.Spell).SwingSpeedBonus;

                int discordanceEffect = 0;

                // Discordance gives a malus of -0/-28% to swing speed.
                if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
                    value -= discordanceEffect;

                if (EssenceOfWindSpell.IsDebuffed(m))
                    value -= EssenceOfWindSpell.GetSSIMalus(m);

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.GuildOfAssassins))
                    value += 5;
                #endregion

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 45;

                if (TransformationSpellHelper.UnderTransformation(m, typeof(Spells.Mysticism.StoneFormSpell)))
                    value -= 10;

                if (StickySkin.IsUnderEffects(m))
                    value -= 30;
                #endregion
            }
            else if (attribute == AosAttribute.AttackChance)
            {
                if (AuraOfNausea.UnderNausea(m))
                    value -= 60;

                if (DivineFurySpell.UnderEffect(m))
                    value += DivineFurySpell.GetAttackBonus(m);                

                if (BaseWeapon.CheckAnimal(m, typeof(GreyWolf)) || BaseWeapon.CheckAnimal(m, typeof(BakeKitsune)))
                    value += 20; // attacker gets 20% bonus when under Wolf or Bake Kitsune form

                if (HitLower.IsUnderAttackEffect(m))
                    value -= 25; // Under Hit Lower Attack effect -> 25% malus

                WeaponAbility ability = WeaponAbility.GetCurrentAbility(m);

                if (ability != null)
                    value += ability.AccuracyBonus;

                SpecialMove move = SpecialMove.GetCurrentMove(m);

                if (move != null)
                    value += move.GetAccuracyBonus(m);

                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.WarriorsGuild))
                    value += 5;
                #endregion

                #region SA
                if (Spells.Mysticism.SleepSpell.IsUnderSleepEffects(m))
                    value -= 45;

                if (m.Race == Race.Gargoyle)
                    value += 5;  //Gargoyles get a +5 HCI
                #endregion

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.HitChance))
                    value += 8;
                #endregion
            }
            else if (attribute == AosAttribute.DefendChance)
            {
                if (AuraOfNausea.UnderNausea(m))
                    value -= 60;

                if (DivineFurySpell.UnderEffect(m))
                    value -= DivineFurySpell.GetDefendMalus(m);

                value -= HitLower.GetDefenseMalus(m);

                int discordanceEffect = 0;
                int surpriseMalus = 0;

                value += Block.GetBonus(m);

                if (SurpriseAttack.GetMalus(m, ref surpriseMalus))
                    value -= surpriseMalus;

                // Defender loses -0/-28% if under the effect of Discordance.
                if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
                    value -= discordanceEffect;

                #region High Seas
                if (BaseFishPie.IsUnderEffects(m, FishPieEffect.DefChance))
                    value += 8;
                #endregion
            }
            else if (attribute == AosAttribute.RegenHits)
            {
                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.MaritimeGuild))
                    value += 2;
                #endregion

                #region High Seas
                if (m is PlayerMobile && BaseFishPie.IsUnderEffects(m, FishPieEffect.HitsRegen))
                    value += 3;

                if (SurgeShield.IsUnderEffects(m, SurgeType.Hits))
                    value += 10;

                if (SearingWeaponContext.HasContext(m))
                    value -= m is PlayerMobile ? 20 : 60;
                #endregion

                //Virtue Artifacts
                value += AnkhPendant.GetHitsRegenModifier(m);
            }
            else if (attribute == AosAttribute.RegenStam)
            {
                #region High Seas
                if (m is PlayerMobile && BaseFishPie.IsUnderEffects(m, FishPieEffect.StamRegen))
                    value += 3;

                if (SurgeShield.IsUnderEffects(m, SurgeType.Stam))
                    value += 10;
                #endregion

                //Virtue Artifacts
                value += AnkhPendant.GetStamRegenModifier(m);
            }
            else if (attribute == AosAttribute.RegenMana)
            {
                #region City Loyalty
                if (CityLoyaltySystem.HasTradeDeal(m, TradeDeal.MerchantsAssociation))
                    value += 1;
                #endregion

                #region High Seas
                if (m is PlayerMobile && BaseFishPie.IsUnderEffects(m, FishPieEffect.ManaRegen))
                    value += 3;

                if (SurgeShield.IsUnderEffects(m, SurgeType.Mana))
                    value += 10;
                #endregion

                //Virtue Artifacts
                value += AnkhPendant.GetManaRegenModifier(m);
            }
            #endregion

            return value;
        }

        public override void SetValue(int bitmask, int value)
        {
            if (Core.SA && bitmask == (int)AosAttribute.WeaponSpeed && Owner is BaseWeapon)
            {
                ((BaseWeapon)Owner).WeaponAttributes.ScaleLeech(value);
            }

            base.SetValue(bitmask, value);
        }

        public AosAttributes(Item owner)
            : base(owner)
        {
        }

        public AosAttributes(Item owner, AosAttributes other)
            : base(owner, other)
        {
        }

        public AosAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }


        public int this[AosAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public override string ToString()
        {
            return "...";
        }

        public void AddStatBonuses(Mobile to)
        {
            int strBonus = BonusStr;
            int dexBonus = BonusDex;
            int intBonus = BonusInt;

            if (strBonus != 0 || dexBonus != 0 || intBonus != 0)
            {
                string modName = Owner.Serial.ToString();

                if (strBonus != 0)
                    to.AddStatMod(new StatMod(StatType.Str, modName + "Str", strBonus, TimeSpan.Zero));

                if (dexBonus != 0)
                    to.AddStatMod(new StatMod(StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero));

                if (intBonus != 0)
                    to.AddStatMod(new StatMod(StatType.Int, modName + "Int", intBonus, TimeSpan.Zero));
            }

            to.CheckStatTimers();
        }

        public void RemoveStatBonuses(Mobile from)
        {
            string modName = Owner.Serial.ToString();

            from.RemoveStatMod(modName + "Str");
            from.RemoveStatMod(modName + "Dex");
            from.RemoveStatMod(modName + "Int");

            from.CheckStatTimers();
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int RegenHits
        {
            get
            {
                return this[AosAttribute.RegenHits];
            }
            set
            {
                this[AosAttribute.RegenHits] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int RegenStam
        {
            get
            {
                return this[AosAttribute.RegenStam];
            }
            set
            {
                this[AosAttribute.RegenStam] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int RegenMana
        {
            get
            {
                return this[AosAttribute.RegenMana];
            }
            set
            {
                this[AosAttribute.RegenMana] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int DefendChance
        {
            get
            {
                return this[AosAttribute.DefendChance];
            }
            set
            {
                this[AosAttribute.DefendChance] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int AttackChance
        {
            get
            {
                return this[AosAttribute.AttackChance];
            }
            set
            {
                this[AosAttribute.AttackChance] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusStr
        {
            get
            {
                return this[AosAttribute.BonusStr];
            }
            set
            {
                this[AosAttribute.BonusStr] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusDex
        {
            get
            {
                return this[AosAttribute.BonusDex];
            }
            set
            {
                this[AosAttribute.BonusDex] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusInt
        {
            get
            {
                return this[AosAttribute.BonusInt];
            }
            set
            {
                this[AosAttribute.BonusInt] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusHits
        {
            get
            {
                return this[AosAttribute.BonusHits];
            }
            set
            {
                this[AosAttribute.BonusHits] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusStam
        {
            get
            {
                return this[AosAttribute.BonusStam];
            }
            set
            {
                this[AosAttribute.BonusStam] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BonusMana
        {
            get
            {
                return this[AosAttribute.BonusMana];
            }
            set
            {
                this[AosAttribute.BonusMana] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int WeaponDamage
        {
            get
            {
                return this[AosAttribute.WeaponDamage];
            }
            set
            {
                this[AosAttribute.WeaponDamage] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int WeaponSpeed
        {
            get
            {
                return this[AosAttribute.WeaponSpeed];
            }
            set
            {
                this[AosAttribute.WeaponSpeed] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SpellDamage
        {
            get
            {
                return this[AosAttribute.SpellDamage];
            }
            set
            {
                this[AosAttribute.SpellDamage] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int CastRecovery
        {
            get
            {
                return this[AosAttribute.CastRecovery];
            }
            set
            {
                this[AosAttribute.CastRecovery] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int CastSpeed
        {
            get
            {
                return this[AosAttribute.CastSpeed];
            }
            set
            {
                this[AosAttribute.CastSpeed] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerManaCost
        {
            get
            {
                return this[AosAttribute.LowerManaCost];
            }
            set
            {
                this[AosAttribute.LowerManaCost] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerRegCost
        {
            get
            {
                return this[AosAttribute.LowerRegCost];
            }
            set
            {
                this[AosAttribute.LowerRegCost] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ReflectPhysical
        {
            get
            {
                return this[AosAttribute.ReflectPhysical];
            }
            set
            {
                this[AosAttribute.ReflectPhysical] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EnhancePotions
        {
            get
            {
                return this[AosAttribute.EnhancePotions];
            }
            set
            {
                this[AosAttribute.EnhancePotions] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Luck
        {
            get
            {
                return this[AosAttribute.Luck];
            }
            set
            {
                this[AosAttribute.Luck] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SpellChanneling
        {
            get
            {
                return this[AosAttribute.SpellChanneling];
            }
            set
            {
                this[AosAttribute.SpellChanneling] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int NightSight
        {
            get
            {
                return this[AosAttribute.NightSight];
            }
            set
            {
                this[AosAttribute.NightSight] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int IncreasedKarmaLoss
        {
            get
            {
                return this[AosAttribute.IncreasedKarmaLoss];
            }
            set
            {
                this[AosAttribute.IncreasedKarmaLoss] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Brittle
        {
            get
            {
                return this[AosAttribute.Brittle];
            }
            set
            {
                this[AosAttribute.Brittle] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerAmmoCost
        {
            get
            {
                return this[AosAttribute.LowerAmmoCost];
            }
            set
            {
                this[AosAttribute.LowerAmmoCost] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BalancedWeapon
        {
            get
            {
                return this[AosAttribute.BalancedWeapon];
            }
            set
            {
                this[AosAttribute.BalancedWeapon] = value;
            }
        }
    }

    [Flags]
    public enum AosWeaponAttribute : long
    {
        LowerStatReq = 0x00000001,
        SelfRepair = 0x00000002,
        HitLeechHits = 0x00000004,
        HitLeechStam = 0x00000008,
        HitLeechMana = 0x00000010,
        HitLowerAttack = 0x00000020,
        HitLowerDefend = 0x00000040,
        HitMagicArrow = 0x00000080,
        HitHarm = 0x00000100,
        HitFireball = 0x00000200,
        HitLightning = 0x00000400,
        HitDispel = 0x00000800,
        HitColdArea = 0x00001000,
        HitFireArea = 0x00002000,
        HitPoisonArea = 0x00004000,
        HitEnergyArea = 0x00008000,
        HitPhysicalArea = 0x00010000,
        ResistPhysicalBonus = 0x00020000,
        ResistFireBonus = 0x00040000,
        ResistColdBonus = 0x00080000,
        ResistPoisonBonus = 0x00100000,
        ResistEnergyBonus = 0x00200000,
        UseBestSkill = 0x00400000,
        MageWeapon = 0x00800000,
        DurabilityBonus = 0x01000000,
        BloodDrinker = 0x02000000,
        BattleLust = 0x04000000,
        HitCurse = 0x08000000,
        HitFatigue = 0x10000000,
        HitManaDrain = 0x20000000,
        SplinteringWeapon = 0x40000000,
        ReactiveParalyze =  0x80000000,
    }

    public sealed class AosWeaponAttributes : BaseAttributes
    {
        public static bool IsValid(AosWeaponAttribute attribute)
        {
            if (!Core.AOS)
            {
                return false;
            }

            if (!Core.SA && attribute >= AosWeaponAttribute.BloodDrinker)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params AosWeaponAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<AosWeaponAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<AosWeaponAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, AosWeaponAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                AosWeaponAttributes attrs = RunicReforging.GetAosWeaponAttributes(m.Items[i]);

                if (attrs != null)
                    value += attrs[attribute];
            }

            return value;
        }

        public override void SetValue(int bitmask, int value)
        {
            if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && Owner is BaseWeapon)
            {
                ((BaseWeapon)Owner).UnscaleDurability();
            }

            base.SetValue(bitmask, value);

            if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && Owner is BaseWeapon)
            {
                ((BaseWeapon)Owner).ScaleDurability();
            }
        }

        public AosWeaponAttributes(Item owner)
            : base(owner)
        {
        }

        public AosWeaponAttributes(Item owner, AosWeaponAttributes other)
            : base(owner, other)
        {
        }

        public AosWeaponAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public int this[AosWeaponAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public void ScaleLeech(int weaponSpeed)
        {
            BaseWeapon wep = Owner as BaseWeapon;

            if (wep == null || wep.IsArtifact)
                return;

            if (HitLeechHits > 0)
            {
                double postcap = (double)HitLeechHits / (double)ItemPropertyInfo.GetMaxIntensity(wep, AosWeaponAttribute.HitLeechHits);
                if (postcap < 1.0) postcap = 1.0;

                int newhits = (int)((wep.MlSpeed * 2500 / (100 + weaponSpeed)) * postcap);

                if (wep is BaseRanged)
                    newhits /= 2;

                if(HitLeechHits > newhits)
                    HitLeechHits = newhits;
            }

            if (HitLeechMana > 0)
            {
                double postcap = (double)HitLeechMana / (double)ItemPropertyInfo.GetMaxIntensity(wep, AosWeaponAttribute.HitLeechMana);
                if (postcap < 1.0) postcap = 1.0;

                int newmana = (int)((wep.MlSpeed * 2500 / (100 + weaponSpeed)) * postcap);

                if (wep is BaseRanged)
                    newmana /= 2;

                if(HitLeechMana > newmana)
                    HitLeechMana = newmana;
            }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerStatReq
        {
            get
            {
                return this[AosWeaponAttribute.LowerStatReq];
            }
            set
            {
                this[AosWeaponAttribute.LowerStatReq] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SelfRepair
        {
            get
            {
                return this[AosWeaponAttribute.SelfRepair];
            }
            set
            {
                this[AosWeaponAttribute.SelfRepair] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLeechHits
        {
            get
            {
                return this[AosWeaponAttribute.HitLeechHits];
            }
            set
            {
                this[AosWeaponAttribute.HitLeechHits] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLeechStam
        {
            get
            {
                return this[AosWeaponAttribute.HitLeechStam];
            }
            set
            {
                this[AosWeaponAttribute.HitLeechStam] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLeechMana
        {
            get
            {
                return this[AosWeaponAttribute.HitLeechMana];
            }
            set
            {
                this[AosWeaponAttribute.HitLeechMana] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLowerAttack
        {
            get
            {
                return this[AosWeaponAttribute.HitLowerAttack];
            }
            set
            {
                this[AosWeaponAttribute.HitLowerAttack] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLowerDefend
        {
            get
            {
                return this[AosWeaponAttribute.HitLowerDefend];
            }
            set
            {
                this[AosWeaponAttribute.HitLowerDefend] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitMagicArrow
        {
            get
            {
                return this[AosWeaponAttribute.HitMagicArrow];
            }
            set
            {
                this[AosWeaponAttribute.HitMagicArrow] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitHarm
        {
            get
            {
                return this[AosWeaponAttribute.HitHarm];
            }
            set
            {
                this[AosWeaponAttribute.HitHarm] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitFireball
        {
            get
            {
                return this[AosWeaponAttribute.HitFireball];
            }
            set
            {
                this[AosWeaponAttribute.HitFireball] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitLightning
        {
            get
            {
                return this[AosWeaponAttribute.HitLightning];
            }
            set
            {
                this[AosWeaponAttribute.HitLightning] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitDispel
        {
            get
            {
                return this[AosWeaponAttribute.HitDispel];
            }
            set
            {
                this[AosWeaponAttribute.HitDispel] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitColdArea
        {
            get
            {
                return this[AosWeaponAttribute.HitColdArea];
            }
            set
            {
                this[AosWeaponAttribute.HitColdArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitFireArea
        {
            get
            {
                return this[AosWeaponAttribute.HitFireArea];
            }
            set
            {
                this[AosWeaponAttribute.HitFireArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitPoisonArea
        {
            get
            {
                return this[AosWeaponAttribute.HitPoisonArea];
            }
            set
            {
                this[AosWeaponAttribute.HitPoisonArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitEnergyArea
        {
            get
            {
                return this[AosWeaponAttribute.HitEnergyArea];
            }
            set
            {
                this[AosWeaponAttribute.HitEnergyArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitPhysicalArea
        {
            get
            {
                return this[AosWeaponAttribute.HitPhysicalArea];
            }
            set
            {
                this[AosWeaponAttribute.HitPhysicalArea] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistPhysicalBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistPhysicalBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistPhysicalBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistFireBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistFireBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistFireBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistColdBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistColdBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistColdBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistPoisonBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistPoisonBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistPoisonBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResistEnergyBonus
        {
            get
            {
                return this[AosWeaponAttribute.ResistEnergyBonus];
            }
            set
            {
                this[AosWeaponAttribute.ResistEnergyBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int UseBestSkill
        {
            get
            {
                return this[AosWeaponAttribute.UseBestSkill];
            }
            set
            {
                this[AosWeaponAttribute.UseBestSkill] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MageWeapon
        {
            get
            {
                return this[AosWeaponAttribute.MageWeapon];
            }
            set
            {
                this[AosWeaponAttribute.MageWeapon] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int DurabilityBonus
        {
            get
            {
                return this[AosWeaponAttribute.DurabilityBonus];
            }
            set
            {
                this[AosWeaponAttribute.DurabilityBonus] = value;
            }
        }

        #region SA
        [CommandProperty(AccessLevel.GameMaster)]
        public int BloodDrinker
        {
            get
            {
                return this[AosWeaponAttribute.BloodDrinker];
            }
            set
            {
                this[AosWeaponAttribute.BloodDrinker] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BattleLust
        {
            get
            {
                return this[AosWeaponAttribute.BattleLust];
            }
            set
            {
                this[AosWeaponAttribute.BattleLust] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitCurse
        {
            get
            {
                return this[AosWeaponAttribute.HitCurse];
            }
            set
            {
                this[AosWeaponAttribute.HitCurse] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitFatigue
        {
            get
            {
                return this[AosWeaponAttribute.HitFatigue];
            }
            set
            {
                this[AosWeaponAttribute.HitFatigue] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitManaDrain
        {
            get
            {
                return this[AosWeaponAttribute.HitManaDrain];
            }
            set
            {
                this[AosWeaponAttribute.HitManaDrain] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SplinteringWeapon
        {
            get
            {
                return this[AosWeaponAttribute.SplinteringWeapon];
            }
            set
            {
                this[AosWeaponAttribute.SplinteringWeapon] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ReactiveParalyze
        {
            get
            {
                return this[AosWeaponAttribute.ReactiveParalyze];
            }
            set
            {
                this[AosWeaponAttribute.ReactiveParalyze] = value;
            }
        }
        #endregion
    }

    [Flags]
    public enum ExtendedWeaponAttribute
    {
        BoneBreaker     = 0x00000001,
        HitSwarm        = 0x00000002,
        HitSparks       = 0x00000004,
        Bane            = 0x00000008,
        MysticWeapon    = 0x00000010,
        AssassinHoned   = 0x00000020,
        Focus           = 0x00000040,
        HitExplosion    = 0x00000080
    }

    public sealed class ExtendedWeaponAttributes : BaseAttributes
    {
        public ExtendedWeaponAttributes(Item owner)
            : base(owner)
        {
        }

        public ExtendedWeaponAttributes(Item owner, ExtendedWeaponAttributes other)
            : base(owner, other)
        {
        }

        public ExtendedWeaponAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public static int GetValue(Mobile m, ExtendedWeaponAttribute attribute)
        {
            if (!Core.AOS)
                return 0;

            int value = 0;

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                Item obj = m.Items[i];

                if (obj is BaseWeapon)
                {
                    ExtendedWeaponAttributes attrs = ((BaseWeapon)obj).ExtendedWeaponAttributes;

                    if (attrs != null)
                        value += attrs[attribute];
                }
            }

            return value;
        }

        public int this[ExtendedWeaponAttribute attribute]
        {
            get
            {
                return GetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int BoneBreaker
        {
            get
            {
                return this[ExtendedWeaponAttribute.BoneBreaker];
            }
            set
            {
                this[ExtendedWeaponAttribute.BoneBreaker] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitSwarm
        {
            get
            {
                return this[ExtendedWeaponAttribute.HitSwarm];
            }
            set
            {
                this[ExtendedWeaponAttribute.HitSwarm] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitSparks
        {
            get
            {
                return this[ExtendedWeaponAttribute.HitSparks];
            }
            set
            {
                this[ExtendedWeaponAttribute.HitSparks] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Bane
        {
            get
            {
                return this[ExtendedWeaponAttribute.Bane];
            }
            set
            {
                this[ExtendedWeaponAttribute.Bane] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MysticWeapon
        {
            get
            {
                return this[ExtendedWeaponAttribute.MysticWeapon];
            }
            set
            {
                this[ExtendedWeaponAttribute.MysticWeapon] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int AssassinHoned
        {
            get
            {
                return this[ExtendedWeaponAttribute.AssassinHoned];
            }
            set
            {
                this[ExtendedWeaponAttribute.AssassinHoned] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Focus
        {
            get
            {
                return this[ExtendedWeaponAttribute.Focus];
            }
            set
            {
                this[ExtendedWeaponAttribute.Focus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitExplosion
        {
            get
            {
                return this[ExtendedWeaponAttribute.HitExplosion];
            }
            set
            {
                this[ExtendedWeaponAttribute.HitExplosion] = value;
            }
        }
    }

    [Flags]
    public enum AosArmorAttribute
    {
        LowerStatReq = 0x00000001,
        SelfRepair = 0x00000002,
        MageArmor = 0x00000004,
        DurabilityBonus = 0x00000008,
        #region Stygian Abyss
        ReactiveParalyze = 0x00000010,
        SoulCharge = 0x00000020
        #endregion
    }

    public sealed class AosArmorAttributes : BaseAttributes
    {
        public static bool IsValid(AosArmorAttribute attribute)
        {
            if (!Core.AOS)
            {
                return false;
            }

            if (!Core.SA && attribute >= AosArmorAttribute.ReactiveParalyze)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params AosArmorAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<AosArmorAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<AosArmorAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, AosArmorAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            for (int i = 0; i < m.Items.Count; ++i)
            {
                AosArmorAttributes attrs = RunicReforging.GetAosArmorAttributes(m.Items[i]);

                if (attrs != null)
                    value += attrs[attribute];
            }

            return value;
        }

        public override void SetValue(int bitmask, int value)
        {
            if (bitmask == (int)AosArmorAttribute.DurabilityBonus)
            {
                if (Owner is BaseArmor)
                {
                    ((BaseArmor)Owner).UnscaleDurability();
                }
                else if (Owner is BaseClothing)
                {
                    ((BaseClothing)Owner).UnscaleDurability();
                }
            }

            base.SetValue(bitmask, value);

            if (bitmask == (int)AosArmorAttribute.DurabilityBonus)
            {
                if (Owner is BaseArmor)
                {
                    ((BaseArmor)Owner).ScaleDurability();
                }
                else if (Owner is BaseClothing)
                {
                    ((BaseClothing)Owner).ScaleDurability();
                }
            }
        }

        public AosArmorAttributes(Item owner)
            : base(owner)
        {
        }

        public AosArmorAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public AosArmorAttributes(Item owner, AosArmorAttributes other)
            : base(owner, other)
        {
        }

        public int this[AosArmorAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LowerStatReq
        {
            get
            {
                return this[AosArmorAttribute.LowerStatReq];
            }
            set
            {
                this[AosArmorAttribute.LowerStatReq] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SelfRepair
        {
            get
            {
                return this[AosArmorAttribute.SelfRepair];
            }
            set
            {
                this[AosArmorAttribute.SelfRepair] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MageArmor
        {
            get
            {
                return this[AosArmorAttribute.MageArmor];
            }
            set
            {
                this[AosArmorAttribute.MageArmor] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int DurabilityBonus
        {
            get
            {
                return this[AosArmorAttribute.DurabilityBonus];
            }
            set
            {
                this[AosArmorAttribute.DurabilityBonus] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ReactiveParalyze
        {
            get
            {
                return this[AosArmorAttribute.ReactiveParalyze];
            }
            set
            {
                this[AosArmorAttribute.ReactiveParalyze] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SoulCharge
        {
            get
            {
                return this[AosArmorAttribute.SoulCharge];
            }
            set
            {
                this[AosArmorAttribute.SoulCharge] = value;
            }
        }
    }

    public sealed class AosSkillBonuses : BaseAttributes
    {
        private List<SkillMod> m_Mods;

        public AosSkillBonuses(Item owner)
            : base(owner)
        {
        }

        public AosSkillBonuses(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public AosSkillBonuses(Item owner, AosSkillBonuses other)
            : base(owner, other)
        {
        }

        public static string SeparateCapitals(string msg)
        {
            StringBuilder builder = new StringBuilder();
            foreach (char c in msg)
            {
                if (Char.IsUpper(c) && builder.Length > 0) builder.Append(' ');
                builder.Append(c);
            }
            return msg = builder.ToString();
        }

        public void GetProperties(ObjectPropertyList list)
        {
            for (int i = 0; i < 60; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                list.Add(SeparateCapitals(skill.ToString()) + " +" + bonus.ToString());
            }
        }

        public static int GetLabel(SkillName skill)
        {
            switch (skill)
            {
                case SkillName.EvalInt:
                    return 1002070; // Evaluate Intelligence
                case SkillName.Forensics:
                    return 1002078; // Forensic Evaluation
                case SkillName.Lockpicking:
                    return 1002097; // Lockpicking
                default:
                    return 1044060 + (int)skill;
            }
        }

        public void AddTo(Mobile m)
        {
            if (Discordance.UnderPVPEffects(m))
            {
                return;
            }

            Remove();

            for (int i = 0; i < 60; ++i)
            {
                SkillName skill;
                double bonus;

                if (!GetValues(i, out skill, out bonus))
                    continue;

                if (m_Mods == null)
                    m_Mods = new List<SkillMod>();

                SkillMod sk = new DefaultSkillMod(skill, true, bonus);
                sk.ObeyCap = false;
                m.AddSkillMod(sk);
                m_Mods.Add(sk);
            }
        }

        public void Remove()
        {
            if (m_Mods == null)
                return;

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

                if (Core.ML)
                    CheckCancelMorph(m);
            }
            m_Mods = null;
        }

        public override void SetValue(int bitmask, int value)
        {
            base.SetValue(bitmask, value);

            if (Owner != null && Owner.Parent is Mobile)
            {
                Remove();
                AddTo((Mobile)Owner.Parent);
            }
        }

        public bool GetValues(int index, out SkillName skill, out double bonus)
        {
            int v = GetValue(1 << index);
            int vSkill = 0;
            int vBonus = 0;

            for (int i = 0; i < 16; ++i)
            {
                vSkill <<= 1;
                vSkill |= (v & 1);
                v >>= 1;

                vBonus <<= 1;
                vBonus |= (v & 1);
                v >>= 1;
            }

            skill = (SkillName)vSkill;
            bonus = (double)vBonus / 10;

            return (bonus != 0);
        }

        public void SetValues(int index, SkillName skill, double bonus)
        {
            int v = 0;
            int vSkill = (int)skill;
            int vBonus = (int)(bonus * 10);

            for (int i = 0; i < 16; ++i)
            {
                v <<= 1;
                v |= (vBonus & 1);
                vBonus >>= 1;

                v <<= 1;
                v |= (vSkill & 1);
                vSkill >>= 1;
            }

            SetValue(1 << index, v);
        }

        public SkillName GetSkill(int index)
        {
            SkillName skill;
            double bonus;

            GetValues(index, out skill, out bonus);

            return skill;
        }

        public void SetSkill(int index, SkillName skill)
        {
            SetValues(index, skill, GetBonus(index));
        }

        public double GetBonus(int index)
        {
            SkillName skill;
            double bonus;

            GetValues(index, out skill, out bonus);

            return bonus;
        }

        public void SetBonus(int index, double bonus)
        {
            SetValues(index, GetSkill(index), bonus);
        }

        public override string ToString()
        {
            return "...";
        }

        public void CheckCancelMorph(Mobile m)
        {
            if (m == null)
                return;

            double minSkill, maxSkill;

            AnimalFormContext acontext = AnimalForm.GetContext(m);
            TransformContext context = TransformationSpellHelper.GetContext(m);

            if (context != null)
            {
                Spell spell = context.Spell as Spell;
                spell.GetCastSkills(out minSkill, out maxSkill);

                if (m.Skills[spell.CastSkill].Value < minSkill)
                {
                    TransformationSpellHelper.RemoveContext(m, context, true);
                }
            }

            if (acontext != null)
            {
                if (acontext.Type == typeof(WildWhiteTiger) && m.Skills[SkillName.Ninjitsu].Value < 90)
                {
                    AnimalForm.RemoveContext(m, true);
                }
                else
                {
                    int i;

                    for (i = 0; i < AnimalForm.Entries.Length; ++i)
                    {
                        if (AnimalForm.Entries[i].Type == acontext.Type)
                            break;
                    }

                    if (i < AnimalForm.Entries.Length && m.Skills[SkillName.Ninjitsu].Value < AnimalForm.Entries[i].ReqSkill)
                    {
                        AnimalForm.RemoveContext(m, true);
                    }
                }
            }
            if (!m.CanBeginAction(typeof(PolymorphSpell)) && m.Skills[SkillName.Magery].Value < 66.1)
            {
                m.BodyMod = 0;
                m.HueMod = -1;
                m.NameMod = null;
                m.EndAction(typeof(PolymorphSpell));
                BaseArmor.ValidateMobile(m);
                BaseClothing.ValidateMobile(m);
            }
            if (!m.CanBeginAction(typeof(IncognitoSpell)) && m.Skills[SkillName.Magery].Value < 38.1)
            {
                if (m is PlayerMobile)
                    ((PlayerMobile)m).SetHairMods(-1, -1);
                m.BodyMod = 0;
                m.HueMod = -1;
                m.NameMod = null;
                m.EndAction(typeof(IncognitoSpell));
                BaseArmor.ValidateMobile(m);
                BaseClothing.ValidateMobile(m);
                BuffInfo.RemoveBuff(m, BuffIcon.Incognito);
            }
            return;
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_1_Value
        {
            get
            {
                return GetBonus(0);
            }
            set
            {
                SetBonus(0, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_1_Name
        {
            get
            {
                return GetSkill(0);
            }
            set
            {
                SetSkill(0, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_2_Value
        {
            get
            {
                return GetBonus(1);
            }
            set
            {
                SetBonus(1, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_2_Name
        {
            get
            {
                return GetSkill(1);
            }
            set
            {
                SetSkill(1, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_3_Value
        {
            get
            {
                return GetBonus(2);
            }
            set
            {
                SetBonus(2, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_3_Name
        {
            get
            {
                return GetSkill(2);
            }
            set
            {
                SetSkill(2, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_4_Value
        {
            get
            {
                return GetBonus(3);
            }
            set
            {
                SetBonus(3, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_4_Name
        {
            get
            {
                return GetSkill(3);
            }
            set
            {
                SetSkill(3, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_5_Value
        {
            get
            {
                return GetBonus(4);
            }
            set
            {
                SetBonus(4, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_5_Name
        {
            get
            {
                return GetSkill(4);
            }
            set
            {
                SetSkill(4, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_6_Value
        {
            get
            {
                return GetBonus(5);
            }
            set
            {
                SetBonus(5, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_6_Name
        {
            get
            {
                return GetSkill(5);
            }
            set
            {
                SetSkill(5, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_7_Value
        {
            get
            {
                return GetBonus(6);
            }
            set
            {
                SetBonus(6, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_7_Name
        {
            get
            {
                return GetSkill(6);
            }
            set
            {
                SetSkill(6, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_8_Value
        {
            get
            {
                return GetBonus(7);
            }
            set
            {
                SetBonus(7, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_8_Name
        {
            get
            {
                return GetSkill(7);
            }
            set
            {
                SetSkill(7, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_9_Value
        {
            get
            {
                return GetBonus(8);
            }
            set
            {
                SetBonus(8, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_9_Name
        {
            get
            {
                return GetSkill(8);
            }
            set
            {
                SetSkill(8, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_10_Value
        {
            get
            {
                return GetBonus(9);
            }
            set
            {
                SetBonus(9, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_10_Name
        {
            get
            {
                return GetSkill(9);
            }
            set
            {
                SetSkill(9, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_11_Value
        {
            get
            {
                return GetBonus(10);
            }
            set
            {
                SetBonus(10, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_11_Name
        {
            get
            {
                return GetSkill(10);
            }
            set
            {
                SetSkill(10, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_12_Value
        {
            get
            {
                return GetBonus(11);
            }
            set
            {
                SetBonus(11, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_12_Name
        {
            get
            {
                return GetSkill(11);
            }
            set
            {
                SetSkill(11, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_13_Value
        {
            get
            {
                return GetBonus(12);
            }
            set
            {
                SetBonus(12, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_13_Name
        {
            get
            {
                return GetSkill(12);
            }
            set
            {
                SetSkill(12, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_14_Value
        {
            get
            {
                return GetBonus(13);
            }
            set
            {
                SetBonus(13, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_14_Name
        {
            get
            {
                return GetSkill(13);
            }
            set
            {
                SetSkill(13, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_15_Value
        {
            get
            {
                return GetBonus(14);
            }
            set
            {
                SetBonus(14, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_15_Name
        {
            get
            {
                return GetSkill(14);
            }
            set
            {
                SetSkill(14, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_16_Value
        {
            get
            {
                return GetBonus(15);
            }
            set
            {
                SetBonus(15, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_16_Name
        {
            get
            {
                return GetSkill(15);
            }
            set
            {
                SetSkill(15, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_17_Value
        {
            get
            {
                return GetBonus(16);
            }
            set
            {
                SetBonus(16, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_17_Name
        {
            get
            {
                return GetSkill(16);
            }
            set
            {
                SetSkill(16, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_18_Value
        {
            get
            {
                return GetBonus(17);
            }
            set
            {
                SetBonus(17, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_18_Name
        {
            get
            {
                return GetSkill(17);
            }
            set
            {
                SetSkill(17, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_19_Value
        {
            get
            {
                return GetBonus(18);
            }
            set
            {
                SetBonus(18, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_19_Name
        {
            get
            {
                return GetSkill(18);
            }
            set
            {
                SetSkill(18, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_20_Value
        {
            get
            {
                return GetBonus(19);
            }
            set
            {
                SetBonus(19, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_20_Name
        {
            get
            {
                return GetSkill(19);
            }
            set
            {
                SetSkill(19, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_21_Value
        {
            get
            {
                return GetBonus(20);
            }
            set
            {
                SetBonus(20, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_21_Name
        {
            get
            {
                return GetSkill(20);
            }
            set
            {
                SetSkill(20, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_22_Value
        {
            get
            {
                return GetBonus(21);
            }
            set
            {
                SetBonus(21, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_22_Name
        {
            get
            {
                return GetSkill(21);
            }
            set
            {
                SetSkill(21, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_23_Value
        {
            get
            {
                return GetBonus(22);
            }
            set
            {
                SetBonus(22, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_23_Name
        {
            get
            {
                return GetSkill(22);
            }
            set
            {
                SetSkill(22, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_24_Value
        {
            get
            {
                return GetBonus(23);
            }
            set
            {
                SetBonus(23, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_24_Name
        {
            get
            {
                return GetSkill(23);
            }
            set
            {
                SetSkill(23, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_25_Value
        {
            get
            {
                return GetBonus(24);
            }
            set
            {
                SetBonus(24, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_25_Name
        {
            get
            {
                return GetSkill(24);
            }
            set
            {
                SetSkill(24, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_26_Value
        {
            get
            {
                return GetBonus(25);
            }
            set
            {
                SetBonus(25, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_26_Name
        {
            get
            {
                return GetSkill(25);
            }
            set
            {
                SetSkill(25, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_27_Value
        {
            get
            {
                return GetBonus(26);
            }
            set
            {
                SetBonus(26, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_27_Name
        {
            get
            {
                return GetSkill(26);
            }
            set
            {
                SetSkill(26, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_28_Value
        {
            get
            {
                return GetBonus(27);
            }
            set
            {
                SetBonus(27, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_28_Name
        {
            get
            {
                return GetSkill(27);
            }
            set
            {
                SetSkill(27, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_29_Value
        {
            get
            {
                return GetBonus(28);
            }
            set
            {
                SetBonus(28, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_29_Name
        {
            get
            {
                return GetSkill(28);
            }
            set
            {
                SetSkill(28, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_30_Value
        {
            get
            {
                return GetBonus(29);
            }
            set
            {
                SetBonus(29, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_30_Name
        {
            get
            {
                return GetSkill(29);
            }
            set
            {
                SetSkill(29, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_31_Value
        {
            get
            {
                return GetBonus(30);
            }
            set
            {
                SetBonus(30, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_31_Name
        {
            get
            {
                return GetSkill(30);
            }
            set
            {
                SetSkill(30, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_32_Value
        {
            get
            {
                return GetBonus(31);
            }
            set
            {
                SetBonus(31, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_32_Name
        {
            get
            {
                return GetSkill(31);
            }
            set
            {
                SetSkill(31, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_33_Value
        {
            get
            {
                return GetBonus(32);
            }
            set
            {
                SetBonus(32, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_33_Name
        {
            get
            {
                return GetSkill(32);
            }
            set
            {
                SetSkill(32, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_34_Value
        {
            get
            {
                return GetBonus(33);
            }
            set
            {
                SetBonus(33, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_34_Name
        {
            get
            {
                return GetSkill(33);
            }
            set
            {
                SetSkill(33, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_35_Value
        {
            get
            {
                return GetBonus(34);
            }
            set
            {
                SetBonus(34, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_35_Name
        {
            get
            {
                return GetSkill(34);
            }
            set
            {
                SetSkill(34, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_36_Value
        {
            get
            {
                return GetBonus(35);
            }
            set
            {
                SetBonus(35, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_36_Name
        {
            get
            {
                return GetSkill(35);
            }
            set
            {
                SetSkill(35, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_37_Value
        {
            get
            {
                return GetBonus(36);
            }
            set
            {
                SetBonus(36, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_37_Name
        {
            get
            {
                return GetSkill(36);
            }
            set
            {
                SetSkill(36, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_38_Value
        {
            get
            {
                return GetBonus(37);
            }
            set
            {
                SetBonus(37, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_38_Name
        {
            get
            {
                return GetSkill(37);
            }
            set
            {
                SetSkill(37, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_39_Value
        {
            get
            {
                return GetBonus(38);
            }
            set
            {
                SetBonus(38, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_39_Name
        {
            get
            {
                return GetSkill(38);
            }
            set
            {
                SetSkill(38, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_40_Value
        {
            get
            {
                return GetBonus(39);
            }
            set
            {
                SetBonus(39, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_40_Name
        {
            get
            {
                return GetSkill(39);
            }
            set
            {
                SetSkill(39, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_41_Value
        {
            get
            {
                return GetBonus(40);
            }
            set
            {
                SetBonus(40, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_41_Name
        {
            get
            {
                return GetSkill(40);
            }
            set
            {
                SetSkill(40, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_42_Value
        {
            get
            {
                return GetBonus(41);
            }
            set
            {
                SetBonus(41, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_42_Name
        {
            get
            {
                return GetSkill(41);
            }
            set
            {
                SetSkill(41, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_43_Value
        {
            get
            {
                return GetBonus(42);
            }
            set
            {
                SetBonus(42, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_43_Name
        {
            get
            {
                return GetSkill(42);
            }
            set
            {
                SetSkill(42, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_44_Value
        {
            get
            {
                return GetBonus(43);
            }
            set
            {
                SetBonus(43, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_44_Name
        {
            get
            {
                return GetSkill(43);
            }
            set
            {
                SetSkill(43, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_45_Value
        {
            get
            {
                return GetBonus(44);
            }
            set
            {
                SetBonus(44, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_45_Name
        {
            get
            {
                return GetSkill(44);
            }
            set
            {
                SetSkill(44, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_46_Value
        {
            get
            {
                return GetBonus(45);
            }
            set
            {
                SetBonus(45, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_46_Name
        {
            get
            {
                return GetSkill(45);
            }
            set
            {
                SetSkill(45, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_47_Value
        {
            get
            {
                return GetBonus(46);
            }
            set
            {
                SetBonus(46, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_47_Name
        {
            get
            {
                return GetSkill(46);
            }
            set
            {
                SetSkill(46, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_48_Value
        {
            get
            {
                return GetBonus(47);
            }
            set
            {
                SetBonus(47, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_48_Name
        {
            get
            {
                return GetSkill(47);
            }
            set
            {
                SetSkill(47, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_49_Value
        {
            get
            {
                return GetBonus(48);
            }
            set
            {
                SetBonus(48, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_49_Name
        {
            get
            {
                return GetSkill(48);
            }
            set
            {
                SetSkill(48, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_50_Value
        {
            get
            {
                return GetBonus(49);
            }
            set
            {
                SetBonus(49, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_50_Name
        {
            get
            {
                return GetSkill(49);
            }
            set
            {
                SetSkill(49, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_51_Value
        {
            get
            {
                return GetBonus(50);
            }
            set
            {
                SetBonus(50, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_51_Name
        {
            get
            {
                return GetSkill(50);
            }
            set
            {
                SetSkill(50, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_52_Value
        {
            get
            {
                return GetBonus(51);
            }
            set
            {
                SetBonus(51, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_52_Name
        {
            get
            {
                return GetSkill(51);
            }
            set
            {
                SetSkill(51, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_53_Value
        {
            get
            {
                return GetBonus(52);
            }
            set
            {
                SetBonus(52, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_53_Name
        {
            get
            {
                return GetSkill(52);
            }
            set
            {
                SetSkill(52, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_54_Value
        {
            get
            {
                return GetBonus(53);
            }
            set
            {
                SetBonus(53, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_54_Name
        {
            get
            {
                return GetSkill(53);
            }
            set
            {
                SetSkill(53, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_55_Value
        {
            get
            {
                return GetBonus(54);
            }
            set
            {
                SetBonus(54, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_55_Name
        {
            get
            {
                return GetSkill(54);
            }
            set
            {
                SetSkill(54, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_56_Value
        {
            get
            {
                return GetBonus(55);
            }
            set
            {
                SetBonus(55, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_56_Name
        {
            get
            {
                return GetSkill(55);
            }
            set
            {
                SetSkill(55, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_57_Value
        {
            get
            {
                return GetBonus(56);
            }
            set
            {
                SetBonus(56, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_57_Name
        {
            get
            {
                return GetSkill(56);
            }
            set
            {
                SetSkill(56, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_58_Value
        {
            get
            {
                return GetBonus(57);
            }
            set
            {
                SetBonus(57, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_58_Name
        {
            get
            {
                return GetSkill(57);
            }
            set
            {
                SetSkill(57, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_59_Value
        {
            get
            {
                return GetBonus(58);
            }
            set
            {
                SetBonus(58, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_59_Name
        {
            get
            {
                return GetSkill(58);
            }
            set
            {
                SetSkill(58, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public double Skill_60_Value
        {
            get
            {
                return GetBonus(59);
            }
            set
            {
                SetBonus(59, value);
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill_60_Name
        {
            get
            {
                return GetSkill(59);
            }
            set
            {
                SetSkill(59, value);
            }
        }

    }

    #region Stygian Abyss
    [Flags]
    public enum SAAbsorptionAttribute
    {
        EaterFire = 0x00000001,
        EaterCold = 0x00000002,
        EaterPoison = 0x00000004,
        EaterEnergy = 0x00000008,
        EaterKinetic = 0x00000010,
        EaterDamage = 0x00000020,
        ResonanceFire = 0x00000040,
        ResonanceCold = 0x00000080,
        ResonancePoison = 0x00000100,
        ResonanceEnergy = 0x00000200,
        ResonanceKinetic = 0x00000400,
        /*Soul Charge is wrong.
         * Do not use these types.
         * Use AosArmorAttribute type only.
         * Fill these in with any new attributes.*/
        SoulChargeFire = 0x00000800,
        SoulChargeCold = 0x00001000,
        SoulChargePoison = 0x00002000,
        SoulChargeEnergy = 0x00004000,
        SoulChargeKinetic = 0x00008000,
        CastingFocus = 0x00010000
    }

    public sealed class SAAbsorptionAttributes : BaseAttributes
    {
        public static bool IsValid(SAAbsorptionAttribute attribute)
        {
            if (!Core.SA)
            {
                return false;
            }

            return true;
        }

        public static int[] GetValues(Mobile m, params SAAbsorptionAttribute[] attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static int[] GetValues(Mobile m, IEnumerable<SAAbsorptionAttribute> attributes)
        {
            return EnumerateValues(m, attributes).ToArray();
        }

        public static IEnumerable<int> EnumerateValues(Mobile m, IEnumerable<SAAbsorptionAttribute> attributes)
        {
            return attributes.Select(a => GetValue(m, a));
        }

        public static int GetValue(Mobile m, SAAbsorptionAttribute attribute)
        {
            if (World.Loading || !IsValid(attribute))
            {
                return 0;
            }

            int value = 0;

            #region Enhancement
            value += Enhancement.GetValue(m, attribute);
            #endregion

            for (int i = 0; i < m.Items.Count; ++i)
            {
                SAAbsorptionAttributes attrs = RunicReforging.GetSAAbsorptionAttributes(m.Items[i]);

                if (attrs != null)
                    value += attrs[attribute];
            }

            value += SkillMasterySpell.GetAttributeBonus(m, attribute);

            return value;
        }

        public SAAbsorptionAttributes(Item owner)
            : base(owner)
        {
        }

        public SAAbsorptionAttributes(Item owner, SAAbsorptionAttributes other)
            : base(owner, other)
        {
        }

        public SAAbsorptionAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public int this[SAAbsorptionAttribute attribute]
        {
            get
            {
                return GetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterFire
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterFire];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterFire] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterCold
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterCold];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterCold] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterPoison
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterPoison];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterPoison] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterEnergy
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterEnergy];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterEnergy] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterKinetic
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterKinetic];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterKinetic] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int EaterDamage
        {
            get
            {
                return this[SAAbsorptionAttribute.EaterDamage];
            }
            set
            {
                this[SAAbsorptionAttribute.EaterDamage] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceFire
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceFire];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceFire] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceCold
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceCold];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceCold] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonancePoison
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonancePoison];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonancePoison] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceEnergy
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceEnergy];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceEnergy] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ResonanceKinetic
        {
            get
            {
                return this[SAAbsorptionAttribute.ResonanceKinetic];
            }
            set
            {
                this[SAAbsorptionAttribute.ResonanceKinetic] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeFire
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeFire];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeFire] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeCold
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeCold];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeCold] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargePoison
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargePoison];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargePoison] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeEnergy
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeEnergy];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeEnergy] = value;
            }
        }

        //[CommandProperty(AccessLevel.GameMaster)]
        public int SoulChargeKinetic
        {
            get
            {
                return this[SAAbsorptionAttribute.SoulChargeKinetic];
            }
            set
            {
                //this[SAAbsorptionAttribute.SoulChargeKinetic] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int CastingFocus
        {
            get
            {
                return this[SAAbsorptionAttribute.CastingFocus];
            }
            set
            {
                this[SAAbsorptionAttribute.CastingFocus] = value;
            }
        }
    }
    #endregion

    [Flags]
    public enum AosElementAttribute
    {
        Physical = 0x00000001,
        Fire = 0x00000002,
        Cold = 0x00000004,
        Poison = 0x00000008,
        Energy = 0x00000010,
        Chaos = 0x00000020,
        Direct = 0x00000040
    }

    public sealed class AosElementAttributes : BaseAttributes
    {
        public AosElementAttributes(Item owner)
            : base(owner)
        {
        }

        public AosElementAttributes(Item owner, AosElementAttributes other)
            : base(owner, other)
        {
        }

        public AosElementAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public int this[AosElementAttribute attribute]
        {
            get
            {
                return ExtendedGetValue((int)attribute);
            }
            set
            {
                SetValue((int)attribute, value);
            }
        }

        public int ExtendedGetValue(int bitmask)
        {
            int value = GetValue(bitmask);

            XmlAosAttributes xaos = (XmlAosAttributes)XmlAttach.FindAttachment(Owner, typeof(XmlAosAttributes));

            if (xaos != null)
            {
                value += xaos.GetValue(bitmask);
            }

            return (value);
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Physical
        {
            get
            {
                return this[AosElementAttribute.Physical];
            }
            set
            {
                this[AosElementAttribute.Physical] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Fire
        {
            get
            {
                return this[AosElementAttribute.Fire];
            }
            set
            {
                this[AosElementAttribute.Fire] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Cold
        {
            get
            {
                return this[AosElementAttribute.Cold];
            }
            set
            {
                this[AosElementAttribute.Cold] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Poison
        {
            get
            {
                return this[AosElementAttribute.Poison];
            }
            set
            {
                this[AosElementAttribute.Poison] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Energy
        {
            get
            {
                return this[AosElementAttribute.Energy];
            }
            set
            {
                this[AosElementAttribute.Energy] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Chaos
        {
            get
            {
                return this[AosElementAttribute.Chaos];
            }
            set
            {
                this[AosElementAttribute.Chaos] = value;
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Direct
        {
            get
            {
                return this[AosElementAttribute.Direct];
            }
            set
            {
                this[AosElementAttribute.Direct] = value;
            }
        }
    }

    [Flags]
    public enum NegativeAttribute
    {
        Brittle = 0x00000001,
        Prized = 0x00000002,
        Massive = 0x00000004,
        Unwieldly = 0x00000008,
        Antique = 0x00000010,
        NoRepair = 0x00000020
    }

    public sealed class NegativeAttributes : BaseAttributes
    {
        public NegativeAttributes(Item owner)
            : base(owner)
        {
        }

        public NegativeAttributes(Item owner, NegativeAttributes other)
            : base(owner, other)
        {
        }

        public NegativeAttributes(Item owner, GenericReader reader)
            : base(owner, reader)
        {
        }

        public void GetProperties(ObjectPropertyList list, Item item)
        {
            if (NoRepair > 0)
                list.Add(1151782);

            if (Brittle > 0 ||
                item is BaseWeapon && ((BaseWeapon)item).Attributes.Brittle > 0 ||
                item is BaseArmor && ((BaseArmor)item).Attributes.Brittle > 0 ||
                item is BaseJewel && ((BaseJewel)item).Attributes.Brittle > 0 ||
                item is BaseClothing && ((BaseClothing)item).Attributes.Brittle > 0)
                list.Add(1116209);

            if (Prized > 0)
                list.Add(1154910);

            //if (Massive > 0)
            //    list.Add(1038003);

            //if (Unwieldly > 0)
            //    list.Add(1154909);

            if (Antique > 0)
                list.Add(1076187);
        }

        public const double CombatDecayChance = 0.02;

        public static void OnCombatAction(Mobile m)
        {
            if (m == null || !m.Alive)
                return;

            var list = new List<Item>();

            foreach (var item in m.Items.Where(i => i is IDurability))
            {
                NegativeAttributes attrs = RunicReforging.GetNegativeAttributes(item);

                if (attrs != null && attrs.Antique > 0 && CombatDecayChance > Utility.RandomDouble())
                {
                    list.Add(item);
                }
            }

            foreach (var item in list)
            {
                IDurability dur = item as IDurability;

                if (dur == null)
                    continue;

                if (dur.HitPoints >= 1)
                {
                    if (dur.HitPoints >= 4)
                    {
                        dur.HitPoints -= 4;
                    }
                    else
                    {
                        dur.HitPoints = 0;
                    }
                }
                else
                {
                    if (dur.MaxHitPoints > 1)
                    {
                        dur.MaxHitPoints--;

                        if (item.Parent is Mobile)
                            ((Mobile)item.Parent).LocalOverheadMessage(Server.Network.MessageType.Regular, 0x3B2, 1061121); // Your equipment is severely damaged.
                    }
                    else
                    {
                        item.Delete();
                    }
                }
            }

            ColUtility.Free(list);
        }

        public int this[NegativeAttribute attribute]
        {
            get { return GetValue((int)attribute); }
            set { SetValue((int)attribute, value); }
        }

        public override string ToString()
        {
            return "...";
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Brittle { get { return this[NegativeAttribute.Brittle]; } set { this[NegativeAttribute.Brittle] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Prized { get { return this[NegativeAttribute.Prized]; } set { this[NegativeAttribute.Prized] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Massive { get { return this[NegativeAttribute.Massive]; } set { this[NegativeAttribute.Massive] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Unwieldly { get { return this[NegativeAttribute.Unwieldly]; } set { this[NegativeAttribute.Unwieldly] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Antique { get { return this[NegativeAttribute.Antique]; } set { this[NegativeAttribute.Antique] = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int NoRepair { get { return this[NegativeAttribute.NoRepair]; } set { this[NegativeAttribute.NoRepair] = value; } }
    }

    [PropertyObject]
    public abstract class BaseAttributes
    {
        private readonly Item m_Owner;
        private uint m_Names;
        private int[] m_Values;

        private static readonly int[] m_Empty = new int[0];

        public bool IsEmpty
        {
            get
            {
                return (m_Names == 0);
            }
        }
        public Item Owner
        {
            get
            {
                return m_Owner;
            }
        }

        public BaseAttributes(Item owner)
        {
            m_Owner = owner;
            m_Values = m_Empty;
        }

        public BaseAttributes(Item owner, BaseAttributes other)
        {
            m_Owner = owner;
            m_Values = new int[other.m_Values.Length];
            other.m_Values.CopyTo(m_Values, 0);
            m_Names = other.m_Names;
        }

        public BaseAttributes(Item owner, GenericReader reader)
        {
            m_Owner = owner;

            int version = reader.ReadByte();

            switch (version)
            {
                case 1:
                    {
                        m_Names = reader.ReadUInt();
                        m_Values = new int[reader.ReadEncodedInt()];

                        for (int i = 0; i < m_Values.Length; ++i)
                            m_Values[i] = reader.ReadEncodedInt();

                        break;
                    }
                case 0:
                    {
                        m_Names = reader.ReadUInt();
                        m_Values = new int[reader.ReadInt()];

                        for (int i = 0; i < m_Values.Length; ++i)
                            m_Values[i] = reader.ReadInt();

                        break;
                    }
            }
        }

        public void Serialize(GenericWriter writer)
        {
            writer.Write((byte)1); // version;

            writer.Write((uint)m_Names);
            writer.WriteEncodedInt((int)m_Values.Length);

            for (int i = 0; i < m_Values.Length; ++i)
                writer.WriteEncodedInt((int)m_Values[i]);
        }

        public int GetValue(int bitmask)
        {
            if (!Core.AOS)
                return 0;

            uint mask = (uint)bitmask;

            if ((m_Names & mask) == 0)
                return 0;

            int index = GetIndex(mask);

            if (index >= 0 && index < m_Values.Length)
                return m_Values[index];

            return 0;
        }

        public virtual void SetValue(int bitmask, int value)
        {
            uint mask = (uint)bitmask;

            if (value != 0)
            {
                if ((m_Names & mask) != 0)
                {
                    int index = GetIndex(mask);

                    if (index >= 0 && index < m_Values.Length)
                        m_Values[index] = value;
                }
                else
                {
                    int index = GetIndex(mask);

                    if (index >= 0 && index <= m_Values.Length)
                    {
                        int[] old = m_Values;
                        m_Values = new int[old.Length + 1];

                        for (int i = 0; i < index; ++i)
                            m_Values[i] = old[i];

                        m_Values[index] = value;

                        for (int i = index; i < old.Length; ++i)
                            m_Values[i + 1] = old[i];

                        m_Names |= mask;
                    }
                }
            }
            else if ((m_Names & mask) != 0)
            {
                int index = GetIndex(mask);

                if (index >= 0 && index < m_Values.Length)
                {
                    m_Names &= ~mask;

                    if (m_Values.Length == 1)
                    {
                        m_Values = m_Empty;
                    }
                    else
                    {
                        int[] old = m_Values;
                        m_Values = new int[old.Length - 1];

                        for (int i = 0; i < index; ++i)
                            m_Values[i] = old[i];

                        for (int i = index + 1; i < old.Length; ++i)
                            m_Values[i - 1] = old[i];
                    }
                }
            }

            if (m_Owner != null && m_Owner.Parent is Mobile)
            {
                Mobile m = (Mobile)m_Owner.Parent;

                m.CheckStatTimers();
                m.UpdateResistances();
                m.Delta(MobileDelta.Stat | MobileDelta.WeaponDamage | MobileDelta.Hits | MobileDelta.Stam | MobileDelta.Mana);
            }

            if (m_Owner != null)
                m_Owner.InvalidateProperties();
        }

        private int GetIndex(uint mask)
        {
            int index = 0;
            uint ourNames = m_Names;
            uint currentBit = 1;

            while (currentBit != mask)
            {
                if ((ourNames & currentBit) != 0)
                    ++index;

                if (currentBit == 0x80000000)
                    return -1;

                currentBit <<= 1;
            }

            return index;
        }
    }
}

**EDIT**
It doesn't like the 30's for some reason.. yeah it desn't like anything more than around 30 then it starts to duplicate in the 30ish range a little into the 40's and then it's normal again.. weird..
View attachment 20210

A quick glance says it's probably these two still being at "i < 16" instead of 57. There are still only 58 skills in normal UO right? :eek::p

C#:
public bool GetValues(int index, out SkillName skill, out double bonus)
        {
            int v = GetValue(1 << index);
            int vSkill = 0;
            int vBonus = 0;

            for (int i = 0; i < 16; ++i)
            {
                vSkill <<= 1;
                vSkill |= (v & 1);
                v >>= 1;

                vBonus <<= 1;
                vBonus |= (v & 1);
                v >>= 1;
            }

            skill = (SkillName)vSkill;
            bonus = (double)vBonus / 10;

            return (bonus != 0);
        }

        public void SetValues(int index, SkillName skill, double bonus)
        {
            int v = 0;
            int vSkill = (int)skill;
            int vBonus = (int)(bonus * 10);

            for (int i = 0; i < 16; ++i)
            {
                v <<= 1;
                v |= (vBonus & 1);
                vBonus >>= 1;

                v <<= 1;
                v |= (vSkill & 1);
                vSkill >>= 1;
            }

            SetValue(1 << index, v);
        }
 
Last edited:
I saw those but wasn't sure about adjusting them since they're already at 16, also lol yeah I removed 2 and brought it down to 58 because yes there are indeed only 58 skills :p

**EDIT**
Nope it did not like me changing that number to 57 lol, doesn't allow it to even work but does compile.
 
Last edited:
I saw those but wasn't sure about adjusting them since they're already at 16, also lol yeah I removed 2 and brought it down to 58 because yes there are indeed only 58 skills :p

**EDIT**
Nope it did not like me changing that number to 57 lol, doesn't allow it to even work but does compile.
Ohhh, it uses UInt32 is why. I didn't really pay much attention to that. Not sure if we could easily swap uint for ulong without adding/changing additional code.
 
Is there a specific reason you're wanting all 58 skills or was it just because? Haha. Either way, if it did work without additional changes required, I doubt you would want all 58 skills listed in the OPL anyway and it'd be much easier/less to read with a single line along the lines of "All Skills +10" or "Bonus To All Skills" or something like that.

I'm sure this could still be done or if not, I know it can be done using the ancient smithy hammer way. I made different skill template earrings years ago for RunUO 2.2 that decreased all skills to 0 and increased 7 to GM as well as different stats using that method.
 
Yeah I wasn't sure how to code the smithy hammer so I left it alone, and as far as all 58 Skills, mostly just because I'm crazy I wanted the "option" of adding all 58 skills lol.
 
From what I could tell on the ring you made using that method before you went back to the AOS way of doing it, everything appeared to be correct.

It is a lot of code lines doing that for 58 skills though haha.
 
Yes it would be lol, I just set it to 30 haha if I want more I'll have to do it the other way for now :)

I might make one with all skills just to do it haha
 
I mean you could also go a bit further, and if you have everything of a skill group, it just says the skillgroup + X
 
Back