AvatarsConquest/Scripts/Items/Weapons/BaseWeapon.cs

1866 lines
51 KiB
C#

using System;
using System.Text;
using System.Collections;
using Server.Network;
using Server.Targeting;
using Server.Mobiles;
using Server.Spells;
using Server.Engines.Craft;
using System.Collections.Generic;
namespace Server.Items
{
public interface ISlayer
{
SlayerName Slayer { get; set; }
SlayerName Slayer2 { get; set; }
}
public abstract class BaseWeapon : Item, IWeapon, ICraftable, ISlayer, IDurability
{
/* Weapon internals work differently now (Mar 13 2003)
*
* The attributes defined below default to -1.
* If the value is -1, the corresponding virtual 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
*/
#region Var declarations
// Instance values. These values are unique to each weapon.
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 int m_Hits;
private int m_MaxHits;
private SlayerName m_Slayer;
private SlayerName m_Slayer2;
private SkillMod m_SkillMod, m_MageMod;
private CraftResource m_Resource;
private bool m_PlayerConstructed;
// 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 float m_Speed;
private int m_MaxRange;
private SkillName m_Skill;
private WeaponType m_Type;
private WeaponAnimation m_Animation;
#endregion
#region Virtual Properties
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 UOStrengthReq{ get{ return 0; } }
public virtual int UODexterityReq{ get{ return 0; } }
public virtual int UOIntelligenceReq{ get{ return 0; } }
public virtual int UOMinDamage{ get{ return 0; } }
public virtual int UOMaxDamage{ get{ return 0; } }
public virtual int UOSpeed{ get{ return 0; } }
public virtual int UOMaxRange{ get{ return DefMaxRange; } }
public virtual int UOHitSound{ get{ return DefHitSound; } }
public virtual int UOMissSound{ get{ return DefMissSound; } }
public virtual SkillName UOSkill{ get{ return DefSkill; } }
public virtual WeaponType UOType{ get{ return DefType; } }
public virtual WeaponAnimation UOAnimation{ get{ return DefAnimation; } }
public virtual int InitMinHits{ get{ return 0; } }
public virtual int InitMaxHits{ get{ return 0; } }
public virtual SkillName AccuracySkill { get { return SkillName.Tactics; } }
#endregion
#region Getters & Setters
[CommandProperty( AccessLevel.GameMaster )]
public int HitPoints
{
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 MaxHitPoints
{
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 SlayerName Slayer2
{
get { return m_Slayer2; }
set { m_Slayer2 = 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 ? UOMaxRange : m_MaxRange ); }
set{ m_MaxRange = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public WeaponAnimation Animation
{
get{ return ( m_Animation == (WeaponAnimation)(-1) ? UOAnimation : m_Animation ); }
set{ m_Animation = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public WeaponType Type
{
get{ return ( m_Type == (WeaponType)(-1) ? UOType : m_Type ); }
set{ m_Type = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public SkillName Skill
{
get{ return ( m_Skill == (SkillName)(-1) ? UOSkill : m_Skill ); }
set{ m_Skill = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public int HitSound
{
get{ return ( m_HitSound == -1 ? UOHitSound : m_HitSound ); }
set{ m_HitSound = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public int MissSound
{
get{ return ( m_MissSound == -1 ? UOMissSound : m_MissSound ); }
set{ m_MissSound = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public int MinDamage
{
get{ return ( m_MinDamage == -1 ? UOMinDamage : m_MinDamage ); }
set{ m_MinDamage = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public int MaxDamage
{
get{ return ( m_MaxDamage == -1 ? UOMaxDamage : m_MaxDamage ); }
set{ m_MaxDamage = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public float Speed
{
get
{
if ( m_Speed != -1 )
return m_Speed;
return UOSpeed;
}
set{ m_Speed = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public int StrRequirement
{
get{ return ( m_StrReq == -1 ? UOStrengthReq : m_StrReq ); }
set{ m_StrReq = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public int DexRequirement
{
get{ return ( m_DexReq == -1 ? UODexterityReq : m_DexReq ); }
set{ m_DexReq = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public int IntRequirement
{
get{ return ( m_IntReq == -1 ? UOIntelligenceReq : m_IntReq ); }
set{ m_IntReq = value; }
}
[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();
}
}
}
#endregion
public override void OnAfterDuped( Item newItem )
{
BaseWeapon weap = newItem as BaseWeapon;
if ( weap == null )
return;
}
public virtual void UnscaleDurability()
{
int scale = 100 + GetDurabilityBonus();
m_Hits = ((m_Hits * 100) + (scale - 1)) / scale;
m_MaxHits = ((m_MaxHits * 100) + (scale - 1)) / scale;
InvalidateProperties();
}
public virtual 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;
}
return bonus;
}
public int GetLowerStatReq()
{
return 0;
}
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 && layer == Layer.OneHanded )
{
m.SendLocalizedMessage( 500214 ); // You already have something in both hands.
return true;
}
else if ( this.Layer == Layer.OneHanded && layer == Layer.TwoHanded && !(item is BaseShield) && !(item is BaseEquipableLight) )
{
m.SendLocalizedMessage( 500215 ); // You can only wield one weapon at a time.
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 < Ultima.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 true; } }
public override bool OnEquip( Mobile from )
{
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 );
}
return true;
}
public override void OnAdded( object parent )
{
base.OnAdded( parent );
if ( parent is Mobile )
{
Mobile from = (Mobile)parent;
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;
}
m.CheckStatTimers();
m.Delta( MobileDelta.WeaponDamage );
}
}
public virtual SkillName GetUsedSkill( Mobile m, bool checkSkillAttrs )
{
SkillName sk;
sk = Skill;
if ( sk != SkillName.HandToHand && !m.Player && !m.Body.IsHuman && m.Skills[SkillName.HandToHand].Value > m.Skills[sk].Value )
sk = SkillName.HandToHand;
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 );
double ourValue, theirValue;
int bonus = GetHitChanceBonus();
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);
return attacker.CheckSkill( atkSkill.SkillName, chance );
}
public virtual TimeSpan GetDelay( Mobile m )
{
double speed = this.Speed;
if ( speed == 0 )
return TimeSpan.FromHours( 1.0 );
double delayInSeconds;
int v = (m.Stam + 100) * (int) speed;
if ( v <= 0 )
v = 1;
delayInSeconds = 15000.0 / v;
return TimeSpan.FromSeconds( delayInSeconds );
}
public virtual void OnBeforeSwing( Mobile attacker, Mobile defender )
{
}
public virtual TimeSpan OnSwing( Mobile attacker, Mobile defender )
{
return OnSwing( attacker, defender, 1.0 );
}
public virtual TimeSpan OnSwing( Mobile attacker, Mobile defender, double damageBonus )
{
bool canSwing = true;
if ( canSwing && attacker.HarmfulCheck( defender ) )
{
attacker.DisruptiveAction();
if ( attacker.NetState != null )
attacker.Send( new Swing( 0, attacker, defender ) );
if ( CheckHit( attacker, defender ) )
OnHit( attacker, defender, damageBonus );
else
OnMiss( attacker, defender );
}
return GetDelay( attacker );
}
#region Sounds
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;
}
#endregion
public static int DodgeArmor( Item item, int impact )
{
if ( item is BaseArmor )
{
CraftResource resource = ((BaseArmor)item).Resource;
if ( resource == CraftResource.Iron )
return ( impact * 6 );
else if ( resource == CraftResource.Wooden )
return ( impact * 4 );
else if ( resource == CraftResource.Leathered )
return ( impact * 2 );
}
return 0;
}
public static int ArmorRating( Mobile defender )
{
int armorScore = 0;
if ( defender.FindItemOnLayer( Layer.Pants ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.Pants ), 3 ); }
if ( defender.FindItemOnLayer( Layer.Neck ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.Neck ), 1 ); }
if ( defender.FindItemOnLayer( Layer.InnerTorso ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.InnerTorso ), 4 ); }
if ( defender.FindItemOnLayer( Layer.Helm ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.Helm ), 2 ); }
if ( defender.FindItemOnLayer( Layer.Gloves ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.Gloves ), 1 ); }
if ( defender.FindItemOnLayer( Layer.MiddleTorso ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.MiddleTorso ), 4 ); }
if ( defender.FindItemOnLayer( Layer.Arms ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.Arms ), 2 ); }
if ( defender.FindItemOnLayer( Layer.OuterTorso ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.OuterTorso ), 4 ); }
if ( defender.FindItemOnLayer( Layer.OuterLegs ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.OuterLegs ), 3 ); }
if ( defender.FindItemOnLayer( Layer.InnerLegs ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.InnerLegs ), 3 ); }
if ( defender.FindItemOnLayer( Layer.TwoHanded ) != null ) { armorScore = armorScore + DodgeArmor( defender.FindItemOnLayer( Layer.TwoHanded ), 2 ); }
if ( armorScore > 0 )
armorScore = armorScore + 10;
return armorScore;
}
public static bool CheckDodge( Mobile defender, bool skillUp )
{
if ( defender == null )
return false;
int armorScore = ArmorRating( defender );
if ( armorScore > Utility.RandomMinMax(1,100) )
return false;
double dodge = defender.Skills[SkillName.Dodging].Value;
double chance = dodge / 400.0;
if ( chance < 0 ) // chance shouldn't go below 0
chance = 0;
// Dodge over 100 grants a 5% bonus.
if ( dodge >= 100.0 )
chance += 0.05;
// Low dexterity lowers the chance.
if ( defender.Dex < 80 )
chance = chance * (20 + defender.Dex) / 100;
if ( !skillUp )
{
if ( defender.Skills[SkillName.Dodging].Value >= Utility.RandomMinMax( 1, 100 ) )
return true;
else
return false;
}
return defender.CheckSkill( SkillName.Dodging, chance );
}
public virtual int AbsorbDamage( Mobile attacker, Mobile defender, int damage )
{
if ( CheckDodge( defender, true ) )
{
defender.FixedEffect( 0x37B9, 10, 16 );
return 0;
}
double chance = Utility.RandomDouble();
Item armorItem;
if( chance < 0.07 )
armorItem = defender.NeckArmor;
else if( chance < 0.14 )
armorItem = defender.HandArmor;
else if( chance < 0.28 )
armorItem = defender.ArmsArmor;
else if( chance < 0.43 )
armorItem = defender.HeadArmor;
else if( chance < 0.65 )
armorItem = defender.LegsArmor;
else
armorItem = defender.ChestArmor;
IWearableDurability armor = armorItem as IWearableDurability;
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 void OnHit( Mobile attacker, Mobile defender )
{
OnHit( attacker, defender, 1.0 );
}
public virtual void OnHit( Mobile attacker, Mobile defender, double damageBonus )
{
PlaySwingAnimation( attacker );
PlayHurtAnimation( defender );
attacker.PlaySound( GetHitAttackSound( attacker, defender ) );
defender.PlaySound( GetHitDefendSound( attacker, defender ) );
int damage = ComputeDamage( attacker, defender );
#region Damage Multipliers
/*
* The following damage bonuses multiply damage by a factor.
* Capped at x3 (300%).
*/
//double factor = 1.0;
int percentageBonus = 0;
//factor *= damageBonus;
percentageBonus += (int)(damageBonus * 100) - 100;
CheckSlayerResult cs = CheckSlayers( attacker, defender );
if ( cs != CheckSlayerResult.None )
{
if ( cs == CheckSlayerResult.Slayer )
defender.FixedEffect( 0x37B9, 10, 5 );
//factor *= 2.0;
percentageBonus += 100;
}
percentageBonus = Math.Min( percentageBonus, 300 );
//damage = (int)(damage * factor);
damage = Ultima.Scale( damage, 100 + percentageBonus );
#endregion
if ( attacker is BaseCreature )
((BaseCreature)attacker).AlterMeleeDamageTo( defender, ref damage );
if ( defender is BaseCreature )
((BaseCreature)defender).AlterMeleeDamageFrom( attacker, ref damage );
damage = AbsorbDamage( attacker, defender, damage );
if ( damage < 1 )
damage = 1;
AddBlood( attacker, defender, damage );
int dmg = Ultima.Damage( defender, attacker, damage );
if ( m_MaxHits > 0 && ((MaxRange <= 1 && (defender is LargeSlime || defender is Slime || defender is AcidElemental)) || Utility.Random( 25 ) == 0) ) // Stratics says 50% chance, seems more like 4%..
{
if ( MaxRange <= 1 && (defender is LargeSlime || defender is Slime || defender is AcidElemental) )
attacker.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500263 ); // *Acid blood scars your weapon!*
if ( m_Hits > 0 )
{
--HitPoints;
}
else if ( m_MaxHits > 1 )
{
--MaxHitPoints;
if ( Parent is Mobile )
((Mobile)Parent).LocalOverheadMessage( MessageType.Regular, 0x3B2, 1061121 ); // Your equipment is severely damaged.
}
else
{
Delete();
}
}
if ( attacker is BaseCreature )
((BaseCreature)attacker).OnGaveMeleeAttack( defender );
if ( defender is BaseCreature )
((BaseCreature)defender).OnGotMeleeAttack( attacker );
}
public virtual CheckSlayerResult CheckSlayers( Mobile attacker, Mobile defender )
{
BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon;
SlayerEntry atkSlayer = SlayerGroup.GetEntryByName( atkWeapon.Slayer );
SlayerEntry atkSlayer2 = SlayerGroup.GetEntryByName( atkWeapon.Slayer2 );
if ( atkSlayer != null && atkSlayer.Slays( defender ) || atkSlayer2 != null && atkSlayer2.Slays( defender ) )
return CheckSlayerResult.Slayer;
return CheckSlayerResult.None;
}
public virtual void AddBlood( Mobile attacker, Mobile defender, int damage )
{
if ( defender is BaseCreature && ((BaseCreature)defender).BleedImmune )
return;
if ( damage > 0 )
{
new Blood().MoveToWorld( defender.Location, defender.Map );
int extraBlood = Utility.RandomMinMax( 0, 1 );
for( int i = 0; i < extraBlood; i++ )
{
new Blood().MoveToWorld( new Point3D(
defender.X + Utility.RandomMinMax( -1, 1 ),
defender.Y + Utility.RandomMinMax( -1, 1 ),
defender.Z ), defender.Map );
}
}
}
public virtual void OnMiss( Mobile attacker, Mobile defender )
{
PlaySwingAnimation( attacker );
attacker.PlaySound( GetMissAttackSound( attacker, defender ) );
defender.PlaySound( GetMissDefendSound( 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()
{
return 0;
}
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 );
min = Math.Max( (int)ScaleDamageOld( from, baseMin, false ), 1 );
max = Math.Max( (int)ScaleDamageOld( from, baseMax, false ), 1 );
}
public virtual int VirtualDamageBonus{ get{ return 0; } }
public virtual double ScaleDamageOld( Mobile attacker, double damage, bool checkSkills )
{
if ( checkSkills )
{
attacker.CheckSkill( SkillName.Tactics, 0.0, attacker.Skills[SkillName.Tactics].Cap ); // Passively check tactics 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 warrior modifier
* : 0.0 = 50% loss
* : 50.0 = unchanged
* : 100.0 = 50% bonus
*/
double warriorBonus = ( ( attacker.Skills[SkillName.Swords].Value + attacker.Skills[SkillName.Bludgeoning].Value + attacker.Skills[SkillName.Fencing].Value / 3 ) - 50.0 ) / 100.0;
if ( this is BaseRanged )
warriorBonus = 0;
/* Compute strength modifier
* : 1% bonus for every 5 strength
*/
double strBonus = (attacker.Str / 5.0) / 100.0;
/* Compute dex modifier
* : 1% bonus for every 5 points of dex
* : +10% bonus at 100
*/
double dexValue = attacker.Dex;
double dexBonus = (dexValue / 5.0) / 100.0;
if ( dexValue >= 100.0 )
dexBonus += 0.1;
// New quality bonus:
double qualityBonus = ((int)m_Quality - 1) * 0.2;
// Apply bonuses
damage += (damage * tacticsBonus) + (damage * strBonus) + (damage * warriorBonus) + (damage * dexBonus) + (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;
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 Ultima.Scale( damage, scale );
}
public virtual int ComputeDamage( Mobile attacker, Mobile defender )
{
return (int)ScaleDamageOld( attacker, GetBaseDamage( attacker ), 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 );
}
#region Serialization/Deserialization
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 );
writer.Write( (int) 9 ); // version
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.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.PlayerConstructed, m_PlayerConstructed );
SetSaveFlag( ref flags, SaveFlag.Slayer2, m_Slayer2 != SlayerName.None );
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( (float) 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.Slayer2 ) )
writer.Write( (int)m_Slayer2 );
}
[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,
StrReq = 0x00000400,
DexReq = 0x00000800,
IntReq = 0x00001000,
MinDamage = 0x00002000,
MaxDamage = 0x00004000,
HitSound = 0x00008000,
MissSound = 0x00010000,
Speed = 0x00020000,
MaxRange = 0x00040000,
Skill = 0x00080000,
Type = 0x00100000,
Animation = 0x00200000,
Resource = 0x00400000,
PlayerConstructed = 0x00800000,
Slayer2 = 0x01000000
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch ( version )
{
case 9:
case 8:
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.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 ) )
{
if ( version < 9 )
m_Speed = reader.ReadInt();
else
m_Speed = reader.ReadFloat();
}
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 ( UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && Parent is Mobile )
{
m_SkillMod = new DefaultSkillMod( AccuracySkill, true, (int)m_AccuracyLevel * 5 );
((Mobile)Parent).AddSkillMod( m_SkillMod );
}
if ( GetSaveFlag( flags, SaveFlag.PlayerConstructed ) )
m_PlayerConstructed = true;
if( GetSaveFlag( flags, SaveFlag.Slayer2 ) )
m_Slayer2 = (SlayerName)reader.ReadInt();
break;
}
case 4:
{
m_Slayer = (SlayerName)reader.ReadInt();
goto case 3;
}
case 3:
{
m_StrReq = reader.ReadInt();
m_DexReq = reader.ReadInt();
m_IntReq = reader.ReadInt();
goto case 2;
}
case 2:
{
goto case 1;
}
case 1:
{
m_MaxRange = reader.ReadInt();
goto case 0;
}
case 0:
{
if ( version == 0 )
m_MaxRange = 1; // default
if ( version < 5 )
{
m_Resource = CraftResource.Iron;
}
m_MinDamage = reader.ReadInt();
m_MaxDamage = reader.ReadInt();
m_Speed = reader.ReadInt();
m_HitSound = reader.ReadInt();
m_MissSound = reader.ReadInt();
m_Skill = (SkillName)reader.ReadInt();
m_Type = (WeaponType)reader.ReadInt();
m_Animation = (WeaponAnimation)reader.ReadInt();
m_DamageLevel = (WeaponDamageLevel)reader.ReadInt();
m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt();
m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt();
m_Quality = (WeaponQuality)reader.ReadInt();
m_Crafter = reader.ReadMobile();
m_Poison = Poison.Deserialize( reader );
m_PoisonCharges = reader.ReadInt();
if ( m_StrReq == UOStrengthReq )
m_StrReq = -1;
if ( m_DexReq == UODexterityReq )
m_DexReq = -1;
if ( m_IntReq == UOIntelligenceReq )
m_IntReq = -1;
if ( m_MinDamage == UOMinDamage )
m_MinDamage = -1;
if ( m_MaxDamage == UOMaxDamage )
m_MaxDamage = -1;
if ( m_HitSound == UOHitSound )
m_HitSound = -1;
if ( m_MissSound == UOMissSound )
m_MissSound = -1;
if ( m_Speed == UOSpeed )
m_Speed = -1;
if ( m_MaxRange == UOMaxRange )
m_MaxRange = -1;
if ( m_Skill == UOSkill )
m_Skill = (SkillName)(-1);
if ( m_Type == UOType )
m_Type = (WeaponType)(-1);
if ( m_Animation == UOAnimation )
m_Animation = (WeaponAnimation)(-1);
if ( UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && Parent is Mobile )
{
m_SkillMod = new DefaultSkillMod( AccuracySkill, true, (int)m_AccuracyLevel * 5);
((Mobile)Parent).AddSkillMod( m_SkillMod );
}
break;
}
}
if ( Parent is Mobile )
((Mobile)Parent).CheckStatTimers();
if ( m_Hits <= 0 && m_MaxHits <= 0 )
{
m_Hits = m_MaxHits = Utility.RandomMinMax( InitMinHits, InitMaxHits );
}
if ( version < 6 )
m_PlayerConstructed = true; // we don't know, so, assume it's crafted
}
#endregion
public BaseWeapon( int itemID ) : base( itemID )
{
Layer = (Layer)ItemData.Quality;
m_Quality = WeaponQuality.Regular;
m_StrReq = -1;
m_DexReq = -1;
m_IntReq = -1;
m_MinDamage = -1;
m_MaxDamage = -1;
m_HitSound = -1;
m_MissSound = -1;
m_Speed = -1;
m_MaxRange = -1;
m_Skill = (SkillName)(-1);
m_Type = (WeaponType)(-1);
m_Animation = (WeaponAnimation)(-1);
m_Hits = m_MaxHits = Utility.RandomMinMax( InitMinHits, InitMaxHits );
m_Resource = CraftResource.Iron;
}
public BaseWeapon( Serial serial ) : base( serial )
{
}
private string GetNameString()
{
string name = this.Name;
if ( name == null )
name = String.Format( "#{0}", LabelNumber );
return name;
}
[Hue, CommandProperty( AccessLevel.GameMaster )]
public override int Hue
{
get{ return base.Hue; }
set{ base.Hue = value; InvalidateProperties(); }
}
public override bool AllowEquipedCast( Mobile from )
{
if ( base.AllowEquipedCast( from ) )
return true;
return false;
}
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
if ( m_Crafter != null )
list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~
if ( m_Quality == WeaponQuality.Exceptional )
list.Add( 1060636 ); // exceptional
if ( m_DamageLevel == WeaponDamageLevel.Ruin )
list.Add( 1038022 ); // Ruin
else if ( m_DamageLevel == WeaponDamageLevel.Might )
list.Add( 1038023 ); // Might
else if ( m_DamageLevel == WeaponDamageLevel.Force )
list.Add( 1038024 ); // Force
else if ( m_DamageLevel == WeaponDamageLevel.Power )
list.Add( 1038025 ); // Power
else if ( m_DamageLevel == WeaponDamageLevel.Vanq )
list.Add( 1038026 ); // Vanquishing
if ( m_AccuracyLevel == WeaponAccuracyLevel.Accurate )
list.Add( 1038011 ); // Accurate
else if ( m_AccuracyLevel == WeaponAccuracyLevel.Surpassingly )
list.Add( 1038012 ); // Surpassingly Accurate
else if ( m_AccuracyLevel == WeaponAccuracyLevel.Eminently )
list.Add( 1038013 ); // Eminently Accurate
else if ( m_AccuracyLevel == WeaponAccuracyLevel.Exceedingly )
list.Add( 1038014 ); // Exceedingly Accurate
else if ( m_AccuracyLevel == WeaponAccuracyLevel.Supremely )
list.Add( 1038015 ); // Supremely Accurate
if ( m_DurabilityLevel == WeaponDurabilityLevel.Durable )
list.Add( 1036365 ); // Durable Material
else if ( m_DurabilityLevel == WeaponDurabilityLevel.Substantial )
list.Add( 1036366 ); // Substantial Material
else if ( m_DurabilityLevel == WeaponDurabilityLevel.Massive )
list.Add( 1036367 ); // Massive Material
else if ( m_DurabilityLevel == WeaponDurabilityLevel.Fortified )
list.Add( 1036368 ); // Fortified Material
else if ( m_DurabilityLevel == WeaponDurabilityLevel.Indestructible )
list.Add( 1036369 ); // Indestructible Material
if ( this is IUsesRemaining && ((IUsesRemaining)this).ShowUsesRemaining )
list.Add( 1060584, ((IUsesRemaining)this).UsesRemaining.ToString() ); // uses remaining: ~1_val~
if ( Magical > 0 && Uses > 0 )
{
list.Add( 1062520, "\t#{0}", Magical );
}
if ( Uses > 0 && Server.Misc.Settings.DisplayInfo() && !(this is BaseWand) )
{
if ( Uses > 1 )
list.Add( 1062516, "{0}", Uses );
else
list.Add( 1062517, "{0}", Uses );
}
else if ( Uses > 0 && !(this is BaseWand) )
{
double usage = (double)Uses / (double)UsesMax;
if ( usage > 0.95 )
list.Add( 1063269 ); // Fully Charged
else if ( usage > 0.75 )
list.Add( 1063270 ); // Mostly Charged
else if ( usage > 0.50 )
list.Add( 1063271 ); // Partially Charged
else if ( usage > 0.25 )
list.Add( 1063272 ); // Somewhat Charged
else if ( usage > 0.05 )
list.Add( 1063273 ); // Barely Charged
else
list.Add( 1063274 ); // Almost Drained
}
if( m_Slayer != SlayerName.None )
{
SlayerEntry entry = SlayerGroup.GetEntryByName( m_Slayer );
if( entry != null )
list.Add( entry.Title );
}
if( m_Slayer2 != SlayerName.None )
{
SlayerEntry entry = SlayerGroup.GetEntryByName( m_Slayer2 );
if( entry != null )
list.Add( entry.Title );
}
if ( m_Poison != null && m_PoisonCharges > 0 )
{
if ( Server.Misc.Settings.DisplayInfo() )
list.Add( 1062412 + m_Poison.Level, m_PoisonCharges.ToString() );
else
list.Add( 1017383 ); // Poisoned
}
if ( Server.Misc.Settings.DisplayInfo() )
{
list.Add( 1061168, "{0}\t{1}", MinDamage.ToString(), MaxDamage.ToString() ); // weapon damage ~1_val~ - ~2_val~
list.Add( 1061167, Speed.ToString() );
if ( MaxRange > 1 )
list.Add( 1061169, MaxRange.ToString() ); // range ~1_val~
int strReq = Ultima.Scale( StrRequirement, 100 - GetLowerStatReq() );
if ( strReq > 0 )
list.Add( 1061170, strReq.ToString() ); // strength requirement ~1_val~
if ( Layer == Layer.TwoHanded )
list.Add( 1036381 ); // two-handed weapon
else
list.Add( 1036380 ); // one-handed weapon
switch ( Skill )
{
case SkillName.Swords: list.Add( 1044063 ); break; // Swordsmanship
case SkillName.Bludgeoning: list.Add( 1044061 ); break; // Bludgeoning
case SkillName.Fencing: list.Add( 1044062 ); break; // Fencing
case SkillName.Archery: list.Add( 1044060 ); break; // Archery
}
if ( m_Hits >= 0 && m_MaxHits > 0 )
list.Add( 1060639, "{0}\t{1}", m_Hits, m_MaxHits ); // durability ~1_val~ / ~2_val~
}
else
{
double durable = (double)m_Hits / (double)m_MaxHits;
if ( durable > 0.95 ){}
// DO NOT SHOW YET
else if ( durable > 0.75 )
list.Add( 1036374 ); // Perfect Condition
else if ( durable > 0.50 )
list.Add( 1036373 ); // Good Condition
else if ( durable > 0.25 )
list.Add( 1036372 ); // Fair Condition
else if ( durable > 0.05 )
list.Add( 1036371 ); // Poor Condition
else
list.Add( 1036370 ); // Horrible Condition
}
}
public override void OnSingleClick( Mobile from )
{
List<EquipInfoAttribute> attrs = new List<EquipInfoAttribute>();
if ( DisplayLootType )
{
if ( LootType == LootType.Blessed )
attrs.Add( new EquipInfoAttribute( 1038021 ) ); // blessed
}
if ( m_Quality == WeaponQuality.Exceptional )
attrs.Add( new EquipInfoAttribute( 1018305 - (int)m_Quality ) );
if( m_Slayer != SlayerName.None )
{
SlayerEntry entry = SlayerGroup.GetEntryByName( m_Slayer );
if( entry != null )
attrs.Add( new EquipInfoAttribute( entry.Title ) );
}
if( m_Slayer2 != SlayerName.None )
{
SlayerEntry entry = SlayerGroup.GetEntryByName( m_Slayer2 );
if( entry != null )
attrs.Add( new EquipInfoAttribute( entry.Title ) );
}
if ( m_DurabilityLevel != WeaponDurabilityLevel.Regular )
attrs.Add( new EquipInfoAttribute( 1038000 + (int)m_DurabilityLevel ) );
if ( m_DamageLevel != WeaponDamageLevel.Regular )
attrs.Add( new EquipInfoAttribute( 1038015 + (int)m_DamageLevel ) );
if ( m_AccuracyLevel != WeaponAccuracyLevel.Regular )
attrs.Add( new EquipInfoAttribute( 1038010 + (int)m_AccuracyLevel ) );
if ( m_Poison != null && m_PoisonCharges > 0 )
attrs.Add( new EquipInfoAttribute( 1017383, m_PoisonCharges ) );
int number;
if ( Name == null )
{
number = LabelNumber;
}
else
{
this.LabelTo( from, Name );
number = 1041000;
}
if ( attrs.Count == 0 && Crafter == null && Name != null )
return;
EquipmentInfo eqInfo = new EquipmentInfo( number, m_Crafter, false, attrs.ToArray() );
from.Send( new DisplayEquipmentInfo( this, eqInfo ) );
}
private static BaseWeapon m_Fists; // This value holds the default--fist--weapon
public static BaseWeapon Fists
{
get{ return m_Fists; }
set{ m_Fists = value; }
}
#region ICraftable Members
public int OnCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue )
{
Quality = (WeaponQuality)quality;
if ( makersMark )
Crafter = from;
PlayerConstructed = true;
Type resourceType = typeRes;
if ( resourceType == null )
resourceType = craftItem.Resources.GetAt( 0 ).ItemType;
return quality;
}
#endregion
}
public enum CheckSlayerResult
{
None,
Slayer
}
}