Go Back   RunUO - Ultima Online Emulation > RunUO > Server Support on Windows

Server Support on Windows Get (and give) support on general questions related to the RunUO server itself.

Reply
 
Thread Tools Display Modes
Old 11-06-2005, 11:11 PM   #1 (permalink)
 
Join Date: Sep 2005
Age: 34
Posts: 14
Default Help with a server crash

Every long once in a while my server will be halted with this error:
Quote:
Error:
System.InvalidCastException: Specified cast is not valid.
at Server.Mobiles.AdvancedPlayerMobile.Bonuses(AosAtt ribute attribute)
at Server.Items.BaseWeapon.ScaleDamageAOS(Mobile attacker, Double damage, Boo
lean checkSkills, Boolean checkAbility)
at Server.Items.BaseWeapon.GetStatusDamage(Mobile from, Int32& min, Int32& ma
x)
at Server.Network.MobileStatusExtended..ctor(Mobile m)
at Server.Mobile.ProcessDelta()
at Server.Mobile.ProcessDeltaQueue()
at Server.Core.Main(String[] args)
Crash: Backing up...done
Crash: Generating report...done
Crash: Restarting...done
Warning:
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.Sleep(Int32 millisecondsTimeout)
at Server.TimerThread.TimerMain()
Here is the crash log:

Quote:
Server Crash Report
===================

RunUO Version 1.0.0, Build 36918
Operating System: Microsoft Windows NT 5.1.2600.0
.NET Framework: 1.1.4322.2032
Time: 11/6/2005 8:55:46 PM
Mobiles: 3344
Items: 61686
Clients:
- Count: 7
+ : (account = Aaron) (mobile = 0x16DB 'Aaron Vanier')
+ : (account = nerano) (mobile = 0xAC4 'Nerano')
+ : (account = boromir) (mobile = 0xD82 'Dirzan Klell')
+ : (account = gouldon) (mobile = 0x12AE 'Toradon Cosidon')
+ : (account = phalar) (mobile = 0xA13 'Sabac Kass')
+ : (account = Alandos) (mobile = 0x2804 'Serin Valimar')
+ : (account = harkonnen) (mobile = 0x2B 'Glossu')

Exception:
System.InvalidCastException: Specified cast is not valid.
at Server.Mobiles.AdvancedPlayerMobile.Bonuses(AosAtt ribute attribute)
at Server.Items.BaseWeapon.ScaleDamageAOS(Mobile attacker, Double damage, Boolean checkSkills, Boolean checkAbility)
at Server.Items.BaseWeapon.GetStatusDamage(Mobile from, Int32& min, Int32& max)
at Server.Network.MobileStatusExtended..ctor(Mobile m)
at Server.Mobile.ProcessDelta()
at Server.Mobile.ProcessDeltaQueue()
at Server.Core.Main(String[] args)
I am posting my advanced player mobile script:

Code:
/*******		LUCENT ECLIPSE - [www.lucenteclipse.com]		********
****																****
**** [Title: Advanced Player Mobile]								****
**** [Type: Mobile]													****
**** [Comments: None]												****
**** [Author(s): Marox <marox@siol.net>]							****
****																****
***********************************************************************/



using Server;
using System;
using System.Collections;
using Server.Accounting;
using Server.Network;
using Server.Items;
using Server.ContextMenus;
using Server.Mobiles;
using Server.Gumps;
using Server.Engines.PartySystem;
using Server.Guilds;

using Server.Engines.Traits;
using Server.Engines.Categories;
using Server.Engines.Races;
using Server.Engines.Perks;
using Server.Engines.Quests;

namespace Server.ContextMenus
{
	public class CharScreenEntry : ContextMenuEntry
	{
		private AdvancedPlayerMobile from;

		public CharScreenEntry( AdvancedPlayerMobile from_p ) : base( 6099 )	// Character Screen
		{
			Color=0xFF9999;
			Enabled=true;
			from=from_p;
		}

		public override void OnClick()
		{
			from.SendGump(new CharScreen(from, 1, false));
		}
	}
}

namespace Server.Mobiles
{
	public enum TmpFlag
	{
			CustomNightsight=0x1,
			HasAbilitiesGump=0x2,
			StopNextFOverride=0x4,
	}

	public class AdvancedPlayerMobile : PlayerMobile
	{


		// Setting stuff in-game, some is handled here, the rest through CharScreen.
		// Current GM interface with all the engines. I'm lazy when it comes to making it easy for GMs.

