Join Date: Sep 2005
Age: 34
Posts: 14
|
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 |