using System;
using System.Text;
using System.Collections;
using Server.ContextMenus;
using Server.Network;
using Server.Targeting;
using Server.Mobiles;
using Server.Spells;
using Server.Spells.Necromancy;
using Server.Spells.Bushido;
using Server.Spells.Ninjitsu;
using Server.Factions;
using Server.Engines.Craft;
using System.Collections.Generic;
using Server.Spells.Spellweaving;
namespace Server.Items
{
public interface ISlayer
{
SlayerName Slayer { get; set; }
SlayerName Slayer2 { get; set; }
}
public abstract class BaseWeapon : Item, IWeapon, IFactionItem, ICraftable, ISlayer, IDurability, ISetItem
{
private string m_EngravedText;
[CommandProperty(AccessLevel.GameMaster)]
public string EngravedText
{
get { return m_EngravedText; }
set { m_EngravedText = value; InvalidateProperties(); }
}
#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
*/
#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 bool m_Identified;
private int m_Hits;
private int m_MaxHits;
private SlayerName m_Slayer;
private SlayerName m_Slayer2;
#region Mondain's Legacy
private TalismanSlayerName m_Slayer3;
#endregion
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.
#region Mondain's Legacy
private bool m_Immolating; // Is this weapon blessed via Immolating Weapon arcanists spell? Temporary; not serialized.
#endregion
private AosAttributes m_AosAttributes;
private AosWeaponAttributes m_AosWeaponAttributes;
private AosSkillBonuses m_AosSkillBonuses;
private AosElementAttributes m_AosElementDamages;
// 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 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 float MlSpeed { get { return 0.0f; } }
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 virtual bool CanFortify { get { return true; } }
#region Mondain's Legacy Sets
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; } }
#endregion
public virtual SkillName AccuracySkill { get { return SkillName.Tactics; } }
#region Personal Bless Deed
private Mobile m_BlessedBy;
[CommandProperty(AccessLevel.GameMaster)]
public Mobile BlessedBy
{
get { return m_BlessedBy; }
set { m_BlessedBy = value; InvalidateProperties(); }
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (BlessedFor == from && BlessedBy == from && RootParent == from)
list.Add(new UnBlessEntry(from, this));
}
private class UnBlessEntry : ContextMenuEntry
{
private Mobile m_From;
private BaseWeapon m_Weapon; // BaseArmor, BaseWeapon or BaseClothing
public UnBlessEntry(Mobile from, BaseWeapon weapon)
: base(6208, -1)
{
m_From = from;
m_Weapon = weapon;
}
public override void OnClick()
{
m_Weapon.BlessedFor = null;
m_Weapon.BlessedBy = null;
Container pack = m_From.Backpack;
if (pack != null)
{
pack.DropItem(new PersonalBlessDeed(m_From));
m_From.SendLocalizedMessage(1062200); // A personal bless deed has been placed in your backpack.
}
}
}
#endregion
#endregion
#region Getters & Setters
[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 AosElementAttributes AosElementDamages
{
get { return m_AosElementDamages; }
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; }
}
#region Mondain's Legacy
[CommandProperty(AccessLevel.GameMaster)]
public bool Immolating
{
get { return m_Immolating; }
set { m_Immolating = value; }
}
#endregion
[CommandProperty(AccessLevel.GameMaster)]
public bool Identified
{
get { return m_Identified; }
set { m_Identified = value; InvalidateProperties(); }
}
[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 TalismanSlayerName Slayer3
{
get { return m_Slayer3; }
set { m_Slayer3 = 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 float Speed
{
get
{
if (m_Speed != -1)
return m_Speed;
if (Core.ML)
return MlSpeed;
else if (Core.AOS)
return AosSpeed;
return 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; }
}
[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;
weap.m_AosAttributes = new AosAttributes(newItem, m_AosAttributes);
weap.m_AosElementDamages = new AosElementAttributes(newItem, m_AosElementDamages);
weap.m_AosSkillBonuses = new AosSkillBonuses(newItem, m_AosSkillBonuses);
weap.m_AosWeaponAttributes = new AosWeaponAttributes(newItem, m_AosWeaponAttributes);
#region Mondain's Legacy
weap.m_SetAttributes = new AosAttributes(newItem, m_SetAttributes);
weap.m_SetSkillBonuses = new AosSkillBonuses(newItem, m_SetSkillBonuses);
#endregion
}
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;
}
if (Core.AOS)
{
bonus += m_AosWeaponAttributes.DurabilityBonus;
#region Mondain's Legacy
if (m_Resource == CraftResource.Heartwood)
return bonus;
#endregion
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;
#region Mondain's Legacy
if (m_Resource == CraftResource.Heartwood)
return v;
#endregion
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 && 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 AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted)
{
if (!Ethics.Ethic.CheckTrade(from, to, newOwner, this))
return false;
return base.AllowSecureTrade(from, to, newOwner, accepted);
}
public virtual Race RequiredRace { get { return null; } } //On OSI, there are no weapons with race requirements, this is for custom stuff
public override bool CanEquip(Mobile from)
{
if (!Ethics.Ethic.CheckEquip(from, this))
return false;
if (RequiredRace != null && from.Race != RequiredRace)
{
if (RequiredRace == Race.Elf)
from.SendLocalizedMessage(1072203); // Only Elves may use this.
else
from.SendMessage("Only {0} may use this.", RequiredRace.PluralName);
return false;
}
else 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;
}
#region Personal Bless Deed
else if (BlessedBy != null && BlessedBy != from)
{
from.SendLocalizedMessage(1075277); // That item is blessed by another player.
return false;
}
#endregion
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);
#region Mondain's Legacy Sets
if (IsSetItem)
{
m_SetEquipped = SetHelper.FullSetEquipped(from, SetID, Pieces);
if (m_SetEquipped)
{
m_LastEquipped = true;
SetHelper.AddSetBonus(from, SetID);
}
}
#endregion
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);
#region Mondain's Legacy Sets
if (IsSetItem && m_SetEquipped)
SetHelper.RemoveSetBonus(m, SetID, this);
#endregion
}
InvalidateProperties();
}
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;
}
private static bool CheckAnimal(Mobile m, Type type)
{
return AnimalForm.UnderTransformation(m, type);
}
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 (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 (CheckAnimal(attacker, typeof(GreyWolf)) || CheckAnimal(attacker, typeof(BakeKitsune)))
bonus += 20; // attacker gets 20% bonus when under Wolf or Bake Kitsune form
if (HitLower.IsUnderAttackEffect(attacker))
bonus -= 25; // Under Hit Lower Attack effect -> 25% malus
WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker);
if (ability != null)
bonus += ability.AccuracyBonus;
SpecialMove move = SpecialMove.GetCurrentMove(attacker);
if (move != null)
bonus += move.GetAccuracyBonus(attacker);
// Max Hit Chance Increase = 45%
if (bonus > 45)
bonus = 45;
ourValue = (atkValue + 20.0) * (100 + bonus);
bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance);
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
int blockBonus = 0;
if (Block.GetBonus(defender, ref blockBonus))
bonus += blockBonus;
int surpriseMalus = 0;
if (SurpriseAttack.GetMalus(defender, ref surpriseMalus))
bonus -= surpriseMalus;
int discordanceEffect = 0;
// Defender loses -0/-28% if under the effect of Discordance.
if (SkillHandlers.Discordance.GetEffect(attacker, ref discordanceEffect))
bonus -= discordanceEffect;
// Defense Chance Increase = 45%
if (bonus > 45)
bonus = 45;
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;
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;
if (Core.SE)
{
/*
* This is likely true for Core.AOS as well... both guides report the same
* formula, and both are wrong.
* The old formula left in for AOS for legacy & because we aren't quite 100%
* Sure that AOS has THIS formula
*/
// Swing speed bonus
int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed);
if (Spells.Chivalry.DivineFurySpell.UnderEffect(m))
bonus += 10;
// Bonus granted by successful use of Honorable Execution.
bonus += HonorableExecution.GetSwingBonus(m);
if (DualWield.Registry.Contains(m))
bonus += ((DualWield.DualWieldTimer)DualWield.Registry[m]).BonusSwingSpeed;
if (Feint.Registry.Contains(m))
bonus -= ((Feint.FeintTimer)Feint.Registry[m]).SwingSpeedReduction;
TransformContext context = TransformationSpellHelper.GetContext(m);
if (context != null && context.Spell is ReaperFormSpell)
bonus += ((ReaperFormSpell)context.Spell).SwingSpeedBonus;
int discordanceEffect = 0;
// Discordance gives a malus of -0/-28% to swing speed.
if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
bonus -= discordanceEffect;
if (EssenceOfWindSpell.IsDebuffed(m))
bonus -= EssenceOfWindSpell.GetSSIMalus(m);
if (bonus > 60)
bonus = 60;
double ticks;
if (Core.ML)
{
int stamTicks = m.Stam / 30;
ticks = speed * 4;
ticks = Math.Floor((ticks - stamTicks) * (100.0 / (100 + bonus)));
}
else
{
speed = Math.Floor(speed * (bonus + 100.0) / 100.0);
if (speed <= 0)
speed = 1;
ticks = Math.Floor((80000.0 / ((m.Stam + 100) * speed)) - 2);
}
// Swing speed currently capped at one swing every 1.25 seconds (5 ticks).
if (ticks < 5)
ticks = 5;
delayInSeconds = ticks * 0.25;
}
else if (Core.AOS)
{
int v = (m.Stam + 100) * (int)speed;
int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed);
if (Spells.Chivalry.DivineFurySpell.UnderEffect(m))
bonus += 10;
int discordanceEffect = 0;
// Discordance gives a malus of -0/-28% to swing speed.
if (SkillHandlers.Discordance.GetEffect(m, ref discordanceEffect))
bonus -= discordanceEffect;
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
// OSI dev said that it has and is supposed to be 1.25
if (delayInSeconds < 1.25)
delayInSeconds = 1.25;
}
else
{
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)
{
WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker);
if (a != null && !a.OnBeforeSwing(attacker, defender))
WeaponAbility.ClearCurrentAbility(attacker);
SpecialMove move = SpecialMove.GetCurrentMove(attacker);
if (move != null && !move.OnBeforeSwing(attacker, defender))
SpecialMove.ClearCurrentMove(attacker);
}
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 (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, 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 bool CheckParry(Mobile defender)
{
if (defender == null)
return false;
BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;
double parry = defender.Skills[SkillName.Parry].Value;
double bushidoNonRacial = defender.Skills[SkillName.Bushido].NonRacialValue;
double bushido = defender.Skills[SkillName.Bushido].Value;
if (shield != null)
{
double chance = (parry - bushidoNonRacial) / 400.0; // As per OSI, no negitive effect from the Racial stuffs, ie, 120 parry and '0' bushido with humans
if (chance < 0) // chance shouldn't go below 0
chance = 0;
// Parry/Bushido over 100 grants a 5% bonus.
if (parry >= 100.0 || bushido >= 100.0)
chance += 0.05;
// Evasion grants a variable bonus post ML. 50% prior.
if (Evasion.IsEvading(defender))
chance *= Evasion.GetParryScalar(defender);
// Low dexterity lowers the chance.
if (defender.Dex < 80)
chance = chance * (20 + defender.Dex) / 100;
return defender.CheckSkill(SkillName.Parry, chance);
}
else if (!(defender.Weapon is Fists) && !(defender.Weapon is BaseRanged))
{
BaseWeapon weapon = defender.Weapon as BaseWeapon;
double divisor = (weapon.Layer == Layer.OneHanded) ? 48000.0 : 41140.0;
double chance = (parry * bushido) / divisor;
double aosChance = parry / 800.0;
// Parry or Bushido over 100 grant a 5% bonus.
if (parry >= 100.0)
{
chance += 0.05;
aosChance += 0.05;
}
else if (bushido >= 100.0)
{
chance += 0.05;
}
// Evasion grants a variable bonus post ML. 50% prior.
if (Evasion.IsEvading(defender))
chance *= Evasion.GetParryScalar(defender);
// Low dexterity lowers the chance.
if (defender.Dex < 80)
chance = chance * (20 + defender.Dex) / 100;
if (chance > aosChance)
return defender.CheckSkill(SkillName.Parry, chance);
else
return (aosChance > Utility.RandomDouble()); // Only skillcheck if wielding a shield & there's no effect from Bushido
}
return false;
}
public virtual int AbsorbDamageAOS(Mobile attacker, Mobile defender, int damage)
{
bool blocked = false;
if (defender.Player || defender.Body.IsHuman)
{
blocked = CheckParry(defender);
if (blocked)
{
defender.FixedEffect(0x37B9, 10, 16);
damage = 0;
// Successful block removes the Honorable Execution penalty.
HonorableExecution.RemovePenalty(defender);
if (CounterAttack.IsCountering(defender))
{
BaseWeapon weapon = defender.Weapon as BaseWeapon;
if (weapon != null)
{
defender.FixedParticles(0x3779, 1, 15, 0x158B, 0x0, 0x3, EffectLayer.Waist);
weapon.OnSwing(defender, attacker);
}
CounterAttack.StopCountering(defender);
}
if (Confidence.IsConfident(defender))
{
defender.SendLocalizedMessage(1063117); // Your confidence reassures you as you successfully block your opponent's blow.
double bushido = defender.Skills.Bushido.Value;
defender.Hits += Utility.RandomMinMax(1, (int)(bushido / 12));
defender.Stam += Utility.RandomMinMax(1, (int)(bushido / 5));
}
BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;
if (shield != null)
{
shield.OnHit(this, damage);
}
}
}
if (!blocked)
{
double positionChance = Utility.RandomDouble();
Item armorItem;
if (positionChance < 0.07)
armorItem = defender.NeckArmor;
else if (positionChance < 0.14)
armorItem = defender.HandArmor;
else if (positionChance < 0.28)
armorItem = defender.ArmsArmor;
else if (positionChance < 0.43)
armorItem = defender.HeadArmor;
else if (positionChance < 0.65)
armorItem = defender.LegsArmor;
else
armorItem = defender.ChestArmor;
IWearableDurability armor = armorItem as IWearableDurability;
if (armor != null)
armor.OnHit(this, damage); // call OnHit to lose durability
}
return damage;
}
public virtual int AbsorbDamage(Mobile attacker, Mobile defender, int damage)
{
if (Core.AOS)
return AbsorbDamageAOS(attacker, defender, damage);
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 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.Controlled && !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.Controlled && !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)
{
OnHit(attacker, defender, 1.0);
}
public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus)
{
if (MirrorImage.HasClone(defender) && (defender.Skills.Ninjitsu.Value / 150.0) > Utility.RandomDouble())
{
Clone bc;
foreach (Mobile m in defender.GetMobilesInRange(4))
{
bc = m as Clone;
if (bc != null && bc.Summoned && bc.SummonMaster == defender)
{
attacker.SendLocalizedMessage(1063141); // Your attack has been diverted to a nearby mirror image of your target!
defender.SendLocalizedMessage(1063140); // You manage to divert the attack onto one of your nearby mirror images.
/*
* TODO: What happens if the Clone parries a blow?
* And what about if the attacker is using Honorable Execution
* and kills it?
*/
defender = m;
break;
}
}
}
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;
WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker);
SpecialMove move = SpecialMove.GetCurrentMove(attacker);
if (a != null)
{
//factor *= a.DamageScalar;
percentageBonus += (int)(a.DamageScalar * 100) - 100;
}
if (move != null)
{
//factor *= move.GetDamageScalar( attacker, defender );
percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100;
}
//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;
}
if (!attacker.Player)
{
if (defender is PlayerMobile)
{
PlayerMobile pm = (PlayerMobile)defender;
if (pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType())
{
//factor *= 2.0;
percentageBonus += 100;
}
}
}
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);
//factor *= 1.5;
percentageBonus += 50;
}
}
}
int packInstinctBonus = GetPackInstinctBonus(attacker, defender);
if (packInstinctBonus != 0)
{
//factor *= 1.0 + (double)packInstinctBonus / 100.0;
percentageBonus += packInstinctBonus;
}
if (m_InDoubleStrike)
{
//factor *= 0.9; // 10% loss when attacking with double-strike
percentageBonus -= 10;
}
TransformContext context = TransformationSpellHelper.GetContext(defender);
if ((m_Slayer == SlayerName.Silver || m_Slayer2 == SlayerName.Silver) && context != null && context.Spell is NecromancerSpell && context.Type != typeof(HorrificBeastSpell))
{
//factor *= 1.25; // Every necromancer transformation other than horrific beast takes an additional 25% damage
percentageBonus += 25;
}
if (attacker is PlayerMobile && !(Core.ML && defender is PlayerMobile))
{
PlayerMobile pmAttacker = (PlayerMobile)attacker;
if (pmAttacker.HonorActive && pmAttacker.InRange(defender, 1))
{
//factor *= 1.25;
percentageBonus += 25;
}
if (pmAttacker.SentHonorContext != null && pmAttacker.SentHonorContext.Target == defender)
{
//pmAttacker.SentHonorContext.ApplyPerfectionDamageBonus( ref factor );
percentageBonus += pmAttacker.SentHonorContext.PerfectionDamageBonus;
}
}
//if ( factor > 3.0 )
// factor = 3.0;
#region Mondain's Legacy
if (Core.ML)
{
BaseTalisman talisman = attacker.Talisman as BaseTalisman;
if (talisman != null && talisman.Killer != null)
percentageBonus += talisman.Killer.DamageBonus(defender);
if (this is ButchersWarCleaver)
{
if (defender is Bull || defender is Cow || defender is Gaman)
percentageBonus += 100;
}
}
#endregion
percentageBonus = Math.Min(percentageBonus, 300);
//damage = (int)(damage * factor);
damage = AOS.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 (!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!
}
}
#region Mondain's Legacy
if (m_Immolating)
{
int d = ImmolatingWeaponSpell.GetDamage(this);
d = AOS.Damage(defender, attacker, d, 0, 100, 0, 0, 0);
AttuneWeaponSpell.TryAbsorb(defender, ref d);
if (d > 0)
defender.Damage(d);
}
#endregion
AddBlood(attacker, defender, damage);
// Mondain's Legacy mod
int phys, fire, cold, pois, nrgy, chaos, direct;
GetDamageTypes(attacker, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);
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;
if (a != null && !a.OnBeforeDamage(attacker, defender))
{
WeaponAbility.ClearCurrentAbility(attacker);
a = null;
}
if (move != null && !move.OnBeforeDamage(attacker, defender))
{
SpecialMove.ClearCurrentMove(attacker);
move = null;
}
bool ignoreArmor = (a is ArmorIgnore || (move != null && move.IgnoreArmor(attacker)));
// damage increase after resists applied
int damageIncrease = 0;
BaseQuiver quiver = attacker.FindItemOnLayer(Layer.Cloak) as BaseQuiver;
if (quiver != null)
damageIncrease = quiver.DamageIncrease;
// Mondain's Legacy Mod
damageGiven = AOS.Damage(defender, attacker, damage, ignoreArmor, phys, fire, cold, pois, nrgy, chaos, direct, false, this is BaseRanged);
double propertyBonus = (move == null) ? 1.0 : move.GetPropertyBonus(attacker);
if (Core.AOS)
{
int lifeLeech = 0;
int stamLeech = 0;
int manaLeech = 0;
int wraithLeech = 0;
// Mondain's Legacy Mod
if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechHits) * propertyBonus) > Utility.Random(100))
lifeLeech += 30; // HitLeechHits% chance to leech 30% of damage as hit points
// Mondain's Legacy Mod
if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechStam) * propertyBonus) > Utility.Random(100))
stamLeech += 100; // HitLeechStam% chance to leech 100% of damage as stamina
// Mondain's Legacy Mod
if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechMana) * propertyBonus) > Utility.Random(100))
manaLeech += 40; // HitLeechMana% chance to leech 40% of damage as mana
if (m_Cursed)
lifeLeech += 50; // Additional 50% life leech for cursed weapons (necro spell)
context = TransformationSpellHelper.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))
{
wraithLeech = (5 + (int)((15 * attacker.Skills.SpiritSpeak.Value) / 100)); // Wraith form gives an additional 5-20% mana leech
// Mana leeched by the Wraith Form spell is actually stolen, not just leeched.
defender.Mana -= AOS.Scale(damageGiven, wraithLeech);
manaLeech += wraithLeech;
}
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!*
// Mondain's Legacy Sets
if (Core.AOS && m_AosWeaponAttributes.SelfRepair + (IsSetItem && m_SetEquipped ? m_SetSelfRepair : 0) > Utility.Random(10))
{
HitPoints += 2;
}
else
{
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 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)
{
// Mondain's Legacy Mod
int physChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPhysicalArea) * propertyBonus);
int fireChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireArea) * propertyBonus);
int coldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitColdArea) * propertyBonus);
int poisChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPoisonArea) * propertyBonus);
int nrgyChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitEnergyArea) * propertyBonus);
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);
// Mondain's Legacy Mod
int maChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitMagicArrow) * propertyBonus);
int harmChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitHarm) * propertyBonus);
int fireballChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireball) * propertyBonus);
int lightningChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLightning) * propertyBonus);
int dispelChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitDispel) * propertyBonus);
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);
// Mondain's Legacy Mod
int laChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) * propertyBonus);
int ldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerDefend) * propertyBonus);
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);
if (move != null)
move.OnHit(attacker, defender, damage);
if (defender is IHonorTarget && ((IHonorTarget)defender).ReceivedHonorContext != null)
((IHonorTarget)defender).ReceivedHonorContext.OnTargetHit(attacker);
if (!(this is BaseRanged))
{
if (AnimalForm.UnderTransformation(attacker, typeof(GiantSerpent)))
defender.ApplyPoison(attacker, Poison.Lesser);
if (AnimalForm.UnderTransformation(defender, typeof(BullFrog)))
attacker.ApplyPoison(defender, Poison.Regular);
}
}
public virtual double GetAosDamage(Mobile attacker, int bonus, int dice, int sides)
{
int damage = Utility.Dice(dice, sides, bonus) * 100;
int damageBonus = 0;
// Inscription bonus
int inscribeSkill = attacker.Skills[SkillName.Inscribe].Fixed;
damageBonus += inscribeSkill / 200;
if (inscribeSkill >= 1000)
damageBonus += 5;
if (attacker.Player)
{
// Int bonus
damageBonus += (attacker.Int / 10);
// SDI bonus
damageBonus += AosAttributes.GetValue(attacker, AosAttribute.SpellDamage);
TransformContext context = TransformationSpellHelper.GetContext(attacker);
if (context != null && context.Spell is ReaperFormSpell)
damageBonus += ((ReaperFormSpell)context.Spell).SpellDamageBonus;
}
damage = AOS.Scale(damage, 100 + damageBonus);
return damage / 100;
}
#region Do<AoSEffect>
public virtual void DoMagicArrow(Mobile attacker, Mobile defender)
{
if (!attacker.CanBeHarmful(defender, false))
return;
attacker.DoHarmful(defender);
double damage = GetAosDamage(attacker, 10, 1, 4);
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, 17, 1, 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, 19, 1, 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, 23, 1, 4);
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.MagerySpell 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;
List<Mobile> list = new List<Mobile>();
foreach (Mobile m in from.GetMobilesInRange(10))
{
if (from != m && defender != m && SpellHelper.ValidIndirectTarget(from, m) && from.CanBeHarmful(m, false) && (!Core.ML || 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 = 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);
}
}
#endregion
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;
BaseTalisman talisman = attacker.Talisman as BaseTalisman;
if (talisman != null && TalismanSlayer.Slays(talisman.Slayer, defender))
return CheckSlayerResult.Slayer;
if (!Core.SE)
{
ISlayer defISlayer = Spellbook.FindEquippedSpellbook(defender);
if (defISlayer == null)
defISlayer = defender.Weapon as ISlayer;
if (defISlayer != null)
{
SlayerEntry defSlayer = SlayerGroup.GetEntryByName(defISlayer.Slayer);
SlayerEntry defSlayer2 = SlayerGroup.GetEntryByName(defISlayer.Slayer2);
if (defSlayer != null && defSlayer.Group.OppositionSuperSlays(attacker) || defSlayer2 != null && defSlayer2.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);
int extraBlood = (Core.SE ? Utility.RandomMinMax(3, 4) : 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 GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, out int nrgy, out int chaos, out int direct)
{
if (wielder is BaseCreature)
{
BaseCreature bc = (BaseCreature)wielder;
phys = bc.PhysicalDamage;
fire = bc.FireDamage;
cold = bc.ColdDamage;
pois = bc.PoisonDamage;
nrgy = bc.EnergyDamage;
#region Mondain's Legacy
chaos = 0;
direct = 0;
#endregion
}
else
{
fire = m_AosElementDamages.Fire;
cold = m_AosElementDamages.Cold;
pois = m_AosElementDamages.Poison;
nrgy = m_AosElementDamages.Energy;
#region Mondain's Legacy
chaos = m_AosElementDamages.Chaos;
direct = m_AosElementDamages.Direct;
#endregion
phys = 100 - fire - cold - pois - nrgy - chaos - direct;
CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);
if (resInfo != null)
{
CraftAttributeInfo attrInfo = resInfo.AttributeInfo;
if (attrInfo != null)
{
int left = phys;
left = ApplyCraftAttributeElementDamage(attrInfo.WeaponColdDamage, ref cold, left);
left = ApplyCraftAttributeElementDamage(attrInfo.WeaponEnergyDamage, ref nrgy, left);
left = ApplyCraftAttributeElementDamage(attrInfo.WeaponFireDamage, ref fire, left);
left = ApplyCraftAttributeElementDamage(attrInfo.WeaponPoisonDamage, ref pois, left);
phys = left;
}
}
}
}
private int ApplyCraftAttributeElementDamage(int attrDamage, ref int element, int totalRemaining)
{
if (totalRemaining <= 0)
return 0;
if (attrDamage <= 0)
return totalRemaining;
int appliedDamage = attrDamage;
if ((appliedDamage + element) > 100)
appliedDamage = 100 - element;
if (appliedDamage > totalRemaining)
appliedDamage = totalRemaining;
element += appliedDamage;
return totalRemaining - appliedDamage;
}
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);
SpecialMove move = SpecialMove.GetCurrentMove(attacker);
if (move != null)
move.OnMiss(attacker, defender);
if (defender is IHonorTarget && ((IHonorTarget)defender).ReceivedHonorContext != null)
((IHonorTarget)defender).ReceivedHonorContext.OnTargetMissed(attacker);
}
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 = Math.Max((int)ScaleDamageAOS(from, baseMin, false), 1);
max = Math.Max((int)ScaleDamageAOS(from, baseMax, false), 1);
}
else
{
min = Math.Max((int)ScaleDamageOld(from, baseMin, false), 1);
max = Math.Max((int)ScaleDamageOld(from, baseMax, false), 1);
}
}
public virtual double ScaleDamageAOS(Mobile attacker, double damage, bool checkSkills)
{
if (checkSkills)
{
attacker.CheckSkill(SkillName.Tactics, 0.0, attacker.Skills[SkillName.Tactics].Cap); // Passively check tactics for gain
attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills[SkillName.Anatomy].Cap); // Passively check Anatomy for gain
if (Type == WeaponType.Axe)
attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain
}
#region Physical bonuses
/*
* These are the bonuses given by the physical characteristics of the mobile.
* No caps apply.
*/
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;
#endregion
#region Modifiers
/*
* The following are damage modifiers whose effect shows on the status bar.
* Capped at 100% total.
*/
int damageBonus = AosAttributes.GetValue(attacker, AosAttribute.WeaponDamage);
// Horrific Beast transformation gives a +25% bonus to damage.
if (TransformationSpellHelper.UnderTransformation(attacker, typeof(HorrificBeastSpell)))
damageBonus += 25;
// Divine Fury gives a +10% bonus to damage.
if (Spells.Chivalry.DivineFurySpell.UnderEffect(attacker))
damageBonus += 10;
int defenseMasteryMalus = 0;
// Defense Mastery gives a -50%/-80% malus to damage.
if (Server.Items.DefenseMastery.GetMalus(attacker, ref defenseMasteryMalus))
damageBonus -= defenseMasteryMalus;
int discordanceEffect = 0;
// Discordance gives a -2%/-48% malus to damage.
if (SkillHandlers.Discordance.GetEffect(attacker, ref discordanceEffect))
damageBonus -= discordanceEffect * 2;
if (damageBonus > 100)
damageBonus = 100;
#endregion
double totalBonus = strengthBonus + anatomyBonus + tacticsBonus + lumberBonus + ((double)(GetDamageBonus() + damageBonus) / 100.0);
return damage + (int)(damage * totalBonus);
}
public virtual int VirtualDamageBonus { get { return 0; } }
public virtual int ComputeDamageAOS(Mobile attacker, Mobile defender)
{
return (int)ScaleDamageAOS(attacker, GetBaseDamage(attacker), true);
}
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
attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills[SkillName.Anatomy].Cap); // 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;
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);
}
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)13); // version
writer.Write((Mobile)m_BlessedBy); // personal bless deed
#region Veteran Rewards Version 11
writer.Write((string)m_EngravedText);
#endregion
#region Mondain's Legacy version 10
writer.Write((int)m_Slayer3);
#endregion
#region Mondain's Legacy Sets version 9
SetFlag sflags = SetFlag.None;
SetSaveFlag(ref sflags, SetFlag.Attributes, !m_SetAttributes.IsEmpty);
SetSaveFlag(ref sflags, SetFlag.SkillBonuses, !m_SetSkillBonuses.IsEmpty);
SetSaveFlag(ref sflags, SetFlag.Hue, m_SetHue != 0);
SetSaveFlag(ref sflags, SetFlag.LastEquipped, m_LastEquipped);
SetSaveFlag(ref sflags, SetFlag.SetEquipped, m_SetEquipped);
SetSaveFlag(ref sflags, SetFlag.SetSelfRepair, m_SetSelfRepair != 0);
writer.WriteEncodedInt((int)sflags);
if (GetSaveFlag(sflags, SetFlag.Attributes))
m_SetAttributes.Serialize(writer);
if (GetSaveFlag(sflags, SetFlag.SkillBonuses))
m_SetSkillBonuses.Serialize(writer);
if (GetSaveFlag(sflags, SetFlag.Hue))
writer.Write((int)m_SetHue);
if (GetSaveFlag(sflags, SetFlag.LastEquipped))
writer.Write((bool)m_LastEquipped);
if (GetSaveFlag(sflags, SetFlag.SetEquipped))
writer.Write((bool)m_SetEquipped);
if (GetSaveFlag(sflags, SetFlag.SetSelfRepair))
writer.WriteEncodedInt((int)m_SetSelfRepair);
#endregion
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);
SetSaveFlag(ref flags, SaveFlag.Slayer2, m_Slayer2 != SlayerName.None);
SetSaveFlag(ref flags, SaveFlag.ElementalDamages, !m_AosElementDamages.IsEmpty);
SetSaveFlag(ref flags, SaveFlag.EngravedText, !String.IsNullOrEmpty(m_EngravedText));
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.xAttributes))
m_AosAttributes.Serialize(writer);
if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes))
m_AosWeaponAttributes.Serialize(writer);
if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
m_AosSkillBonuses.Serialize(writer);
if (GetSaveFlag(flags, SaveFlag.Slayer2))
writer.Write((int)m_Slayer2);
if (GetSaveFlag(flags, SaveFlag.ElementalDamages))
m_AosElementDamages.Serialize(writer);
if (GetSaveFlag(flags, SaveFlag.EngravedText))
writer.Write((string)m_EngravedText);
}
[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,
Slayer2 = 0x10000000,
ElementalDamages = 0x20000000,
EngravedText = 0x40000000
}
#region Mondain's Legacy Sets
private static void SetSaveFlag(ref SetFlag flags, SetFlag toSet, bool setIf)
{
if (setIf)
flags |= toSet;
}
private static bool GetSaveFlag(SetFlag flags, SetFlag toGet)
{
return ((flags & toGet) != 0);
}
[Flags]
private enum SetFlag
{
None = 0x00000000,
Attributes = 0x00000001,
WeaponAttributes = 0x00000002,
SkillBonuses = 0x00000004,
Hue = 0x00000008,
LastEquipped = 0x00000010,
SetEquipped = 0x00000020,
SetSelfRepair = 0x00000040,
}
#endregion
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 13:
//personal bless deed
case 12:
{
m_BlessedBy = reader.ReadMobile();
goto case 11;
}
case 11:
#region Veteran Rewards
m_EngravedText = reader.ReadString();
goto case 10;
#endregion
#region Mondain's Legacy
case 10:
{
m_Slayer3 = (TalismanSlayerName)reader.ReadInt();
goto case 9;
}
case 9:
{
SetFlag flags = (SetFlag)reader.ReadEncodedInt();
if (GetSaveFlag(flags, SetFlag.Attributes))
m_SetAttributes = new AosAttributes(this, reader);
else
m_SetAttributes = new AosAttributes(this);
if (GetSaveFlag(flags, SetFlag.WeaponAttributes))
m_SetSelfRepair = (new AosWeaponAttributes(this, reader)).SelfRepair;
if (GetSaveFlag(flags, SetFlag.SkillBonuses))
m_SetSkillBonuses = new AosSkillBonuses(this, reader);
else
m_SetSkillBonuses = new AosSkillBonuses(this);
if (GetSaveFlag(flags, SetFlag.Hue))
m_SetHue = reader.ReadInt();
if (GetSaveFlag(flags, SetFlag.LastEquipped))
m_LastEquipped = reader.ReadBool();
if (GetSaveFlag(flags, SetFlag.SetEquipped))
m_SetEquipped = reader.ReadBool();
if (GetSaveFlag(flags, SetFlag.SetSelfRepair))
m_SetSelfRepair = reader.ReadEncodedInt();
goto case 8;
}
#endregion
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.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))
{
if (version < 13)
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 (GetSaveFlag(flags, SaveFlag.xAttributes))
m_AosAttributes = new AosAttributes(this, reader);
else
m_AosAttributes = new AosAttributes(this);
if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes))
m_AosWeaponAttributes = new AosWeaponAttributes(this, reader);
else
m_AosWeaponAttributes = new AosWeaponAttributes(this);
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 (version < 7 && m_AosWeaponAttributes.MageWeapon != 0)
m_AosWeaponAttributes.MageWeapon = 30 - m_AosWeaponAttributes.MageWeapon;
if (Core.AOS && m_AosWeaponAttributes.MageWeapon != 0 && m_AosWeaponAttributes.MageWeapon != 30 && Parent is Mobile)
{
m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + m_AosWeaponAttributes.MageWeapon);
((Mobile)Parent).AddSkillMod(m_MageMod);
}
if (GetSaveFlag(flags, SaveFlag.PlayerConstructed))
m_PlayerConstructed = true;
if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
m_AosSkillBonuses = new AosSkillBonuses(this, reader);
else
m_AosSkillBonuses = new AosSkillBonuses(this);
if (GetSaveFlag(flags, SaveFlag.Slayer2))
m_Slayer2 = (SlayerName)reader.ReadInt();
if (GetSaveFlag(flags, SaveFlag.ElementalDamages))
m_AosElementDamages = new AosElementAttributes(this, reader);
else
m_AosElementDamages = new AosElementAttributes(this);
if (GetSaveFlag(flags, SaveFlag.EngravedText))
m_EngravedText = reader.ReadString();
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:
{
m_Identified = reader.ReadBool();
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_AosAttributes = new AosAttributes(this);
m_AosWeaponAttributes = new AosWeaponAttributes(this);
m_AosElementDamages = new AosElementAttributes(this);
m_AosSkillBonuses = new AosSkillBonuses(this);
}
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 == OldStrengthReq)
m_StrReq = -1;
if (m_DexReq == OldDexterityReq)
m_DexReq = -1;
if (m_IntReq == OldIntelligenceReq)
m_IntReq = -1;
if (m_MinDamage == OldMinDamage)
m_MinDamage = -1;
if (m_MaxDamage == OldMaxDamage)
m_MaxDamage = -1;
if (m_HitSound == OldHitSound)
m_HitSound = -1;
if (m_MissSound == OldMissSound)
m_MissSound = -1;
if (m_Speed == OldSpeed)
m_Speed = -1;
if (m_MaxRange == OldMaxRange)
m_MaxRange = -1;
if (m_Skill == OldSkill)
m_Skill = (SkillName)(-1);
if (m_Type == OldType)
m_Type = (WeaponType)(-1);
if (m_Animation == OldAnimation)
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;
}
}
#region Mondain's Legacy Sets
if (m_SetAttributes == null)
m_SetAttributes = new AosAttributes(this);
if (m_SetSkillBonuses == null)
m_SetSkillBonuses = new AosSkillBonuses(this);
#endregion
if (Core.AOS && Parent is Mobile)
m_AosSkillBonuses.AddTo((Mobile)Parent);
int strBonus = m_AosAttributes.BonusStr;
int dexBonus = m_AosAttributes.BonusDex;
int intBonus = m_AosAttributes.BonusInt;
if (this.Parent is Mobile && (strBonus != 0 || dexBonus != 0 || intBonus != 0))
{
Mobile m = (Mobile)this.Parent;
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));
}
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;
m_AosAttributes = new AosAttributes(this);
m_AosWeaponAttributes = new AosWeaponAttributes(this);
m_AosSkillBonuses = new AosSkillBonuses(this);
m_AosElementDamages = new AosElementAttributes(this);
#region Mondain's Legacy Sets
m_SetAttributes = new AosAttributes(this);
m_SetSkillBonuses = new AosSkillBonuses(this);
#endregion
}
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 int GetElementalDamageHue()
{
#region Mondain's Legacy
int phys, fire, cold, pois, nrgy, chaos, direct;
GetDamageTypes(null, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);
#endregion
//Order is Cold, Energy, Fire, Poison, Physical left
int currentMax = 50;
int hue = 0;
if (pois >= currentMax)
{
hue = 1267 + (pois - 50) / 10;
currentMax = pois;
}
if (fire >= currentMax)
{
hue = 1255 + (fire - 50) / 10;
currentMax = fire;
}
if (nrgy >= currentMax)
{
hue = 1273 + (nrgy - 50) / 10;
currentMax = nrgy;
}
if (cold >= currentMax)
{
hue = 1261 + (cold - 50) / 10;
currentMax = cold;
}
return hue;
}
public override void AddNameProperty(ObjectPropertyList list)
{
//Colored Item Name Mod Start
//Getting Props code
BaseWeapon wea = this as BaseWeapon;
int props = 0;
foreach( int i in Enum.GetValues(typeof( AosAttribute ) ) )
{
if ( wea != null && wea.Attributes[ (AosAttribute)i ] > 0 ) ++props;
}
if ( wea != null ){ foreach( int i in Enum.GetValues(typeof( AosWeaponAttribute)) ) if ( wea.WeaponAttributes[ (AosWeaponAttribute)i ] > 0 ) ++props;}
if ( wea != null ){ if(wea.Slayer != SlayerName.None) ++props; if (wea.Slayer2 != SlayerName.None) ++props; }
if(this.SkillBonuses.Skill_1_Value > 0) ++props;
if(this.SkillBonuses.Skill_2_Value > 0) ++props;
if(this.SkillBonuses.Skill_3_Value > 0) ++props;
if(this.SkillBonuses.Skill_4_Value > 0) ++props;
if(this.SkillBonuses.Skill_5_Value > 0) ++props;
//AddNamePropertiey Code
string oreType = CraftResources.GetName( m_Resource );
if ( oreType.ToLower() == "none" || oreType.ToLower() == "normal" ) oreType = "";
// Props code display
if( props == 0 ) // No color (Common)
{
list.Add(1053099, "{0}\t{1}", oreType, GetNameString());
}
if( props >= 1 && props <= 2 ) // Green (Uncommon)
{
list.Add(1053099, "<BASEFONT COLOR=#1EFF00>{0}\t{1}<BASEFONT COLOR=#FFFFFF>", oreType, GetNameString());
}
if( props >= 3 && props <= 4 ) // Blue (Rare)
{
list.Add(1053099, "<BASEFONT COLOR=#0070FF>{0}\t{1}<BASEFONT COLOR=#FFFFFF>", oreType, GetNameString());
}
if( props >= 5 && props <= 6 ) // Purple (Epic)
{
list.Add(1053099, "<BASEFONT COLOR=#A335EE>{0}\t{1}<BASEFONT COLOR=#FFFFFF>", oreType, GetNameString());
}
if( props >= 7 && props <= 8 ) // Orange (Legendary)
{
list.Add(1053099, "<BASEFONT COLOR=#FF8000>{0}\t{1}<BASEFONT COLOR=#FFFFFF>", oreType, GetNameString());
}
if( props >= 9 ) // Golden (Artifact)
{
list.Add(1053099, "<BASEFONT COLOR=#E6CC80>{0}\t{1}<BASEFONT COLOR=#FFFFFF>", oreType, GetNameString());
}
//Colored Item Name Mod End
if (!String.IsNullOrEmpty(m_EngravedText))
list.Add(1062613, m_EngravedText);
}
string oreType;
if (Hue == 0)
{
oreType = "";
}
else
{
switch (m_Resource)
{
case CraftResource.DullCopper: oreType = "Dull Copper"; break; // Dull Copper
case CraftResource.ShadowIron: oreType = "Shadow Iron"; break; // Shadow Iron
case CraftResource.Copper: oreType = "Copper"; break; // Copper
case CraftResource.Bronze: oreType = "Bronze"; break; // Bronze
case CraftResource.Gold: oreType = "Gold"; break; // Gold
case CraftResource.Agapite: oreType = "Agapite"; break; // Agapite
case CraftResource.Verite: oreType = "Verite"; break; // Verite
case CraftResource.Valorite: oreType = "Valorite"; break; // valorite
case CraftResource.Blaze: oreType = "Blaze"; break; // Blaze
case CraftResource.Ice: oreType = "Ice"; break; // Ice
case CraftResource.Toxic: oreType = "Toxic"; break; // Toxic
case CraftResource.Electrum: oreType = "Electrum"; break; // Electrum
case CraftResource.Platinum: oreType = "Platinum"; break; // Platinum
case CraftResource.SpinedLeather: oreType = "Spined Leather"; break; // Spined
case CraftResource.HornedLeather: oreType = "Horned Leather"; break; // Horned
case CraftResource.BarbedLeather: oreType = "Barbed Leather"; break; // Barbed
case CraftResource.PolarLeather: oreType = "Polar Leather"; break; // Polar
case CraftResource.SyntheticLeather: oreType = "Synthetic Leather"; break; // Synthetic
case CraftResource.BlazeLeather: oreType = "Blaze Leather"; break; // Blaze
case CraftResource.DaemonicLeather: oreType = "Daemonic Leather"; break; // Daemonic
case CraftResource.ShadowLeather: oreType = "Shadow Leather"; break; // Shadow
case CraftResource.FrostLeather: oreType = "Frost Leather"; break; // Frost
case CraftResource.EtherealLeather: oreType = "Ethereal Leather"; break; // Ethereal
case CraftResource.RedScales: oreType = "Red Scales"; break; // Red
case CraftResource.YellowScales: oreType = "Yellow Scales"; break; // Yellow
case CraftResource.BlackScales: oreType = "Black Scales"; break; // Black
case CraftResource.GreenScales: oreType = "Green Scales"; break; // Green
case CraftResource.WhiteScales: oreType = "White Scales"; break; // White
case CraftResource.BlueScales: oreType = "Blue Scales"; break; // Blue
case CraftResource.CopperScales: oreType = "Copper Scales"; break; // Copper
case CraftResource.SilverScales: oreType = "Silver Scales"; break; // Silver
case CraftResource.GoldScales: oreType = "Gold Scales"; break; // Gold
case CraftResource.Pine: oreType = "Pine"; break; // Pine
case CraftResource.AshWood: oreType = "Ash Wood"; break; // Ash
case CraftResource.Mohogany: oreType = "Mohogany"; break; // Mohogany
case CraftResource.YewWood: oreType = "Yew Wood"; break; // Yew
case CraftResource.OakWood: oreType = "Oak Wood"; break; // Oak
case CraftResource.Zircote: oreType = "Zircote"; break; // Zircote
case CraftResource.Ebony: oreType = "Ebony"; break; // Ebony
case CraftResource.Bamboo: oreType = "Bamboo"; break; // Bamboo
case CraftResource.Bloodwood: oreType = "bloodwood"; break; // bloodwood
case CraftResource.Heartwood: oreType = "heartwood"; break; // heartwood
case CraftResource.Frostwood: oreType = "frostwood"; break; // frostwood
default: oreType = ""; break;
}
}
if (oreType != "")
list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~
else if (Name == null)
list.Add(LabelNumber);
else
list.Add(Name);
if (!String.IsNullOrEmpty(m_EngravedText))
list.Add(1062613, m_EngravedText);
}
public override bool AllowEquipedCast(Mobile from)
{
if (base.AllowEquipedCast(from))
return true;
return (m_AosAttributes.SpellChanneling != 0);
}
public virtual int ArtifactRarity
{
get { return 0; }
}
public virtual int GetLuckBonus()
{
#region Mondain's Legacy
if (m_Resource == CraftResource.Heartwood)
return 0;
#endregion
CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);
if (resInfo == null)
return 0;
CraftAttributeInfo attrInfo = resInfo.AttributeInfo;
if (attrInfo == null)
return 0;
return attrInfo.WeaponLuck;
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (m_Crafter != null)
list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~
#region Factions
if (m_FactionState != null)
list.Add(1041350); // faction item
#endregion
#region Mondain's Legacy Sets
if (IsSetItem)
{
list.Add(1073491, Pieces.ToString()); // Part of a Weapon/Armor Set (~1_val~ pieces)
if (m_SetEquipped)
{
list.Add(1073492); // Full Weapon/Armor Set Present
GetSetProperties(list);
}
}
#endregion
if (m_AosSkillBonuses != null)
m_AosSkillBonuses.GetProperties(list);
if (m_Quality == WeaponQuality.Exceptional)
list.Add(1060636); // exceptional
if (RequiredRace == Race.Elf)
list.Add(1075086); // Elves Only
if (ArtifactRarity > 0)
list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~
if (this is IUsesRemaining && ((IUsesRemaining)this).ShowUsesRemaining)
list.Add(1060584, ((IUsesRemaining)this).UsesRemaining.ToString()); // uses remaining: ~1_val~
if (m_Poison != null && m_PoisonCharges > 0)
{
#region Mondain's Legacy mod
list.Add(m_Poison.LabelNumber, m_PoisonCharges.ToString());
#endregion
}
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);
}
#region Mondain's Legacy
if (m_Slayer3 != TalismanSlayerName.None)
list.Add((int)m_Slayer3);
#endregion
base.AddResistanceProperties(list);
int prop;
if (Core.ML && this is BaseRanged && ((BaseRanged)this).Balanced)
list.Add(1072792); // Balanced
if ((prop = m_AosWeaponAttributes.UseBestSkill) != 0)
list.Add(1060400); // use best weapon skill
if ((prop = (GetDamageBonus() + m_AosAttributes.WeaponDamage)) != 0)
list.Add(1060401, prop.ToString()); // damage increase ~1_val~%
if ((prop = m_AosAttributes.DefendChance) != 0)
list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~%
if ((prop = m_AosAttributes.EnhancePotions) != 0)
list.Add(1060411, prop.ToString()); // enhance potions ~1_val~%
if ((prop = m_AosAttributes.CastRecovery) != 0)
list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~
if ((prop = m_AosAttributes.CastSpeed) != 0)
list.Add(1060413, prop.ToString()); // faster casting ~1_val~
if ((prop = (GetHitChanceBonus() + m_AosAttributes.AttackChance)) != 0)
list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~%
if ((prop = m_AosWeaponAttributes.HitColdArea) != 0)
list.Add(1060416, prop.ToString()); // hit cold area ~1_val~%
if ((prop = m_AosWeaponAttributes.HitDispel) != 0)
list.Add(1060417, prop.ToString()); // hit dispel ~1_val~%
if ((prop = m_AosWeaponAttributes.HitEnergyArea) != 0)
list.Add(1060418, prop.ToString()); // hit energy area ~1_val~%
if ((prop = m_AosWeaponAttributes.HitFireArea) != 0)
list.Add(1060419, prop.ToString()); // hit fire area ~1_val~%
if ((prop = m_AosWeaponAttributes.HitFireball) != 0)
list.Add(1060420, prop.ToString()); // hit fireball ~1_val~%
if ((prop = m_AosWeaponAttributes.HitHarm) != 0)
list.Add(1060421, prop.ToString()); // hit harm ~1_val~%
if ((prop = m_AosWeaponAttributes.HitLeechHits) != 0)
list.Add(1060422, prop.ToString()); // hit life leech ~1_val~%
if ((prop = m_AosWeaponAttributes.HitLightning) != 0)
list.Add(1060423, prop.ToString()); // hit lightning ~1_val~%
if ((prop = m_AosWeaponAttributes.HitLowerAttack) != 0)
list.Add(1060424, prop.ToString()); // hit lower attack ~1_val~%
if ((prop = m_AosWeaponAttributes.HitLowerDefend) != 0)
list.Add(1060425, prop.ToString()); // hit lower defense ~1_val~%
if ((prop = m_AosWeaponAttributes.HitMagicArrow) != 0)
list.Add(1060426, prop.ToString()); // hit magic arrow ~1_val~%
if ((prop = m_AosWeaponAttributes.HitLeechMana) != 0)
list.Add(1060427, prop.ToString()); // hit mana leech ~1_val~%
if ((prop = m_AosWeaponAttributes.HitPhysicalArea) != 0)
list.Add(1060428, prop.ToString()); // hit physical area ~1_val~%
if ((prop = m_AosWeaponAttributes.HitPoisonArea) != 0)
list.Add(1060429, prop.ToString()); // hit poison area ~1_val~%
if ((prop = m_AosWeaponAttributes.HitLeechStam) != 0)
list.Add(1060430, prop.ToString()); // hit stamina leech ~1_val~%
if (Core.ML && this is BaseRanged && (prop = ((BaseRanged)this).Velocity) != 0)
list.Add(1072793, prop.ToString()); // Velocity ~1_val~%
if ((prop = m_AosAttributes.BonusDex) != 0)
list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~
if ((prop = m_AosAttributes.BonusHits) != 0)
list.Add(1060431, prop.ToString()); // hit point increase ~1_val~
if ((prop = m_AosAttributes.BonusInt) != 0)
list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~
if ((prop = m_AosAttributes.LowerManaCost) != 0)
list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~%
if ((prop = m_AosAttributes.LowerRegCost) != 0)
list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~%
if ((prop = GetLowerStatReq()) != 0)
list.Add(1060435, prop.ToString()); // lower requirements ~1_val~%
if ((prop = (GetLuckBonus() + m_AosAttributes.Luck)) != 0)
list.Add(1060436, prop.ToString()); // luck ~1_val~
if ((prop = m_AosWeaponAttributes.MageWeapon) != 0)
list.Add(1060438, (30 - prop).ToString()); // mage weapon -~1_val~ skill
if ((prop = m_AosAttributes.BonusMana) != 0)
list.Add(1060439, prop.ToString()); // mana increase ~1_val~
if ((prop = m_AosAttributes.RegenMana) != 0)
list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~
if ((prop = m_AosAttributes.NightSight) != 0)
list.Add(1060441); // night sight
if ((prop = m_AosAttributes.ReflectPhysical) != 0)
list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~%
if ((prop = m_AosAttributes.RegenStam) != 0)
list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~
if ((prop = m_AosAttributes.RegenHits) != 0)
list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~
if ((prop = m_AosWeaponAttributes.SelfRepair) != 0)
list.Add(1060450, prop.ToString()); // self repair ~1_val~
if ((prop = m_AosAttributes.SpellChanneling) != 0)
list.Add(1060482); // spell channeling
if ((prop = m_AosAttributes.SpellDamage) != 0)
list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~%
if ((prop = m_AosAttributes.BonusStam) != 0)
list.Add(1060484, prop.ToString()); // stamina increase ~1_val~
if ((prop = m_AosAttributes.BonusStr) != 0)
list.Add(1060485, prop.ToString()); // strength bonus ~1_val~
if ((prop = m_AosAttributes.WeaponSpeed) != 0)
list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~%
int phys, fire, cold, pois, nrgy, chaos, direct;
GetDamageTypes(null, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);
#region Mondain's Legacy
if (chaos != 0)
list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~%
if (direct != 0)
list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~%
#endregion
if (phys != 0)
list.Add(1060403, phys.ToString()); // physical damage ~1_val~%
if (fire != 0)
list.Add(1060405, fire.ToString()); // fire damage ~1_val~%
if (cold != 0)
list.Add(1060404, cold.ToString()); // cold damage ~1_val~%
if (pois != 0)
list.Add(1060406, pois.ToString()); // poison damage ~1_val~%
if (nrgy != 0)
list.Add(1060407, nrgy.ToString()); // energy damage ~1_val~%
if (Core.ML && chaos != 0)
list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~%
if (Core.ML && direct != 0)
list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~%
list.Add(1061168, "{0}\t{1}", MinDamage.ToString(), MaxDamage.ToString()); // weapon damage ~1_val~ - ~2_val~
if (Core.ML)
list.Add(1061167, String.Format("{0}s", Speed)); // weapon speed ~1_val~
else
list.Add(1061167, Speed.ToString());
if (MaxRange > 1)
list.Add(1061169, MaxRange.ToString()); // range ~1_val~
int strReq = AOS.Scale(StrRequirement, 100 - GetLowerStatReq());
if (strReq > 0)
list.Add(1061170, strReq.ToString()); // strength requirement ~1_val~
if (Layer == Layer.TwoHanded)
list.Add(1061171); // two-handed weapon
else
list.Add(1061824); // one-handed weapon
if (Core.SE || m_AosWeaponAttributes.UseBestSkill == 0)
{
switch (Skill)
{
case SkillName.Swords: list.Add(1061172); break; // skill required: swordsmanship
case SkillName.Macing: list.Add(1061173); break; // skill required: mace fighting
case SkillName.Fencing: list.Add(1061174); break; // skill required: fencing
case SkillName.Archery: list.Add(1061175); break; // skill required: archery
}
}
if (m_Hits >= 0 && m_MaxHits > 0)
list.Add(1060639, "{0}\t{1}", m_Hits, m_MaxHits); // durability ~1_val~ / ~2_val~
#region Mondain's Legacy Sets
if (IsSetItem && !m_SetEquipped)
{
list.Add(1072378); // <br>Only when full set is present:
GetSetProperties(list);
}
#endregion
}
public override void OnSingleClick(Mobile from)
{
List<EquipInfoAttribute> attrs = new List<EquipInfoAttribute>();
if (DisplayLootType)
{
if (LootType == LootType.Blessed)
attrs.Add(new EquipInfoAttribute(1038021)); // blessed
else if (LootType == LootType.Cursed)
attrs.Add(new EquipInfoAttribute(1049643)); // cursed
}
#region Factions
if (m_FactionState != null)
attrs.Add(new EquipInfoAttribute(1041350)); // faction item
#endregion
if (m_Quality == WeaponQuality.Exceptional)
attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality));
if (m_Identified || from.AccessLevel >= AccessLevel.GameMaster)
{
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));
}
else if (m_Slayer != SlayerName.None || m_Slayer2 != SlayerName.None || m_DurabilityLevel != WeaponDurabilityLevel.Regular || m_DamageLevel != WeaponDamageLevel.Regular || m_AccuracyLevel != WeaponAccuracyLevel.Regular)
attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified
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 virtual 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;
if (Core.AOS)
{
#region Mondain's Legacy
if (!craftItem.ForceNonExceptional)
Resource = CraftResources.GetFromType(resourceType);
#endregion
CraftContext context = craftSystem.GetContext(from);
if (context != null && context.DoNotColor)
Hue = 0;
// Mondain's Legacy Mod
if (craftItem != null && !craftItem.ForceNonExceptional)
{
if (tool is BaseRunicTool)
((BaseRunicTool)tool).ApplyAttributesTo(this);
}
if (Quality == WeaponQuality.Exceptional)
{
if (Attributes.WeaponDamage > 35)
Attributes.WeaponDamage -= 20;
else
Attributes.WeaponDamage = 15;
if (Core.ML)
{
Attributes.WeaponDamage += (int)(from.Skills.ArmsLore.Value / 20);
if (Attributes.WeaponDamage > 50)
Attributes.WeaponDamage = 50;
from.CheckSkill(SkillName.ArmsLore, 0, 100);
}
}
}
else if (tool is BaseRunicTool)
{
// Mondain's Legacy Mod
if (craftItem != null && !craftItem.ForceNonExceptional)
{
CraftResource thisResource = CraftResources.GetFromType(resourceType);
if (thisResource == ((BaseRunicTool)tool).Resource)
{
Resource = thisResource;
CraftContext context = craftSystem.GetContext(from);
if (context != null && context.DoNotColor)
Hue = 0;
switch (thisResource)
{
case CraftResource.DullCopper:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Durable;
AccuracyLevel = WeaponAccuracyLevel.Accurate;
break;
}
case CraftResource.ShadowIron:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Durable;
DamageLevel = WeaponDamageLevel.Ruin;
break;
}
case CraftResource.Copper:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Fortified;
DamageLevel = WeaponDamageLevel.Ruin;
AccuracyLevel = WeaponAccuracyLevel.Surpassingly;
break;
}
case CraftResource.Bronze:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Fortified;
DamageLevel = WeaponDamageLevel.Might;
AccuracyLevel = WeaponAccuracyLevel.Surpassingly;
break;
}
case CraftResource.Gold:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
DamageLevel = WeaponDamageLevel.Force;
AccuracyLevel = WeaponAccuracyLevel.Eminently;
break;
}
case CraftResource.Agapite:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
DamageLevel = WeaponDamageLevel.Power;
AccuracyLevel = WeaponAccuracyLevel.Eminently;
break;
}
case CraftResource.Verite:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
DamageLevel = WeaponDamageLevel.Power;
AccuracyLevel = WeaponAccuracyLevel.Exceedingly;
break;
}
case CraftResource.Valorite:
{
Identified = true;
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
DamageLevel = WeaponDamageLevel.Vanq;
AccuracyLevel = WeaponAccuracyLevel.Supremely;
break;
}
}
}
}
}
#region Mondain's Legacy
if (craftItem != null && !craftItem.ForceNonExceptional)
{
CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);
if (resInfo == null)
return quality;
CraftAttributeInfo attrInfo = resInfo.AttributeInfo;
if (attrInfo == null)
return quality;
if (m_Resource != CraftResource.Heartwood)
{
m_AosAttributes.WeaponDamage += attrInfo.WeaponDamage;
m_AosAttributes.WeaponSpeed += attrInfo.WeaponSwingSpeed;
m_AosAttributes.AttackChance += attrInfo.WeaponHitChance;
m_AosAttributes.RegenHits += attrInfo.WeaponRegenHits;
m_AosWeaponAttributes.HitLeechHits += attrInfo.WeaponHitLifeLeech;
}
else
{
switch (Utility.Random(6))
{
case 0: m_AosAttributes.WeaponDamage += attrInfo.WeaponDamage; break;
case 1: m_AosAttributes.WeaponSpeed += attrInfo.WeaponSwingSpeed; break;
case 2: m_AosAttributes.AttackChance += attrInfo.WeaponHitChance; break;
case 3: m_AosAttributes.Luck += attrInfo.WeaponLuck; break;
case 4: m_AosWeaponAttributes.LowerStatReq += attrInfo.WeaponLowerRequirements; break;
case 5: m_AosWeaponAttributes.HitLeechHits += attrInfo.WeaponHitLifeLeech; break;
}
}
}
#endregion
return quality;
}
#endregion
#region Mondain's Legacy Sets
public override bool OnDragLift(Mobile from)
{
if (Parent is Mobile && from == Parent)
{
if (IsSetItem && m_SetEquipped)
SetHelper.RemoveSetBonus(from, SetID, this);
}
return base.OnDragLift(from);
}
public virtual SetItem SetID { get { return SetItem.None; } }
public virtual int Pieces { get { return 0; } }
public bool IsSetItem { get { return SetID != SetItem.None; } }
private int m_SetHue;
private bool m_SetEquipped;
private bool m_LastEquipped;
[CommandProperty(AccessLevel.GameMaster)]
public int SetHue
{
get { return m_SetHue; }
set { m_SetHue = value; InvalidateProperties(); }
}
public bool SetEquipped
{
get { return m_SetEquipped; }
set { m_SetEquipped = value; }
}
public bool LastEquipped
{
get { return m_LastEquipped; }
set { m_LastEquipped = value; }
}
private AosAttributes m_SetAttributes;
private AosSkillBonuses m_SetSkillBonuses;
private int m_SetSelfRepair;
[CommandProperty(AccessLevel.GameMaster)]
public AosAttributes SetAttributes
{
get { return m_SetAttributes; }
set { }
}
[CommandProperty(AccessLevel.GameMaster)]
public AosSkillBonuses SetSkillBonuses
{
get { return m_SetSkillBonuses; }
set { }
}
[CommandProperty(AccessLevel.GameMaster)]
public int SetSelfRepair
{
get { return m_SetSelfRepair; }
set { m_SetSelfRepair = value; InvalidateProperties(); }
}
public virtual void GetSetProperties(ObjectPropertyList list)
{
int prop;
if ((prop = m_SetSelfRepair) != 0 && WeaponAttributes.SelfRepair == 0)
list.Add(1060450, prop.ToString()); // self repair ~1_val~
SetHelper.GetSetProperties(list, this);
}
#endregion
}
public enum CheckSlayerResult
{
None,
Slayer,
Opposition
}
}