		[CommandProperty( AccessLevel.GameMaster )]
		public RaceType Player_Race
		{
			get{ return Race; }
			set{ Race = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public CategoryType Player_Category
		{
			get{ return Category; }
			set{ Category = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Perk_Pts
		{
			get{ return PerkPts(); }
			set{ SetPerkPts(value); }
		}

		[CommandProperty( AccessLevel.Administrator )]
		public int Prestige_Perk_Pts
		{
			get{ return PrestigePerkPts(); }
			set{ SetPrestigePerkPts(value); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public QuestName CurrentQuest_Name
		{
			get{ return CurrentQuest.Quest; }
			set{ CurrentQuest.Quest=value; }
		}


		[CommandProperty( AccessLevel.GameMaster )]
		public int CurrentQuest_Stage
		{
			get{ return CurrentQuest.Stage; }
			set{ CurrentQuest.Stage=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Ar_Penalty
		{
			get{ return ArmorPenalty; }
			set{ }
		}

		// TRAITS

		[CommandProperty( AccessLevel.GameMaster )]
		public Trait Add_Trait
		{
			get{ return 0; }
			set{ TraitRegister.OnApplied(value, this); }	// add bonuses also
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public Trait Remove_Trait
		{
			get{ return 0; }
			set{ TraitRegister.RemoveTrait(value, this); }	// does NOT remove the permanent bonuses (e.g. statcap) the trait may have given!!!!
		}

		// END TRAITS

		// PERKS

		[CommandProperty( AccessLevel.GameMaster )]
		public Perk Add_Perk
		{
			get{ return 0; }
			set{ PerkRegister.OnApplied(value, this); }	// check for collision
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public Perk Remove_Perk
		{
			get{ return 0; }
			set{ PerkRegister.RemovePerk(value, this); }	// CAREFUL!! screws up things on armor perks!
		}

		// END PERKS

		// GM SETTING OF SKILL SPECIALIZATIONS

		// Sorry about this humungous list of copy-pasted text. Apparently I got really lazy on the GM interface and instead put it straight into
		// these menus. Although the dynamic menus would be better and easier to read but hey, it's not like you'll be setting this every day.
		// Or atleast you shouldnt be >_>.

		// P.S. there is no trait listing for current traits of the mobile -- refer to the targeted CharScreen when on GM privileges.

		// PRIMARY SKILLS

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName PrimarySkill1
		{
			get{ return PrimarySkills[0]; }
			set{ PrimarySkills[0]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName PrimarySkill2
		{
			get{ return PrimarySkills[1]; }
			set{ PrimarySkills[1]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName PrimarySkill3
		{
			get{ return PrimarySkills[2]; }
			set{ PrimarySkills[2]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName PrimarySkill4
		{
			get{ return PrimarySkills[3]; }
			set{ PrimarySkills[3]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName PrimarySkill5
		{
			get{ return PrimarySkills[4]; }
			set{ PrimarySkills[4]=value; }
		}

		// SECONDARY SKILLS

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName SecondarySkill1
		{
			get{ return SecondarySkills[0]; }
			set{ SecondarySkills[0]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName SecondarySkill2
		{
			get{ return SecondarySkills[1]; }
			set{ SecondarySkills[1]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName SecondarySkill3
		{
			get{ return SecondarySkills[2]; }
			set{ SecondarySkills[2]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName SecondarySkill4
		{
			get{ return SecondarySkills[3]; }
			set{ SecondarySkills[3]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName SecondarySkill5
		{
			get{ return SecondarySkills[4]; }
			set{ SecondarySkills[4]=value; }
		}

		// TERTIARY SKILLS

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName TertiarySkill1
		{
			get{ return TertiarySkills[0]; }
			set{ TertiarySkills[0]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName TertiarySkill2
		{
			get{ return TertiarySkills[1]; }
			set{ TertiarySkills[1]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName TertiarySkill3
		{
			get{ return TertiarySkills[2]; }
			set{ TertiarySkills[2]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName TertiarySkill4
		{
			get{ return TertiarySkills[3]; }
			set{ TertiarySkills[3]=value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName TertiarySkill5
		{
			get{ return TertiarySkills[4]; }
			set{ TertiarySkills[4]=value; }
		}

		// END OF SKILL SPECIALIZATION

		[CommandProperty( AccessLevel.GameMaster )]		// Redefining -- required for some traits.
		public override int HitsMax
		{
			get
			{
				int HpBonus=50;		// default hp bonus

				if (TraitRegister.HasTrait(Trait.Sickly, this))
					HpBonus-=10;	// decrement by 10

				return HpBonus + (Str / 2);
			}
		}

		[CommandProperty( AccessLevel.GameMaster )]		// Redefining -- required for some traits.
		public override int ManaMax
		{
			get
			{
				int Mana=Int;	// default

				if (TraitRegister.HasTrait(Trait.Secular, this))
					Mana-=10;	// decrement by 10

				if (Mana < 0)
					Mana=0;

				return Mana;
			}
		}

		public override int Luck
		{ 
			get
			{ 
				int LuckBonus=0;

				if (TraitRegister.HasTrait(Trait.Lucky, this))
					LuckBonus+=40;	// increment by 40

				if (LuckBonus < 0)
					LuckBonus=0;

				return LuckBonus + AosAttributes.GetValue( this, AosAttribute.Luck ); 
			} 
		}

		public override void OnKillsChange( int oldValue )
		{
			if (TraitRegister.HasTrait(Trait.Villain, this) && Kills < oldValue)
				Kills=oldValue;

			return;
		}

		public override void ComputeBaseLightLevels( out int global, out int personal )
		{
			global = LightCycle.ComputeLevelFor( this );

			if ( this.LightLevel < 21 && (AosAttributes.GetValue( this, AosAttribute.NightSight ) > 0 || HasTempFlag(TmpFlag.CustomNightsight)))
				personal = 21;
			else
				personal = this.LightLevel;
		}

		public Trait [] Traits=new Trait [30]; // max 30 traits.
		public Perk [] Perks=new Perk [100];	// max 100 perks.

		public int PerkPoints;	// no need to have two variables, function splits point types below

		public SkillName [] PrimarySkills=new SkillName [5];	// 5 per each
		public SkillName [] SecondarySkills=new SkillName [5];
		public SkillName [] TertiarySkills=new SkillName [5];

		public RaceType Race;
		public CategoryType Category;

		public TmpFlag TempFlags;	// temporary flags, resets on server restart
		public TmpFlag PFlags;	// non-temporary flags

		public QuestInfo CurrentQuest=new QuestInfo();
		public QuestName FinishedQuests;

		public int GainablePerkPts;

		public int ArmorPenalty;

		// a few helper functions below

		public int CriticalChance()		// based off items and perks
		{
			int chance=0;

			for (int x=1; x <= 24; x++)		// get crit chance from all items
			{
				if ( x != 9 && x != 11 && x != 15 && x != 16 && x != 21  )
				{
					Item Check=FindItemOnLayer((Layer)x);

					if (Check != null)
					{	
						if (Check is BaseArmor)
							chance+=((BaseArmor)Check).CriticalChance;

						else if (Check is BaseWeapon)
							chance+=((BaseWeapon)Check).CriticalChance;

						else if (Check is BaseJewel)
							chance+=((BaseJewel)Check).CriticalChance;
					}
				}
			}
			
			// finished grabbing all item bonuses to critical chance. apply perk bonuses below.

			// placeholder, add perks here

			if (chance > 100)
				chance=100;

			else if (chance < 0)
				chance=0;

			return chance;

		}

		public int MaxWeightBonus()
		{
			int bonus=0;
			
			if ( TraitRegister.HasTrait(Trait.StrongBack, this) )
					bonus+=30;

			if ( PerkRegister.HasPerk(Perk.PackRat, this) )
					bonus+=30;

			return bonus;
		}


		public int Bonuses(AosAttribute attribute)
		{
			int bonus=0;

			switch((int)attribute)
			{
				case (int)AosAttribute.EnhancePotions:
				{
					if (TraitRegister.HasTrait(Trait.HerbalAdaption, this))
						bonus+=15;	//15% to EP if i got herbal adaption

					if (PerkRegister.HasPerk(Perk.Scholar, this))
						bonus+=10;	//10% to EP if im scholar

					if (PerkRegister.HasPerk(Perk.ControlledDosage, this))
						bonus+=10;	//10% to EP if i got C.D.

					if (PerkRegister.HasPerk(Perk.HerbalKnowledge, this))
						bonus+=15;	//15% to EP if i got HK

					if (PerkRegister.HasPerk(Perk.SupernaturalMetabolism, this))
						bonus+=20;	//20% to EP if i got SM

					break;
				}

				case (int)AosAttribute.RegenHits:
				{
					if (TraitRegister.HasTrait(Trait.FastMetabolism, this))
						bonus+=4;	//4 RHP if i got fast metabolism

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=3;	//-3 RHP if I'm nocturnal and it's day

						else
							bonus+=3;	//+3 RHP if I'm nocturnal and it's night
					}

					break;
				}

				case (int)AosAttribute.RegenStam:
				{
					if (TraitRegister.HasTrait(Trait.Conditioning, this))
						bonus+=3;	//3 RSTAM if I got conditioning

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=2;	//-2 RSTAM if I'm nocturnal and it's day

						else
							bonus+=2;	//+2 RSTAM if I'm nocturnal and it's night
					}

					if (PerkRegister.HasPerk(Perk.Tireless, this))
						bonus+=2;	//2 to RSTAM if i got Tireless

					if (PerkRegister.HasPerk(Perk.Athletics, this))
						bonus+=4;	//4 to RSTAM if i got athl

					if (PerkRegister.HasPerk(Perk.SupernaturalBreathControl, this))
						bonus+=4;	//4 to RSTAM if i got SBC

					break;
				}

				case (int)AosAttribute.RegenMana:
				{
					if (TraitRegister.HasTrait(Trait.Imperturbable, this))
						bonus+=1;	//1 RM if I'm imperturbable

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=1;	//-1 RM if I'm nocturnal and it's day

						else
							bonus+=1;	//+1 RM if I'm nocturnal and it's night
					}

					if (PerkRegister.HasPerk(Perk.SuperiorConcentration, this))
						bonus+=1;	//1 to RM if i got SC

					if (PerkRegister.HasPerk(Perk.ArcaneMind, this))
						bonus+=2;	//2 to RM if i got AM

					if (PerkRegister.HasPerk(Perk.MasterOfMana, this))
						bonus+=2;	//1 to RM if i got MOM

					if (PerkRegister.HasPerk(Perk.Athletics, this))
						bonus+=1;	//4 to RM if i got athl

					if (PerkRegister.HasPerk(Perk.SupernaturalBreathControl, this))
						bonus+=3;	//4 to RM if i got SBC

					break;
				}

				case (int)AosAttribute.DefendChance:
				{
					if (TraitRegister.HasTrait(Trait.StoneWall, this))
						bonus+=10;	//+10 DCI if I'm a stonewall

					if (TraitRegister.HasTrait(Trait.Pacifist, this))
						bonus+=10;	//+10 DCI if I'm a pacifist

					if (TraitRegister.HasTrait(Trait.Psychotic, this))
						bonus-=20;	//-20 DCI if I'm psychotic.

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=5;	//-5 DCI if I'm nocturnal and it's day

						else
							bonus+=5;	//+5 DCI if I'm nocturnal and it's night
					}

					if (PerkRegister.HasPerk(Perk.ProperShieldHandling, this) && FindItemOnLayer(Layer.TwoHanded) != null && FindItemOnLayer(Layer.TwoHanded) is BaseShield)
						bonus+=10;	//10% to DCI if i got PSH

					if (PerkRegister.HasPerk(Perk.Countermeasures, this) && FindItemOnLayer(Layer.TwoHanded) != null && FindItemOnLayer(Layer.TwoHanded) is BaseShield)
						bonus+=5;	//5% to DCI if i got CM

					if (PerkRegister.HasPerk(Perk.ShieldBash, this) && FindItemOnLayer(Layer.TwoHanded) != null && FindItemOnLayer(Layer.TwoHanded) is BaseShield)
						bonus+=5;	//5% to DCI if i got SB

					if (Party != null)
					{
						if ( ((Party)Party).Leader != null && ((Party)Party).Leader != this && ((Party)Party).Leader is AdvancedPlayerMobile)
						{
							AdvancedPlayerMobile PartyLeader=((Party)Party).Leader as AdvancedPlayerMobile;

							if ( InRange( PartyLeader.Location, 20 ) && PerkRegister.HasPerk(Perk.Leadership, PartyLeader) )
								bonus+=10;	//10% to DCI if i partyleader has leadership
						}
					}

					if (PerkRegister.HasPerk(Perk.Survivalist, this))
						bonus+=5;	//5% to DCI if i got survivalist

					break;
				}

				case (int)AosAttribute.AttackChance:
				{
					if (TraitRegister.HasTrait(Trait.EyeDamage, this))
					{
						bonus-=10;	//-10 HCI if I got eye damage

						if (Weapon is BaseRanged)
							bonus-=5;	//-5 HCI if I got eye damage and try to use ranged weapons (plus previous -10 HCI)
					}

					if (TraitRegister.HasTrait(Trait.OneHander, this))
					{
						if (((BaseWeapon)Weapon).Layer == Layer.OneHanded && !(((BaseWeapon)Weapon).ActuallyTwoHanded) )
							bonus+=10;	//+5 HCI if I'm a one-hander and am using a one handed weapon

						else
							bonus-=5;	//-5 HCI if I'm a one-hander and am NOT using a one handed weapon
					}

					if (TraitRegister.HasTrait(Trait.TwoHander, this))
					{
						if (((BaseWeapon)Weapon).Layer == Layer.TwoHanded || ((BaseWeapon)Weapon).ActuallyTwoHanded )
							bonus+=10;	//+5 HCI if I'm a two-hander and am using a two handed weapon

						else
							bonus-=5;	//-5 HCI if I'm a two-hander and am NOT using a two handed weapon
					}

					if (TraitRegister.HasTrait(Trait.Pacifist, this))
						bonus-=10;	//-10 HCI if I'm a pacifist

					if (TraitRegister.HasTrait(Trait.Bruiser, this))
						bonus-=10;	//-10 HCI if I'm a bruiser

					if (TraitRegister.HasTrait(Trait.Psychotic, this))
						bonus+=10;	//+10 HCI if I'm psychotic.

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=5;	//-5 HCI if I'm nocturnal and it's day

						else
							bonus+=5;	//+5 HCI if I'm nocturnal and it's night
					}

					if (Party != null)
					{
						if ( ((Party)Party).Leader != null && ((Party)Party).Leader != this && ((Party)Party).Leader is AdvancedPlayerMobile)
						{
							AdvancedPlayerMobile PartyLeader=((Party)Party).Leader as AdvancedPlayerMobile;

							if ( InRange( PartyLeader.Location, 20 ) && PerkRegister.HasPerk(Perk.Leadership, PartyLeader) )
								bonus+=10;	//10% to HCI if i partyleader has leadership
						}
					}

					if (PerkRegister.HasPerk(Perk.BasicCombatTraining, this))
						bonus+=5;	//5% to HCI if i got BCT

					if (PerkRegister.HasPerk(Perk.ProperWeaponHandling, this))
						bonus+=5;	//5% to HCI if i got PWH

					if (PerkRegister.HasPerk(Perk.PrecisionStriking, this))
						bonus+=5;	//5% to HCI if i got PS

					if (PerkRegister.HasPerk(Perk.EagleEye, this) && Weapon is BaseRanged)
						bonus+=5;	//5% to HCI if i got EE

					if (PerkRegister.HasPerk(Perk.WeaponMasteryBows, this) && PerkRegister.CategorizeWeapon(Weapon) == 9)
						bonus+=10;	//10% to HCI if i got RWMB

					if (PerkRegister.HasPerk(Perk.WeaponMasteryCrossbows, this) && PerkRegister.CategorizeWeapon(Weapon) == 10)
						bonus+=10;	//10% to HCI if i got RWMC

					if (PerkRegister.HasPerk(Perk.Sharpshooter, this) && Weapon is BaseRanged)
						bonus+=15;	//15% to HCI if i got SS

					if (PerkRegister.HasPerk(Perk.SkillFocusSwordsmanship, this) && ((BaseWeapon)Weapon).DefSkill == SkillName.Swords)
						bonus+=5;	//5% to HCI if i got SFS

					if (PerkRegister.HasPerk(Perk.SkillFocusMacefighting, this) && ((BaseWeapon)Weapon).DefSkill == SkillName.Macing)
						bonus+=5;	//5% to HCI if i got SFM

					if (PerkRegister.HasPerk(Perk.SkillFocusFencing, this) && ((BaseWeapon)Weapon).DefSkill == SkillName.Fencing)
						bonus+=5;	//5% to HCI if i got SFF

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasterySwords, this) && PerkRegister.CategorizeWeapon(Weapon) == 1)
						bonus+=10;	//10% to HCI if i got SWMS

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasteryAxes, this) && PerkRegister.CategorizeWeapon(Weapon) == 2)
						bonus+=10;	//10% to HCI if i got SWMA

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasteryKnives, this) && PerkRegister.CategorizeWeapon(Weapon) == 3)
						bonus+=10;	//10% to HCI if i got SWMK

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasteryPolearms, this) && PerkRegister.CategorizeWeapon(Weapon) == 4)
						bonus+=10;	//10% to HCI if i got SWMP

					if (PerkRegister.HasPerk(Perk.MacefightingWeaponMasteryBashing, this) && PerkRegister.CategorizeWeapon(Weapon) == 5)
						bonus+=10;	//10% to HCI if i got MWMB

					if (PerkRegister.HasPerk(Perk.MacefightingWeaponMasteryStaves, this) && PerkRegister.CategorizeWeapon(Weapon) == 6)
						bonus+=10;	//10% to HCI if i got MWMS

					if (PerkRegister.HasPerk(Perk.FencingWeaponMasteryExotic, this) && PerkRegister.CategorizeWeapon(Weapon) == 7)
						bonus+=10;	//10% to HCI if i got FWME

					if (PerkRegister.HasPerk(Perk.FencingWeaponMasteryPolearms, this) && PerkRegister.CategorizeWeapon(Weapon) == 8)
						bonus+=10;	//10% to HCI if i got FWMP

					break;
				}

				case (int)AosAttribute.WeaponDamage:
				{
					if (TraitRegister.HasTrait(Trait.Bruiser, this))
						bonus+=15;	//+15 DMI if I'm a bruiser

					if (TraitRegister.HasTrait(Trait.Psychotic, this))
						bonus+=15;	//+15 DMI if I'm psychotic.

					if (TraitRegister.HasTrait(Trait.OneHander, this))
					{
						if (((BaseWeapon)Weapon).Layer == Layer.OneHanded && !(((BaseWeapon)Weapon).ActuallyTwoHanded) )
							bonus+=20;	//+10 DMI if I'm a one-hander and am using a one handed weapon

						else
							bonus-=10;	//-10 DMI if I'm a one-hander and am NOT using a one handed weapon
					}

					if (TraitRegister.HasTrait(Trait.TwoHander, this))
					{
						if (((BaseWeapon)Weapon).Layer == Layer.TwoHanded || ((BaseWeapon)Weapon).ActuallyTwoHanded )
							bonus+=20;	//+10 DMI if I'm a two-hander and am using a two handed weapon

						else
							bonus-=10;	//-10 DMI if I'm a two-hander and am NOT using a two handed weapon
					}

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=10;	//-10 DMI if I'm nocturnal and it's day

						else
							bonus+=10;	//+10 DMI if I'm nocturnal and it's night
					}

					if (Party != null)
					{
						if ( ((Party)Party).Leader != null && ((Party)Party).Leader != this && ((Party)Party).Leader is AdvancedPlayerMobile)
						{
							AdvancedPlayerMobile PartyLeader=((Party)Party).Leader as AdvancedPlayerMobile;

							if ( InRange( PartyLeader.Location, 20 ) && PerkRegister.HasPerk(Perk.Leadership, PartyLeader) )
								bonus+=15;	//15% to DMI if i partyleader has leadership
						}
					}

					if (PerkRegister.HasPerk(Perk.Countermeasures, this) && FindItemOnLayer(Layer.TwoHanded) != null && FindItemOnLayer(Layer.TwoHanded) is BaseShield)
						bonus+=10;	//5% to DMI if i got CM

					if (PerkRegister.HasPerk(Perk.ShieldBash, this) && FindItemOnLayer(Layer.TwoHanded) != null && FindItemOnLayer(Layer.TwoHanded) is BaseShield)
						bonus+=15;	//10% to DMI if i got SB

					if (PerkRegister.HasPerk(Perk.BasicCombatTraining, this))
						bonus+=10;	//5% to DMI if i got BCT

					if (PerkRegister.HasPerk(Perk.ProperWeaponHandling, this))
						bonus+=10;	//5% to DMI if i got PWH

					if (PerkRegister.HasPerk(Perk.PrecisionStriking, this))
						bonus+=10;	//5% to DMI if i got PS

					if (PerkRegister.HasPerk(Perk.ShoulderBash, this) && !(Weapon is BaseRanged))
						bonus+=15;	//15% to DMI if i got SB

					if (PerkRegister.HasPerk(Perk.EagleEye, this) && Weapon is BaseRanged)
						bonus+=15;	//10% to DMI if i got EE

					if (PerkRegister.HasPerk(Perk.WeaponMasteryBows, this) && PerkRegister.CategorizeWeapon(Weapon) == 9)
						bonus+=10;	//5% to DMI if i got RWMB

					if (PerkRegister.HasPerk(Perk.WeaponMasteryCrossbows, this) && PerkRegister.CategorizeWeapon(Weapon) == 10)
						bonus+=10;	//5% to DMI if i got RWMC

					if (PerkRegister.HasPerk(Perk.Sharpshooter, this) && Weapon is BaseRanged)
						bonus+=10;	//5% to DMI if i got SS

					if (PerkRegister.HasPerk(Perk.SkillFocusSwordsmanship, this) && ((BaseWeapon)Weapon).DefSkill == SkillName.Swords)
						bonus+=10;	//5% to DMI if i got SFS

					if (PerkRegister.HasPerk(Perk.SkillFocusMacefighting, this) && ((BaseWeapon)Weapon).DefSkill == SkillName.Macing)
						bonus+=10;	//5% to DMI if i got SFM

					if (PerkRegister.HasPerk(Perk.SkillFocusFencing, this) && ((BaseWeapon)Weapon).DefSkill == SkillName.Fencing)
						bonus+=10;	//5% to DMI if i got SFF

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasterySwords, this) && PerkRegister.CategorizeWeapon(Weapon) == 1)
						bonus+=10;	//5% to DMI if i got SWMS

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasteryAxes, this) && PerkRegister.CategorizeWeapon(Weapon) == 2)
						bonus+=10;	//5% to DMI if i got SWMA

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasteryKnives, this) && PerkRegister.CategorizeWeapon(Weapon) == 3)
						bonus+=10;	//5% to DMI if i got SWMK

					if (PerkRegister.HasPerk(Perk.SwordsmanshipWeaponMasteryPolearms, this) && PerkRegister.CategorizeWeapon(Weapon) == 4)
						bonus+=10;	//5% to DMI if i got SWMP

					if (PerkRegister.HasPerk(Perk.MacefightingWeaponMasteryBashing, this) && PerkRegister.CategorizeWeapon(Weapon) == 5)
						bonus+=10;	//5% to DMI if i got MWMB

					if (PerkRegister.HasPerk(Perk.MacefightingWeaponMasteryStaves, this) && PerkRegister.CategorizeWeapon(Weapon) == 6)
						bonus+=10;	//5% to DMI if i got MWMS

					if (PerkRegister.HasPerk(Perk.FencingWeaponMasteryExotic, this) && PerkRegister.CategorizeWeapon(Weapon) == 7)
						bonus+=10;	//5% to DMI if i got FWME

					if (PerkRegister.HasPerk(Perk.FencingWeaponMasteryPolearms, this) && PerkRegister.CategorizeWeapon(Weapon) == 8)
						bonus+=10;	//5% to DMI if i got FWMP

					break;
				}

				case (int)AosAttribute.OpWeaponDamage:	// this property has been added and is not default.
				{										// this gives the opponent's weapon a damage increase bonus, much like how reducing our
														// resists would work.
					if (TraitRegister.HasTrait(Trait.StoneWall, this))
						bonus+=15;	//+15 DMI to opponent if I'm a stonewall.

					break;
				}

				case (int)AosAttribute.WeaponSpeed:
				{
					if (TraitRegister.HasTrait(Trait.Clumsy, this))
						bonus-=10;	//-10 SSI

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=5;	//-5 SSI if I'm nocturnal and it's day

						else
							bonus+=5;	//+5 SSI if I'm nocturnal and it's night
					}

					if (Party != null)
					{
						if ( ((Party)Party).Leader != null && ((Party)Party).Leader != this && ((Party)Party).Leader is AdvancedPlayerMobile)
						{
							AdvancedPlayerMobile PartyLeader=((Party)Party).Leader as AdvancedPlayerMobile;

							if ( InRange( PartyLeader.Location, 20 ) && PerkRegister.HasPerk(Perk.Leadership, PartyLeader) && PartyLeader.Alive )
								bonus+=5;	//5% to SSI if i partyleader has leadership
						}
					}

					if (PerkRegister.HasPerk(Perk.PrecisionStriking, this))
						bonus+=10;	//5% to SSI if i got PS

					break;
				}

				case (int)AosAttribute.SpellDamage:
				{
					if (TraitRegister.HasTrait(Trait.StuntedMagic, this))
						bonus-=15;	//-10 SDI

					if (TraitRegister.HasTrait(Trait.Nocturnal, this))
					{
						int minutes=0;
						int hours=0;

						Clock.GetTime(Map, X, Y, out hours, out minutes);

						if (hours <= 17 && hours >= 6)
							bonus-=5;	//-5 SDI if I'm nocturnal and it's day

						else
							bonus+=5;	//+5 SDI if I'm nocturnal and it's night
					}

					if (PerkRegister.HasPerk(Perk.BattleCasting, this))
						bonus+=5;	//5 to SDI if i got BC

					if (PerkRegister.HasPerk(Perk.SpellPenetration, this))
						bonus+=5;	//5 to SDI if i got SP

					break;
				}

				case (int)AosAttribute.LowerRegCost:
				{

					break;
				}

				case (int)AosAttribute.LowerManaCost:
				{
					if (PerkRegister.HasPerk(Perk.ArcaneMind, this))
						bonus+=5;	//5 to LMC if i got AM

					if (PerkRegister.HasPerk(Perk.MasterOfMana, this))
						bonus+=15;	//15 to LMC if i got MOM

					if (PerkRegister.HasPerk(Perk.SpellMastery, this))
						bonus+=5;	//5 to LMC if i got SM

					break;
				}

				case (int)AosAttribute.CastRecovery:
				{
					if (PerkRegister.HasPerk(Perk.Scholar, this))
						bonus+=1;	//1 to FCR if im scholar

					if (PerkRegister.HasPerk(Perk.Spellweaving, this))
						bonus+=1;	//1 to FCR if i got SW

					if (PerkRegister.HasPerk(Perk.SpellMastery, this))
						bonus+=1;	//1 to FCR if i got SM

					if (PerkRegister.HasPerk(Perk.BattleCasting, this))
						bonus+=1;	//1 to FCR if i got BC

					break;
				}

				case (int)AosAttribute.CastSpeed:
				{
					if (PerkRegister.HasPerk(Perk.Memorization, this))
						bonus+=1;	//1 to FC if i got MEM

					if (PerkRegister.HasPerk(Perk.SpellMastery, this))
						bonus+=1;	//1 to FC if i got SM

					break;
				}

			}

			return bonus;

		}

		public bool DoneQuest(QuestName Quest)
		{
			int check=(int)FinishedQuests&(int)Quest;	//why, why my dearest C# must I make such bizarre walk-arounds around thy almightiness?

			if (check > 0)
				return true;

			else
				return false;
		}

		public bool HasTempFlag(TmpFlag Flag)
		{
			int check=(int)TempFlags&(int)Flag;

			if (check > 0)
				return true;

			else
				return false;
		}

		public bool HasFlag(TmpFlag Flag)
		{
			int check=(int)PFlags&(int)Flag;

			if (check > 0)
				return true;

			else
				return false;
		}

		public int CharAge()
		{
			return (int)(DateTime.Now - this.CreationTime).TotalDays;
		}

		public int AcctAge()
		{
			Account acct = this.Account as Account;

			return (int)(DateTime.Now - acct.Created).TotalDays;
		}

		public void NotifyQuest()
		{
			SendMessage(65, "Quest Message: Quest information has been updated.");
		}

		public void ClearQuestValues()
		{
			CurrentQuest.Quest=0;
			CurrentQuest.Stage=0;
			CurrentQuest.Count1=0;
			CurrentQuest.Count2=0;
			CurrentQuest.Count3=0;
		}

		public int PerkPts()
		{
			int temp_points=PerkPoints;

			if (temp_points > 5000)
				temp_points%=5000;	//lose the prestige points

			return temp_points;
		}

		public int SetPerkPts(int value)
		{
			int temp_points=PrestigePerkPts();
			PerkPoints=value + temp_points * 5000;

			SendMessage(35, "Your Perk points have been altered. You have now {0} Perk points.", PerkPts());

			return 0;
		}

		public int SetPrestigePerkPts(int value)
		{
			int temp_points=PerkPts();
			PerkPoints=value * 5000 + temp_points;

			SendMessage(35, "Your Prestige Perk points have been altered. You have now {0} Prestige Perk points.", PrestigePerkPts());

			return 0;
		}

		public int PrestigePerkPts()
		{
			int temp_points=PerkPoints;

			temp_points/=5000;	//integers don't hold decimal point, so we are left off with prestige points

			return temp_points;
		}

		public void UpdatePenalty(int addition)
		{
			ArmorPenalty+=addition;

			RemoveStatMod( "ArmorPenalty" ); //remove dex penalties
			AddStatMod( new StatMod( (StatType.Dex), "ArmorPenalty", -ArmorPenalty, TimeSpan.Zero ) ); //add new (combined) dex penalties

			return;
		}

		// events

		public override bool OnEquip( Item item )
		{
			//handle dex loss for armors

			if (item is BaseArmor && !(item is BaseShield) )	// shields are also basearmor
			{
				BaseArmor armor=item as BaseArmor;
				int penalty=PerkRegister.ArmorPenalty(armor, this);

				if (Dex - penalty <= 0)
				{
					SendMessage(45, "You need to increase your dexterity in order to be able to withstand the armor's penalties.");
					return false;
				}

				// apply penalties
				UpdatePenalty(penalty);
			}

			return base.OnEquip(item);

		}

		public override void OnItemAdded( Item item )
		{
			if (item is BaseWeapon && HasGump(typeof(AbilitiesGump)))	// update weapon abilities
			{
				CloseGump(typeof(AbilitiesGump));
				SendGump(new AbilitiesGump(50, 50, this));
			}

		}

		public override void OnItemRemoved( Item item )
		{
			if (item is BaseWeapon && HasGump(typeof(AbilitiesGump)))	// update weapon abilities
			{
				CloseGump(typeof(AbilitiesGump));
				SendGump(new AbilitiesGump(50, 50, this));
			}

			// restore dex for armors

			if (!(item is BaseArmor) || item is BaseShield)	// shields are also basearmor
				return;

			BaseArmor armor=item as BaseArmor;
			int penalty=-PerkRegister.ArmorPenalty(armor, this);

			UpdatePenalty(penalty);
		}

		public override void OnFameChange( int oldValue )
		{
			if (HasTempFlag(TmpFlag.StopNextFOverride))	// only way we have to prevent Mobile.cs from making this an overloading recursive function
				TempFlags^=TmpFlag.StopNextFOverride;	// off flag

			else if (TraitRegister.HasTrait(Trait.Notorious, this))
			{
				TempFlags|=TmpFlag.StopNextFOverride;	// on flag
				Fame=2 * Fame - oldValue;	// double the fame gain/loss rate
			}
		}

		public override void GetContextMenuEntries( Mobile from, ArrayList list )
		{
			if ( Deleted )
				return;

			if ( from == this )
				list.Add( new CharScreenEntry( (AdvancedPlayerMobile)this ) );	// open CharScreen gump

			base.GetContextMenuEntries(from, list);
		}

		public override void AddNameProperties( ObjectPropertyList list )
		{
			string name = Name;

			if ( name == null )
				name = String.Empty;

			string prefix = "";

			if ( ShowFameTitle && (Player || Body.IsHuman) && Fame >= 10000 )
				prefix = Female ? "Lady" : "Lord";

			string suffix = "";

			if ( ClickTitle && Title != null && Title.Length > 0 )
				suffix = Title;

			BaseGuild guild = Guild;

			if ( guild != null && DisplayGuildTitle )
			{
				if ( suffix.Length > 0 )
					suffix = String.Format( "{0} [{1}]", suffix, Utility.FixHtml( guild.Abbreviation ) );
				else
					suffix = String.Format( "[{0}]", Utility.FixHtml( guild.Abbreviation ) );
			}

			suffix = ApplyNameSuffix( suffix );

			list.Add( 1050045, "{0} \t{1}\t {2}", prefix, name, suffix ); // ~1_PREFIX~~2_NAME~~3_SUFFIX~

			if ( guild != null && ( DisplayGuildTitle || (Player && guild.Type != GuildType.Regular) ) )
			{
				string type;

				if ( guild.Type >= 0 && (int)guild.Type < GuildTypes.Length )
					type = GuildTypes[(int)guild.Type];
				else
					type = "";

				string title = GuildTitle;

				if ( title == null )
					title = "";
				else
					title = title.Trim();

				if ( title.Length > 0 )
					list.Add( "{0}, {1} Guild{2}", Utility.FixHtml( title ), Utility.FixHtml( guild.Name ), type );
				else
					list.Add( Utility.FixHtml( guild.Name ) );
			}
		}

		private static string[] GuildTypes = new string[]
		{
			"",
			" (Chaos)",
			" (Order)"
		};

		public override void OnSkillChange( SkillName skill, double oldBase )	// give perk points for every 100.0 hit and available gainableperkpts
		{
		
			if (Skills[skill].Base == 100.0 && GainablePerkPts > 0)
			{
				PerkPoints++;
				GainablePerkPts--;
			}

			base.OnSkillChange(skill, oldBase);
		}

		public static new void Initialize()
		{
			EventSink.Login += new LoginEventHandler( Player_Login );	// for handling player login
			EventSink.Logout += new LogoutEventHandler( Player_Logout );	// for handling player logout
		}

		private static void Player_Login( LoginEventArgs e )
		{
			if (!(e.Mobile is AdvancedPlayerMobile))	// how come not, anyway?
				return;

			AdvancedPlayerMobile from=e.Mobile as AdvancedPlayerMobile;

			if (from.Race <= 0)	// apparently doesn't have race set yet. start the char creation proccess.
			{
				from.CantWalk=true;	// freeze him
				from.SendGump(new CharStartGump(1, (RaceType)0, (CategoryType)0, new Trait [30], 1, new SkillName [5] {(SkillName)1,(SkillName)1,(SkillName)1,(SkillName)1,(SkillName)1}, new SkillName [5] {(SkillName)1,(SkillName)1,(SkillName)1,(SkillName)1,(SkillName)1}, new SkillName [5] {(SkillName)1,(SkillName)1,(SkillName)1,(SkillName)1,(SkillName)1}, from, 0, 0, 0));
			}

			if (from.HasFlag(TmpFlag.HasAbilitiesGump))
				from.SendGump(new AbilitiesGump(50, 50, from));
		}

		private static void Player_Logout( LogoutEventArgs e )
		{
			if (!(e.Mobile is AdvancedPlayerMobile))	// how come not, anyway?
				return;

			AdvancedPlayerMobile from=e.Mobile as AdvancedPlayerMobile;
		}

		public AdvancedPlayerMobile()
		{
		}


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


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

			//store traits; begin

			for (int x=0; x < Traits.Length; x++)
			{
				writer.Write( (int) Traits[x] );
			}

			//store traits; end

			//store perks; begin

			for (int x=0; x < Perks.Length; x++)
			{
				writer.Write( (int) Perks[x] );
			}

			//store perks; end

			//store skills; begin

			for (int x=0; x < PrimarySkills.Length; x++)
			{
				writer.Write( (int) PrimarySkills[x] );
			}

			for (int x=0; x < SecondarySkills.Length; x++)
			{
				writer.Write( (int) SecondarySkills[x] );
			}

			for (int x=0; x < TertiarySkills.Length; x++)
			{
				writer.Write( (int) TertiarySkills[x] );
			}

			//store skills; end

			writer.Write( (int) PerkPoints );
			writer.Write( (int) Race );
			writer.Write( (int) Category );

			writer.Write( (int) CurrentQuest.Quest );
			writer.Write( (int) CurrentQuest.Stage );
			writer.Write( (int) CurrentQuest.Count1 );
			writer.Write( (int) CurrentQuest.Count2 );
			writer.Write( (int) CurrentQuest.Count3 );

			writer.Write( (int) FinishedQuests );

			writer.Write( (int) ArmorPenalty );

			writer.Write( (int) GainablePerkPts );

			writer.Write( (int) PFlags );
		}


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

			switch ( version )
			{
				case 0:
				{
					//read traits; begin

					for (int x=0; x < Traits.Length; x++)
					{
						Traits[x] = (Trait)reader.ReadInt();
					}

					//read traits; end

					//read perks; begin

					for (int x=0; x < Perks.Length; x++)
					{
						Perks[x] = (Perk)reader.ReadInt();
					}

					//read perks; end

					//read skills; begin

					for (int x=0; x < PrimarySkills.Length; x++)
					{
						PrimarySkills[x] = (SkillName)reader.ReadInt();
					}

					for (int x=0; x < SecondarySkills.Length; x++)
					{
						SecondarySkills[x] = (SkillName)reader.ReadInt();
					}

					for (int x=0; x < TertiarySkills.Length; x++)
					{
						TertiarySkills[x] = (SkillName)reader.ReadInt();
					}

					//read skills; end

					PerkPoints = reader.ReadInt();
					Race = (RaceType)reader.ReadInt();
					Category = (CategoryType)reader.ReadInt();

					CurrentQuest=new QuestInfo();
					CurrentQuest.Quest = (QuestName)reader.ReadInt();
					CurrentQuest.Stage = reader.ReadInt();
					CurrentQuest.Count1 = reader.ReadInt();
					CurrentQuest.Count2 = reader.ReadInt();
					CurrentQuest.Count3 = reader.ReadInt();

					FinishedQuests = (QuestName)reader.ReadInt();

					ArmorPenalty = reader.ReadInt();
					GainablePerkPts=reader.ReadInt();

					PFlags=(TmpFlag)reader.ReadInt();

					UpdatePenalty(0);	// load armor penalities back to the memory

					break;
				}
			}
		}
		
	}
}
and the baseweapon.cs

Code:
using System;
using System.Text;
using System.Collections;
using Server.Network;
using Server.Targeting;
using Server.Mobiles;
using Server.Spells;
using Server.Spells.Necromancy;
using Server.Factions;
using Server.Engines.Craft;

using Server.Engines.Traits;
using Server.Engines.Races;

namespace Server.Items
{
	public abstract class BaseWeapon : Item, IWeapon, IFactionItem, ICraftable
	{
		#region Factions
		private FactionItem m_FactionState;

		public FactionItem FactionItemState
		{
			get{ return m_FactionState; }
			set
			{
				m_FactionState = value;

				if ( m_FactionState == null )
					Hue = CraftResources.GetHue( Resource );

				LootType = ( m_FactionState == null ? LootType.Regular : LootType.Blessed );
			}
		}
		#endregion



		/* Weapon internals work differently now (Mar 13 2003)
		 * 
		 * The attributes defined below default to -1.
		 * If the value is -1, the corresponding virtual 'Aos/Old' property is used.
		 * If not, the attribute value itself is used. Here's the list:
		 *  - MinDamage
		 *  - MaxDamage
		 *  - Speed
		 *  - HitSound
		 *  - MissSound
		 *  - StrRequirement, DexRequirement, IntRequirement
		 *  - WeaponType
		 *  - WeaponAnimation
		 *  - MaxRange
		 */

		// Instance values. These values must are unique to each weapon.


		// LUCENT ECLIPSE VARIABLES BEGIN

		public int CriticalChance;	// the criticals system
		public Mobile MadeBy;	// muling prevention
		public RaceType RaceItem;	// race-specific item
		public int OverridePrimaryAbility;	// override prim ability
		public int OverrideSecondaryAbility;	// override sec ability
		public bool ActuallyTwoHanded;		// enables "cool" animations without modifying the runuo core

		[CommandProperty( AccessLevel.GameMaster )]
		public bool Actually_TwoHanded
		{
			get{ return ActuallyTwoHanded; }
			set{ ActuallyTwoHanded = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Override_PrimaryAbility
		{
			get{ return OverridePrimaryAbility; }
			set{ OverridePrimaryAbility = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Override_SecondaryAbility
		{
			get{ return OverrideSecondaryAbility; }
			set{ OverrideSecondaryAbility = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Critical_Chance
		{
			get{ return CriticalChance; }
			set{ CriticalChance = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public RaceType Race_Item
		{
			get{ return RaceItem; }
			set{ RaceItem = value; InvalidateProperties(); }
		}

		// LUCENT ECLIPSE VARIABLES END

		private WeaponDamageLevel m_DamageLevel;
		private WeaponAccuracyLevel m_AccuracyLevel;
		private WeaponDurabilityLevel m_DurabilityLevel;
		private WeaponQuality m_Quality;
		private Mobile m_Crafter;
		private Poison m_Poison;
		private int m_PoisonCharges;
		private bool m_Identified;
		private int m_Hits;
		private int m_MaxHits;
		private SlayerName m_Slayer;
		private SkillMod m_SkillMod, m_MageMod;
		private CraftResource m_Resource;
		private bool m_PlayerConstructed;

		private bool m_Cursed; // Is this weapon cursed via Curse Weapon necromancer spell? Temporary; not serialized.
		private bool m_Consecrated; // Is this weapon blessed via Consecrate Weapon paladin ability? Temporary; not serialized.

		private AosAttributes m_AosAttributes;
		private AosWeaponAttributes m_AosWeaponAttributes;
		private AosSkillBonuses m_AosSkillBonuses;

		// Overridable values. These values are provided to override the defaults which get defined in the individual weapon scripts.
		private int m_StrReq, m_DexReq, m_IntReq;
		private int m_MinDamage, m_MaxDamage;
		private int m_HitSound, m_MissSound;
		private int m_Speed;
		private int m_MaxRange;
		private SkillName m_Skill;
		private WeaponType m_Type;
		private WeaponAnimation m_Animation;

		public virtual WeaponAbility PrimaryAbility{ get{ return null; } }
		public virtual WeaponAbility SecondaryAbility{ get{ return null; } }

		public virtual int DefMaxRange{ get{ return 1; } }
		public virtual int DefHitSound{ get{ return 0; } }
		public virtual int DefMissSound{ get{ return 0; } }
		public virtual SkillName DefSkill{ get{ return SkillName.Swords; } }
		public virtual WeaponType DefType{ get{ return WeaponType.Slashing; } }
		public virtual WeaponAnimation DefAnimation{ get{ return WeaponAnimation.Slash1H; } }

		public virtual int AosStrengthReq{ get{ return 0; } }
		public virtual int AosDexterityReq{ get{ return 0; } }
		public virtual int AosIntelligenceReq{ get{ return 0; } }
		public virtual int AosMinDamage{ get{ return 0; } }
		public virtual int AosMaxDamage{ get{ return 0; } }
		public virtual int AosSpeed{ get{ return 0; } }
		public virtual int AosMaxRange{ get{ return DefMaxRange; } }
		public virtual int AosHitSound{ get{ return DefHitSound; } }
		public virtual int AosMissSound{ get{ return DefMissSound; } }
		public virtual SkillName AosSkill{ get{ return DefSkill; } }
		public virtual WeaponType AosType{ get{ return DefType; } }
		public virtual WeaponAnimation AosAnimation{ get{ return DefAnimation; } }

		public virtual int OldStrengthReq{ get{ return 0; } }
		public virtual int OldDexterityReq{ get{ return 0; } }
		public virtual int OldIntelligenceReq{ get{ return 0; } }
		public virtual int OldMinDamage{ get{ return 0; } }
		public virtual int OldMaxDamage{ get{ return 0; } }
		public virtual int OldSpeed{ get{ return 0; } }
		public virtual int OldMaxRange{ get{ return DefMaxRange; } }
		public virtual int OldHitSound{ get{ return DefHitSound; } }
		public virtual int OldMissSound{ get{ return DefMissSound; } }
		public virtual SkillName OldSkill{ get{ return DefSkill; } }
		public virtual WeaponType OldType{ get{ return DefType; } }
		public virtual WeaponAnimation OldAnimation{ get{ return DefAnimation; } }

		public virtual int InitMinHits{ get{ return 0; } }
		public virtual int InitMaxHits{ get{ return 0; } }

		public override int PhysicalResistance{ get{ return m_AosWeaponAttributes.ResistPhysicalBonus; } }
		public override int FireResistance{ get{ return m_AosWeaponAttributes.ResistFireBonus; } }
		public override int ColdResistance{ get{ return m_AosWeaponAttributes.ResistColdBonus; } }
		public override int PoisonResistance{ get{ return m_AosWeaponAttributes.ResistPoisonBonus; } }
		public override int EnergyResistance{ get{ return m_AosWeaponAttributes.ResistEnergyBonus; } }

		[CommandProperty( AccessLevel.GameMaster )]
		public AosAttributes Attributes
		{
			get{ return m_AosAttributes; }
			set{}
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public AosWeaponAttributes WeaponAttributes
		{
			get{ return m_AosWeaponAttributes; }
			set{}
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public AosSkillBonuses SkillBonuses
		{
			get{ return m_AosSkillBonuses; }
			set{}
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public bool Cursed
		{
			get{ return m_Cursed; }
			set{ m_Cursed = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public bool Consecrated
		{
			get{ return m_Consecrated; }
			set{ m_Consecrated = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public bool Identified
		{
			get{ return m_Identified; }
			set{ m_Identified = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Hits
		{
			get{ return m_Hits; }
			set
			{
				if ( m_Hits == value )
					return;

				if ( value > m_MaxHits )
					value = m_MaxHits;

				m_Hits = value;

				InvalidateProperties();
			}
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int MaxHits
		{
			get{ return m_MaxHits; }
			set{ m_MaxHits = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int PoisonCharges
		{
			get{ return m_PoisonCharges; }
			set{ m_PoisonCharges = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public Poison Poison
		{
			get{ return m_Poison; }
			set{ m_Poison = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public WeaponQuality Quality
		{
			get{ return m_Quality; }
			set{ UnscaleDurability(); m_Quality = value; ScaleDurability(); InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public Mobile Crafter
		{
			get{ return m_Crafter; }
			set{ m_Crafter = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SlayerName Slayer
		{
			get{ return m_Slayer; }
			set{ m_Slayer = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public CraftResource Resource
		{
			get{ return m_Resource; }
			set{ UnscaleDurability(); m_Resource = value; Hue = CraftResources.GetHue( m_Resource ); InvalidateProperties(); ScaleDurability(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public WeaponDamageLevel DamageLevel
		{
			get{ return m_DamageLevel; }
			set{ m_DamageLevel = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public WeaponDurabilityLevel DurabilityLevel
		{
			get{ return m_DurabilityLevel; }
			set{ UnscaleDurability(); m_DurabilityLevel = value; InvalidateProperties(); ScaleDurability(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public bool PlayerConstructed
		{
			get{ return m_PlayerConstructed; }
			set{ m_PlayerConstructed = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int MaxRange
		{
			get{ return ( m_MaxRange == -1 ? Core.AOS ? AosMaxRange : OldMaxRange : m_MaxRange ); }
			set{ m_MaxRange = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public WeaponAnimation Animation
		{
			get{ return ( m_Animation == (WeaponAnimation)(-1) ? Core.AOS ? AosAnimation : OldAnimation : m_Animation ); } 
			set{ m_Animation = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public WeaponType Type
		{
			get{ return ( m_Type == (WeaponType)(-1) ? Core.AOS ? AosType : OldType : m_Type ); }
			set{ m_Type = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public SkillName Skill
		{
			get{ return ( m_Skill == (SkillName)(-1) ? Core.AOS ? AosSkill : OldSkill : m_Skill ); }
			set{ m_Skill = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int HitSound
		{
			get{ return ( m_HitSound == -1 ? Core.AOS ? AosHitSound : OldHitSound : m_HitSound ); }
			set{ m_HitSound = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int MissSound
		{
			get{ return ( m_MissSound == -1 ? Core.AOS ? AosMissSound : OldMissSound : m_MissSound ); }
			set{ m_MissSound = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int MinDamage
		{
			get{ return ( m_MinDamage == -1 ? Core.AOS ? AosMinDamage : OldMinDamage : m_MinDamage ); }
			set{ m_MinDamage = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int MaxDamage
		{
			get{ return ( m_MaxDamage == -1 ? Core.AOS ? AosMaxDamage : OldMaxDamage : m_MaxDamage ); }
			set{ m_MaxDamage = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Speed
		{
			get{ return ( m_Speed == -1 ? Core.AOS ? AosSpeed : OldSpeed : m_Speed ); }
			set{ m_Speed = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int StrRequirement
		{
			get{ return ( m_StrReq == -1 ? Core.AOS ? AosStrengthReq : OldStrengthReq : m_StrReq ); }
			set{ m_StrReq = value; InvalidateProperties(); }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int DexRequirement
		{
			get{ return ( m_DexReq == -1 ? Core.AOS ? AosDexterityReq : OldDexterityReq : m_DexReq ); }
			set{ m_DexReq = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int IntRequirement
		{
			get{ return ( m_IntReq == -1 ? Core.AOS ? AosIntelligenceReq : OldIntelligenceReq : m_IntReq ); }
			set{ m_IntReq = value; }
		}

		public virtual SkillName AccuracySkill{ get{ return SkillName.Tactics; } }

		[CommandProperty( AccessLevel.GameMaster )]
		public WeaponAccuracyLevel AccuracyLevel
		{
			get
			{
				return m_AccuracyLevel;
			}
			set
			{
				if ( m_AccuracyLevel != value )
				{
					m_AccuracyLevel = value;

					if ( UseSkillMod )
					{
						if ( m_AccuracyLevel == WeaponAccuracyLevel.Regular )
						{
							if ( m_SkillMod != null )
								m_SkillMod.Remove();

							m_SkillMod = null;
						}
						else if ( m_SkillMod == null && Parent is Mobile )
						{
							m_SkillMod = new DefaultSkillMod( AccuracySkill, true, (int)m_AccuracyLevel * 5 );
							((Mobile)Parent).AddSkillMod( m_SkillMod );
						}
						else if ( m_SkillMod != null )
						{
							m_SkillMod.Value = (int)m_AccuracyLevel * 5;
						}
					}

					InvalidateProperties();
				}
			}
		}

		public void UnscaleDurability()
		{
			int scale = 100 + GetDurabilityBonus();

			m_Hits = ((m_Hits * 100) + (scale - 1)) / scale;
			m_MaxHits = ((m_MaxHits * 100) + (scale - 1)) / scale;
			InvalidateProperties();
		}

		public void ScaleDurability()
		{
			int scale = 100 + GetDurabilityBonus();

			m_Hits = ((m_Hits * scale) + 99) / 100;
			m_MaxHits = ((m_MaxHits * scale) + 99) / 100;
			InvalidateProperties();
		}

		public int GetDurabilityBonus()
		{
			int bonus = 0;

			if ( m_Quality == WeaponQuality.Exceptional )
				bonus += 20;

			switch ( m_DurabilityLevel )
			{
				case WeaponDurabilityLevel.Durable: bonus += 20; break;
				case WeaponDurabilityLevel.Substantial: bonus += 50; break;
				case WeaponDurabilityLevel.Massive: bonus += 70; break;
				case WeaponDurabilityLevel.Fortified: bonus += 100; break;
				case WeaponDurabilityLevel.Indestructible: bonus += 120; break;
			}

			if ( Core.AOS )
			{
				bonus += m_AosWeaponAttributes.DurabilityBonus;

				CraftResourceInfo resInfo = CraftResources.GetInfo( m_Resource );
				CraftAttributeInfo attrInfo = null;

				if ( resInfo != null )
					attrInfo = resInfo.AttributeInfo;

				if ( attrInfo != null )
					bonus += attrInfo.WeaponDurability;
			}

			return bonus;
		}

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

			int v = m_AosWeaponAttributes.LowerStatReq;

			CraftResourceInfo info = CraftResources.GetInfo( m_Resource );

			if ( info != null )
			{
				CraftAttributeInfo attrInfo = info.AttributeInfo;

				if ( attrInfo != null )
					v += attrInfo.WeaponLowerRequirements;
			}

			if ( v > 100 )
				v = 100;

			return v;
		}

		public static void BlockEquip( Mobile m, TimeSpan duration )
		{
			if ( m.BeginAction( typeof( BaseWeapon ) ) )
				new ResetEquipTimer( m, duration ).Start();
		}

		private class ResetEquipTimer : Timer
		{
			private Mobile m_Mobile;

			public ResetEquipTimer( Mobile m, TimeSpan duration ) : base( duration )
			{
				m_Mobile = m;
			}

			protected override void OnTick()
			{
				m_Mobile.EndAction( typeof( BaseWeapon ) );
			}
		}

		public override bool CheckConflictingLayer( Mobile m, Item item, Layer layer )
		{
			if ( base.CheckConflictingLayer( m, item, layer ) )
				return true;

			if ( (this.Layer == Layer.TwoHanded || this.ActuallyTwoHanded) && layer == Layer.OneHanded )
				return true;
			else if ( (this.Layer == Layer.OneHanded && !this.ActuallyTwoHanded) && layer == Layer.TwoHanded && !(item is BaseShield) && !(item is BaseEquipableLight) )
				return true;
			else if (this.ActuallyTwoHanded && layer == Layer.TwoHanded)
				return true;

			return false;
		}

		public override bool CanEquip( Mobile from )
		{
			if ( from.Dex < DexRequirement )
			{
				from.SendMessage( "You are not nimble enough to equip that." );
				return false;
			} 
			else if ( from.Str < AOS.Scale( StrRequirement, 100 - GetLowerStatReq() ) )
			{
				from.SendLocalizedMessage( 500213 ); // You are not strong enough to equip that.
				return false;
			}
			else if ( from.Int < IntRequirement )
			{
				from.SendMessage( "You are not smart enough to equip that." );
				return false;
			}
			else if ( !from.CanBeginAction( typeof( BaseWeapon ) ) )
			{
				return false;
			}
			else
			{
				return base.CanEquip( from );
			}
		}

		public virtual bool UseSkillMod{ get{ return !Core.AOS; } }

		public override bool OnEquip( Mobile from )
		{
			int strBonus = m_AosAttributes.BonusStr;
			int dexBonus = m_AosAttributes.BonusDex;
			int intBonus = m_AosAttributes.BonusInt;

			if ( (strBonus != 0 || dexBonus != 0 || intBonus != 0) )
			{
				Mobile m = from;

				string modName = this.Serial.ToString();

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

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

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

			from.NextCombatTime = DateTime.Now + GetDelay( from );

			if ( UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular )
			{
				if ( m_SkillMod != null )
					m_SkillMod.Remove();

				m_SkillMod = new DefaultSkillMod( AccuracySkill, true, (int)m_AccuracyLevel * 5 );
				from.AddSkillMod( m_SkillMod );
			}

			if ( Core.AOS && m_AosWeaponAttributes.MageWeapon != 0 && m_AosWeaponAttributes.MageWeapon != 30 )
			{
				if ( m_MageMod != null )
					m_MageMod.Remove();

				m_MageMod = new DefaultSkillMod( SkillName.Magery, true, -30 + m_AosWeaponAttributes.MageWeapon );
				from.AddSkillMod( m_MageMod );
			}

			return true;
		}

		public override void OnAdded( object parent )
		{
			base.OnAdded( parent );

			if ( parent is Mobile )
			{
				Mobile from = (Mobile)parent;

				if ( Core.AOS )
					m_AosSkillBonuses.AddTo( from );
				from.CheckStatTimers();
				from.Delta( MobileDelta.WeaponDamage );
			}
		}

		public override void OnRemoved( object parent )
		{
			if ( parent is Mobile )
			{
				Mobile m = (Mobile)parent;
				BaseWeapon weapon = m.Weapon as BaseWeapon;

				string modName = this.Serial.ToString();

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

				if ( weapon != null )
					m.NextCombatTime = DateTime.Now + weapon.GetDelay( m );

				if ( UseSkillMod && m_SkillMod != null )
				{
					m_SkillMod.Remove();
					m_SkillMod = null;
				}

				if ( m_MageMod != null )
				{
					m_MageMod.Remove();
					m_MageMod = null;
				}

				if ( Core.AOS )
					m_AosSkillBonuses.Remove();

				m.CheckStatTimers();

				m.Delta( MobileDelta.WeaponDamage );
			}
		}

		public virtual SkillName GetUsedSkill( Mobile m, bool checkSkillAttrs )
		{
			SkillName sk;

			if ( checkSkillAttrs && m_AosWeaponAttributes.UseBestSkill != 0 )
			{
				double swrd = m.Skills[SkillName.Swords].Value;
				double fenc = m.Skills[SkillName.Fencing].Value;
				double mcng = m.Skills[SkillName.Macing].Value;
				double val;

				sk = SkillName.Swords;
				val = swrd;

				if ( fenc > val ){ sk = SkillName.Fencing; val = fenc; }
				if ( mcng > val ){ sk = SkillName.Macing; val = mcng; }
			}
			else if ( m_AosWeaponAttributes.MageWeapon != 0 )
			{
				if ( m.Skills[SkillName.Magery].Value > m.Skills[Skill].Value )
					sk = SkillName.Magery;
				else
					sk = Skill;
			}
			else
			{
				sk = Skill;

				if ( sk != SkillName.Wrestling && !m.Player && !m.Body.IsHuman && m.Skills[SkillName.Wrestling].Value > m.Skills[sk].Value )
					sk = SkillName.Wrestling;
			}

			return sk;
		}

		public virtual double GetAttackSkillValue( Mobile attacker, Mobile defender )
		{
			return attacker.Skills[GetUsedSkill( attacker, true )].Value;
		}

		public virtual double GetDefendSkillValue( Mobile attacker, Mobile defender )
		{
			return defender.Skills[GetUsedSkill( defender, true )].Value;
		}

		public virtual bool CheckHit( Mobile attacker, Mobile defender )
		{
			BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon;
			BaseWeapon defWeapon = defender.Weapon as BaseWeapon;

			Skill atkSkill = attacker.Skills[atkWeapon.Skill];
			Skill defSkill = defender.Skills[defWeapon.Skill];

			double atkValue = atkWeapon.GetAttackSkillValue( attacker, defender );
			double defValue = defWeapon.GetDefendSkillValue( attacker, defender );

			//attacker.CheckSkill( atkSkill.SkillName, defValue - 20.0, 120.0 );
			//defender.CheckSkill( defSkill.SkillName, atkValue - 20.0, 120.0 );

			double ourValue, theirValue;

			int bonus = GetHitChanceBonus();

			if ( Core.AOS )
			{
				if ( atkValue <= -20.0 )
					atkValue = -19.9;

				if ( defValue <= -20.0 )
					defValue = -19.9;

				// Hit Chance Increase = 45%
				int atkChance = AosAttributes.GetValue( attacker, AosAttribute.AttackChance );
				if ( atkChance > 45 )
					atkChance = 45;

				bonus += atkChance;

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

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

				if (attacker is AdvancedPlayerMobile)
					bonus += ((AdvancedPlayerMobile)attacker).Bonuses(AosAttribute.AttackChance);

				ourValue = (atkValue + 20.0) * (100 + bonus);

				// Defense Chance Increase = 45%
				bonus = AosAttributes.GetValue( defender, AosAttribute.DefendChance );
				if ( bonus > 45 )
					bonus = 45;

				if ( Spells.Chivalry.DivineFurySpell.UnderEffect( defender ) )
					bonus -= 20; // defender loses 20% bonus when they're under divine fury

				if ( HitLower.IsUnderDefenseEffect( defender ) )
					bonus -= 25; // Under Hit Lower Defense effect -> 25% malus

				if (defender is AdvancedPlayerMobile)
					bonus += ((AdvancedPlayerMobile)defender).Bonuses(AosAttribute.DefendChance);

				double discordanceScalar = 0.0;

				if ( SkillHandlers.Discordance.GetScalar( attacker, ref discordanceScalar ) )
					bonus += (int)(discordanceScalar * 100);

				theirValue = (defValue + 20.0) * (100 + bonus);

				bonus = 0;
			}
			else
			{
				if ( atkValue <= -50.0 )
					atkValue = -49.9;

				if ( defValue <= -50.0 )
					defValue = -49.9;

				ourValue = (atkValue + 50.0);
				theirValue = (defValue + 50.0);
			}

			double chance = ourValue / (theirValue * 2.0);

			chance *= 1.0 + ((double)bonus / 100);

			if ( Core.AOS && chance < 0.02 )
				chance = 0.02;

			WeaponAbility ability = WeaponAbility.GetCurrentAbility( attacker );

			if ( ability != null )
				chance *= ability.AccuracyScalar;

			return attacker.CheckSkill( atkSkill.SkillName, chance );

			//return ( chance >= Utility.RandomDouble() );
		}

		public virtual TimeSpan GetDelay( Mobile m )
		{
			int speed = this.Speed;

			if ( speed == 0 )
				return TimeSpan.FromHours( 1.0 );

			double delayInSeconds;

			if ( Core.AOS )
			{
				int v = (m.Stam + 100) * speed;

				int bonus = AosAttributes.GetValue( m, AosAttribute.WeaponSpeed );

				if ( Spells.Chivalry.DivineFurySpell.UnderEffect( m ) )
					bonus += 10;

				if (m is AdvancedPlayerMobile)
					bonus+=((AdvancedPlayerMobile)m).Bonuses(AosAttribute.WeaponSpeed);

				double discordanceScalar = 0.0;

				if ( SkillHandlers.Discordance.GetScalar( m, ref discordanceScalar ) )
					bonus += (int)(discordanceScalar * 100);

				v += AOS.Scale( v, bonus );

				if ( v <= 0 )
					v = 1;

				delayInSeconds = Math.Floor( 40000.0 / v ) * 0.5;

				// Maximum swing rate capped at one swing per second 
				if ( delayInSeconds < 1.0 )
					delayInSeconds = 1.0;
			}
			else
			{
				int v = (m.Stam + 100) * speed;

				if ( v <= 0 )
					v = 1;

				delayInSeconds = 15000.0 / v;
			}

			return TimeSpan.FromSeconds( delayInSeconds );
		}

		public virtual TimeSpan OnSwing( Mobile attacker, Mobile defender )
		{
			bool canSwing = true;

			if ( Core.AOS )
			{
				canSwing = ( !attacker.Paralyzed && !attacker.Frozen );

				if ( canSwing )
				{
					Spell sp = attacker.Spell as Spell;

					canSwing = ( sp == null || !sp.IsCasting || !sp.BlocksMovement );
				}
			}

			if ( canSwing && attacker.HarmfulCheck( defender ) )
			{
				attacker.DisruptiveAction();

				if ( attacker.NetState != null )
					attacker.Send( new Swing( 0, attacker, defender ) );

				if ( attacker is BaseCreature )
				{
					BaseCreature bc = (BaseCreature)attacker;
					WeaponAbility ab = bc.GetWeaponAbility();

					if ( ab != null )
					{
						if ( bc.WeaponAbilityChance > Utility.RandomDouble() )
							WeaponAbility.SetCurrentAbility( bc, ab );
						else
							WeaponAbility.ClearCurrentAbility( bc );
					}
				}

				if ( CheckHit( attacker, defender ) )
					OnHit( attacker, defender );
				else
					OnMiss( attacker, defender );
			}

			return GetDelay( attacker );
		}

		public virtual int GetHitAttackSound( Mobile attacker, Mobile defender )
		{
			int sound = attacker.GetAttackSound();

			if ( sound == -1 )
				sound = HitSound;

			return sound;
		}

		public virtual int GetHitDefendSound( Mobile attacker, Mobile defender )
		{
			return defender.GetHurtSound();
		}

		public virtual int GetMissAttackSound( Mobile attacker, Mobile defender )
		{
			if ( attacker.GetAttackSound() == -1 )
				return MissSound;
			else
				return -1;
		}

		public virtual int GetMissDefendSound( Mobile attacker, Mobile defender )
		{
			return -1;
		}

		public virtual int AbsorbDamageAOS( Mobile attacker, Mobile defender, int damage )
		{
			double positionChance = Utility.RandomDouble();
			BaseArmor armor;

			if ( positionChance < 0.07 )
				armor = defender.NeckArmor as BaseArmor;
			else if ( positionChance < 0.14 )
				armor = defender.HandArmor as BaseArmor;
			else if ( positionChance < 0.28 )
				armor = defender.ArmsArmor as BaseArmor;
			else if ( positionChance < 0.43 )
				armor = defender.HeadArmor as BaseArmor;
			else if ( positionChance < 0.65 )
				armor = defender.LegsArmor as BaseArmor;
			else
				armor = defender.ChestArmor as BaseArmor;

			if ( armor != null )
				armor.OnHit( this, damage ); // call OnHit to lose durability

			if ( defender.Player || defender.Body.IsHuman )
			{
				BaseShield shield = defender.FindItemOnLayer( Layer.TwoHanded ) as BaseShield;

				bool blocked = false;

				// Dexterity below 80 reduces the chance to parry 
				double chance = ( defender.Skills[SkillName.Parry].Value * 0.0030 );
				if ( defender.Dex < 80 )
					chance = chance * (20 + defender.Dex) / 100;

				if ( shield != null )
				{
					blocked = defender.CheckSkill( SkillName.Parry, chance );
				}
				else if ( !(defender.Weapon is Fists) && !(defender.Weapon is BaseRanged) )
				{
					chance /= 2;

					blocked = ( chance > Utility.RandomDouble() ); // Only skillcheck if wielding a shield
				}

				if ( blocked )
				{
					defender.FixedEffect( 0x37B9, 10, 16 );
					damage = 0;

					if ( shield != null )
					{
						double halfArmor = shield.ArmorRating / 2.0;
						int absorbed = (int)(halfArmor + (halfArmor*Utility.RandomDouble()));

						if ( absorbed < 2 )
							absorbed = 2;

						int wear;

						if ( Type == WeaponType.Bashing )
							wear = (absorbed / 2);
						else
							wear = Utility.Random( 2 );

						if ( wear > 0 && shield.MaxHitPoints > 0 )
						{
							if ( shield.HitPoints >= wear )
							{
								shield.HitPoints -= wear;
								wear = 0;
							}
							else
							{
								wear -= shield.HitPoints;
								shield.HitPoints = 0;
							}

							if ( wear > 0 )
							{
								if ( shield.MaxHitPoints > wear )
								{
									shield.MaxHitPoints -= wear;

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

			return damage;
		}

		public virtual int AbsorbDamage( Mobile attacker, Mobile defender, int damage )
		{
			if ( Core.AOS )
				return AbsorbDamageAOS( attacker, defender, damage );

			double chance = Utility.RandomDouble();
			BaseArmor armor;

			if ( chance < 0.07 )
				armor = defender.NeckArmor as BaseArmor;
			else if ( chance < 0.14 )
				armor = defender.HandArmor as BaseArmor;
			else if ( chance < 0.28 )
				armor = defender.ArmsArmor as BaseArmor;
			else if ( chance < 0.43 )
				armor = defender.HeadArmor as BaseArmor;
			else if ( chance < 0.65 )
				armor = defender.LegsArmor as BaseArmor;
			else
				armor = defender.ChestArmor as BaseArmor;

			if ( armor != null )
				damage = armor.OnHit( this, damage );

			BaseShield shield = defender.FindItemOnLayer( Layer.TwoHanded ) as BaseShield;
			if ( shield != null )
				damage = shield.OnHit( this, damage );

			int virtualArmor = defender.VirtualArmor + defender.VirtualArmorMod;

			if ( virtualArmor > 0 )
			{
				double scalar;

				if ( chance < 0.14 )
					scalar = 0.07;
				else if ( chance < 0.28 )
					scalar = 0.14;
				else if ( chance < 0.43 )
					scalar = 0.15;
				else if ( chance < 0.65 )
					scalar = 0.22;
				else
					scalar = 0.35;

				int from = (int)(virtualArmor * scalar) / 2;
				int to = (int)(virtualArmor * scalar);

				damage -= Utility.Random( from, (to - from) + 1 );
			}

			return damage;
		}

		public virtual int GetPackInstinctBonus( Mobile attacker, Mobile defender )
		{
			if ( attacker.Player || defender.Player )
				return 0;

			BaseCreature bc = attacker as BaseCreature;

			if ( bc == null || bc.PackInstinct == PackInstinct.None || (!bc.Controled && !bc.Summoned) )
				return 0;

			Mobile master = bc.ControlMaster;

			if ( master == null )
				master = bc.SummonMaster;

			if ( master == null )
				return 0;

			int inPack = 1;

			foreach ( Mobile m in defender.GetMobilesInRange( 1 ) )
			{
				if ( m != attacker && m is BaseCreature )
				{
					BaseCreature tc = (BaseCreature)m;

					if ( (tc.PackInstinct & bc.PackInstinct) == 0 || (!tc.Controled && !tc.Summoned) )
						continue;

					Mobile theirMaster = tc.ControlMaster;

					if ( theirMaster == null )
						theirMaster = tc.SummonMaster;

					if ( master == theirMaster && tc.Combatant == defender )
						++inPack;
				}
			}

			if ( inPack >= 5 )
				return 100;
			else if ( inPack >= 4 )
				return 75;
			else if ( inPack >= 3 )
				return 50;
			else if ( inPack >= 2 )
				return 25;

			return 0;
		}

		private static bool m_InDoubleStrike;

		public static bool InDoubleStrike
		{
			get{ return m_InDoubleStrike; }
			set{ m_InDoubleStrike = value; }
		}

		public virtual void OnHit( Mobile attacker, Mobile defender )
		{
			PlaySwingAnimation( attacker );
			PlayHurtAnimation( defender );

			attacker.PlaySound( GetHitAttackSound( attacker, defender ) );
			defender.PlaySound( GetHitDefendSound( attacker, defender ) );

			int damage = ComputeDamage( attacker, defender );

			CheckSlayerResult cs = CheckSlayers( attacker, defender );

			if ( cs != CheckSlayerResult.None )
			{
				if ( cs == CheckSlayerResult.Slayer )
					defender.FixedEffect( 0x37B9, 10, 5 );

				damage *= 2;
			}

			if ( !attacker.Player )
			{
				if ( defender is PlayerMobile )
				{
					PlayerMobile pm = (PlayerMobile)defender;

					if ( pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType() )
						damage *= 2;
				}
			}
			else if ( !defender.Player )
			{
				if ( attacker is PlayerMobile )
				{
					PlayerMobile pm = (PlayerMobile)attacker;

					if ( pm.WaitingForEnemy )
					{
						pm.EnemyOfOneType = defender.GetType();
						pm.WaitingForEnemy = false;
					}

					if ( pm.EnemyOfOneType == defender.GetType() )
					{
						defender.FixedEffect( 0x37B9, 10, 5, 1160, 0 );
						damage += AOS.Scale( damage, 50 );
					}
				}
			}

			int packInstinctBonus = GetPackInstinctBonus( attacker, defender );

			if ( packInstinctBonus != 0 )
				damage += AOS.Scale( damage, packInstinctBonus );

			if ( m_InDoubleStrike )
				damage -= AOS.Scale( damage, 10 ); // 10% loss when attacking with double-strike

			if ( attacker is BaseCreature )
				((BaseCreature)attacker).AlterMeleeDamageTo( defender, ref damage );

			if ( defender is BaseCreature )
				((BaseCreature)defender).AlterMeleeDamageFrom( attacker, ref damage );

			WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker );

			damage = AbsorbDamage( attacker, defender, damage );

			if ( !Core.AOS && damage < 1 )
				damage = 1;
			else if ( Core.AOS && damage == 0 ) // parried
			{
				if ( a != null && a.Validate( attacker ) /*&& a.CheckMana( attacker, true )*/ ) // Parried special moves have no mana cost 
				{
					a = null;
					WeaponAbility.ClearCurrentAbility( attacker );

					attacker.SendLocalizedMessage( 1061140 ); // Your attack was parried!
				}
			}

			AddBlood( attacker, defender, damage );

			int phys, fire, cold, pois, nrgy;

			GetDamageTypes( attacker, out phys, out fire, out cold, out pois, out nrgy );

			if ( m_Consecrated )
			{
				phys = defender.PhysicalResistance;
				fire = defender.FireResistance;
				cold = defender.ColdResistance;
				pois = defender.PoisonResistance;
				nrgy = defender.EnergyResistance;

				int low = phys, type = 0;

				if ( fire < low ){ low = fire; type = 1; }
				if ( cold < low ){ low = cold; type = 2; }
				if ( pois < low ){ low = pois; type = 3; }
				if ( nrgy < low ){ low = nrgy; type = 4; }

				phys = fire = cold = pois = nrgy = 0;

				if ( type == 0 ) phys = 100;
				else if ( type == 1 ) fire = 100;
				else if ( type == 2 ) cold = 100;
				else if ( type == 3 ) pois = 100;
				else if ( type == 4 ) nrgy = 100;
			}

			int damageGiven = damage;

			AOS.ArmorIgnore = ( a is ArmorIgnore );

			damageGiven = AOS.Damage( defender, attacker, damage, phys, fire, cold, pois, nrgy );

			AOS.ArmorIgnore = false;

			TransformContext context = TransformationSpell.GetContext( defender );

			if ( Core.AOS )
			{
				int lifeLeech = 0;//m_AosWeaponAttributes.HitLeechHits;
				int stamLeech = 0;//m_AosWeaponAttributes.HitLeechStam;
				int manaLeech = 0;//m_AosWeaponAttributes.HitLeechMana;

				if ( m_AosWeaponAttributes.HitLeechHits > Utility.Random( 100 ) )
					lifeLeech += 35; // HitLeechHits% chance to leech 35% of damage as hit points

				if ( m_AosWeaponAttributes.HitLeechStam > Utility.Random( 100 ) )
					stamLeech += 100; // HitLeechStam% chance to leech 100% of damage as stamina

				if ( m_AosWeaponAttributes.HitLeechMana > Utility.Random( 100 ) )
					manaLeech += 50; // HitLeechMana% chance to leech 50% of damage as mana

				if ( m_Cursed )
					lifeLeech += 50; // Additional 50% life leech for cursed weapons (necro spell)

				context = TransformationSpell.GetContext( attacker );

				if ( context != null && context.Type == typeof( VampiricEmbraceSpell ) )
					lifeLeech += 20; // Vampiric embrace gives an additional 20% life leech

				if ( context != null && context.Type == typeof( WraithFormSpell ) )
					manaLeech += (5 + (int)((15 * attacker.Skills.SpiritSpeak.Value) / 100)); // Wraith form gives an additional 5-20% mana leech

				if ( lifeLeech != 0 )
					attacker.Hits += AOS.Scale( damageGiven, lifeLeech );

				if ( stamLeech != 0 )
					attacker.Stam += AOS.Scale( damageGiven, stamLeech );

				if ( manaLeech != 0 )
					attacker.Mana += AOS.Scale( damageGiven, manaLeech );

				if ( lifeLeech != 0 || stamLeech != 0 || manaLeech != 0 )
					attacker.PlaySound( 0x44D );
			}

			if ( m_MaxHits > 0 && ((MaxRange <= 1 && (defender is Slime || defender is ToxicElemental)) || Utility.Random( 25 ) == 0) ) // Stratics says 50% chance, seems more like 4%..
			{
				if ( MaxRange <= 1 && (defender is Slime || defender is ToxicElemental) )
					attacker.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500263 ); // *Acid blood scars your weapon!*

				if ( Core.AOS && m_AosWeaponAttributes.SelfRepair > Utility.Random( 10 ) )
				{
					Hits += 2;
				}
				else
				{
					if ( m_Hits > 0 )
					{
						--Hits;
					}
					else if ( m_MaxHits > 1 )
					{
						--MaxHits;

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

			if ( attacker is VampireBatFamiliar )
			{
				BaseCreature bc = (BaseCreature)attacker;
				Mobile caster = bc.ControlMaster;

				if ( caster == null )
					caster = bc.SummonMaster;

				if ( caster != null && caster.Map == bc.Map && caster.InRange( bc, 2 ) )
					caster.Hits += damage;
				else
					bc.Hits += damage;
			}

			if ( Core.AOS )
			{
				int physChance = m_AosWeaponAttributes.HitPhysicalArea;
				int fireChance = m_AosWeaponAttributes.HitFireArea;
				int coldChance = m_AosWeaponAttributes.HitColdArea;
				int poisChance = m_AosWeaponAttributes.HitPoisonArea;
				int nrgyChance = m_AosWeaponAttributes.HitEnergyArea;

				if ( physChance != 0 && physChance > Utility.Random( 100 ) )
					DoAreaAttack( attacker, defender, 0x10E,   50, 100, 0, 0, 0, 0 );

				if ( fireChance != 0 && fireChance > Utility.Random( 100 ) )
					DoAreaAttack( attacker, defender, 0x11D, 1160, 0, 100, 0, 0, 0 );

				if ( coldChance != 0 && coldChance > Utility.Random( 100 ) )
					DoAreaAttack( attacker, defender, 0x0FC, 2100, 0, 0, 100, 0, 0 );

				if ( poisChance != 0 && poisChance > Utility.Random( 100 ) )
					DoAreaAttack( attacker, defender, 0x205, 1166, 0, 0, 0, 100, 0 );

				if ( nrgyChance != 0 && nrgyChance > Utility.Random( 100 ) )
					DoAreaAttack( attacker, defender, 0x1F1,  120, 0, 0, 0, 0, 100 );

				int maChance = m_AosWeaponAttributes.HitMagicArrow;
				int harmChance = m_AosWeaponAttributes.HitHarm;
				int fireballChance = m_AosWeaponAttributes.HitFireball;
				int lightningChance = m_AosWeaponAttributes.HitLightning;
				int dispelChance = m_AosWeaponAttributes.HitDispel;

				if ( maChance != 0 && maChance > Utility.Random( 100 ) )
					DoMagicArrow( attacker, defender );

				if ( harmChance != 0 && harmChance > Utility.Random( 100 ) )
					DoHarm( attacker, defender );

				if ( fireballChance != 0 && fireballChance > Utility.Random( 100 ) )
					DoFireball( attacker, defender );

				if ( lightningChance != 0 && lightningChance > Utility.Random( 100 ) )
					DoLightning( attacker, defender );

				if ( dispelChance != 0 && dispelChance > Utility.Random( 100 ) )
					DoDispel( attacker, defender );

				int laChance = m_AosWeaponAttributes.HitLowerAttack;
				int ldChance = m_AosWeaponAttributes.HitLowerDefend;

				if ( laChance != 0 && laChance > Utility.Random( 100 ) )
					DoLowerAttack( attacker, defender );

				if ( ldChance != 0 && ldChance > Utility.Random( 100 ) )
					DoLowerDefense( attacker, defender );
			}

			if ( attacker is BaseCreature )
				((BaseCreature)attacker).OnGaveMeleeAttack( defender );

			if ( defender is BaseCreature )
				((BaseCreature)defender).OnGotMeleeAttack( attacker );

			if ( a != null )
				a.OnHit( attacker, defender, damage );
		}

		public virtual double GetAosDamage( Mobile attacker, int min, int random, double div )
		{
			double scale = 1.0;

			scale += attacker.Skills[SkillName.Inscribe].Value * 0.001;

			if ( attacker.Player )
			{
				scale += attacker.Int * 0.001;
				scale += AosAttributes.GetValue( attacker, AosAttribute.SpellDamage ) * 0.01;

				if (attacker is AdvancedPlayerMobile)
					scale += ((AdvancedPlayerMobile)attacker).Bonuses(AosAttribute.SpellDamage) * 0.01;
			}

			int baseDamage = min + (int)(attacker.Skills[SkillName.EvalInt].Value / div);

			double damage = Utility.RandomMinMax( baseDamage, baseDamage + random );

			return damage * scale;
		}

		public virtual void DoMagicArrow( Mobile attacker, Mobile defender )
		{
			if ( !attacker.CanBeHarmful( defender, false ) )
				return;

			attacker.DoHarmful( defender );

			double damage = GetAosDamage( attacker, 3, 1, 10.0 );

			attacker.MovingParticles( defender, 0x36E4, 5, 0, false, true, 3006, 4006, 0 );
			attacker.PlaySound( 0x1E5 );

			SpellHelper.Damage( TimeSpan.FromSeconds( 1.0 ), defender, attacker, damage, 0, 100, 0, 0, 0 );
		}

		public virtual void DoHarm( Mobile attacker, Mobile defender )
		{
			if ( !attacker.CanBeHarmful( defender, false ) )
				return;

			attacker.DoHarmful( defender );

			double damage = GetAosDamage( attacker, 6, 3, 6.5 );

			if ( !defender.InRange( attacker, 2 ) )
				damage *= 0.25; // 1/4 damage at > 2 tile range
			else if ( !defender.InRange( attacker, 1 ) )
				damage *= 0.50; // 1/2 damage at 2 tile range

			defender.FixedParticles( 0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist );
			defender.PlaySound( 0x0FC );

			SpellHelper.Damage( TimeSpan.Zero, defender, attacker, damage, 0, 0, 100, 0, 0 );
		}

		public virtual void DoFireball( Mobile attacker, Mobile defender )
		{
			if ( !attacker.CanBeHarmful( defender, false ) )
				return;

			attacker.DoHarmful( defender );

			double damage = GetAosDamage( attacker, 6, 3, 5.5 );

			attacker.MovingParticles( defender, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160 );
			attacker.PlaySound( 0x15E );

			SpellHelper.Damage( TimeSpan.FromSeconds( 1.0 ), defender, attacker, damage, 0, 100, 0, 0, 0 );
		}

		public virtual void DoLightning( Mobile attacker, Mobile defender )
		{
			if ( !attacker.CanBeHarmful( defender, false ) )
				return;

			attacker.DoHarmful( defender );

			double damage = GetAosDamage( attacker, 6, 3, 5.0 );

			defender.BoltEffect( 0 );

			SpellHelper.Damage( TimeSpan.Zero, defender, attacker, damage, 0, 0, 0, 0, 100 );
		}

		public virtual void DoDispel( Mobile attacker, Mobile defender )
		{
			bool dispellable = false;

			if ( defender is BaseCreature )
				dispellable = ((BaseCreature)defender).Summoned && !((BaseCreature)defender).IsAnimatedDead;

			if ( !dispellable )
				return;

			if ( !attacker.CanBeHarmful( defender, false ) )
				return;

			attacker.DoHarmful( defender );

			Spells.Spell sp = new Spells.Sixth.DispelSpell( attacker, null );

			if ( sp.CheckResisted( defender ) )
			{
				defender.FixedEffect( 0x3779, 10, 20 );
			}
			else
			{
				Effects.SendLocationParticles( EffectItem.Create( defender.Location, defender.Map, EffectItem.DefaultDuration ), 0x3728, 8, 20, 5042 );
				Effects.PlaySound( defender, defender.Map, 0x201 );

				defender.Delete();
			}
		}

		public virtual void DoLowerAttack( Mobile from, Mobile defender )
		{
			if ( HitLower.ApplyAttack( defender ) )
			{
				defender.PlaySound( 0x28E );
				Effects.SendTargetEffect( defender, 0x37BE, 1, 4, 0xA, 3 );
			}
		}

		public virtual void DoLowerDefense( Mobile from, Mobile defender )
		{
			if ( HitLower.ApplyDefense( defender ) )
			{
				defender.PlaySound( 0x28E );
				Effects.SendTargetEffect( defender, 0x37BE, 1, 4, 0x23, 3 );
			}
		}

		public virtual void DoAreaAttack( Mobile from, Mobile defender, int sound, int hue, int phys, int fire, int cold, int pois, int nrgy )
		{
			Map map = from.Map;

			if ( map == null )
				return;

			ArrayList list = new ArrayList();

			foreach ( Mobile m in from.GetMobilesInRange( 10 ) )
			{
				if ( from != m && defender != m && SpellHelper.ValidIndirectTarget( from, m ) && from.CanBeHarmful( m, false ) && from.InLOS( m ) )
					list.Add( m );
			}

			if ( list.Count == 0 )
				return;

			Effects.PlaySound( from.Location, map, sound );

			// TODO: What is the damage calculation?

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

				double scalar = (11 - from.GetDistanceToSqrt( m )) / 10;

				if ( scalar > 1.0 )
					scalar = 1.0;
				else if ( scalar < 0.0 )
					continue;

				from.DoHarmful( m, true );
				m.FixedEffect( 0x3779, 1, 15, hue, 0 );
				AOS.Damage( m, from, (int)(GetBaseDamage( from ) * scalar), phys, fire, cold, pois, nrgy );
			}
		}

		public virtual CheckSlayerResult CheckSlayers( Mobile attacker, Mobile defender )
		{
			BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon;
			SlayerEntry atkSlayer = SlayerGroup.GetEntryByName( atkWeapon.Slayer );

			if ( atkSlayer != null && atkSlayer.Slays( defender ) )
				return CheckSlayerResult.Slayer;

			BaseWeapon defWeapon = defender.Weapon as BaseWeapon;
			SlayerEntry defSlayer = SlayerGroup.GetEntryByName( defWeapon.Slayer );

			if( defSlayer != null && defSlayer.Group.OppositionSuperSlays( attacker ))
				return CheckSlayerResult.Opposition;

			return CheckSlayerResult.None;
		}

		public virtual void AddBlood( Mobile attacker, Mobile defender, int damage )
		{
			if ( damage > 0 )
			{
				new Blood().MoveToWorld( defender.Location, defender.Map );

				if ( Utility.RandomBool() )
				{
					new Blood().MoveToWorld( new Point3D(
						defender.X + Utility.RandomMinMax( -1, 1 ),
						defender.Y + Utility.RandomMinMax( -1, 1 ),
						defender.Z ), defender.Map );
				}
			}

			/* if ( damage <= 2 )
				return;

			Direction d = defender.GetDirectionTo( attacker );

			int maxCount = damage / 15;

			if ( maxCount < 1 )
				maxCount = 1;
			else if ( maxCount > 4 )
				maxCount = 4;

			for( int i = 0; i < Utility.Random( 1, maxCount ); ++i )
			{
				int x = defender.X;
				int y = defender.Y;

				switch( d )
				{
					case Direction.North:
						x += Utility.Random( -1, 3 );
						y += Utility.Random( 2 );
						break;
					case Direction.East:
						y += Utility.Random( -1, 3 );
						x += Utility.Random( -1, 2 );
						break;
					case Direction.West:
						y += Utility.Random( -1, 3 );
						x += Utility.Random( 2 );
						break;
					case Direction.South:
						x += Utility.Random( -1, 3 );
						y += Utility.Random( -1, 2 );
						break;
					case Direction.Up:
						x += Utility.Random( 2 );
						y += Utility.Random( 2 );
						break;
					case Direction.Down:
						x += Utility.Random( -1, 2 );
						y += Utility.Random( -1, 2 );
						break;
					case Direction.Left:
						x += Utility.Random( 2 );
						y += Utility.Random( -1, 2 );
						break;
					case Direction.Right:
						x += Utility.Random( -1, 2 );
						y += Utility.Random( 2 );
						break;
				}

				new Blood().MoveToWorld( new Point3D( x, y, defender.Z ), defender.Map );
			}*/
		}

		public virtual void GetDamageTypes( Mobile wielder, out int phys, out int fire, out int cold, out int pois, out int nrgy )
		{
			if ( wielder is BaseCreature )
			{
				BaseCreature bc = (BaseCreature)wielder;

				phys = bc.PhysicalDamage;
				fire = bc.FireDamage;
				cold = bc.ColdDamage;
				pois = bc.PoisonDamage;
				nrgy = bc.EnergyDamage;
			}
			else
			{
				CraftResourceInfo resInfo = CraftResources.GetInfo( m_Resource );

				if ( resInfo != null )
				{
					CraftAttributeInfo attrInfo = resInfo.AttributeInfo;

					if ( attrInfo != null )
					{
						fire = attrInfo.WeaponFireDamage;
						cold = attrInfo.WeaponColdDamage;
						pois = attrInfo.WeaponPoisonDamage;
						nrgy = attrInfo.WeaponEnergyDamage;
						phys = 100 - fire - cold - pois - nrgy;
						return;
					}
				}

				phys = 100;
				fire = 0;
				cold = 0;
				pois = 0;
				nrgy = 0;
			}
		}

		public virtual void OnMiss( Mobile attacker, Mobile defender )
		{
			PlaySwingAnimation( attacker );
			attacker.PlaySound( GetMissAttackSound( attacker, defender ) );
			defender.PlaySound( GetMissDefendSound( attacker, defender ) );

			WeaponAbility ability = WeaponAbility.GetCurrentAbility( attacker );

			if ( ability != null )
				ability.OnMiss( attacker, defender );
		}

		public virtual void GetBaseDamageRange( Mobile attacker, out int min, out int max )
		{
			if ( attacker is BaseCreature )
			{
				BaseCreature c = (BaseCreature)attacker;

				if ( c.DamageMin >= 0 )
				{
					min = c.DamageMin;
					max = c.DamageMax;
					return;
				}

				if ( this is Fists && !attacker.Body.IsHuman )
				{
					min = attacker.Str / 28;
					max = attacker.Str / 28;
					return;
				}
			}

			min = MinDamage;
			max = MaxDamage;
		}

		public virtual double GetBaseDamage( Mobile attacker )
		{
			int min, max;

			GetBaseDamageRange( attacker, out min, out max );

			return Utility.RandomMinMax( min, max );
		}

		public virtual double GetBonus( double value, double scalar, double threshold, double offset )
		{
			double bonus = value * scalar;

			if ( value >= threshold )
				bonus += offset;

			return bonus / 100;
		}

		public virtual int GetHitChanceBonus()
		{
			if ( !Core.AOS )
				return 0;

			int bonus = 0;

			switch ( m_AccuracyLevel )
			{
				case WeaponAccuracyLevel.Accurate:		bonus += 02; break;
				case WeaponAccuracyLevel.Surpassingly:	bonus += 04; break;
				case WeaponAccuracyLevel.Eminently:		bonus += 06; break;
				case WeaponAccuracyLevel.Exceedingly:	bonus += 08; break;
				case WeaponAccuracyLevel.Supremely:		bonus += 10; break;
			}

			return bonus;
		}

		public virtual int GetDamageBonus()
		{
			int bonus = VirtualDamageBonus;

			switch ( m_Quality )
			{
				case WeaponQuality.Low:			bonus -= 20; break;
				case WeaponQuality.Exceptional:	bonus += 20; break;
			}

			switch ( m_DamageLevel )
			{
				case WeaponDamageLevel.Ruin:	bonus += 15; break;
				case WeaponDamageLevel.Might:	bonus += 20; break;
				case WeaponDamageLevel.Force:	bonus += 25; break;
				case WeaponDamageLevel.Power:	bonus += 30; break;
				case WeaponDamageLevel.Vanq:	bonus += 35; break;
			}

			return bonus;
		}

		public virtual void GetStatusDamage( Mobile from, out int min, out int max )
		{
			int baseMin, baseMax;

			GetBaseDamageRange( from, out baseMin, out baseMax );

			if ( Core.AOS )
			{
				min = (int)ScaleDamageAOS( from, baseMin, false, false );
				max = (int)ScaleDamageAOS( from, baseMax, false, false );
			}
			else
			{
				min = (int)ScaleDamageOld( from, baseMin, false, false );
				max = (int)ScaleDamageOld( from, baseMax, false, false );
			}

			if ( min < 1 )
				min = 1;

			if ( max < 1 )
				max = 1;
		}

		public virtual double ScaleDamageAOS( Mobile attacker, double damage, bool checkSkills, bool checkAbility )
		{
			if ( checkSkills )
			{
				attacker.CheckSkill( SkillName.Tactics, 0.0, 120.0 ); // Passively check tactics for gain
				attacker.CheckSkill( SkillName.Anatomy, 0.0, 120.0 ); // Passively check Anatomy for gain

				if ( Type == WeaponType.Axe )
					attacker.CheckSkill( SkillName.Lumberjacking, 0.0, 100.0 ); // Passively check Lumberjacking for gain
			}

			double strengthBonus = GetBonus( attacker.Str,										0.300, 100.0,  5.00 );
			double  anatomyBonus = GetBonus( attacker.Skills[SkillName.Anatomy].Value,			0.500, 100.0,  5.00 );
			double  tacticsBonus = GetBonus( attacker.Skills[SkillName.Tactics].Value,			0.625, 100.0,  6.25 );
			double   lumberBonus = GetBonus( attacker.Skills[SkillName.Lumberjacking].Value,	0.200, 100.0, 10.00 );

			if ( Type != WeaponType.Axe )
				lumberBonus = 0.0;

			// Damage Increase = 100%
			int damageBonus = AosAttributes.GetValue( attacker, AosAttribute.WeaponDamage );
			if ( damageBonus > 100 )
				damageBonus = 100;

			Mobile defender=attacker.Combatant;

			if (attacker is AdvancedPlayerMobile)
			{
				damageBonus+=((AdvancedPlayerMobile)attacker).Bonuses(AosAttribute.WeaponDamage);

				if (((AdvancedPlayerMobile)attacker).CriticalChance() > Utility.Random(100))
				{
					damageBonus+=100;	// the attack is a critical one, thus doubled damage.
					attacker.SendMessage(35, "You score a critical blow!");

					if (defender is AdvancedPlayerMobile)
						defender.SendMessage(35, attacker.Name + " scores a critical blow!");
				}
			}

			// if (defender is AdvancedPlayerMobile)
			//	damageBonus+=((AdvancedPlayerMobile)defender).Bonuses(AosAttribute.OpWeaponDamage);	//lucent eclipse aosattribute

			double totalBonus = strengthBonus + anatomyBonus + tacticsBonus + lumberBonus + ((double)(GetDamageBonus() + damageBonus) / 100);

			if ( TransformationSpell.UnderTransformation( attacker, typeof( HorrificBeastSpell ) ) )
				totalBonus += 0.25;

			if ( Spells.Chivalry.DivineFurySpell.UnderEffect( attacker ) )
				totalBonus += 0.1;

			double discordanceScalar = 0.0;

			if ( SkillHandlers.Discordance.GetScalar( attacker, ref discordanceScalar ) )
				totalBonus += discordanceScalar * 2;

			damage += (damage * totalBonus);

			WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker );

			if ( checkAbility && a != null )
				damage *= a.DamageScalar;

			return damage;
		}

		public virtual int VirtualDamageBonus{ get{ return 0; } }

		public virtual int ComputeDamageAOS( Mobile attacker, Mobile defender )
		{
			return (int)ScaleDamageAOS( attacker, GetBaseDamage( attacker ), true, true );
		}

		public virtual double ScaleDamageOld( Mobile attacker, double damage, bool checkSkills, bool checkAbility )
		{
			if ( checkSkills )
			{
				attacker.CheckSkill( SkillName.Tactics, 0.0, 120.0 ); // Passively check tactics for gain
				attacker.CheckSkill( SkillName.Anatomy, 0.0, 120.0 ); // Passively check Anatomy for gain

				if ( Type == WeaponType.Axe )
					attacker.CheckSkill( SkillName.Lumberjacking, 0.0, 100.0 ); // Passively check Lumberjacking for gain
			}

			/* Compute tactics modifier
			 * :   0.0 = 50% loss
			 * :  50.0 = unchanged
			 * : 100.0 = 50% bonus
			 */
			double tacticsBonus = (attacker.Skills[SkillName.Tactics].Value - 50.0) / 100.0;

			/* Compute strength modifier
			 * : 1% bonus for every 5 strength
			 */
			double strBonus = (attacker.Str / 5.0) / 100.0;

			/* Compute anatomy modifier
			 * : 1% bonus for every 5 points of anatomy
			 * : +10% bonus at Grandmaster or higher
			 */
			double anatomyValue = attacker.Skills[SkillName.Anatomy].Value;
			double anatomyBonus = (anatomyValue / 5.0) / 100.0;

			if ( anatomyValue >= 100.0 )
				anatomyBonus += 0.1;

			/* Compute lumberjacking bonus
			 * : 1% bonus for every 5 points of lumberjacking
			 * : +10% bonus at Grandmaster or higher
			 */
			double lumberBonus;

			if ( Type == WeaponType.Axe )
			{
				double lumberValue = attacker.Skills[SkillName.Lumberjacking].Value;

				lumberBonus = (lumberValue / 5.0) / 100.0;

				if ( lumberValue >= 100.0 )
					lumberBonus += 0.1;
			}
			else
			{
				lumberBonus = 0.0;
			}

			// New quality bonus:
			double qualityBonus = ((int)m_Quality - 1) * 0.2;

			// Apply bonuses
			damage += (damage * tacticsBonus) + (damage * strBonus) + (damage * anatomyBonus) + (damage * lumberBonus) + (damage * qualityBonus) + ((damage * VirtualDamageBonus) / 100);

			// Old quality bonus:
#if false
			/* Apply quality offset
			 * : Low         : -4
			 * : Regular     :  0
			 * : Exceptional : +4
			 */
			damage += ((int)m_Quality - 1) * 4.0;
#endif

			/* Apply damage level offset
			 * : Regular : 0
			 * : Ruin    : 1
			 * : Might   : 3
			 * : Force   : 5
			 * : Power   : 7
			 * : Vanq    : 9
			 */
			if ( m_DamageLevel != WeaponDamageLevel.Regular )
				damage += (2.0 * (int)m_DamageLevel) - 1.0;

			// Halve the computed damage and return
			damage /= 2.0;

			WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker );

			if ( checkAbility && a != null )
				damage *= a.DamageScalar;

			return ScaleDamageByDurability( (int)damage );
		}

		public virtual int ScaleDamageByDurability( int damage )
		{
			int scale = 100;

			if ( m_MaxHits > 0 && m_Hits < m_MaxHits )
				scale = 50 + ((50 * m_Hits) / m_MaxHits);

			return AOS.Scale( damage, scale );
		}

		public virtual int ComputeDamage( Mobile attacker, Mobile defender )
		{
			if ( Core.AOS )
				return ComputeDamageAOS( attacker, defender );

			return (int)ScaleDamageOld( attacker, GetBaseDamage( attacker ), true, true );
		}

		public virtual void PlayHurtAnimation( Mobile from )
		{
			int action;
			int frames;

			switch ( from.Body.Type )
			{
				case BodyType.Sea:
				case BodyType.Animal:
				{
					action = 7;
					frames = 5;
					break;
				}
				case BodyType.Monster:
				{
					action = 10;
					frames = 4;
					break;
				}
				case BodyType.Human:
				{
					action = 20;
					frames = 5;
					break;
				}
				default: return;
			}

			if ( from.Mounted )
				return;

			from.Animate( action, frames, 1, true, false, 0 );
		}

		public virtual void PlaySwingAnimation( Mobile from )
		{
			int action;

			switch ( from.Body.Type )
			{
				case BodyType.Sea:
				case BodyType.Animal:
				{
					action = Utility.Random( 5, 2 );
					break;
				}
				case BodyType.Monster:
				{
					switch ( Animation )
					{
						default:
						case WeaponAnimation.Wrestle:
						case WeaponAnimation.Bash1H:
						case WeaponAnimation.Pierce1H:
						case WeaponAnimation.Slash1H:
						case WeaponAnimation.Bash2H:
						case WeaponAnimation.Pierce2H:
						case WeaponAnimation.Slash2H: action = Utility.Random( 4, 3 ); break;
						case WeaponAnimation.ShootBow:  return; // 7
						case WeaponAnimation.ShootXBow: return; // 8
					}

					break;
				}
				case BodyType.Human:
				{
					if ( !from.Mounted )
					{
						action = (int)Animation;
					}
					else
					{
						switch ( Animation )
						{
							default:
							case WeaponAnimation.Wrestle:
							case WeaponAnimation.Bash1H:
							case WeaponAnimation.Pierce1H:
							case WeaponAnimation.Slash1H: action = 26; break;
							case WeaponAnimation.Bash2H:
							case WeaponAnimation.Pierce2H:
							case WeaponAnimation.Slash2H: action = 29; break;
							case WeaponAnimation.ShootBow: action = 27; break;
							case WeaponAnimation.ShootXBow: action = 28; break;
						}
					}

					break;
				}
				default: return;
			}

			from.Animate( action, 7, 1, true, false, 0 );
		}

		private static void SetSaveFlag( ref SaveFlag flags, SaveFlag toSet, bool setIf )
		{
			if ( setIf )
				flags |= toSet;
		}

		private static bool GetSaveFlag( SaveFlag flags, SaveFlag toGet )
		{
			return ( (flags & toGet) != 0 );
		}

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

			// Version 10
			// AUTHOR: Marox
			// CHANGES: Added ActuallyTwoHanded

			// Version 9
			// AUTHOR: Marox
			// CHANGES: Added OverridePrimaryAbility, OverrideSecondaryAbility

			// Version 8
			// AUTHOR: Marox
			// CHANGES: Added CriticalChance, MadeBy, RaceItem

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

			writer.Write( (bool) ActuallyTwoHanded );

			writer.Write( (int) OverridePrimaryAbility );
			writer.Write( (int) OverrideSecondaryAbility );

			writer.Write( (int) CriticalChance );
			writer.Write( (int) RaceItem );
			writer.Write( (Mobile) MadeBy );

			SaveFlag flags = SaveFlag.None;

			SetSaveFlag( ref flags, SaveFlag.DamageLevel,		m_DamageLevel != WeaponDamageLevel.Regular );
			SetSaveFlag( ref flags, SaveFlag.AccuracyLevel,		m_AccuracyLevel != WeaponAccuracyLevel.Regular );
			SetSaveFlag( ref flags, SaveFlag.DurabilityLevel,	m_DurabilityLevel != WeaponDurabilityLevel.Regular );
			SetSaveFlag( ref flags, SaveFlag.Quality,			m_Quality != WeaponQuality.Regular );
			SetSaveFlag( ref flags, SaveFlag.Hits,				m_Hits != 0 );
			SetSaveFlag( ref flags, SaveFlag.MaxHits,			m_MaxHits != 0 );
			SetSaveFlag( ref flags, SaveFlag.Slayer,			m_Slayer != SlayerName.None );
			SetSaveFlag( ref flags, SaveFlag.Poison,			m_Poison != null );
			SetSaveFlag( ref flags, SaveFlag.PoisonCharges,		m_PoisonCharges != 0 );
			SetSaveFlag( ref flags, SaveFlag.Crafter,			m_Crafter != null );
			SetSaveFlag( ref flags, SaveFlag.Identified,		m_Identified != false );
			SetSaveFlag( ref flags, SaveFlag.StrReq,			m_StrReq != -1 );
			SetSaveFlag( ref flags, SaveFlag.DexReq,			m_DexReq != -1 );
			SetSaveFlag( ref flags, SaveFlag.IntReq,			m_IntReq != -1 );
			SetSaveFlag( ref flags, SaveFlag.MinDamage,			m_MinDamage != -1 );
			SetSaveFlag( ref flags, SaveFlag.MaxDamage,			m_MaxDamage != -1 );
			SetSaveFlag( ref flags, SaveFlag.HitSound,			m_HitSound != -1 );
			SetSaveFlag( ref flags, SaveFlag.MissSound,			m_MissSound != -1 );
			SetSaveFlag( ref flags, SaveFlag.Speed,				m_Speed != -1 );
			SetSaveFlag( ref flags, SaveFlag.MaxRange,			m_MaxRange != -1 );
			SetSaveFlag( ref flags, SaveFlag.Skill,				m_Skill != (SkillName)(-1) );
			SetSaveFlag( ref flags, SaveFlag.Type,				m_Type != (WeaponType)(-1) );
			SetSaveFlag( ref flags, SaveFlag.Animation,			m_Animation != (WeaponAnimation)(-1) );
			SetSaveFlag( ref flags, SaveFlag.Resource,			m_Resource != CraftResource.Iron );
			SetSaveFlag( ref flags, SaveFlag.xAttributes,		!m_AosAttributes.IsEmpty );
			SetSaveFlag( ref flags, SaveFlag.xWeaponAttributes,	!m_AosWeaponAttributes.IsEmpty );
			SetSaveFlag( ref flags, SaveFlag.PlayerConstructed,	m_PlayerConstructed );
			SetSaveFlag( ref flags, SaveFlag.SkillBonuses,		!m_AosSkillBonuses.IsEmpty );

			writer.Write( (int) flags );

			if ( GetSaveFlag( flags, SaveFlag.DamageLevel ) )
				writer.Write( (int) m_DamageLevel );

			if ( GetSaveFlag( flags, SaveFlag.AccuracyLevel ) )
				writer.Write( (int) m_AccuracyLevel );

			if ( GetSaveFlag( flags, SaveFlag.DurabilityLevel ) )
				writer.Write( (int) m_DurabilityLevel );

			if ( GetSaveFlag( flags, SaveFlag.Quality ) )
				writer.Write( (int) m_Quality );

			if ( GetSaveFlag( flags, SaveFlag.Hits ) )
				writer.Write( (int) m_Hits );

			if ( GetSaveFlag( flags, SaveFlag.MaxHits ) )
				writer.Write( (int) m_MaxHits );

			if ( GetSaveFlag( flags, SaveFlag.Slayer ) )
				writer.Write( (int) m_Slayer );

			if ( GetSaveFlag( flags, SaveFlag.Poison ) )
				Poison.Serialize( m_Poison, writer );

			if ( GetSaveFlag( flags, SaveFlag.PoisonCharges ) )
				writer.Write( (int) m_PoisonCharges );

			if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
				writer.Write( (Mobile) m_Crafter );

			if ( GetSaveFlag( flags, SaveFlag.StrReq ) )
				writer.Write( (int) m_StrReq );

			if ( GetSaveFlag( flags, SaveFlag.DexReq ) )
				writer.Write( (int) m_DexReq );

			if ( GetSaveFlag( flags, SaveFlag.IntReq ) )
				writer.Write( (int) m_IntReq );

			if ( GetSaveFlag( flags, SaveFlag.MinDamage ) )
				writer.Write( (int) m_MinDamage );

			if ( GetSaveFlag( flags, SaveFlag.MaxDamage ) )
				writer.Write( (int) m_MaxDamage );

			if ( GetSaveFlag( flags, SaveFlag.HitSound ) )
				writer.Write( (int) m_HitSound );

			if ( GetSaveFlag( flags, SaveFlag.MissSound ) )
				writer.Write( (int) m_MissSound );

			if ( GetSaveFlag( flags, SaveFlag.Speed ) )
				writer.Write( (int) m_Speed );

			if ( GetSaveFlag( flags, SaveFlag.MaxRange ) )
				writer.Write( (int) m_MaxRange );

			if ( GetSaveFlag( flags, SaveFlag.Skill ) )
				writer.Write( (int) m_Skill );

			if ( GetSaveFlag( flags, SaveFlag.Type ) )
				writer.Write( (int) m_Type );

			if ( GetSaveFlag( flags, SaveFlag.Animation ) )
				writer.Write( (int) m_Animation );

			if ( GetSaveFlag( flags, SaveFlag.Resource ) )
				writer.Write( (int) m_Resource );

			if ( GetSaveFlag( flags, SaveFlag.xAttributes ) )
				m_AosAttributes.Serialize( writer );

			if ( GetSaveFlag( flags, SaveFlag.xWeaponAttributes ) )
				m_AosWeaponAttributes.Serialize( writer );

			if ( GetSaveFlag( flags, SaveFlag.SkillBonuses ) )
				m_AosSkillBonuses.Serialize( writer );
		}

		[Flags]
		private enum SaveFlag
		{
			None					= 0x00000000,
			DamageLevel				= 0x00000001,
			AccuracyLevel			= 0x00000002,
			DurabilityLevel			= 0x00000004,
			Quality					= 0x00000008,
			Hits					= 0x00000010,
			MaxHits					= 0x00000020,
			Slayer					= 0x00000040,
			Poison					= 0x00000080,
			PoisonCharges			= 0x00000100,
			Crafter					= 0x00000200,
			Identified				= 0x00000400,
			StrReq					= 0x00000800,
			DexReq					= 0x00001000,
			IntReq					= 0x00002000,
			MinDamage				= 0x00004000,
			MaxDamage				= 0x00008000,
			HitSound				= 0x00010000,
			MissSound				= 0x00020000,
			Speed					= 0x00040000,
			MaxRange				= 0x00080000,
			Skill					= 0x00100000,
			Type					= 0x00200000,
			Animation				= 0x00400000,
			Resource				= 0x00800000,
			xAttributes				= 0x01000000,
			xWeaponAttributes		= 0x02000000,
			PlayerConstructed		= 0x04000000,
			SkillBonuses			= 0x08000000
		}

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

			int version = reader.ReadInt();

			switch ( version )
			{
				case 10:
				{
					ActuallyTwoHanded=reader.ReadBool();

					goto case 9;
				}

				case 9:
				{
					OverridePrimaryAbility=reader.ReadInt();
					OverrideSecondaryAbility=reader.ReadInt();

					goto case 8;
				}

				case 8:
				{
					CriticalChance=reader.ReadInt();
					RaceItem=(RaceType)reader.ReadInt();
					MadeBy=reader.ReadMobile();

					goto case 7;
				}
				case 7:
				case 6:
				case 5:
				{
					SaveFlag flags = (SaveFlag)reader.ReadInt();

					if ( GetSaveFlag( flags, SaveFlag.DamageLevel ) )
					{
						m_DamageLevel = (WeaponDamageLevel)reader.ReadInt();

						if ( m_DamageLevel > WeaponDamageLevel.Vanq )
							m_DamageLevel = WeaponDamageLevel.Ruin;
					}

					if ( GetSaveFlag( flags, SaveFlag.AccuracyLevel ) )
					{
						m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt();

						if ( m_AccuracyLevel > WeaponAccuracyLevel.Supremely )
							m_AccuracyLevel = WeaponAccuracyLevel.Accurate;
					}

					if ( GetSaveFlag( flags, SaveFlag.DurabilityLevel ) )
					{
						m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt();

						if ( m_DurabilityLevel > WeaponDurabilityLevel.Indestructible )
							m_DurabilityLevel = WeaponDurabilityLevel.Durable;
					}

					if ( GetSaveFlag( flags, SaveFlag.Quality ) )
						m_Quality = (WeaponQuality)reader.ReadInt();
					else
						m_Quality = WeaponQuality.Regular;

					if ( GetSaveFlag( flags, SaveFlag.Hits ) )
						m_Hits = reader.ReadInt();

					if ( GetSaveFlag( flags, SaveFlag.MaxHits ) )
						m_MaxHits = reader.ReadInt();

					if ( GetSaveFlag( flags, SaveFlag.Slayer ) )
						m_Slayer = (SlayerName)reader.ReadInt();

					if ( GetSaveFlag( flags, SaveFlag.Poison ) )
						m_Poison = Poison.Deserialize( reader );

					if ( GetSaveFlag( flags, SaveFlag.PoisonCharges ) )
						m_PoisonCharges = reader.ReadInt();

					if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
						m_Crafter = reader.ReadMobile();

					if ( GetSaveFlag( flags, SaveFlag.Identified ) )
						m_Identified = ( version >= 6 || reader.ReadBool() );

					if ( GetSaveFlag( flags, SaveFlag.StrReq ) )
						m_StrReq = reader.ReadInt();
					else
						m_StrReq = -1;

					if ( GetSaveFlag( flags, SaveFlag.DexReq ) )
						m_DexReq = reader.ReadInt();
					else
						m_DexReq = -1;

					if ( GetSaveFlag( flags, SaveFlag.IntReq ) )
						m_IntReq = reader.ReadInt();
					else
						m_IntReq = -1;

					if ( GetSaveFlag( flags, SaveFlag.MinDamage ) )
						m_MinDamage = reader.ReadInt();
					else
						m_MinDamage = -1;

					if ( GetSaveFlag( flags, SaveFlag.MaxDamage ) )
						m_MaxDamage = reader.ReadInt();
					else
						m_MaxDamage = -1;

					if ( GetSaveFlag( flags, SaveFlag.HitSound ) )
						m_HitSound = reader.ReadInt();
					else
						m_HitSound = -1;

					if ( GetSaveFlag( flags, SaveFlag.MissSound ) )
						m_MissSound = reader.ReadInt();
					else
						m_MissSound = -1;

					if ( GetSaveFlag( flags, SaveFlag.Speed ) )
						m_Speed = reader.ReadInt();
					else
						m_Speed = -1;

					if ( GetSaveFlag( flags, SaveFlag.MaxRange ) )
						m_MaxRange = reader.ReadInt();
					else
						m_MaxRange = -1;

					if ( GetSaveFlag( flags, SaveFlag.Skill ) )
						m_Skill = (SkillName)reader.ReadInt();
					else
						m_Skill = (SkillName)(-1);

					if ( GetSaveFlag( flags, SaveFlag.Type ) )
						m_Type = (WeaponType)reader.ReadInt();
					else
						m_Type = (WeaponType)(-1);

					if ( GetSaveFlag( flags, SaveFlag.Animation ) )
						m_Animation = (WeaponAnimation)reader.ReadInt();
					else
						m_Animation = (WeaponAnimation)(-1);

					if ( GetSaveFlag( flags, SaveFlag.Resource ) )
						m_Resource = (CraftResource)reader.ReadInt();
					else
						m_Resource = CraftResource.Iron;

					if ( GetSaveFlag( fl