diff --git a/Scripts/Abilities/Abilities.cs b/Scripts/Abilities/Abilities.cs index de082dc580..cdf2a06069 100644 --- a/Scripts/Abilities/Abilities.cs +++ b/Scripts/Abilities/Abilities.cs @@ -241,8 +241,11 @@ public static void UseDiscord(BaseCreature from) return; if (from.Combatant is BaseCreature) + { + BaseCreature bc = (BaseCreature)from.Combatant; + if (from.Target != null) - from.Target.Invoke(from, from.Combatant); + from.Target.Invoke(from, bc); else { double effect = -(from.Skills[SkillName.Discordance].Value / 5.0); @@ -257,11 +260,12 @@ public static void UseDiscord(BaseCreature from) new ResistanceMod(ResistanceType.Energy, (int)(effect * 0.01)) }; - TimedResistanceMod.AddMod(from.Combatant, "Discordance", mods, duration); - from.Combatant.AddStatMod(new StatMod(StatType.Str, "DiscordanceStr", (int)(from.Combatant.RawStr * effect), duration)); - from.Combatant.AddStatMod(new StatMod(StatType.Int, "DiscordanceInt", (int)(from.Combatant.RawInt * effect), duration)); - from.Combatant.AddStatMod(new StatMod(StatType.Dex, "DiscordanceDex", (int)(from.Combatant.RawDex * effect), duration)); + TimedResistanceMod.AddMod(bc, "Discordance", mods, duration); + bc.AddStatMod(new StatMod(StatType.Str, "DiscordanceStr", (int)(bc.RawStr * effect), duration)); + bc.AddStatMod(new StatMod(StatType.Int, "DiscordanceInt", (int)(bc.RawInt * effect), duration)); + bc.AddStatMod(new StatMod(StatType.Dex, "DiscordanceDex", (int)(bc.RawDex * effect), duration)); } + } } public class DiscordEffectTimer : Timer @@ -292,7 +296,7 @@ protected override void OnTick() public static void UsePeace(BaseCreature from) { - if (from.Combatant == null || !CanUse(from) || !CheckBarding(from)) + if (from.Combatant == null || !(from.Combatant is Mobile) || !CanUse(from) || !CheckBarding(from)) return; if (!from.UseSkill(SkillName.Peacemaking)) @@ -315,7 +319,7 @@ public static void UsePeace(BaseCreature from) public static void UseProvo(BaseCreature from, bool randomly) { - if (from.Combatant == null && randomly || !CheckBarding(from)) + if (((from.Combatant == null || !(from.Combatant is Mobile)) && randomly) || !CheckBarding(from)) return; if (!CanUse(from)) @@ -332,7 +336,7 @@ public static void UseProvo(BaseCreature from, bool randomly) if (from.Target != null) from.Target.Invoke(from, targetone); - Mobile targettwo = randomly ? FindRandomTarget(from, randomly) : from.Combatant; + Mobile targettwo = randomly ? FindRandomTarget(from, randomly) : from.Combatant as Mobile; if (targettwo == null) return; @@ -346,13 +350,13 @@ public static void UseProvo(BaseCreature from, bool randomly) #region MimicThem public static void MimicThem(BaseCreature from) { - Mobile targ = from.Combatant; + Mobile targ = from.Combatant as Mobile; MimicThem(from, false, false); } public static void MimicThem(BaseCreature from, bool allowskillchanges, bool allowAIchanges) { - Mobile targ = from.Combatant; + Mobile targ = from.Combatant as Mobile; MimicThem(from, targ, allowskillchanges, allowAIchanges); } @@ -482,7 +486,7 @@ public static void BullRush(Mobile from) public static void BullRush(Mobile from, string text, int duration) { - Mobile target = from.Combatant; + Mobile target = from.Combatant as Mobile; if (target == null || CanUse(from, target)) return; @@ -698,7 +702,7 @@ public static void TossBola(Mobile from) if (from == null) return; - Mobile target = from.Combatant; + Mobile target = from.Combatant as Mobile; if (target == null) return; @@ -1192,7 +1196,7 @@ public static void Strike(Mobile from, int count) if (from.Frozen || from.Paralyzed) return; - Mobile target = from.Combatant; + Mobile target = from.Combatant as Mobile; if (target == null) return; diff --git a/Scripts/Items/Decorative/DamageableItem.cs b/Scripts/Items/Decorative/DamageableItem.cs index f5e58730e1..4c0a62c338 100644 --- a/Scripts/Items/Decorative/DamageableItem.cs +++ b/Scripts/Items/Decorative/DamageableItem.cs @@ -3,9 +3,19 @@ using Server.Mobiles; using Server.Targeting; using Server.Targets; +using Server.Network; +using System.Collections.Generic; +using System.Linq; namespace Server.Items { + public interface IDamageableItem : IDamageable + { + bool CanDamage { get; } + bool CheckHit(Mobile attacker); + void OnHarmfulSpell(Mobile attacker); + } + public class DamageableItem : Item, IDamageableItem { public enum ItemLevel @@ -25,36 +35,22 @@ public enum ItemLevel private int m_DestroyedID; private int m_HalfHitsID; private ItemLevel m_ItemLevel; - private DamagePlaceholder m_Child; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Link - { - get - { - return this.m_Child; - } - set - { } - } [CommandProperty(AccessLevel.GameMaster)] public ItemLevel Level { get { - return this.m_ItemLevel; + return m_ItemLevel; } set { - this.m_ItemLevel = value; - - double bonus = (double)(((int)this.m_ItemLevel * 100.0) * ((int)this.m_ItemLevel * 5)); + m_ItemLevel = value; - this.HitsMax = ((int)(100 + bonus)); - this.Hits = ((int)(100 + bonus)); + double bonus = (double)(((int)m_ItemLevel * 100.0) * ((int)m_ItemLevel * 5)); - this.InvalidateProperties(); + HitsMax = ((int)(100 + bonus)); + Hits = ((int)(100 + bonus)); } } @@ -63,24 +59,22 @@ public int IDStart { get { - return this.m_StartID; + return m_StartID; } set { if (value < 0) - this.m_StartID = 0; + m_StartID = 0; else if (value > int.MaxValue) - this.m_StartID = int.MaxValue; + m_StartID = int.MaxValue; else - this.m_StartID = value; + m_StartID = value; - if (this.m_Hits >= (this.m_HitsMax * IDChange)) + if (m_Hits >= (m_HitsMax * IDChange)) { - if (this.ItemID != this.m_StartID) - this.ItemID = this.m_StartID; + if (ItemID != m_StartID) + ItemID = m_StartID; } - - this.InvalidateProperties(); } } @@ -89,24 +83,22 @@ public int IDHalfHits { get { - return this.m_HalfHitsID; + return m_HalfHitsID; } set { if (value < 0) - this.m_HalfHitsID = 0; + m_HalfHitsID = 0; else if (value > int.MaxValue) - this.m_HalfHitsID = int.MaxValue; + m_HalfHitsID = int.MaxValue; else - this.m_HalfHitsID = value; + m_HalfHitsID = value; - if (this.m_Hits < (this.m_HitsMax * IDChange)) + if (m_Hits < (m_HitsMax * IDChange)) { - if (this.ItemID != this.m_HalfHitsID) - this.ItemID = this.m_HalfHitsID; + if (ItemID != m_HalfHitsID) + ItemID = m_HalfHitsID; } - - this.InvalidateProperties(); } } @@ -131,20 +123,22 @@ public int Hits { get { - if (m_Child != null && m_Hits != m_Child.Hits) - m_Hits = m_Child.Hits; - - return this.m_Hits; + return m_Hits; } set { - if (value > this.m_HitsMax) - this.m_Hits = this.m_HitsMax; - else - this.m_Hits = value; + if (value > HitsMax) + { + value = HitsMax; + } - if (this.m_Child != null && this.m_Hits != this.m_Child.Hits) - this.UpdateHitsToEntity(); + if (m_Hits != value) + { + int oldValue = m_Hits; + m_Hits = value; + UpdateDelta(); + OnHitsChange(oldValue); + } int id = ItemID; @@ -155,16 +149,15 @@ public int Hits } else if (m_Hits <= (m_HitsMax * IDChange) && id == m_StartID) { - this.ItemID = m_HalfHitsID; + ItemID = m_HalfHitsID; OnIDChange(id); } - else if (m_Hits <= 0) + + if (m_Hits < 0) { - this.Destroy(); + Destroy(); return; } - - this.InvalidateProperties(); } } @@ -173,64 +166,116 @@ public int HitsMax { get { - return this.m_HitsMax; + return m_HitsMax; } set { if (value > int.MaxValue) - this.m_HitsMax = int.MaxValue; + m_HitsMax = int.MaxValue; else - this.m_HitsMax = value; - - if (this.Hits > this.m_HitsMax) - this.Hits = this.m_HitsMax; + m_HitsMax = value; - if (this.m_Child != null && this.m_HitsMax != this.m_Child.HitsMax) - this.UpdateMaxHitsToEntity(); - - this.InvalidateProperties(); + if (Hits > m_HitsMax) + Hits = m_HitsMax; } } [CommandProperty(AccessLevel.GameMaster)] - public string PlaceholderName { get; set; } + public bool Destroyed { get; set; } [CommandProperty(AccessLevel.GameMaster)] - public bool Destroyed { get; set; } + public int ResistBasePhys { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistBaseFire { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistBaseCold { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistBasePoison { get; set; } - public virtual int HitEffect { get { return 14265; } } + [CommandProperty(AccessLevel.GameMaster)] + public int ResistBaseEnergy { get; set; } + + public Dictionary DamageStore { get; set; } + + public virtual int HitEffect { get { return -1; } } public virtual int DestroySound { get { return 0x3B3; } } public virtual double IDChange { get { return 0.5; } } public virtual bool DeleteOnDestroy { get { return true; } } + public virtual bool Alive { get { return !Destroyed; } } + public virtual bool CanDamage { get { return true; } } - public virtual DamagePlaceholder Placeholder { get { return new DamagePlaceholder(this); } } - - public override int PhysicalResistance { get { return 50; } } - public override int FireResistance { get { return 99; } } - public override int ColdResistance { get { return 99; } } - public override int PoisonResistance { get { return 99; } } - public override int EnergyResistance { get { return 99; } } + public override int PhysicalResistance { get { return ResistBasePhys; } } + public override int FireResistance { get { return ResistBaseFire; } } + public override int ColdResistance { get { return ResistBaseCold; } } + public override int PoisonResistance { get { return ResistBasePoison; } } + public override int EnergyResistance { get { return ResistBaseEnergy; } } - public override bool ForceShowProperties { get { return true; } } + public override bool ForceShowProperties { get { return false; } } [Constructable] public DamageableItem(int StartID, int HalfID, int destroyID = -1) : base(StartID) { - this.Hue = 0; - this.Movable = false; + Hue = 0; + Movable = false; - this.Level = ItemLevel.NotSet; + Level = ItemLevel.NotSet; - this.IDStart = StartID; - this.IDHalfHits = HalfID; - this.IDDestroyed = destroyID; + IDStart = StartID; + IDHalfHits = HalfID; + IDDestroyed = destroyID; } - public virtual void OnDamage(int amount, Mobile from, bool willKill) - { - return; - } + public override void OnDoubleClick(Mobile m) + { + if (m.Warmode) + m.Attack(this); + } + + public virtual bool CheckHit(Mobile attacker) + { + return true; // Always hits + } + + public virtual void OnHarmfulSpell(Mobile attacker) + { + } + + public virtual void OnStatsQuery(Mobile from) + { + if (from.Map == Map && Utility.InUpdateRange(this, from) && from.CanSee(this)) + { + from.Send(new MobileStatusCompact(false, this)); + } + } + + public virtual void UpdateDelta() + { + var eable = Map.GetClientsInRange(Location); + Mobile beholder = null; + + Packet status = Packet.Acquire(new MobileHitsN(this)); + + foreach (NetState ns in eable) + { + beholder = ns.Mobile; + + if (beholder != null && beholder.CanSee(this)) + { + ns.Send(status); + } + } + + Packet.Release(status); + eable.Free(); + } + + public virtual void OnHitsChange(int oldhits) + { + } public virtual bool OnBeforeDestroyed() { @@ -242,153 +287,107 @@ public virtual void OnDestroyed(WoodenBox lootbox) return; } - public void UpdateMaxHitsToEntity() + public virtual void Damage(int amount, Mobile from) { - this.m_Child.SetHits(this.HitsMax); - } - - public void UpdateHitsToEntity() - { - this.m_Child.Hits = this.Hits; - } + if (!CanDamage && from.Combatant == this) + { + from.Combatant = null; + return; + } - public virtual void Damage(int amount, Mobile from, bool willKill) - { - if (willKill) - { - this.Destroy(); - return; - } + Hits -= amount; - this.Hits -= amount; + if (amount > 0) + RegisterDamage(from, amount); if (HitEffect > 0) - Effects.SendLocationEffect(this.Location, this.Map, HitEffect, 10, 5); - - this.OnDamage(amount, from, willKill); - } - - public bool Destroy() - { - if (this == null || this.Deleted || Destroyed) - return false; + Effects.SendLocationEffect(Location, Map, HitEffect, 10, 5); - Effects.PlaySound(this.Location, this.Map, DestroySound); + NetState theirState = (from == null ? null : from.NetState); - if (this.OnBeforeDestroyed()) + if (theirState == null && from != null) { - if (this.m_Child != null && !this.m_Child.Deleted && !this.m_Child.Alive) - this.m_Child.Delete(); + Mobile master = from.GetDamageMaster(null); - if (DeleteOnDestroy) + if (master != null) { - this.Delete(); - } - else if (m_DestroyedID >= 0) - { - ItemID = m_DestroyedID; + theirState = master.NetState; } + } - Destroyed = true; - return true; + if (amount > 0 && theirState != null) + { + theirState.Send(Packet.Acquire(new DamagePacket(this, amount))); } - return false; + OnDamage(amount, from, Hits < 0); } - public virtual void OnIDChange(int oldID) + public void RegisterDamage(Mobile m, int damage) { + if(m == null) + return; + + if (DamageStore == null) + DamageStore = new Dictionary(); + + if (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile) + m = ((BaseCreature)m).GetMaster(); + + if (!DamageStore.ContainsKey(m)) + DamageStore[m] = 0; + + DamageStore[m] += damage; } - public virtual void OnPlaceholderCreated(BaseCreature bc) + public List GetLootingRights() { + if (DamageStore == null) + return null; + + return DamageStore.Keys.Where(m => DamageStore[m] > 0 && DamageStore[m] >= HitsMax / 16).ToList(); } - public void CheckEntity() + public virtual void OnDamage(int amount, Mobile from, bool willkill) { - if (m_Child != null && !m_Child.Deleted) - { - m_Child.Update(); - } - else if (!Destroyed) - { - this.ProvideEntity(); - - if (m_Child != null && !m_Child.Deleted) - { - this.m_Child.Update(); - } - } } - protected void ProvideEntity() + public bool Destroy() { - if (Destroyed) - return; - - if (this.m_Child != null) - { - this.m_Child.Delete(); - } + if (this == null || Deleted || Destroyed) + return false; - DamagePlaceholder Idam = Placeholder; + Effects.PlaySound(Location, Map, DestroySound); - if (Idam != null && !Idam.Deleted && this.Map != null) - { - this.m_Child = Idam; - this.m_Child.Update(); - } - } + if (OnBeforeDestroyed()) + { + if (DeleteOnDestroy) + { + Delete(); + } + else if (m_DestroyedID >= 0) + { + ItemID = m_DestroyedID; + } - public override void OnLocationChange(Point3D oldLocation) - { - if (this.Location != oldLocation) - { - if (this.m_Child != null && !this.m_Child.Deleted) - { - if (this.m_Child.Location == oldLocation) - this.m_Child.Update(); - } - } + Destroyed = true; + return true; + } - base.OnLocationChange(oldLocation); + return false; } - public override void OnMapChange() + public override void OnAfterDelete() { - base.OnMapChange(); + base.OnAfterDelete(); - if(m_Child != null) - m_Child.Update(); + if (DamageStore != null) + DamageStore.Clear(); } - public override void OnDoubleClick(Mobile from) - { - CheckEntity(); - - if (from.InRange(Location, 12) && from.InLOS(this) && from.CanBeHarmful(m_Child, true, false)) - { - from.Combatant = m_Child; - } - else - base.OnDoubleClick(from); - } - - public override bool OnDragLift(Mobile from) - { - return (from.IsStaff()); - } - - public override void Delete() - { - base.Delete(); - - if (this.m_Child != null && !this.m_Child.Deleted) - { - this.m_Child.Delete(); - return; - } - } + public virtual void OnIDChange(int oldID) + { + } public DamageableItem(Serial serial) : base(serial) @@ -401,15 +400,19 @@ public override void Serialize(GenericWriter writer) writer.Write((int)0); // version - writer.Write((Mobile)this.m_Child); - writer.Write((int)this.m_StartID); - writer.Write((int)this.m_HalfHitsID); - writer.Write((int)this.m_DestroyedID); - writer.Write((int)this.m_ItemLevel); - writer.Write((int)this.m_Hits); - writer.Write((int)this.m_HitsMax); - writer.Write((bool)this.Movable); + writer.Write((int)m_StartID); + writer.Write((int)m_HalfHitsID); + writer.Write((int)m_DestroyedID); + writer.Write((int)m_ItemLevel); + writer.Write((int)m_Hits); + writer.Write((int)m_HitsMax); writer.Write(Destroyed); + + writer.Write(ResistBasePhys); + writer.Write(ResistBaseFire); + writer.Write(ResistBaseCold); + writer.Write(ResistBasePoison); + writer.Write(ResistBaseEnergy); } public override void Deserialize(GenericReader reader) @@ -418,137 +421,32 @@ public override void Deserialize(GenericReader reader) int version = reader.ReadInt(); - this.m_Child = (DamagePlaceholder)reader.ReadMobile(); - this.m_StartID = (int)reader.ReadInt(); - this.m_HalfHitsID = (int)reader.ReadInt(); - this.m_DestroyedID = (int)reader.ReadInt(); - this.m_ItemLevel = (ItemLevel)reader.ReadInt(); - this.m_Hits = (int)reader.ReadInt(); - this.m_HitsMax = (int)reader.ReadInt(); - this.Movable = (bool)reader.ReadBool(); + m_StartID = (int)reader.ReadInt(); + m_HalfHitsID = (int)reader.ReadInt(); + m_DestroyedID = (int)reader.ReadInt(); + m_ItemLevel = (ItemLevel)reader.ReadInt(); + m_Hits = (int)reader.ReadInt(); + m_HitsMax = (int)reader.ReadInt(); Destroyed = reader.ReadBool(); - } - } - - public class DamagePlaceholder : BaseCreature - { - private DamageableItem m_Parent; - - [CommandProperty(AccessLevel.GameMaster)] - public DamageableItem Link - { - get - { - return this.m_Parent; - } - set - { - } - } - - public override bool CanRegenHits { get { return false; } } - public override bool DeleteCorpseOnDeath { get { return true; } } - public override bool BleedImmune { get { return true; } } - public override bool BardImmune { get { return false; } } - - public DamagePlaceholder(DamageableItem parent) - : base(AIType.AI_Melee, FightMode.None, 1, 1, 0.2, 0.4) - { - if (parent != null && !parent.Deleted) - this.m_Parent = parent; - - if (!String.IsNullOrEmpty(parent.PlaceholderName)) - Name = parent.PlaceholderName; - else - Name = parent.Name; - - this.Body = 803; //Mustache is barely visible! - this.BodyValue = 803; //Mustache is barely visible! - this.Hue = 0; - this.BaseSoundID = 0; //QUIET!!! - this.Fame = 0; - this.Karma = 0; - this.ControlSlots = 0; - this.Tamable = false; - - this.Frozen = true; - this.Paralyzed = true; - this.CantWalk = true; - - this.DamageMin = 0; - this.DamageMax = 0; - - this.SetStr(this.m_Parent.HitsMax); - this.SetHits(this.m_Parent.HitsMax); - this.Hits = this.m_Parent.Hits; - - this.SetResistance(ResistanceType.Physical, parent.PhysicalResistance); - this.SetResistance(ResistanceType.Fire, parent.FireResistance); - this.SetResistance(ResistanceType.Cold, parent.ColdResistance); - this.SetResistance(ResistanceType.Poison, parent.PoisonResistance); - this.SetResistance(ResistanceType.Energy, parent.EnergyResistance); - - for (int skill = 0; skill < this.Skills.Length; skill++) - { - this.Skills[(SkillName)skill].Cap = 1.0 + ((int)this.m_Parent.Level * 0.05); - this.Skills[(SkillName)skill].Base = 1.0 + ((int)this.m_Parent.Level * 0.05); - } - - parent.OnPlaceholderCreated(this); - - this.Update(); - } - - public override Poison PoisonImmune - { - get - { - return Poison.Lethal; - } - } - - public void Update() - { - if (this == null || this.Deleted) - return; - if (this.m_Parent != null && !this.m_Parent.Deleted) - { - this.Home = this.m_Parent.Location; - this.Location = this.m_Parent.Location; - this.Map = this.m_Parent.Map; - - return; - } - - if (this.m_Parent == null || this.m_Parent.Deleted) - { - this.Delete(); - return; - } + ResistBasePhys = reader.ReadInt(); + ResistBaseFire = reader.ReadInt(); + ResistBaseCold = reader.ReadInt(); + ResistBasePoison = reader.ReadInt(); + ResistBaseEnergy = reader.ReadInt(); } + } - public override void OnDamage(int amount, Mobile from, bool willKill) - { - base.OnDamage(amount, from, willKill); - - if (this.m_Parent != null && !this.m_Parent.Deleted) - { - this.m_Parent.Damage(amount, from, willKill); - } - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (this.m_Parent != null && !this.m_Parent.Deleted) - { - this.m_Parent.Destroy(); - } - } + public class TestDamageableItem : DamageableItem + { + [Constructable] + public TestDamageableItem(int itemid) + : base(itemid, itemid) + { + Name = "Test Damageable Item"; + } - public DamagePlaceholder(Serial serial) + public TestDamageableItem(Serial serial) : base(serial) { } @@ -556,21 +454,13 @@ public DamagePlaceholder(Serial serial) public override void Serialize(GenericWriter writer) { base.Serialize(writer); - writer.Write((int)0); - - writer.Write((Item)this.m_Parent); + writer.Write((int)0); // version } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); - - this.m_Parent = (DamageableItem)reader.ReadItem(); - - Frozen = true; - Paralyzed = true; - CantWalk = true; } - } + } } \ No newline at end of file diff --git a/Scripts/Items/Equipment/Weapons/BaseAxe.cs b/Scripts/Items/Equipment/Weapons/BaseAxe.cs index f840a89df3..7c875a7d9a 100644 --- a/Scripts/Items/Equipment/Weapons/BaseAxe.cs +++ b/Scripts/Items/Equipment/Weapons/BaseAxe.cs @@ -192,18 +192,18 @@ public override void Deserialize(GenericReader reader) } } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable defender, double damageBonus) { base.OnHit(attacker, defender, damageBonus); - if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && this.Layer == Layer.TwoHanded && (attacker.Skills[SkillName.Anatomy].Value / 400.0) >= Utility.RandomDouble() && Engines.ConPVP.DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) + if (!Core.AOS && defender is Mobile && (attacker.Player || attacker.Body.IsHuman) && this.Layer == Layer.TwoHanded && (attacker.Skills[SkillName.Anatomy].Value / 400.0) >= Utility.RandomDouble() && Engines.ConPVP.DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) { - StatMod mod = defender.GetStatMod("Concussion"); + StatMod mod = ((Mobile)defender).GetStatMod("Concussion"); if (mod == null) { - defender.SendMessage("You receive a concussion blow!"); - defender.AddStatMod(new StatMod(StatType.Int, "Concussion", -(defender.RawInt / 2), TimeSpan.FromSeconds(30.0))); + ((Mobile)defender).SendMessage("You receive a concussion blow!"); + ((Mobile)defender).AddStatMod(new StatMod(StatType.Int, "Concussion", -(((Mobile)defender).RawInt / 2), TimeSpan.FromSeconds(30.0))); attacker.SendMessage("You deliver a concussion blow!"); attacker.PlaySound(0x308); diff --git a/Scripts/Items/Equipment/Weapons/BaseBashing.cs b/Scripts/Items/Equipment/Weapons/BaseBashing.cs index be25144a8b..f08d907eae 100644 --- a/Scripts/Items/Equipment/Weapons/BaseBashing.cs +++ b/Scripts/Items/Equipment/Weapons/BaseBashing.cs @@ -63,11 +63,12 @@ public override void Deserialize(GenericReader reader) int version = reader.ReadInt(); } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable defender, double damageBonus) { base.OnHit(attacker, defender, damageBonus); - defender.Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss + if(defender is Mobile) + ((Mobile)defender).Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss } public override double GetBaseDamage(Mobile attacker) diff --git a/Scripts/Items/Equipment/Weapons/BaseKnife.cs b/Scripts/Items/Equipment/Weapons/BaseKnife.cs index b8953539ed..5a34c714c0 100644 --- a/Scripts/Items/Equipment/Weapons/BaseKnife.cs +++ b/Scripts/Items/Equipment/Weapons/BaseKnife.cs @@ -71,16 +71,16 @@ public override void OnDoubleClick(Mobile from) from.Target = new BladedItemTarget(this); } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable defender, double damageBonus) { base.OnHit(attacker, defender, damageBonus); - if (!Core.AOS && this.Poison != null && this.PoisonCharges > 0) + if (!Core.AOS && defender is Mobile && this.Poison != null && this.PoisonCharges > 0) { --this.PoisonCharges; if (Utility.RandomDouble() >= 0.5) // 50% chance to poison - defender.ApplyPoison(attacker, this.Poison); + ((Mobile)defender).ApplyPoison(attacker, this.Poison); } } } diff --git a/Scripts/Items/Equipment/Weapons/BasePoleArm.cs b/Scripts/Items/Equipment/Weapons/BasePoleArm.cs index b317dc4018..a8cc4d6707 100644 --- a/Scripts/Items/Equipment/Weapons/BasePoleArm.cs +++ b/Scripts/Items/Equipment/Weapons/BasePoleArm.cs @@ -146,18 +146,18 @@ public override void Deserialize(GenericReader reader) } } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable defender, double damageBonus) { base.OnHit(attacker, defender, damageBonus); - if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && this.Layer == Layer.TwoHanded && (attacker.Skills[SkillName.Anatomy].Value / 400.0) >= Utility.RandomDouble() && Engines.ConPVP.DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) + if (!Core.AOS && defender is Mobile && (attacker.Player || attacker.Body.IsHuman) && this.Layer == Layer.TwoHanded && (attacker.Skills[SkillName.Anatomy].Value / 400.0) >= Utility.RandomDouble() && Engines.ConPVP.DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) { - StatMod mod = defender.GetStatMod("Concussion"); + StatMod mod = ((Mobile)defender).GetStatMod("Concussion"); if (mod == null) { - defender.SendMessage("You receive a concussion blow!"); - defender.AddStatMod(new StatMod(StatType.Int, "Concussion", -(defender.RawInt / 2), TimeSpan.FromSeconds(30.0))); + ((Mobile)defender).SendMessage("You receive a concussion blow!"); + ((Mobile)defender).AddStatMod(new StatMod(StatType.Int, "Concussion", -(((Mobile)defender).RawInt / 2), TimeSpan.FromSeconds(30.0))); attacker.SendMessage("You deliver a concussion blow!"); attacker.PlaySound(0x11C); diff --git a/Scripts/Items/Equipment/Weapons/BaseRanged.cs b/Scripts/Items/Equipment/Weapons/BaseRanged.cs index 83fbb268dd..6db0591945 100644 --- a/Scripts/Items/Equipment/Weapons/BaseRanged.cs +++ b/Scripts/Items/Equipment/Weapons/BaseRanged.cs @@ -63,10 +63,8 @@ public BaseRanged(Serial serial) : base(serial) { } - public override TimeSpan OnSwing(Mobile attacker, Mobile defender) + public override TimeSpan OnSwing(Mobile attacker, IDamageable damageable) { - //WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker); - // Make sure we've been standing still for .25/.5/1 second depending on Era if (Core.TickCount - attacker.LastMoveTime >= (Core.SE ? 250 : Core.AOS ? 500 : 1000) || (Core.AOS && WeaponAbility.GetCurrentAbility(attacker) is MovingShot)) @@ -97,20 +95,20 @@ public override TimeSpan OnSwing(Mobile attacker, Mobile defender) } #endregion - if (canSwing && attacker.HarmfulCheck(defender)) + if (canSwing && attacker.HarmfulCheck(damageable)) { attacker.DisruptiveAction(); - attacker.Send(new Swing(0, attacker, defender)); + attacker.Send(new Swing(0, attacker, damageable)); - if (OnFired(attacker, defender)) + if (OnFired(attacker, damageable)) { - if (CheckHit(attacker, defender)) + if (CheckHit(attacker, damageable)) { - OnHit(attacker, defender); + OnHit(attacker, damageable); } else { - OnMiss(attacker, defender); + OnMiss(attacker, damageable); } } } @@ -125,38 +123,38 @@ public override TimeSpan OnSwing(Mobile attacker, Mobile defender) return TimeSpan.FromSeconds(0.25); } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable damageable, double damageBonus) { - if (AmmoType != null && attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) && + if (AmmoType != null && attacker.Player && damageable is Mobile && !((Mobile)damageable).Player && (((Mobile)damageable).Body.IsAnimal || ((Mobile)damageable).Body.IsMonster) && 0.4 >= Utility.RandomDouble()) { - defender.AddToBackpack(Ammo); + ((Mobile)damageable).AddToBackpack(Ammo); } if (Core.ML && m_Velocity > 0) { - int bonus = (int)attacker.GetDistanceToSqrt(defender); + int bonus = (int)attacker.GetDistanceToSqrt(damageable); if (bonus > 0 && m_Velocity > Utility.Random(100)) { - AOS.Damage(defender, attacker, bonus * 3, 100, 0, 0, 0, 0); + AOS.Damage(damageable, attacker, bonus * 3, 100, 0, 0, 0, 0); if (attacker.Player) { attacker.SendLocalizedMessage(1072794); // Your arrow hits its mark with velocity! } - if (defender.Player) + if (damageable is Mobile && ((Mobile)damageable).Player) { - defender.SendLocalizedMessage(1072795); // You have been hit by an arrow with velocity! + ((Mobile)damageable).SendLocalizedMessage(1072795); // You have been hit by an arrow with velocity! } } } - base.OnHit(attacker, defender, damageBonus); + base.OnHit(attacker, damageable, damageBonus); } - public override void OnMiss(Mobile attacker, Mobile defender) + public override void OnMiss(Mobile attacker, IDamageable damageable) { if (attacker.Player && 0.4 >= Utility.RandomDouble()) { @@ -193,16 +191,18 @@ public override void OnMiss(Mobile attacker, Mobile defender) } else { + Point3D loc = damageable.Location; + Ammo.MoveToWorld( - new Point3D(defender.X + Utility.RandomMinMax(-1, 1), defender.Y + Utility.RandomMinMax(-1, 1), defender.Z), - defender.Map); + new Point3D(loc.X + Utility.RandomMinMax(-1, 1), loc.Y + Utility.RandomMinMax(-1, 1), loc.Z), + damageable.Map); } } - base.OnMiss(attacker, defender); + base.OnMiss(attacker, damageable); } - public virtual bool OnFired(Mobile attacker, Mobile defender) + public virtual bool OnFired(Mobile attacker, IDamageable damageable) { WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker); @@ -238,7 +238,7 @@ public virtual bool OnFired(Mobile attacker, Mobile defender) } } - attacker.MovingEffect(defender, EffectID, 18, 1, false, false); + attacker.MovingEffect(damageable, EffectID, 18, 1, false, false); return true; } diff --git a/Scripts/Items/Equipment/Weapons/BaseSpear.cs b/Scripts/Items/Equipment/Weapons/BaseSpear.cs index fe67b23756..3cfb539983 100644 --- a/Scripts/Items/Equipment/Weapons/BaseSpear.cs +++ b/Scripts/Items/Equipment/Weapons/BaseSpear.cs @@ -63,25 +63,25 @@ public override void Deserialize(GenericReader reader) int version = reader.ReadInt(); } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable defender, double damageBonus) { base.OnHit(attacker, defender, damageBonus); - if (!Core.AOS && this.Layer == Layer.TwoHanded && (attacker.Skills[SkillName.Anatomy].Value / 400.0) >= Utility.RandomDouble() && Engines.ConPVP.DuelContext.AllowSpecialAbility(attacker, "Paralyzing Blow", false)) + if (!Core.AOS && defender is Mobile && this.Layer == Layer.TwoHanded && (attacker.Skills[SkillName.Anatomy].Value / 400.0) >= Utility.RandomDouble() && Engines.ConPVP.DuelContext.AllowSpecialAbility(attacker, "Paralyzing Blow", false)) { - defender.SendMessage("You receive a paralyzing blow!"); // Is this not localized? - defender.Freeze(TimeSpan.FromSeconds(2.0)); + ((Mobile)defender).SendMessage("You receive a paralyzing blow!"); // Is this not localized? + ((Mobile)defender).Freeze(TimeSpan.FromSeconds(2.0)); attacker.SendMessage("You deliver a paralyzing blow!"); // Is this not localized? attacker.PlaySound(0x11C); } - if (!Core.AOS && this.Poison != null && this.PoisonCharges > 0) + if (!Core.AOS && defender is Mobile && this.Poison != null && this.PoisonCharges > 0) { --this.PoisonCharges; if (Utility.RandomDouble() >= 0.5) // 50% chance to poison - defender.ApplyPoison(attacker, this.Poison); + ((Mobile)defender).ApplyPoison(attacker, this.Poison); } } } diff --git a/Scripts/Items/Equipment/Weapons/BaseStaff.cs b/Scripts/Items/Equipment/Weapons/BaseStaff.cs index 9dae7e4fd5..6a324be5bd 100644 --- a/Scripts/Items/Equipment/Weapons/BaseStaff.cs +++ b/Scripts/Items/Equipment/Weapons/BaseStaff.cs @@ -63,11 +63,12 @@ public override void Deserialize(GenericReader reader) int version = reader.ReadInt(); } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable defender, double damageBonus) { base.OnHit(attacker, defender, damageBonus); - defender.Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss + if(defender is Mobile) + ((Mobile)defender).Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss } } } \ No newline at end of file diff --git a/Scripts/Items/Equipment/Weapons/BaseSword.cs b/Scripts/Items/Equipment/Weapons/BaseSword.cs index c97be2b8e7..9891255d45 100644 --- a/Scripts/Items/Equipment/Weapons/BaseSword.cs +++ b/Scripts/Items/Equipment/Weapons/BaseSword.cs @@ -57,16 +57,16 @@ public override void OnDoubleClick(Mobile from) from.Target = new BladedItemTarget(this); } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable damageable, double damageBonus) { - base.OnHit(attacker, defender, damageBonus); + base.OnHit(attacker, damageable, damageBonus); - if (!Core.AOS && this.Poison != null && this.PoisonCharges > 0) + if (!Core.AOS && this.Poison != null && this.PoisonCharges > 0 && damageable is Mobile) { --this.PoisonCharges; if (Utility.RandomDouble() >= 0.5) // 50% chance to poison - defender.ApplyPoison(attacker, this.Poison); + ((Mobile)damageable).ApplyPoison(attacker, this.Poison); } } } diff --git a/Scripts/Items/Equipment/Weapons/BaseThrown.cs b/Scripts/Items/Equipment/Weapons/BaseThrown.cs index 4fc2940951..c3b6866147 100644 --- a/Scripts/Items/Equipment/Weapons/BaseThrown.cs +++ b/Scripts/Items/Equipment/Weapons/BaseThrown.cs @@ -97,9 +97,9 @@ public override SkillName AccuracySkill return SkillName.Throwing; } } - public override TimeSpan OnSwing(Mobile attacker, Mobile defender) + public override TimeSpan OnSwing(Mobile attacker, IDamageable damageable) { - TimeSpan ts = base.OnSwing(attacker, defender); + TimeSpan ts = base.OnSwing(attacker, damageable); // time it takes to throw it around including mystic arc if (ts < TimeSpan.FromMilliseconds(1000)) @@ -108,39 +108,37 @@ public override TimeSpan OnSwing(Mobile attacker, Mobile defender) return ts; } - public override bool OnFired(Mobile attacker, Mobile defender) + public override bool OnFired(Mobile attacker, IDamageable damageable) { this.m_Thrower = attacker; - if (!attacker.InRange(defender, 1)) + if (!attacker.InRange(damageable, 1)) { - //Internalize(); this.Visible = false; - attacker.MovingEffect(defender, this.EffectID, 18, 1, false, false, this.Hue, 0); + attacker.MovingEffect(damageable, this.EffectID, 18, 1, false, false, this.Hue, 0); } return true; } - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public override void OnHit(Mobile attacker, IDamageable damageable, double damageBonus) { - this.m_Target = defender; - this.m_KillSave = defender.Location; + this.m_KillSave = damageable.Location; if (!(WeaponAbility.GetCurrentAbility(attacker) is MysticArc)) Timer.DelayCall(TimeSpan.FromMilliseconds(333.0), new TimerCallback(ThrowBack)); - base.OnHit(attacker, defender, damageBonus); + base.OnHit(attacker, damageable, damageBonus); } - public override void OnMiss(Mobile attacker, Mobile defender) + public override void OnMiss(Mobile attacker, IDamageable damageable) { - this.m_Target = defender; + this.m_Target = damageable as Mobile; if (!(WeaponAbility.GetCurrentAbility(attacker) is MysticArc)) Timer.DelayCall(TimeSpan.FromMilliseconds(333.0), new TimerCallback(ThrowBack)); - base.OnMiss(attacker, defender); + base.OnMiss(attacker, damageable); } public virtual void ThrowBack() @@ -157,9 +155,6 @@ public virtual void UnHide() { if (this != null) this.Visible = true; - //if ( m_Thrower != null ) - //if ( !m_Thrower.EquipItem( this ) ) - //MoveToWorld( m_Thrower.Location, m_Thrower.Map ); } public override void Serialize(GenericWriter writer) diff --git a/Scripts/Items/Equipment/Weapons/BaseWeapon.cs b/Scripts/Items/Equipment/Weapons/BaseWeapon.cs index 1f8f6d7492..6f4b650fed 100644 --- a/Scripts/Items/Equipment/Weapons/BaseWeapon.cs +++ b/Scripts/Items/Equipment/Weapons/BaseWeapon.cs @@ -1173,8 +1173,18 @@ public static bool CheckAnimal(Mobile m, Type type) return AnimalForm.UnderTransformation(m, type); } - public virtual bool CheckHit(Mobile attacker, Mobile defender) + public virtual bool CheckHit(Mobile attacker, IDamageable damageable) { + Mobile defender = damageable as Mobile; + + if (defender == null) + { + if (damageable is IDamageableItem) + return ((IDamageableItem)damageable).CheckHit(attacker); + + return true; + } + BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon; BaseWeapon defWeapon = defender.Weapon as BaseWeapon; @@ -1392,8 +1402,10 @@ public virtual TimeSpan GetDelay(Mobile m) return TimeSpan.FromSeconds(delayInSeconds); } - public virtual void OnBeforeSwing(Mobile attacker, Mobile defender) + public virtual void OnBeforeSwing(Mobile attacker, IDamageable damageable) { + Mobile defender = damageable as Mobile; + WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker); if (a != null && !a.OnBeforeSwing(attacker, defender)) @@ -1409,12 +1421,12 @@ public virtual void OnBeforeSwing(Mobile attacker, Mobile defender) } } - public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender) + public virtual TimeSpan OnSwing(Mobile attacker, IDamageable damageable) { - return OnSwing(attacker, defender, 1.0); + return OnSwing(attacker, damageable, 1.0); } - public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus) + public virtual TimeSpan OnSwing(Mobile attacker, IDamageable damageable, double damageBonus) { bool canSwing = true; @@ -1449,13 +1461,13 @@ public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageB } #endregion - if (canSwing && attacker.HarmfulCheck(defender)) + if (canSwing && attacker.HarmfulCheck(damageable)) { attacker.DisruptiveAction(); if (attacker.NetState != null) { - attacker.Send(new Swing(0, attacker, defender)); + attacker.Send(new Swing(0, attacker, damageable)); } if (attacker is BaseCreature) @@ -1476,13 +1488,13 @@ public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageB } } - if (CheckHit(attacker, defender)) + if (CheckHit(attacker, damageable)) { - OnHit(attacker, defender, damageBonus); + OnHit(attacker, damageable, damageBonus); } else { - OnMiss(attacker, defender); + OnMiss(attacker, damageable); } } @@ -1898,14 +1910,16 @@ public virtual int GetPackInstinctBonus(Mobile attacker, Mobile defender) public static bool InDoubleStrike { get { return m_InDoubleStrike; } set { m_InDoubleStrike = value; } } - public void OnHit(Mobile attacker, Mobile defender) + public void OnHit(Mobile attacker, IDamageable damageable) { - OnHit(attacker, defender, 1.0); + OnHit(attacker, damageable, 1.0); } - public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus) + public virtual void OnHit(Mobile attacker, IDamageable damageable, double damageBonus) { - if (MirrorImage.HasClone(defender) && (defender.Skills.Ninjitsu.Value / 150.0) > Utility.RandomDouble()) + Mobile defender = damageable as Mobile; + + if (defender != null && MirrorImage.HasClone(defender) && (defender.Skills.Ninjitsu.Value / 150.0) > Utility.RandomDouble()) { Clone bc; @@ -1931,13 +1945,144 @@ public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus) } PlaySwingAnimation(attacker); - PlayHurtAnimation(defender); + + if(defender != null) + PlayHurtAnimation(defender); attacker.PlaySound(GetHitAttackSound(attacker, defender)); - defender.PlaySound(GetHitDefendSound(attacker, defender)); + + if(defender != null) + defender.PlaySound(GetHitDefendSound(attacker, defender)); int damage = ComputeDamage(attacker, defender); + 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 = damageable.PhysicalResistance; + fire = damageable.FireResistance; + cold = damageable.ColdResistance; + pois = damageable.PoisonResistance; + nrgy = damageable.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 = chaos = direct = 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; + } + } + + bool splintering = false; + if (m_AosWeaponAttributes.SplinteringWeapon > 0 && m_AosWeaponAttributes.SplinteringWeapon > Utility.Random(100)) + { + if (SplinteringWeaponContext.CheckHit(attacker, defender, this)) + splintering = true; + } + + if (m_MaxHits > 0 && + ((MaxRange <= 1 && (defender is Slime || defender is ToxicElemental || defender is CorrosiveSlime)) || (defender != null && splintering) || + Utility.Random(250) == 0)) // Stratics says 50% chance, seems more like 4%.. + { + if (MaxRange <= 1 && (defender is Slime || defender is ToxicElemental || defender is CorrosiveSlime)) + { + attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!* + } + + if (Core.AOS && + m_AosWeaponAttributes.SelfRepair + (IsSetItem && m_SetEquipped ? m_SetSelfRepair : 0) > Utility.Random(10)) + { + HitPoints += 2; + } + else + { + if (m_Hits > 0) + { + HitPoints -= NegativeAttributes.Antique > 0 ? 2 : 1; + } + else if (m_MaxHits > 1) + { + MaxHitPoints -= NegativeAttributes.Antique > 0 ? 2 : 1; + + if (Parent is Mobile) + { + ((Mobile)Parent).LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061121); + // Your equipment is severely damaged. + } + } + else + { + Delete(); + } + } + } + + WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker); + SpecialMove move = SpecialMove.GetCurrentMove(attacker); + + bool ignoreArmor = (a is ArmorIgnore || (move != null && move.IgnoreArmor(attacker))); + + // object is not a mobile, so we end here + if (defender == null) + { + AOS.Damage(damageable, attacker, damage, ignoreArmor, phys, fire, cold, pois, nrgy, chaos, direct, false, this is BaseRanged, false); + + // TODO: WeaponAbility/SpecialMove OnHit(...) convert target to IDamageable + // Figure out which specials work on items. For now AI only. + if (ignoreArmor) + { + Effects.PlaySound(damageable.Location, damageable.Map, 0x56); + Effects.SendTargetParticles(damageable, 0x3728, 200, 25, 0, 0, 9942, EffectLayer.Waist, 0); + } + + WeaponAbility.ClearCurrentAbility(attacker); + SpecialMove.ClearCurrentMove(attacker); + + return; + } + #region Damage Multipliers /* * The following damage bonuses multiply damage by a factor. @@ -1945,9 +2090,6 @@ public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus) */ int percentageBonus = 0; - WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker); - SpecialMove move = SpecialMove.GetCurrentMove(attacker); - if (a != null) { percentageBonus += (int)(a.DamageScalar * 100) - 100; @@ -2176,21 +2318,10 @@ public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus) attacker.Mana--; } } - - bool splintering = false; - if (m_AosWeaponAttributes.SplinteringWeapon > 0 && m_AosWeaponAttributes.SplinteringWeapon > Utility.Random(100)) - { - if (SplinteringWeaponContext.CheckHit(attacker, defender, this)) - splintering = true; - } #endregion AddBlood(attacker, defender, damage); - 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 (Core.ML && this is BaseRanged) { BaseQuiver quiver = attacker.FindItemOnLayer(Layer.Cloak) as BaseQuiver; @@ -2201,61 +2332,6 @@ public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus) } } - 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 = chaos = direct = 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; - } - } - // TODO: Scale damage, alongside the leech effects below, to weapon speed. if (ImmolatingWeaponSpell.IsImmolating(this) && damage > 0) { @@ -2276,8 +2352,6 @@ public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus) move = null; } - bool ignoreArmor = (a is ArmorIgnore || (move != null && move.IgnoreArmor(attacker))); - if (Feint.Registry.ContainsKey(defender) && Feint.Registry[defender].Enemy == attacker) damage -= (int)((double)damage * ((double)Feint.Registry[defender].DamageReduction / 100)); @@ -2412,43 +2486,6 @@ public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus) } } - if (m_MaxHits > 0 && - ((MaxRange <= 1 && (defender is Slime || defender is ToxicElemental || defender is CorrosiveSlime)) || splintering || - Utility.Random(250) == 0)) // Stratics says 50% chance, seems more like 4%.. - { - if (MaxRange <= 1 && (defender is Slime || defender is ToxicElemental || defender is CorrosiveSlime)) - { - attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!* - } - - if (Core.AOS && - m_AosWeaponAttributes.SelfRepair + (IsSetItem && m_SetEquipped ? m_SetSelfRepair : 0) > Utility.Random(10)) - { - HitPoints += 2; - } - else - { - if (m_Hits > 0) - { - HitPoints -= NegativeAttributes.Antique > 0 ? 2 : 1; - } - else if (m_MaxHits > 1) - { - MaxHitPoints -= NegativeAttributes.Antique > 0 ? 2 : 1; - - 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; @@ -2938,7 +2975,7 @@ public virtual CheckSlayerResult CheckSlayers(Mobile attacker, Mobile defender, public virtual void AddBlood(Mobile attacker, Mobile defender, int damage) { - if (damage > 0 && !(defender is DamagePlaceholder)) + if (damage > 0) { new Blood().MoveToWorld(defender.Location, defender.Map); @@ -3031,11 +3068,15 @@ private int ApplyCraftAttributeElementDamage(int attrDamage, ref int element, in return totalRemaining - appliedDamage; } - public virtual void OnMiss(Mobile attacker, Mobile defender) + public virtual void OnMiss(Mobile attacker, IDamageable damageable) { + Mobile defender = damageable as Mobile; + PlaySwingAnimation(attacker); attacker.PlaySound(GetMissAttackSound(attacker, defender)); - defender.PlaySound(GetMissDefendSound(attacker, defender)); + + if(defender != null) + defender.PlaySound(GetMissDefendSound(attacker, defender)); WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker); diff --git a/Scripts/Items/Equipment/Weapons/Fists.cs b/Scripts/Items/Equipment/Weapons/Fists.cs index c28bef4c11..13b56b54ea 100644 --- a/Scripts/Items/Equipment/Weapons/Fists.cs +++ b/Scripts/Items/Equipment/Weapons/Fists.cs @@ -259,10 +259,10 @@ private void CheckPreAOSMoves(Mobile attacker, Mobile defender) } } - public override TimeSpan OnSwing(Mobile attacker, Mobile defender) + public override TimeSpan OnSwing(Mobile attacker, IDamageable defender) { - if (!Core.AOS) - this.CheckPreAOSMoves(attacker, defender); + if (!Core.AOS && defender is Mobile) + this.CheckPreAOSMoves(attacker, (Mobile)defender); return base.OnSwing(attacker, defender); } diff --git a/Scripts/Misc/AOS.cs b/Scripts/Misc/AOS.cs index 3a0c84828a..8051a212bc 100644 --- a/Scripts/Misc/AOS.cs +++ b/Scripts/Misc/AOS.cs @@ -32,52 +32,56 @@ public static void DisableStatInfluences() } } - public static int Damage(Mobile m, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy) + public static int Damage(IDamageable m, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy) { return Damage(m, null, damage, ignoreArmor, phys, fire, cold, pois, nrgy); } - public static int Damage(Mobile m, int damage, int phys, int fire, int cold, int pois, int nrgy) + public static int Damage(IDamageable m, int damage, int phys, int fire, int cold, int pois, int nrgy) { return Damage(m, null, damage, phys, fire, cold, pois, nrgy); } - public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy) + public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy) { return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, false, false, false); } - public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos) + public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos) { return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, 0, false, false, false); } - public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct) + public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct) { return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, false, false, false); } - public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy) + public static int Damage(IDamageable m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy) { return Damage(m, from, damage, ignoreArmor, phys, fire, cold, pois, nrgy, 0, 0, false, false, false); } - public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, bool keepAlive) + public static int Damage(IDamageable m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, bool keepAlive) { return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, keepAlive, false, false); } - public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, bool keepAlive, bool archer, bool deathStrike) + public static int Damage(IDamageable damageable, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, bool keepAlive, bool archer, bool deathStrike) { - if (m == null || m.Deleted || !m.Alive || damage <= 0) + Mobile m = damageable as Mobile; + + if (damageable == null || damageable.Deleted || !damageable.Alive || damage <= 0) return 0; - if (phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0) + if (m != null && phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0) Mobiles.MeerMage.StopEffect(m, true); if (!Core.AOS) { - m.Damage(damage, from); + if(m != null) + m.Damage(damage, from); + return damage; } @@ -120,24 +124,15 @@ public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, in if (!ignoreArmor) { - // Armor Ignore on OSI ignores all defenses, not just physical. - int resPhys = m.PhysicalResistance; - - #region SA - int physDamage = damage * phys * (100 - m.PhysicalResistance); - int fireDamage = damage * fire * (100 - m.FireResistance); - int coldDamage = damage * cold * (100 - m.ColdResistance); - int poisonDamage = damage * pois * (100 - m.PoisonResistance); - int energyDamage = damage * nrgy * (100 - m.EnergyResistance); - - int[] amounts = new int[] { physDamage, fireDamage, coldDamage, poisonDamage, energyDamage }; + int physDamage = damage * phys * (100 - damageable.PhysicalResistance); + int fireDamage = damage * fire * (100 - damageable.FireResistance); + int coldDamage = damage * cold * (100 - damageable.ColdResistance); + int poisonDamage = damage * pois * (100 - damageable.PoisonResistance); + int energyDamage = damage * nrgy * (100 - damageable.EnergyResistance); totalDamage = physDamage + fireDamage + coldDamage + poisonDamage + energyDamage; totalDamage /= 10000; - - #endregion - if (Core.ML) { totalDamage += damage * direct / 100; @@ -146,7 +141,8 @@ public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, in totalDamage += totalDamage * quiver.DamageIncrease / 100; } - BaseFishPie.ScaleDamage(m, ref totalDamage, phys, fire, cold, pois, nrgy, direct); + if (m != null) + BaseFishPie.ScaleDamage(m, ref totalDamage, phys, fire, cold, pois, nrgy, direct); if (totalDamage < 1) totalDamage = 1; @@ -169,6 +165,13 @@ public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, in totalDamage += totalDamage * quiver.DamageIncrease / 100; } + // object being damaged is not a mobile, so we will end here + if (m == null) + { + damageable.Damage(totalDamage, from); + return totalDamage; + } + #region Evil Omen and Blood Oath if (EvilOmenSpell.TryEndEffect(m)) { diff --git a/Scripts/Misc/LootPack.cs b/Scripts/Misc/LootPack.cs index 8bbab7010e..b5c56e3f04 100644 --- a/Scripts/Misc/LootPack.cs +++ b/Scripts/Misc/LootPack.cs @@ -22,11 +22,7 @@ public static int GetLuckChance(Mobile killer, Mobile victim) return 0; } - int luck = killer.Luck; - - luck += FountainOfFortune.GetLuckBonus(killer); - - luck += TenthAnniversarySculpture.GetLuckBonus(killer); + int luck = killer is PlayerMobile ? ((PlayerMobile)killer).RealLuck : killer.Luck; PlayerMobile pmKiller = killer as PlayerMobile; if (pmKiller != null && pmKiller.SentHonorContext != null && pmKiller.SentHonorContext.Target == victim) diff --git a/Scripts/Misc/Notoriety.cs b/Scripts/Misc/Notoriety.cs index 6e413daaa3..1304bcc26b 100644 --- a/Scripts/Misc/Notoriety.cs +++ b/Scripts/Misc/Notoriety.cs @@ -163,8 +163,10 @@ public static bool Mobile_AllowBeneficial(Mobile from, Mobile target) return CheckBeneficialStatus(GetGuildStatus(from), GetGuildStatus(target)); } - public static bool Mobile_AllowHarmful(Mobile from, Mobile target) + public static bool Mobile_AllowHarmful(Mobile from, IDamageable damageable) { + Mobile target = damageable as Mobile; + if (from == null || target == null || from.IsStaff() || target.IsStaff()) return true; @@ -398,8 +400,13 @@ public static int CorpseNotoriety(Mobile source, Corpse target) } } - public static int MobileNotoriety(Mobile source, Mobile target) + public static int MobileNotoriety(Mobile source, IDamageable damagable) { + Mobile target = damagable as Mobile; + + if (target == null) + return Notoriety.CanBeAttacked; + if (Core.AOS && (target.Blessed || (target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier)) return Notoriety.Invulnerable; diff --git a/Scripts/Mobiles/AI/AIControlMobileTarget.cs b/Scripts/Mobiles/AI/AIControlMobileTarget.cs index 07a0231504..9e8904c005 100644 --- a/Scripts/Mobiles/AI/AIControlMobileTarget.cs +++ b/Scripts/Mobiles/AI/AIControlMobileTarget.cs @@ -38,21 +38,19 @@ public void AddAI(BaseAI ai) protected override void OnTarget(Mobile from, object o) { - if (o is DamageableItem) - o = ((DamageableItem)o).Link; - - if (o is Mobile) + if (o is IDamageable) { - Mobile m = (Mobile)o; + IDamageable dam = o as IDamageable; + for (int i = 0; i < this.m_List.Count; ++i) - this.m_List[i].EndPickTarget(from, m, this.m_Order); + this.m_List[i].EndPickTarget(from, dam, this.m_Order); } - else if ( o is MoonglowDonationBox && m_Order == OrderType.Transfer && from is PlayerMobile ) + else if (o is MoonglowDonationBox && m_Order == OrderType.Transfer && from is PlayerMobile) { - PlayerMobile pm = (PlayerMobile)from; - MoonglowDonationBox box = (MoonglowDonationBox)o; - - pm.SendGump( new ConfirmTransferPetGump( box, from.Location, m_Mobile ) ); + PlayerMobile pm = (PlayerMobile)from; + MoonglowDonationBox box = (MoonglowDonationBox)o; + + pm.SendGump(new ConfirmTransferPetGump(box, from.Location, m_Mobile)); } } } diff --git a/Scripts/Mobiles/AI/AnimalAI.cs b/Scripts/Mobiles/AI/AnimalAI.cs index 313dcf9831..374808f239 100644 --- a/Scripts/Mobiles/AI/AnimalAI.cs +++ b/Scripts/Mobiles/AI/AnimalAI.cs @@ -64,7 +64,7 @@ public override bool DoActionWander() public override bool DoActionCombat() { - Mobile combatant = this.m_Mobile.Combatant; + IDamageable combatant = this.m_Mobile.Combatant; if (combatant == null || combatant.Deleted || combatant.Map != this.m_Mobile.Map) { @@ -144,7 +144,7 @@ public override bool DoActionFlee() this.AcquireFocusMob(this.m_Mobile.RangePerception * 2, this.m_Mobile.FightMode, true, false, true); if (this.m_Mobile.FocusMob == null) - this.m_Mobile.FocusMob = this.m_Mobile.Combatant; + this.m_Mobile.FocusMob = this.m_Mobile.Combatant as Mobile; return base.DoActionFlee(); } diff --git a/Scripts/Mobiles/AI/ArcherAI.cs b/Scripts/Mobiles/AI/ArcherAI.cs index ec8c742e58..f4b31f530d 100644 --- a/Scripts/Mobiles/AI/ArcherAI.cs +++ b/Scripts/Mobiles/AI/ArcherAI.cs @@ -40,8 +40,8 @@ public override bool DoActionWander() public override bool DoActionCombat() { - if (m_Mobile.Combatant == null || m_Mobile.Combatant.Deleted || !m_Mobile.Combatant.Alive || - m_Mobile.Combatant.IsDeadBondedPet) + if (m_Mobile.Combatant == null || m_Mobile.Combatant.Deleted || + !m_Mobile.Combatant.Alive || (m_Mobile.Combatant is Mobile && ((Mobile)m_Mobile.Combatant).IsDeadBondedPet)) { m_Mobile.DebugSay("My combatant is deleted"); Action = ActionType.Guard; diff --git a/Scripts/Mobiles/AI/BaseAI.cs b/Scripts/Mobiles/AI/BaseAI.cs index 6ae4d7d05e..d3eadb00ff 100644 --- a/Scripts/Mobiles/AI/BaseAI.cs +++ b/Scripts/Mobiles/AI/BaseAI.cs @@ -299,7 +299,7 @@ public virtual void BeginPickTarget(Mobile from, OrderType order) public virtual void OnAggressiveAction(Mobile aggressor) { - Mobile currentCombat = m_Mobile.Combatant; + Mobile currentCombat = m_Mobile.Combatant as Mobile; if (currentCombat != null && !aggressor.Hidden && currentCombat != aggressor && m_Mobile.GetDistanceToSqrt(currentCombat) > m_Mobile.GetDistanceToSqrt(aggressor)) @@ -308,7 +308,7 @@ public virtual void OnAggressiveAction(Mobile aggressor) } } - public virtual void EndPickTarget(Mobile from, Mobile target, OrderType order) + public virtual void EndPickTarget(Mobile from, IDamageable target, OrderType order) { if (m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange(m_Mobile, 14) || from.Map != m_Mobile.Map || !from.CheckAlive()) @@ -996,8 +996,8 @@ public virtual bool DoActionWander() } } - if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) + if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && + m_Mobile.Combatant.Alive && (!(m_Mobile.Combatant is Mobile) || !((Mobile)m_Mobile.Combatant).IsDeadBondedPet)) { m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); } @@ -1013,9 +1013,9 @@ public virtual bool DoActionCombat() } else { - Mobile c = m_Mobile.Combatant; + IDamageable c = m_Mobile.Combatant; - if (c == null || c.Deleted || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet) + if (c == null || c.Deleted || c.Map != m_Mobile.Map || !c.Alive || (c is Mobile && ((Mobile)c).IsDeadBondedPet)) { Action = ActionType.Wander; } @@ -1050,7 +1050,7 @@ public virtual bool DoActionGuard() public virtual bool DoActionFlee() { - Mobile from = m_Mobile.FocusMob; + Mobile from = m_Mobile.FocusMob as Mobile; if (from == null || from.Deleted || from.Map != m_Mobile.Map) { @@ -1243,8 +1243,8 @@ public virtual bool DoOrderNone() WalkRandomInHome(3, 2, 1); - if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) + if (m_Mobile.Combatant is Mobile && !m_Mobile.Combatant.Deleted && + m_Mobile.Combatant.Alive && (!(m_Mobile.Combatant is Mobile) || !((Mobile)m_Mobile.Combatant).IsDeadBondedPet)) { m_Mobile.Warmode = true; m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); @@ -1278,8 +1278,8 @@ public virtual bool DoOrderCome() if (WalkMobileRange(m_Mobile.ControlMaster, 1, bRun, 0, 1)) { - if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) + if (m_Mobile.Combatant is Mobile && !m_Mobile.Combatant.Deleted && + m_Mobile.Combatant.Alive && (!(m_Mobile.Combatant is Mobile) || !((Mobile)m_Mobile.Combatant).IsDeadBondedPet)) { m_Mobile.Warmode = true; m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); @@ -1395,8 +1395,8 @@ public virtual bool DoOrderFollow() { m_Mobile.DebugSay("I have lost the one to follow. I stay here"); - if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) + if (m_Mobile.Combatant is Mobile && !m_Mobile.Combatant.Deleted && + m_Mobile.Combatant.Alive && (!(m_Mobile.Combatant is Mobile) || !((Mobile)m_Mobile.Combatant).IsDeadBondedPet)) { m_Mobile.Warmode = true; m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); @@ -1415,8 +1415,8 @@ public virtual bool DoOrderFollow() if (WalkMobileRange(m_Mobile.ControlTarget, 1, bRun, 0, 1)) { - if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) + if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && + m_Mobile.Combatant.Alive && (!(m_Mobile.Combatant is Mobile) || !((Mobile)m_Mobile.Combatant).IsDeadBondedPet)) { m_Mobile.Warmode = true; m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); @@ -1445,7 +1445,7 @@ public virtual bool DoOrderFollow() public virtual bool DoOrderFriend() { Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; + Mobile to = m_Mobile.ControlTarget as Mobile; if (from == null || to == null || from == to || from.Deleted || to.Deleted || !to.Player) { @@ -1516,7 +1516,7 @@ public virtual bool DoOrderFriend() public virtual bool DoOrderUnfriend() { Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; + Mobile to = m_Mobile.ControlTarget as Mobile; if (from == null || to == null || from == to || from.Deleted || to.Deleted || !to.Player) { @@ -1559,7 +1559,7 @@ public virtual bool DoOrderGuard() return true; } - Mobile combatant = m_Mobile.Combatant; + Mobile combatant = m_Mobile.Combatant as Mobile; var aggressors = controlMaster.Aggressors; @@ -1586,7 +1586,7 @@ public virtual bool DoOrderGuard() } if (combatant != null && combatant != m_Mobile && combatant != m_Mobile.ControlMaster && !combatant.Deleted && - combatant.Alive && !combatant.IsDeadBondedPet && m_Mobile.CanSee(combatant) && + combatant.Alive && (!(combatant is Mobile) || !((Mobile)combatant).IsDeadBondedPet) && m_Mobile.CanBeHarmful(combatant, false) && combatant.Map == m_Mobile.Map) { m_Mobile.DebugSay("Guarding from target..."); @@ -1625,7 +1625,7 @@ public virtual bool DoOrderAttack() } if (m_Mobile.ControlTarget == null || m_Mobile.ControlTarget.Deleted || m_Mobile.ControlTarget.Map != m_Mobile.Map || - !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet) + !m_Mobile.ControlTarget.Alive || (m_Mobile.ControlTarget is Mobile && ((Mobile)m_Mobile.ControlTarget).IsDeadBondedPet)) { m_Mobile.DebugSay( "I think he might be dead. He's not anywhere around here at least. That's cool. I'm glad he's dead."); @@ -1950,7 +1950,7 @@ public virtual bool DoOrderTransfer() } Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; + Mobile to = m_Mobile.ControlTarget as Mobile; if (from != to && from != null && !from.Deleted && to != null && !to.Deleted && to.Player) { @@ -2252,7 +2252,7 @@ public virtual bool DoMove(Direction d, bool badStateOk) public virtual MoveResult DoMoveImpl(Direction d) { - if (m_Mobile.Deleted || m_Mobile.Frozen || m_Mobile.Paralyzed || (m_Mobile.Spell != null && m_Mobile.Spell.IsCasting) || + if (m_Mobile.Deleted || m_Mobile.Frozen || m_Mobile.Paralyzed || (m_Mobile.Spell != null && m_Mobile.Spell.IsCasting && m_Mobile.FreezeOnCast) || m_Mobile.DisallowAllMoves) { return MoveResult.BadState; @@ -2509,7 +2509,7 @@ public virtual bool CheckFlee() { if (m_Mobile.CheckFlee()) { - Mobile combatant = m_Mobile.Combatant; + Mobile combatant = m_Mobile.Combatant as Mobile; if (combatant == null) { @@ -2542,20 +2542,20 @@ public virtual void OnTeleported() } } - public virtual bool MoveTo(Mobile m, bool run, int range) + public virtual bool MoveTo(IPoint3D p, bool run, int range) { - if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves || m == null || m.Deleted) + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves || p == null || (p is IDamageable && ((IDamageable)p).Deleted)) { return false; } - if (m_Mobile.InRange(m, range)) + if (m_Mobile.InRange(p, range)) { m_Path = null; return true; } - if (m_Path != null && m_Path.Goal == m) + if (m_Path != null && m_Path.Goal == p) { if (m_Path.Follow(run, 1)) { @@ -2563,9 +2563,9 @@ public virtual bool MoveTo(Mobile m, bool run, int range) return true; } } - else if (!DoMove(m_Mobile.GetDirectionTo(m), true)) + else if (!DoMove(m_Mobile.GetDirectionTo(p), true)) { - m_Path = new PathFollower(m_Mobile, m); + m_Path = new PathFollower(m_Mobile, p); m_Path.Mover = DoMoveImpl; if (m_Path.Follow(run, 1)) @@ -2593,26 +2593,26 @@ public virtual bool MoveTo(Mobile m, bool run, int range) * */ - public virtual bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax) + public virtual bool WalkMobileRange(IPoint3D p, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax) { if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) { return false; } - if (m != null) + if (p != null) { for (int i = 0; i < iSteps; i++) { // Get the curent distance - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m); + int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(p); if (iCurrDist < iWantDistMin || iCurrDist > iWantDistMax) { bool needCloser = (iCurrDist > iWantDistMax); bool needFurther = !needCloser; - if (needCloser && m_Path != null && m_Path.Goal == m) + if (needCloser && m_Path != null && m_Path.Goal == p) { if (m_Path.Follow(bRun, 1)) { @@ -2625,11 +2625,11 @@ public virtual bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDi if (iCurrDist > iWantDistMax) { - dirTo = m_Mobile.GetDirectionTo(m); + dirTo = m_Mobile.GetDirectionTo(p); } else { - dirTo = m.GetDirectionTo(m_Mobile); + dirTo = Utility.GetDirection(p, m_Mobile); } // Add the run flag @@ -2640,7 +2640,7 @@ public virtual bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDi if (!DoMove(dirTo, true) && needCloser) { - m_Path = new PathFollower(m_Mobile, m); + m_Path = new PathFollower(m_Mobile, p); m_Path.Mover = DoMoveImpl; if (m_Path.Follow(bRun, 1)) @@ -2661,7 +2661,7 @@ public virtual bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDi } // Get the curent distance - int iNewDist = (int)m_Mobile.GetDistanceToSqrt(m); + int iNewDist = (int)m_Mobile.GetDistanceToSqrt(p); if (iNewDist >= iWantDistMin && iNewDist <= iWantDistMax) { @@ -2709,8 +2709,8 @@ public virtual bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayerO } else if (m_Mobile.Controlled) { - if (m_Mobile.ControlTarget == null || m_Mobile.ControlTarget.Deleted || m_Mobile.ControlTarget.Hidden || - !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet || + if (m_Mobile.ControlTarget == null || m_Mobile.ControlTarget.Deleted || (m_Mobile.ControlTarget is Mobile && ((Mobile)m_Mobile.ControlTarget).Hidden) || + !m_Mobile.ControlTarget.Alive || (m_Mobile.ControlTarget is Mobile && ((Mobile)m_Mobile.ControlTarget).IsDeadBondedPet) || !m_Mobile.InRange(m_Mobile.ControlTarget, m_Mobile.RangePerception * 2)) { if (m_Mobile.ControlTarget != null && m_Mobile.ControlTarget != m_Mobile.ControlMaster) @@ -3185,4 +3185,4 @@ protected override void OnTick() } } } -} +} \ No newline at end of file diff --git a/Scripts/Mobiles/AI/MageAI.cs b/Scripts/Mobiles/AI/MageAI.cs index 3aeb15cbce..e36c4ca481 100644 --- a/Scripts/Mobiles/AI/MageAI.cs +++ b/Scripts/Mobiles/AI/MageAI.cs @@ -129,40 +129,40 @@ public override bool DoActionWander() return true; } - public void RunTo(Mobile m) + public void RunTo(IDamageable d) { if (!this.SmartAI) { - if (!this.MoveTo(m, true, this.m_Mobile.RangeFight)) + if (!this.MoveTo(d, true, this.m_Mobile.RangeFight)) this.OnFailedMove(); return; } - if (m.Paralyzed || m.Frozen) + if (d is Mobile && (((Mobile)d).Paralyzed || ((Mobile)d).Frozen)) { - if (this.m_Mobile.InRange(m, 1)) - this.RunFrom(m); - else if (!this.m_Mobile.InRange(m, this.m_Mobile.RangeFight > 2 ? this.m_Mobile.RangeFight : 2) && !this.MoveTo(m, true, 1)) + if (this.m_Mobile.InRange(d, 1)) + this.RunFrom(d); + else if (!this.m_Mobile.InRange(d, this.m_Mobile.RangeFight > 2 ? this.m_Mobile.RangeFight : 2) && !this.MoveTo(d, true, 1)) this.OnFailedMove(); } else { - if (!this.m_Mobile.InRange(m, this.m_Mobile.RangeFight)) + if (!this.m_Mobile.InRange(d, this.m_Mobile.RangeFight)) { - if (!this.MoveTo(m, true, 1)) + if (!this.MoveTo(d, true, 1)) this.OnFailedMove(); } - else if (this.m_Mobile.InRange(m, this.m_Mobile.RangeFight - 1)) + else if (this.m_Mobile.InRange(d, this.m_Mobile.RangeFight - 1)) { - this.RunFrom(m); + this.RunFrom(d); } } } - public void RunFrom(Mobile m) + public void RunFrom(IDamageable d) { - this.Run((Direction)((int)this.m_Mobile.GetDirectionTo(m) - 4) & Direction.Mask); + this.Run((Direction)((int)this.m_Mobile.GetDirectionTo(d) - 4) & Direction.Mask); } public void OnFailedMove() @@ -311,8 +311,15 @@ public virtual Spell DoDispel(Mobile toDispel) return spell; } - public virtual Spell ChooseSpell(Mobile c) + public virtual Spell ChooseSpell(IDamageable d) { + if (!(d is Mobile)) + { + m_Mobile.DebugSay("Just doing damage"); + return GetRandomDamageSpell(); + } + + Mobile c = d as Mobile; Spell spell = null; if (!this.SmartAI) @@ -407,9 +414,6 @@ public virtual Spell ChooseSpell(Mobile c) if (spell != null) return spell; - if (spell != null) - return spell; - switch( Utility.Random(3) ) { case 0: // Poison them @@ -586,13 +590,13 @@ protected TimeSpan GetDelay() public override bool DoActionCombat() { - Mobile c = this.m_Mobile.Combatant; - this.m_Mobile.Warmode = true; + IDamageable c = this.m_Mobile.Combatant; + m_Mobile.Warmode = true; if (m_Mobile.Target != null) ProcessTarget(); - if (c == null || c.Deleted || !c.Alive || c.IsDeadBondedPet || !this.m_Mobile.CanSee(c) || !this.m_Mobile.CanBeHarmful(c, false) || c.Map != this.m_Mobile.Map) + if (c == null || c.Deleted || !c.Alive || (c is Mobile && ((Mobile)c).IsDeadBondedPet) || !this.m_Mobile.CanSee(c) || !this.m_Mobile.CanBeHarmful(c, false) || c.Map != this.m_Mobile.Map) { // Our combatant is deleted, dead, hidden, or we cannot hurt them // Try to find another combatant @@ -639,7 +643,7 @@ public override bool DoActionCombat() this.m_Mobile.Combatant = null; } - c = this.m_Mobile.Combatant; + c = this.m_Mobile.Combatant as Mobile; if (c == null) { @@ -697,11 +701,11 @@ public override bool DoActionCombat() spell = this.DoDispel(toDispel); } - else if (this.SmartAI && this.m_Combo != -1) // We are doing a spell combo + else if (c is Mobile && this.SmartAI && this.m_Combo != -1) // We are doing a spell combo { - spell = this.DoCombo(c); + spell = this.DoCombo((Mobile)c); } - else if (this.SmartAI && (c.Spell is HealSpell || c.Spell is GreaterHealSpell) && !c.Poisoned) // They have a heal spell out + else if (c is Mobile && this.SmartAI && (((Mobile)c).Spell is HealSpell || ((Mobile)c).Spell is GreaterHealSpell) && !((Mobile)c).Poisoned) // They have a heal spell out { spell = new PoisonSpell(this.m_Mobile, null); } @@ -716,17 +720,19 @@ public override bool DoActionCombat() TimeSpan ts = !SmartAI && !(spell is DispelSpell) ? TimeSpan.FromSeconds(1.5) : m_Combo > -1 ? TimeSpan.FromSeconds(.5) : TimeSpan.FromSeconds(1.5); TimeSpan delay = spell == null ? TimeSpan.FromSeconds(m_Mobile.ActiveSpeed) : spell.GetCastDelay() + spell.GetCastRecovery() + ts; + RunTo(c); + if (spell != null) spell.Cast(); this.m_NextCastTime = DateTime.UtcNow + delay; } - else if (this.m_Mobile.Spell == null || !this.m_Mobile.Spell.IsCasting) + else/* if (this.m_Mobile.Spell == null || !this.m_Mobile.Spell.IsCasting)*/ { this.RunTo(c); } - this.m_LastTarget = c; + this.m_LastTarget = c as Mobile; this.m_LastTargetLoc = c.Location; return true; @@ -783,7 +789,7 @@ public override bool DoActionGuard() public override bool DoActionFlee() { - Mobile c = this.m_Mobile.Combatant; + Mobile c = this.m_Mobile.Combatant as Mobile; if ((this.m_Mobile.Mana > 20 || this.m_Mobile.Mana == this.m_Mobile.ManaMax) && this.m_Mobile.Hits > (this.m_Mobile.HitsMax / 2)) { @@ -824,7 +830,7 @@ public Mobile FindDispelTarget(bool activeOnly) Mobile active = null; double activePrio = 0.0; - Mobile comb = this.m_Mobile.Combatant; + Mobile comb = this.m_Mobile.Combatant as Mobile; if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && this.m_Mobile.InRange(comb, Core.ML ? 10 : 12) && this.CanDispel(comb)) { @@ -886,7 +892,7 @@ public Mobile FindDispelTarget(bool activeOnly) Mobile active = null, inactive = null; double actPrio = 0.0, inactPrio = 0.0; - Mobile comb = this.m_Mobile.Combatant; + Mobile comb = this.m_Mobile.Combatant as Mobile; if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && this.CanDispel(comb)) { @@ -1079,7 +1085,7 @@ protected virtual bool ProcessTarget() if (isTeleport && m_Mobile.CanSwim) targ.Cancel(m_Mobile, TargetCancelType.Canceled); - Mobile toTarget = null; + IDamageable toTarget = null; if (isDispel) { @@ -1103,7 +1109,7 @@ protected virtual bool ProcessTarget() if (toTarget == null) { - toTarget = m_Mobile.Combatant; + toTarget = m_Mobile.Combatant as Mobile; if (toTarget != null) RunTo(toTarget); diff --git a/Scripts/Mobiles/AI/MeleeAI.cs b/Scripts/Mobiles/AI/MeleeAI.cs index 205fae7063..03b3adf24d 100644 --- a/Scripts/Mobiles/AI/MeleeAI.cs +++ b/Scripts/Mobiles/AI/MeleeAI.cs @@ -35,9 +35,9 @@ public override bool DoActionWander() public override bool DoActionCombat() { - Mobile combatant = this.m_Mobile.Combatant; + IDamageable combatant = this.m_Mobile.Combatant; - if (combatant == null || combatant.Deleted || combatant.Map != this.m_Mobile.Map || !combatant.Alive || combatant.IsDeadBondedPet) + if (combatant == null || combatant.Deleted || combatant.Map != this.m_Mobile.Map || !combatant.Alive || (combatant is Mobile && ((Mobile)combatant).IsDeadBondedPet)) { this.m_Mobile.DebugSay("My combatant is gone, so my guard is up"); @@ -70,15 +70,6 @@ public override bool DoActionCombat() } } - /*if ( !m_Mobile.InLOS( combatant ) ) - { - if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) ) - { - m_Mobile.Combatant = combatant = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - }*/ - if (this.MoveTo(combatant, true, this.m_Mobile.RangeFight)) { this.m_Mobile.Direction = this.m_Mobile.GetDirectionTo(combatant); @@ -167,7 +158,7 @@ public override bool DoActionFlee() } else { - this.m_Mobile.FocusMob = this.m_Mobile.Combatant; + this.m_Mobile.FocusMob = this.m_Mobile.Combatant as Mobile; base.DoActionFlee(); } diff --git a/Scripts/Mobiles/AI/NecroMageAI.cs b/Scripts/Mobiles/AI/NecroMageAI.cs index 248df8b1c9..9bec2ffcdb 100644 --- a/Scripts/Mobiles/AI/NecroMageAI.cs +++ b/Scripts/Mobiles/AI/NecroMageAI.cs @@ -130,14 +130,17 @@ public override Spell GetRandomSummonSpell() return new AnimateDeadSpell(m_Mobile, null); } - public override Spell ChooseSpell(Mobile c) + public override Spell ChooseSpell(IDamageable c) { + if (!(c is Mobile)) + return base.ChooseSpell(c); + Spell spell = CheckCastHealingSpell(); if (spell != null) return spell; - double damage = ((m_Mobile.Skills[SkillName.SpiritSpeak].Value - c.Skills[SkillName.MagicResist].Value) / 10) + (c.Player ? 18 : 30); + double damage = ((m_Mobile.Skills[SkillName.SpiritSpeak].Value - ((Mobile)c).Skills[SkillName.MagicResist].Value) / 10) + (c is PlayerMobile ? 18 : 30); if (damage > c.Hits) return new PainSpikeSpell(m_Mobile, null); diff --git a/Scripts/Mobiles/AI/NinjaAI.cs b/Scripts/Mobiles/AI/NinjaAI.cs index 11e345b87a..60923ac8bf 100644 --- a/Scripts/Mobiles/AI/NinjaAI.cs +++ b/Scripts/Mobiles/AI/NinjaAI.cs @@ -89,7 +89,7 @@ public virtual SpecialMove GetSpecialMove() public void DoRangedAttack() { - Mobile c = m_Mobile.Combatant; + Mobile c = m_Mobile.Combatant as Mobile; if(c == null) return; diff --git a/Scripts/Mobiles/AI/Omni AI/OmniAI Bushido.cs b/Scripts/Mobiles/AI/Omni AI/OmniAI Bushido.cs index a399913361..6c02f34f21 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniAI Bushido.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniAI Bushido.cs @@ -46,7 +46,7 @@ public void UseBushidoMove() if (this.m_Mobile.Debug) this.m_Mobile.Say(2117, "Using a samurai or special move strike"); - Mobile comb = this.m_Mobile.Combatant; + Mobile comb = this.m_Mobile.Combatant as Mobile; if (comb == null) return; diff --git a/Scripts/Mobiles/AI/Omni AI/OmniAI Chivalry.cs b/Scripts/Mobiles/AI/Omni AI/OmniAI Chivalry.cs index 1332a1b37a..32dbb83774 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniAI Chivalry.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniAI Chivalry.cs @@ -133,7 +133,7 @@ public bool CheckForRemoveCurse() if (mod != null) return true; - Mobile foe = this.m_Mobile.Combatant; + Mobile foe = this.m_Mobile.Combatant as Mobile; if (foe == null) return false; diff --git a/Scripts/Mobiles/AI/Omni AI/OmniAI Core.cs b/Scripts/Mobiles/AI/Omni AI/OmniAI Core.cs index 06e5b2a4e0..ecd77eb599 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniAI Core.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniAI Core.cs @@ -192,7 +192,7 @@ public override bool DoActionWander() public override bool DoActionCombat() { - Mobile combatant = this.m_Mobile.Combatant; + Mobile combatant = this.m_Mobile.Combatant as Mobile; if (DateTime.UtcNow > this.m_NextPetCommand) { @@ -239,7 +239,7 @@ public override bool DoActionCombat() this.m_Mobile.Combatant = null; } - combatant = this.m_Mobile.Combatant; + combatant = this.m_Mobile.Combatant as Mobile; if (combatant == null) { @@ -419,19 +419,19 @@ public override bool DoActionFlee() this.m_Mobile.PlaySound(0x22F); } - this.m_Mobile.FocusMob = this.m_Mobile.Combatant; + this.m_Mobile.FocusMob = this.m_Mobile.Combatant as Mobile; base.DoActionFlee(); return true; } - public override bool MoveTo(Mobile m, bool run, int range) + public override bool MoveTo(IPoint3D p, bool run, int range) { if (this.m_Mobile.Hidden && !this.m_Mobile.Poisoned && this.m_CanUseNinjitsu) { Server.SkillHandlers.Stealth.OnUse(this.m_Mobile); - if (base.MoveTo(m, false, range) == false) + if (base.MoveTo(p, false, range) == false) { if (this.m_Mobile.Hidden && this.m_Mobile.AllowedStealthSteps >= 1 && this.m_CanUseNinjitsu) { @@ -444,13 +444,13 @@ public override bool MoveTo(Mobile m, bool run, int range) else return true; } - else if (!this.m_Melees && m != null) + else if (!this.m_Melees && p != null) { - if (this.m_Mobile.InRange(m, 2) && this.CheckMove()) + if (this.m_Mobile.InRange(p, 2) && this.CheckMove()) { Direction d = Direction.North; - switch( this.m_Mobile.GetDirectionTo(m) ) + switch( this.m_Mobile.GetDirectionTo(p) ) { case Direction.North: d = Direction.South; @@ -481,23 +481,23 @@ public override bool MoveTo(Mobile m, bool run, int range) return this.DoMove(d, run); // base.DoActionFlee(); } - else if (this.m_Mobile.InRange(m, 4)) + else if (this.m_Mobile.InRange(p, 4)) return true; } - return base.MoveTo(m, run, range); + return base.MoveTo(p, run, range); } - public override bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax) + public override bool WalkMobileRange(IPoint3D p, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax) { if (this.m_Mobile.Hidden && !this.m_Mobile.Poisoned && this.m_CanUseNinjitsu) { Server.SkillHandlers.Stealth.OnUse(this.m_Mobile); - return base.WalkMobileRange(m, iSteps, false, iWantDistMin, iWantDistMax); + return base.WalkMobileRange(p, iSteps, false, iWantDistMin, iWantDistMax); } else - return base.WalkMobileRange(m, iSteps, bRun, iWantDistMin, iWantDistMax); + return base.WalkMobileRange(p, iSteps, bRun, iWantDistMin, iWantDistMax); } public override void WalkRandom(int iChanceToNotMove, int iChanceToDir, int iSteps) @@ -529,7 +529,7 @@ private bool ProcessTarget() Mobile toTarget; - toTarget = this.m_Mobile.Combatant; + toTarget = this.m_Mobile.Combatant as Mobile; //if ( toTarget != null ) //RunTo( toTarget ); diff --git a/Scripts/Mobiles/AI/Omni AI/OmniAI Magery.cs b/Scripts/Mobiles/AI/Omni AI/OmniAI Magery.cs index 6bde5ba837..d96beee00a 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniAI Magery.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniAI Magery.cs @@ -65,7 +65,7 @@ public Spell GetMagerySpell() } // 25% chance to cast poison if needed - if (this.m_Mobile.Combatant != null && !this.m_Mobile.Combatant.Poisoned && Utility.RandomDouble() > 0.75) + if (this.m_Mobile.Combatant is Mobile && !((Mobile)m_Mobile.Combatant).Poisoned && Utility.RandomDouble() > 0.75) { if (this.m_Mobile.Debug) this.m_Mobile.Say(1156, "Casting Poison"); @@ -132,7 +132,7 @@ public Spell CheckBless() public Spell CheckCurse() { - Mobile foe = this.m_Mobile.Combatant; + Mobile foe = this.m_Mobile.Combatant as Mobile; if (foe == null) return null; @@ -172,7 +172,7 @@ public Spell CheckCurse() public double CheckManaDrain() { - Mobile foe = this.m_Mobile.Combatant; + Mobile foe = this.m_Mobile.Combatant as Mobile; if (foe == null || foe.Mana < 10) return 0.0; diff --git a/Scripts/Mobiles/AI/Omni AI/OmniAI Mysicism.cs b/Scripts/Mobiles/AI/Omni AI/OmniAI Mysicism.cs index 05b50142e9..5678cc7232 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniAI Mysicism.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniAI Mysicism.cs @@ -27,7 +27,7 @@ public Spell GetMysticSpell() case 0: case 1: { - if (this.CheckForSleep(this.m_Mobile.Combatant)) + if (m_Mobile.Combatant is Mobile && this.CheckForSleep((Mobile)this.m_Mobile.Combatant)) { this.m_Mobile.DebugSay("Casting Sleep"); spell = new SleepSpell(this.m_Mobile, null); @@ -73,7 +73,7 @@ public Spell GetMysticSpell() case 4: case 5: { - if (!SpellPlagueSpell.HasSpellPlague(this.m_Mobile.Combatant) && this.m_Mobile.Skills[SkillName.Mysticism].Value > 70.0) + if (m_Mobile.Combatant is Mobile && !SpellPlagueSpell.HasSpellPlague((Mobile)m_Mobile.Combatant) && this.m_Mobile.Skills[SkillName.Mysticism].Value > 70.0) { this.m_Mobile.DebugSay("Casting Spell Plague"); spell = new SpellPlagueSpell(this.m_Mobile, null); diff --git a/Scripts/Mobiles/AI/Omni AI/OmniAI Ninjitsu.cs b/Scripts/Mobiles/AI/Omni AI/OmniAI Ninjitsu.cs index 704d6bc633..0d174519a7 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniAI Ninjitsu.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniAI Ninjitsu.cs @@ -86,7 +86,7 @@ public void GetNinjaMove() public virtual void ShurikenDamage() { - Mobile target = this.m_Mobile.Combatant; + Mobile target = this.m_Mobile.Combatant as Mobile; if (target != null) { diff --git a/Scripts/Mobiles/AI/Omni AI/OmniAI Spellweaving.cs b/Scripts/Mobiles/AI/Omni AI/OmniAI Spellweaving.cs index 242c46ce68..5162ae1fcb 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniAI Spellweaving.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniAI Spellweaving.cs @@ -93,7 +93,7 @@ public void SpellweavingPower() } case 6: // Essence of Wind, cold aura and speed debuff. { - if (!EssenceOfWindSpell.IsDebuffed(this.m_Mobile.Combatant)) + if (m_Mobile.Combatant is Mobile && !EssenceOfWindSpell.IsDebuffed((Mobile)m_Mobile.Combatant)) { new EssenceOfWindSpell(this.m_Mobile, null).Cast(); break; diff --git a/Scripts/Mobiles/AI/Omni AI/OmniIA Bard.cs b/Scripts/Mobiles/AI/Omni AI/OmniIA Bard.cs index dbaf2ba158..a880d1551c 100644 --- a/Scripts/Mobiles/AI/Omni AI/OmniIA Bard.cs +++ b/Scripts/Mobiles/AI/Omni AI/OmniIA Bard.cs @@ -65,7 +65,7 @@ public bool CheckInstrument() #region discord public void UseDiscord() { - Mobile target = this.m_Mobile.Combatant; + Mobile target = this.m_Mobile.Combatant as Mobile; if (target == null) return; @@ -134,7 +134,7 @@ public bool UseProvocation() else if (this.m_Mobile.Target != null) this.m_Mobile.Target.Cancel(this.m_Mobile, TargetCancelType.Canceled); - Mobile target = this.m_Mobile.Combatant; + Mobile target = this.m_Mobile.Combatant as Mobile; if (this.m_Mobile.Combatant is BaseCreature) { diff --git a/Scripts/Mobiles/AI/OrcScoutAI.cs b/Scripts/Mobiles/AI/OrcScoutAI.cs index 206a0e0597..fddd9c22bb 100644 --- a/Scripts/Mobiles/AI/OrcScoutAI.cs +++ b/Scripts/Mobiles/AI/OrcScoutAI.cs @@ -55,7 +55,7 @@ public override bool DoActionWander() public override bool DoActionCombat() { - Mobile combatant = m_Mobile.Combatant; + Mobile combatant = m_Mobile.Combatant as Mobile; if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive || combatant.IsDeadBondedPet) @@ -85,7 +85,7 @@ public override bool DoActionCombat() m_Mobile.Combatant = null; } - combatant = m_Mobile.Combatant; + combatant = m_Mobile.Combatant as Mobile; if (combatant == null) { @@ -208,7 +208,7 @@ public override bool DoActionFlee() } else { - m_Mobile.FocusMob = m_Mobile.Combatant; + m_Mobile.FocusMob = m_Mobile.Combatant as Mobile; PerformHide(); diff --git a/Scripts/Mobiles/AI/PaladinAI.cs b/Scripts/Mobiles/AI/PaladinAI.cs index 843b8b8153..5dfb7a8bde 100644 --- a/Scripts/Mobiles/AI/PaladinAI.cs +++ b/Scripts/Mobiles/AI/PaladinAI.cs @@ -84,9 +84,9 @@ public override bool DoActionCombat() spell = new DispelEvilSpell( m_Mobile, null ); } - else + else if(m_Mobile.Combatant != null) { - spell = ChooseSpell( m_Mobile.Combatant ); + spell = ChooseSpell(); } if ( spell != null ) @@ -160,7 +160,7 @@ public Mobile FindDispelTarget( bool activeOnly ) Mobile active = null; double activePrio = 0.0; - Mobile comb = m_Mobile.Combatant; + Mobile comb = m_Mobile.Combatant as Mobile; if ( comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && m_Mobile.InRange( comb, 12 ) && CanDispel( comb ) ) { @@ -219,7 +219,7 @@ public bool CanDispel( Mobile m ) return ( m is BaseCreature && ((BaseCreature)m).Summoned && m_Mobile.CanBeHarmful( m, false ) && !((BaseCreature)m).IsAnimatedDead ); } - public virtual Spell ChooseSpell( Mobile c ) + public virtual Spell ChooseSpell() { Spell spell = CheckCastHealingSpell(); diff --git a/Scripts/Mobiles/AI/PredatorAI.cs b/Scripts/Mobiles/AI/PredatorAI.cs index 25f66a74c7..8e975eb1e2 100644 --- a/Scripts/Mobiles/AI/PredatorAI.cs +++ b/Scripts/Mobiles/AI/PredatorAI.cs @@ -36,7 +36,7 @@ public override bool DoActionWander() public override bool DoActionCombat() { - Mobile combatant = this.m_Mobile.Combatant; + Mobile combatant = this.m_Mobile.Combatant as Mobile; if (combatant == null || combatant.Deleted || combatant.Map != this.m_Mobile.Map) { diff --git a/Scripts/Mobiles/AI/SamuraiAI.cs b/Scripts/Mobiles/AI/SamuraiAI.cs index e6bc04ba64..8be22319cf 100644 --- a/Scripts/Mobiles/AI/SamuraiAI.cs +++ b/Scripts/Mobiles/AI/SamuraiAI.cs @@ -78,7 +78,7 @@ public override bool DoActionCombat() { base.DoActionCombat(); - Mobile c = m_Mobile.Combatant; + Mobile c = m_Mobile.Combatant as Mobile; if(c != null) { diff --git a/Scripts/Mobiles/AI/SpellbinderAI.cs b/Scripts/Mobiles/AI/SpellbinderAI.cs index 8aec940f0d..52620d8943 100644 --- a/Scripts/Mobiles/AI/SpellbinderAI.cs +++ b/Scripts/Mobiles/AI/SpellbinderAI.cs @@ -1,4 +1,4 @@ -using System; +/*using System; using System.Collections.Generic; using Server.Spells; using Server.Spells.Fifth; @@ -150,7 +150,7 @@ public void RunTo(Mobile m) } } - public void RunFrom(Mobile m) + public void RunFrom(IDamageable m) { this.Run((Direction)((int)this.m_Mobile.GetDirectionTo(m) - 4) & Direction.Mask); } @@ -251,13 +251,18 @@ public virtual Spell DoDispel(Mobile toDispel) return this.ChooseSpell(toDispel); } - public virtual Spell ChooseSpell(Mobile c) + public virtual Spell ChooseSpell(IDamageable c) { Spell spell = this.CheckCastHealingSpell(); if (spell != null) return spell; - + + if(!(c is Mobile) + { + return null; + } + double damage = ((this.m_Mobile.Skills[SkillName.SpiritSpeak].Value - c.Skills[SkillName.MagicResist].Value) / 10) + (c.Player ? 18 : 30); if (damage > c.Hits) @@ -324,10 +329,10 @@ public virtual Spell ChooseSpell(Mobile c) public override bool DoActionCombat() { - Mobile c = this.m_Mobile.Combatant; + IDamageable c = this.m_Mobile.Combatant; this.m_Mobile.Warmode = true; - if (c == null || c.Deleted || !c.Alive || c.IsDeadBondedPet || !this.m_Mobile.CanSee(c) || !this.m_Mobile.CanBeHarmful(c, false) || c.Map != this.m_Mobile.Map) + if (c == null || c.Deleted || !c.Alive || (c is Mobile && ((Mobile)c).IsDeadBondedPet) || !this.m_Mobile.CanSee(c) || !this.m_Mobile.CanBeHarmful(c, false) || c.Map != this.m_Mobile.Map) { // Our combatant is deleted, dead, hidden, or we cannot hurt them // Try to find another combatant @@ -431,7 +436,7 @@ public override bool DoActionCombat() spell = this.DoDispel(toDispel); } - else if ((c.Spell is HealSpell || c.Spell is GreaterHealSpell) && !c.Poisoned) // They have a heal spell out + else if (c is Mobile && (((Mobile)c).Spell is HealSpell || ((Mobile)c).Spell is GreaterHealSpell) && !((Mobile)c).Poisoned) // They have a heal spell out { spell = new BloodOathSpell(this.m_Mobile, null); } @@ -518,7 +523,7 @@ public override bool DoActionGuard() public override bool DoActionFlee() { - Mobile c = this.m_Mobile.Combatant; + Mobile c = this.m_Mobile.Combatant as Mobile; if ((this.m_Mobile.Mana > 20 || this.m_Mobile.Mana == this.m_Mobile.ManaMax) && this.m_Mobile.Hits > (this.m_Mobile.HitsMax / 2)) { @@ -560,7 +565,7 @@ public Mobile FindDispelTarget(bool activeOnly) Mobile active = null; double activePrio = 0.0; - Mobile comb = this.m_Mobile.Combatant; + Mobile comb = this.m_Mobile.Combatant as Mobile; if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && this.m_Mobile.InRange(comb, 12) && this.CanDispel(comb)) { @@ -622,7 +627,7 @@ public Mobile FindDispelTarget(bool activeOnly) Mobile active = null, inactive = null; double actPrio = 0.0, inactPrio = 0.0; - Mobile comb = this.m_Mobile.Combatant; + Mobile comb = this.m_Mobile.Combatant as Mobile; if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && this.CanDispel(comb)) { @@ -738,7 +743,7 @@ private void ProcessTarget(Target targ) if (toTarget == null) { - toTarget = this.m_Mobile.Combatant; + toTarget = this.m_Mobile.Combatant as Mobile; if (toTarget != null) this.RunTo(toTarget); @@ -755,7 +760,7 @@ private void ProcessTarget(Target targ) } else { - toTarget = this.m_Mobile.Combatant; + toTarget = this.m_Mobile.Combatant as Mobile; if (toTarget != null) this.RunTo(toTarget); @@ -845,4 +850,4 @@ private void ProcessTarget(Target targ) } } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/Scripts/Mobiles/AI/ThiefAI.cs b/Scripts/Mobiles/AI/ThiefAI.cs index de990ecc2d..6c0201b943 100644 --- a/Scripts/Mobiles/AI/ThiefAI.cs +++ b/Scripts/Mobiles/AI/ThiefAI.cs @@ -46,7 +46,7 @@ public override bool DoActionWander() public override bool DoActionCombat() { - Mobile combatant = m_Mobile.Combatant; + Mobile combatant = m_Mobile.Combatant as Mobile; if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map) { @@ -209,7 +209,7 @@ public override bool DoActionFlee() } else { - m_Mobile.FocusMob = m_Mobile.Combatant; + m_Mobile.FocusMob = m_Mobile.Combatant as Mobile; base.DoActionFlee(); } diff --git a/Scripts/Mobiles/AI/VendorAI.cs b/Scripts/Mobiles/AI/VendorAI.cs index 9c116fc64b..42245c890e 100644 --- a/Scripts/Mobiles/AI/VendorAI.cs +++ b/Scripts/Mobiles/AI/VendorAI.cs @@ -48,7 +48,7 @@ public override bool DoActionWander() public override bool DoActionInteract() { - Mobile customer = this.m_Mobile.FocusMob; + Mobile customer = this.m_Mobile.FocusMob as Mobile; if (this.m_Mobile.Combatant != null) { @@ -94,7 +94,7 @@ public override bool DoActionInteract() public override bool DoActionGuard() { - this.m_Mobile.FocusMob = this.m_Mobile.Combatant; + this.m_Mobile.FocusMob = this.m_Mobile.Combatant as Mobile; return base.DoActionGuard(); } diff --git a/Scripts/Mobiles/Bosses/LadyMelisande.cs b/Scripts/Mobiles/Bosses/LadyMelisande.cs index f5e7d1748e..cb119fbe67 100644 --- a/Scripts/Mobiles/Bosses/LadyMelisande.cs +++ b/Scripts/Mobiles/Bosses/LadyMelisande.cs @@ -116,14 +116,19 @@ public override void OnThink() { base.OnThink(); - if (this.CanTakeLife(this.Combatant)) - this.TakeLife(this.Combatant); + Mobile combatant = Combatant as Mobile; - if (this.CanSmackTalk()) - this.SmackTalk(); + if (combatant != null) + { + if (this.CanTakeLife(combatant)) + this.TakeLife(combatant); + + if (this.CanSmackTalk()) + this.SmackTalk(); - if (this.CanPutridNausea()) - this.PutridNausea(); + if (this.CanPutridNausea()) + this.PutridNausea(); + } } public override void SetLocation(Point3D newLocation, bool isTeleport) diff --git a/Scripts/Mobiles/Bosses/MonstrousInterredGrizzle.cs b/Scripts/Mobiles/Bosses/MonstrousInterredGrizzle.cs index e886b3fb48..0a10566fde 100644 --- a/Scripts/Mobiles/Bosses/MonstrousInterredGrizzle.cs +++ b/Scripts/Mobiles/Bosses/MonstrousInterredGrizzle.cs @@ -299,12 +299,12 @@ public virtual void DropOoze() ooze.MoveToWorld(p, this.Map); } - if (this.Combatant != null) + if (this.Combatant is PlayerMobile) { if (corrosive) - this.Combatant.SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! + ((PlayerMobile)Combatant).SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! else - this.Combatant.SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! + ((PlayerMobile)Combatant).SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! } } diff --git a/Scripts/Mobiles/Bosses/PrimevalLich.cs b/Scripts/Mobiles/Bosses/PrimevalLich.cs index a174390888..2d1d7cb5bf 100644 --- a/Scripts/Mobiles/Bosses/PrimevalLich.cs +++ b/Scripts/Mobiles/Bosses/PrimevalLich.cs @@ -222,7 +222,7 @@ public override void OnThink() { if (this.m_NextDiscordTime <= DateTime.UtcNow) { - Mobile target = this.Combatant; + Mobile target = this.Combatant as Mobile; if (target != null && target.InRange(this, this.PerceptionRange) && this.CanBeHarmful(target)) this.Discord(target); @@ -233,15 +233,15 @@ public void Discord(Mobile target) { if (Utility.RandomDouble() < 0.9) { - target.AddSkillMod(new TimedSkillMod(SkillName.Magery, true, this.Combatant.Skills.Magery.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Necromancy, true, this.Combatant.Skills.Necromancy.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Tactics, true, this.Combatant.Skills.Tactics.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Swords, true, this.Combatant.Skills.Swords.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Meditation, true, this.Combatant.Skills.Meditation.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Focus, true, this.Combatant.Skills.Focus.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Chivalry, true, this.Combatant.Skills.Chivalry.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Wrestling, true, this.Combatant.Skills.Wrestling.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); - target.AddSkillMod(new TimedSkillMod(SkillName.Spellweaving, true, this.Combatant.Skills.Spellweaving.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Magery, true, target.Skills.Magery.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Necromancy, true, target.Skills.Necromancy.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Tactics, true, target.Skills.Tactics.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Swords, true, target.Skills.Swords.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Meditation, true, target.Skills.Meditation.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Focus, true, target.Skills.Focus.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Chivalry, true, target.Skills.Chivalry.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Wrestling, true, target.Skills.Wrestling.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); + target.AddSkillMod(new TimedSkillMod(SkillName.Spellweaving, true, target.Skills.Spellweaving.Base * this.DiscordModifier * -1, TimeSpan.FromSeconds(this.DiscordDuration))); Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), (int)this.DiscordDuration, new TimerStateCallback(Animate), target); diff --git a/Scripts/Mobiles/Bosses/Travesty.cs b/Scripts/Mobiles/Bosses/Travesty.cs index 61964b42f1..358d3525c6 100644 --- a/Scripts/Mobiles/Bosses/Travesty.cs +++ b/Scripts/Mobiles/Bosses/Travesty.cs @@ -193,22 +193,22 @@ public override void OnThink() if (this.Combatant == null) return; - if (this.Combatant.Player && this.Name != this.Combatant.Name) - this.Morph(); + if (this.Combatant is Mobile && this.Name != this.Combatant.Name) + this.Morph((Mobile)Combatant); } - public virtual void Morph() + public virtual void Morph(Mobile combatant) { this.m_Name = this.Name; this.m_Hue = this.Hue; - this.Body = this.Combatant.Body; - this.Hue = this.Combatant.Hue; - this.Name = this.Combatant.Name; - this.Female = this.Combatant.Female; - this.Title = this.Combatant.Title; + this.Body = combatant.Body; + this.Hue = combatant.Hue; + this.Name = combatant.Name; + this.Female = combatant.Female; + this.Title = combatant.Title; - foreach (Item item in this.Combatant.Items) + foreach (Item item in combatant.Items) { if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) if (this.FindItemOnLayer(item.Layer) == null) @@ -251,9 +251,9 @@ public virtual void EndMorph() this.m_Timer = null; } - if (this.Combatant != null) + if (this.Combatant is Mobile) { - this.Morph(); + this.Morph((Mobile)Combatant); return; } diff --git a/Scripts/Mobiles/Named/Ilhenir.cs b/Scripts/Mobiles/Named/Ilhenir.cs index 3554206a86..a0d5bcfb9f 100644 --- a/Scripts/Mobiles/Named/Ilhenir.cs +++ b/Scripts/Mobiles/Named/Ilhenir.cs @@ -339,12 +339,12 @@ public virtual void DropOoze() ooze.MoveToWorld(p, this.Map); } - if (this.Combatant != null) + if (this.Combatant is PlayerMobile) { if (corrosive) - this.Combatant.SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! + ((PlayerMobile)Combatant).SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! else - this.Combatant.SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! + ((PlayerMobile)Combatant).SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! } } diff --git a/Scripts/Mobiles/Normal/BaseCreature.cs b/Scripts/Mobiles/Normal/BaseCreature.cs index df5968ed10..a9dae648e6 100644 --- a/Scripts/Mobiles/Normal/BaseCreature.cs +++ b/Scripts/Mobiles/Normal/BaseCreature.cs @@ -209,7 +209,7 @@ public class BaseCreature : Mobile, IHonorTarget private bool m_bControlled; // Is controlled private Mobile m_ControlMaster; // My master - private Mobile m_ControlTarget; // My target mobile + private IDamageable m_ControlTarget; // My target mobile private Point3D m_ControlDest; // My target destination (patrol) private OrderType m_ControlOrder; // My order @@ -596,6 +596,9 @@ public bool IsChampionSpawn // at difficulty - focus we have 0%, at difficulty + focus we have 100% public virtual bool DisplayWeight { get { return Backpack is StrongBackpack; } } + public virtual bool ShowSpellMantra { get { return false; } } + public virtual bool FreezeOnCast { get { return ShowSpellMantra; } } + #region High Seas public virtual bool TaintedLifeAura { get { return false; } } #endregion @@ -650,7 +653,7 @@ public bool IsChampionSpawn public virtual int BreathAngerSound { get { return GetAngerSound(); } } public virtual int BreathAngerAnimation { get { return 12; } } - public virtual void BreathStart(Mobile target) + public virtual void BreathStart(IDamageable target) { BreathStallMovement(); BreathPlayAngerSound(); @@ -681,7 +684,7 @@ public virtual void BreathPlayAngerAnimation() public virtual void BreathEffect_Callback(object state) { - Mobile target = (Mobile)state; + IDamageable target = (IDamageable)state; if (!target.Alive || !CanBeHarmful(target)) { @@ -699,7 +702,7 @@ public virtual void BreathPlayEffectSound() PlaySound(BreathEffectSound); } - public virtual void BreathPlayEffect(Mobile target) + public virtual void BreathPlayEffect(IDamageable target) { Effects.SendMovingEffect( this, @@ -715,7 +718,7 @@ public virtual void BreathPlayEffect(Mobile target) public virtual void BreathDamage_Callback(object state) { - Mobile target = (Mobile)state; + IDamageable target = (IDamageable)state; if (target is BaseCreature && ((BaseCreature)target).BreathImmune) { @@ -729,9 +732,9 @@ public virtual void BreathDamage_Callback(object state) } } - public virtual void BreathDealDamage(Mobile target) + public virtual void BreathDealDamage(IDamageable target) { - if (!Evasion.CheckSpellEvasion(target)) + if (!(target is Mobile) || !Evasion.CheckSpellEvasion((Mobile)target)) { int physDamage = BreathPhysicalDamage; int fireDamage = BreathFireDamage; @@ -1933,7 +1936,7 @@ public override void Serialize(GenericWriter writer) writer.Write(m_bControlled); writer.Write(m_ControlMaster); - writer.Write(m_ControlTarget); + writer.Write(m_ControlTarget is Mobile ? (Mobile)m_ControlTarget : null); writer.Write(m_ControlDest); writer.Write((int)m_ControlOrder); writer.Write(m_dMinTameSkill); @@ -2680,9 +2683,6 @@ public void ChangeAIType(AIType NewAI) case AIType.AI_OrcScout: m_AI = new OrcScoutAI(this); break; - case AIType.AI_Spellbinder: - m_AI = new SpellbinderAI(this); - break; case AIType.AI_Samurai: m_AI = new SamuraiAI(this); break; @@ -2742,7 +2742,7 @@ public virtual void OnTeamChange() { } [CommandProperty(AccessLevel.GameMaster)] - public Mobile FocusMob { get; set; } + public IDamageable FocusMob { get; set; } [CommandProperty(AccessLevel.GameMaster)] public FightMode FightMode { get { return m_FightMode; } set { m_FightMode = value; } } @@ -2981,7 +2981,7 @@ public Mobile SummonMaster } [CommandProperty(AccessLevel.GameMaster)] - public Mobile ControlTarget { get { return m_ControlTarget; } set { m_ControlTarget = value; } } + public IDamageable ControlTarget { get { return m_ControlTarget; } set { m_ControlTarget = value; } } [CommandProperty(AccessLevel.GameMaster)] public Point3D ControlDest { get { return m_ControlDest; } set { m_ControlDest = value; } } @@ -3692,8 +3692,10 @@ public override void OnSpeech(SpeechEventArgs e) } } - public override bool IsHarmfulCriminal(Mobile target) + public override bool IsHarmfulCriminal(IDamageable damageable) { + Mobile target = damageable as Mobile; + if ((Controlled && target == m_ControlMaster) || (Summoned && target == m_SummonMaster)) { return false; @@ -3709,7 +3711,7 @@ public override bool IsHarmfulCriminal(Mobile target) return false; } - return base.IsHarmfulCriminal(target); + return base.IsHarmfulCriminal(damageable); } public override void CriminalAction(bool message) @@ -3729,9 +3731,14 @@ public override void CriminalAction(bool message) } } - public override void DoHarmful(Mobile target, bool indirect) + public override void DoHarmful(IDamageable damageable, bool indirect) { - base.DoHarmful(target, indirect); + base.DoHarmful(damageable, indirect); + + Mobile target = damageable as Mobile; + + if (target == null) + return; if (target == this || target == m_ControlMaster || target == m_SummonMaster || (!Controlled && !Summoned)) { @@ -5507,8 +5514,10 @@ public override void OnDelete() } } - public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness) + public override bool CanBeHarmful(IDamageable damageable, bool message, bool ignoreOurBlessedness) { + Mobile target = damageable as Mobile; + if (target is BaseFactionGuard) { return false; @@ -5516,22 +5525,15 @@ public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBle if ((target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier) { - if (message) - { - if (target.Title == null) - { - SendMessage("{0} the vendor cannot be harmed.", target.Name); - } - else - { - SendMessage("{0} {1} cannot be harmed.", target.Name, target.Title); - } - } + return false; + } + if (damageable is IDamageableItem && !((IDamageableItem)damageable).CanDamage) + { return false; } - return base.CanBeHarmful(target, message, ignoreOurBlessedness); + return base.CanBeHarmful(damageable, message, ignoreOurBlessedness); } public override bool CanBeRenamedBy(Mobile from) @@ -6308,10 +6310,10 @@ public BaseInstrument CheckInstrument() /// public virtual Mobile GetBardTarget(bool creaturesOnly = false) { - Mobile m = this.Combatant; + Mobile m = this.Combatant as Mobile; if (m == null && GetMaster() is PlayerMobile) - m = GetMaster().Combatant; + m = GetMaster().Combatant as Mobile; if (m == null || m == this || !CanBeHarmful(m, false) || (creaturesOnly && !(m is BaseCreature))) { @@ -6495,10 +6497,10 @@ public virtual void OnThink() if (CanBreath && tc - m_NextBreathTime >= 0) // tested: controlled dragons do breath fire, what about summoned skeletal dragons? { - Mobile target = Combatant; + IDamageable target = Combatant; - if (target != null && target.Alive && !target.IsDeadBondedPet && CanBeHarmful(target) && target.Map == Map && - !IsDeadBondedPet && target.InRange(this, BreathRange) && InLOS(target) && !BardPacified) + if (target != null && target.Alive && (!(target is Mobile) || !((Mobile)target).IsDeadBondedPet) && CanBeHarmful(target) && target.Map == Map && + !IsDeadBondedPet && InRange(target, BreathRange) && InLOS(target) && !BardPacified) { if ((Core.TickCount - m_NextBreathTime) < 30000 && Utility.RandomBool()) { diff --git a/Scripts/Mobiles/Normal/BattleChickenLizard.cs b/Scripts/Mobiles/Normal/BattleChickenLizard.cs index 11ace4851e..c17f899e3f 100644 --- a/Scripts/Mobiles/Normal/BattleChickenLizard.cs +++ b/Scripts/Mobiles/Normal/BattleChickenLizard.cs @@ -43,7 +43,7 @@ public BattleChickenLizard() public override int GetHurtSound() { return 1510; } public override int GetDeathSound() { return 1509; } - public override Mobile Combatant + public override IDamageable Combatant { get { return base.Combatant; } set diff --git a/Scripts/Mobiles/Normal/Betrayer.cs b/Scripts/Mobiles/Normal/Betrayer.cs index 893a14fc52..bbdb999648 100644 --- a/Scripts/Mobiles/Normal/Betrayer.cs +++ b/Scripts/Mobiles/Normal/Betrayer.cs @@ -160,7 +160,7 @@ public override void OnGaveMeleeAttack(Mobile defender) public override void OnActionCombat() { - Mobile combatant = this.Combatant; + Mobile combatant = this.Combatant as Mobile; if (DateTime.UtcNow < this.m_NextAbilityTime || combatant == null || combatant.Deleted || combatant.Map != this.Map || !this.InRange(combatant, 3) || !this.CanBeHarmful(combatant) || !this.InLOS(combatant)) return; diff --git a/Scripts/Mobiles/Normal/Changeling.cs b/Scripts/Mobiles/Normal/Changeling.cs index 1cb22f0ccb..dd8b4d6719 100644 --- a/Scripts/Mobiles/Normal/Changeling.cs +++ b/Scripts/Mobiles/Normal/Changeling.cs @@ -175,8 +175,8 @@ public override void OnThink() this.m_NextFireRing = DateTime.UtcNow + TimeSpan.FromMinutes(2); } - if (this.Combatant.Player && this.m_MorphedInto != this.Combatant && Utility.RandomDouble() < 0.05) - this.MorphedInto = this.Combatant; + if (this.Combatant is PlayerMobile && this.m_MorphedInto != this.Combatant && Utility.RandomDouble() < 0.05) + this.MorphedInto = this.Combatant as Mobile; } } diff --git a/Scripts/Mobiles/Normal/CrystalHydra.cs b/Scripts/Mobiles/Normal/CrystalHydra.cs index f6008813a5..6f501b9ca1 100644 --- a/Scripts/Mobiles/Normal/CrystalHydra.cs +++ b/Scripts/Mobiles/Normal/CrystalHydra.cs @@ -136,7 +136,7 @@ public override bool HasBreath } } - public override void BreathStart(Mobile target) + public override void BreathStart(IDamageable target) { this.BreathStallMovement(); this.BreathPlayAngerSound(); @@ -145,8 +145,10 @@ public override void BreathStart(Mobile target) this.Direction = this.GetDirectionTo(target); int count = 0; - - foreach (Mobile m in this.GetMobilesInRange(this.BreathRange)) + + IPooledEnumerable eable = this.GetMobilesInRange(this.BreathRange); + + foreach (Mobile m in eable) { if (count++ > 3) break; @@ -154,6 +156,9 @@ public override void BreathStart(Mobile target) if (m != null && m != target && m.Alive && !m.IsDeadBondedPet && this.CanBeHarmful(m) && m.Map == this.Map && !this.IsDeadBondedPet && m.InRange(this, this.BreathRange) && this.InLOS(m) && !this.BardPacified) Timer.DelayCall(TimeSpan.FromSeconds(this.BreathEffectDelay), new TimerStateCallback(BreathEffect_Callback), m); } + + eable.Free(); + Timer.DelayCall(TimeSpan.FromSeconds(this.BreathEffectDelay), new TimerStateCallback(BreathEffect_Callback), target); } diff --git a/Scripts/Mobiles/Normal/DeathWatchBeetle.cs b/Scripts/Mobiles/Normal/DeathWatchBeetle.cs index 2895631363..1a7d1f4bb9 100644 --- a/Scripts/Mobiles/Normal/DeathWatchBeetle.cs +++ b/Scripts/Mobiles/Normal/DeathWatchBeetle.cs @@ -131,7 +131,7 @@ public override void AlterMeleeDamageTo(Mobile to, ref int damage) public override void OnDamage(int amount, Mobile from, bool willKill) { - Mobile combatant = this.Combatant; + Mobile combatant = this.Combatant as Mobile; if (combatant == null || combatant.Deleted || combatant.Map != this.Map || !this.InRange(combatant, 12) || !this.CanBeHarmful(combatant) || !this.InLOS(combatant)) return; diff --git a/Scripts/Mobiles/Normal/EnragedCreatures.cs b/Scripts/Mobiles/Normal/EnragedCreatures.cs index f9291d2328..c10c738e55 100644 --- a/Scripts/Mobiles/Normal/EnragedCreatures.cs +++ b/Scripts/Mobiles/Normal/EnragedCreatures.cs @@ -253,7 +253,7 @@ public override void OnThink() { bc = (BaseCreature)this.Combatant; } - if (this.Combatant.Player || (bc != null && (bc.Controlled || bc.SummonMaster != null))) + if (this.Combatant is PlayerMobile || (bc != null && (bc.Controlled || bc.SummonMaster != null))) { this.SummonMaster.Combatant = this.Combatant; } @@ -290,7 +290,8 @@ public override void Deserialize(GenericReader reader) private bool Combat(Mobile mobile) { - Mobile combatant = mobile.Combatant; + Mobile combatant = mobile.Combatant as Mobile; + if (combatant == null || combatant.Deleted) { return false; diff --git a/Scripts/Mobiles/Normal/GargishRouser.cs b/Scripts/Mobiles/Normal/GargishRouser.cs index ec657e39aa..788ad0f9d5 100644 --- a/Scripts/Mobiles/Normal/GargishRouser.cs +++ b/Scripts/Mobiles/Normal/GargishRouser.cs @@ -152,7 +152,8 @@ public override void OnThink() { if (!m_Manifested && m_ManifestChance > Utility.RandomDouble()) { - Mobile m = this.Combatant; + IDamageable m = this.Combatant; + if (m is BaseCreature && (((BaseCreature)m).Summoned || ((BaseCreature)m).Controlled)) m = ((BaseCreature)m).GetMaster(); diff --git a/Scripts/Mobiles/Normal/MeerEternal.cs b/Scripts/Mobiles/Normal/MeerEternal.cs index 27db835efe..29a4f53258 100644 --- a/Scripts/Mobiles/Normal/MeerEternal.cs +++ b/Scripts/Mobiles/Normal/MeerEternal.cs @@ -126,7 +126,7 @@ public override void OnThink() { if (DateTime.UtcNow >= this.m_NextAbilityTime) { - Mobile combatant = this.Combatant; + Mobile combatant = this.Combatant as Mobile; if (combatant != null && combatant.Map == this.Map && combatant.InRange(this, 12)) { diff --git a/Scripts/Mobiles/Normal/MeerMage.cs b/Scripts/Mobiles/Normal/MeerMage.cs index 5510ab37e0..00ead22a26 100644 --- a/Scripts/Mobiles/Normal/MeerMage.cs +++ b/Scripts/Mobiles/Normal/MeerMage.cs @@ -138,7 +138,7 @@ public override void OnThink() { if (DateTime.UtcNow >= this.m_NextAbilityTime) { - Mobile combatant = this.Combatant; + Mobile combatant = this.Combatant as Mobile; if (combatant != null && combatant.Map == this.Map && combatant.InRange(this, 12) && this.IsEnemy(combatant) && !UnderEffect(combatant)) { diff --git a/Scripts/Mobiles/Normal/Niporailem.cs b/Scripts/Mobiles/Normal/Niporailem.cs index 97b9adca3a..f37d5d1639 100644 --- a/Scripts/Mobiles/Normal/Niporailem.cs +++ b/Scripts/Mobiles/Normal/Niporailem.cs @@ -209,7 +209,7 @@ public override void OnDelete() public override void OnActionCombat() { - Mobile combatant = Combatant; + Mobile combatant = Combatant as Mobile; if ( combatant == null || combatant.Deleted || combatant.Map != Map || !InRange( combatant, 20 ) || !CanBeHarmful( combatant ) || !InLOS( combatant ) ) return; diff --git a/Scripts/Mobiles/Normal/OrcBomber.cs b/Scripts/Mobiles/Normal/OrcBomber.cs index cc91d37f6c..0fe440f81c 100644 --- a/Scripts/Mobiles/Normal/OrcBomber.cs +++ b/Scripts/Mobiles/Normal/OrcBomber.cs @@ -115,7 +115,7 @@ public override void AggressiveAction(Mobile aggressor, bool criminal) public override void OnActionCombat() { - Mobile combatant = this.Combatant; + Mobile combatant = this.Combatant as Mobile; if (combatant == null || combatant.Deleted || combatant.Map != this.Map || !this.InRange(combatant, 12) || !this.CanBeHarmful(combatant) || !this.InLOS(combatant)) return; diff --git a/Scripts/Mobiles/Normal/Ronin.cs b/Scripts/Mobiles/Normal/Ronin.cs index 2b70e51daf..cd7365c1a3 100644 --- a/Scripts/Mobiles/Normal/Ronin.cs +++ b/Scripts/Mobiles/Normal/Ronin.cs @@ -106,7 +106,7 @@ public override double WeaponAbilityChance { get { - if(Combatant != null && Combatant.Mounted) + if(Combatant is Mobile && ((Mobile)Combatant).Mounted) return 0.8; return base.WeaponAbilityChance; diff --git a/Scripts/Mobiles/Normal/SandVortex.cs b/Scripts/Mobiles/Normal/SandVortex.cs index 4e5d2bb632..95dae2e19f 100644 --- a/Scripts/Mobiles/Normal/SandVortex.cs +++ b/Scripts/Mobiles/Normal/SandVortex.cs @@ -55,7 +55,7 @@ public override void GenerateLoot() public override void OnActionCombat() { - Mobile combatant = this.Combatant; + Mobile combatant = this.Combatant as Mobile; if (combatant == null || combatant.Deleted || combatant.Map != this.Map || !this.InRange(combatant, 12) || !this.CanBeHarmful(combatant) || !this.InLOS(combatant)) return; diff --git a/Scripts/Mobiles/Normal/SkeletalLich.cs b/Scripts/Mobiles/Normal/SkeletalLich.cs index 8ef3e21718..b35515cfe2 100644 --- a/Scripts/Mobiles/Normal/SkeletalLich.cs +++ b/Scripts/Mobiles/Normal/SkeletalLich.cs @@ -14,7 +14,7 @@ public override WeaponAbility GetWeaponAbility() } [Constructable] - public SkeletalLich() : base( AIType.AI_Spellbinder, FightMode.Closest, 10, 1, 0.2, 0.4 ) + public SkeletalLich() : base( AIType.AI_NecroMage, FightMode.Closest, 10, 1, 0.2, 0.4 ) { Name = "a skeletal lich"; Body = 309; diff --git a/Scripts/Mobiles/Normal/Spellbinder.cs b/Scripts/Mobiles/Normal/Spellbinder.cs index 17bfa82784..4a6df994f2 100644 --- a/Scripts/Mobiles/Normal/Spellbinder.cs +++ b/Scripts/Mobiles/Normal/Spellbinder.cs @@ -7,34 +7,29 @@ public class Spellbinder : BaseCreature { [Constructable] public Spellbinder() - : base(AIType.AI_Spellbinder, FightMode.Closest, 10, 1, 0.2, 0.4) + : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) { this.Name = "a Spectral Spellbinder"; this.Body = 153; this.BaseSoundID = 0x482; - this.SetStr(76, 100); - this.SetDex(76, 95); - this.SetInt(36, 60); + this.SetStr(46, 70); + this.SetDex(47, 65); + this.SetInt(187, 210); - this.SetHits(46, 60); - this.SetMana(100); + this.SetHits(36, 50); - this.SetDamage(0, 1); + this.SetDamage(3, 6); this.SetDamageType(ResistanceType.Physical, 100); - this.SetResistance(ResistanceType.Physical, 25, 30); - this.SetResistance(ResistanceType.Cold, 20, 30); - this.SetResistance(ResistanceType.Poison, 5, 10); - this.SetResistance(ResistanceType.Energy, 10, 20); + this.SetResistance(ResistanceType.Physical, 20, 30); + this.SetResistance(ResistanceType.Cold, 15, 25); + this.SetResistance(ResistanceType.Poison, 10, 20); - this.SetSkill(SkillName.MagicResist, 45.1, 60.0); - this.SetSkill(SkillName.Tactics, 45.1, 60.0); - this.SetSkill(SkillName.Wrestling, 45.1, 55.0); - this.SetSkill(SkillName.Magery, 70.0, 80.0); - this.SetSkill(SkillName.Meditation, 100.0, 120.0); - this.SetSkill(SkillName.Necromancy, 100.0, 120.0); + this.SetSkill(SkillName.MagicResist, 35.1, 45.0); + this.SetSkill(SkillName.Tactics, 35.1, 50.0); + this.SetSkill(SkillName.Wrestling, 35.1, 50.0); this.Fame = 2500; this.Karma = -2500; diff --git a/Scripts/Mobiles/Normal/VoidManesfistation.cs b/Scripts/Mobiles/Normal/VoidManesfistation.cs index b6dc9e194c..a91367044a 100644 --- a/Scripts/Mobiles/Normal/VoidManesfistation.cs +++ b/Scripts/Mobiles/Normal/VoidManesfistation.cs @@ -104,7 +104,7 @@ public override void OnThink() m_NextSummon = DateTime.UtcNow + TimeSpan.FromSeconds(30); } - Mobile combatant = Combatant; + IDamageable combatant = Combatant; if(m_NextAIChange < DateTime.UtcNow) { diff --git a/Scripts/Mobiles/PlayerMobile.cs b/Scripts/Mobiles/PlayerMobile.cs index cde07dd120..80a7784d1a 100644 --- a/Scripts/Mobiles/PlayerMobile.cs +++ b/Scripts/Mobiles/PlayerMobile.cs @@ -1458,8 +1458,10 @@ public override void OnSubItemAdded(Item item) } } - public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness) + public override bool CanBeHarmful(IDamageable damageable, bool message, bool ignoreOurBlessedness) { + Mobile target = damageable as Mobile; + if (m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null)) { return false; @@ -1490,7 +1492,15 @@ public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBle return false; } - return base.CanBeHarmful(target, message, ignoreOurBlessedness); + if (damageable is IDamageableItem && !((IDamageableItem)damageable).CanDamage) + { + if (message) + SendMessage("That cannot be harmed."); + + return false; + } + + return base.CanBeHarmful(damageable, message, ignoreOurBlessedness); } public override bool CanBeBeneficial(Mobile target, bool message, bool allowDead) @@ -2512,6 +2522,7 @@ public override void DisruptiveAction() base.DisruptiveAction(); } + public override bool Meditating { set @@ -3635,8 +3646,12 @@ public PlayerMobile(Serial s) public override int Luck { get { return AosAttributes.GetValue(this, AosAttribute.Luck); } } - public override bool IsHarmfulCriminal(Mobile target) + public int RealLuck { get { return Luck + TenthAnniversarySculpture.GetLuckBonus(this) + FountainOfFortune.GetLuckBonus(this); } } + + public override bool IsHarmfulCriminal(IDamageable damageable) { + Mobile target = damageable as Mobile; + if (Stealing.ClassicMode && target is PlayerMobile && ((PlayerMobile)target).m_PermaFlags.Count > 0) { int noto = Notoriety.Compute(this, target); @@ -3660,7 +3675,7 @@ public override bool IsHarmfulCriminal(Mobile target) return false; } - return base.IsHarmfulCriminal(target); + return base.IsHarmfulCriminal(damageable); } public bool AntiMacroCheck(Skill skill, object obj) diff --git a/Scripts/Mobiles/Summons/BaseFamiliar.cs b/Scripts/Mobiles/Summons/BaseFamiliar.cs index 576eb94fdd..1db5029951 100644 --- a/Scripts/Mobiles/Summons/BaseFamiliar.cs +++ b/Scripts/Mobiles/Summons/BaseFamiliar.cs @@ -107,14 +107,16 @@ public override void OnThink() if ((master.Combatant !=null) && (!InRange(master.Combatant, 1))) { Warmode = false; - FocusMob = Combatant = null; + FocusMob = null; + Combatant = null; CurrentSpeed = 0.01; } if (master.Combatant == null) { Warmode = false; - FocusMob = Combatant = null; + FocusMob = null; + Combatant = null; CurrentSpeed = 0.01; } @@ -122,7 +124,8 @@ public override void OnThink() else { Warmode = false; - FocusMob = Combatant = null; + FocusMob = null; + Combatant = null; CurrentSpeed = .01; } diff --git a/Scripts/Mobiles/Summons/SummonedPaladin.cs b/Scripts/Mobiles/Summons/SummonedPaladin.cs index f3f6267c5d..2f1393b51a 100644 --- a/Scripts/Mobiles/Summons/SummonedPaladin.cs +++ b/Scripts/Mobiles/Summons/SummonedPaladin.cs @@ -69,9 +69,9 @@ public static void BeginSummon(PlayerMobile player) new SummonTimer(player).Start(); } - public override bool IsHarmfulCriminal(Mobile target) + public override bool IsHarmfulCriminal(IDamageable target) { - if (target == this.m_Necromancer) + if (target is Mobile && (Mobile)target == this.m_Necromancer) return false; return base.IsHarmfulCriminal(target); diff --git a/Scripts/Regions/Jail.cs b/Scripts/Regions/Jail.cs index fac9cd939b..c09d10e936 100644 --- a/Scripts/Regions/Jail.cs +++ b/Scripts/Regions/Jail.cs @@ -18,9 +18,9 @@ public override bool AllowBeneficial(Mobile from, Mobile target) return (from.IsStaff()); } - public override bool AllowHarmful(Mobile from, Mobile target) + public override bool AllowHarmful(Mobile from, IDamageable target) { - if (from.IsPlayer()) + if (from.Player) from.SendMessage("You may not do that in jail."); return (from.IsStaff()); @@ -52,7 +52,7 @@ public override bool OnSkillUse(Mobile from, int Skill) return (from.IsStaff()); } - public override bool OnCombatantChange(Mobile from, Mobile Old, Mobile New) + public override bool OnCombatantChange(Mobile from, IDamageable Old, IDamageable New) { return (from.IsStaff()); } diff --git a/Scripts/Services/Factions/Mobiles/Guards/GuardAI.cs b/Scripts/Services/Factions/Mobiles/Guards/GuardAI.cs index 1625ecaa71..0ead8fe15f 100644 --- a/Scripts/Services/Factions/Mobiles/Guards/GuardAI.cs +++ b/Scripts/Services/Factions/Mobiles/Guards/GuardAI.cs @@ -324,7 +324,7 @@ public Mobile FindDispelTarget(bool activeOnly) Mobile active = null; double activePrio = 0.0; - Mobile comb = m_Mobile.Combatant; + Mobile comb = m_Mobile.Combatant as Mobile; if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && m_Mobile.InRange(comb, 12) && CanDispel(comb)) @@ -393,7 +393,7 @@ public Mobile FindDispelTarget(bool activeOnly) Mobile active = null, inactive = null; double actPrio = 0.0, inactPrio = 0.0; - Mobile comb = m_Mobile.Combatant; + Mobile comb = m_Mobile.Combatant as Mobile; if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && CanDispel(comb)) { @@ -513,7 +513,7 @@ public override bool Think() return false; } - Mobile combatant = m_Guard.Combatant; + Mobile combatant = m_Guard.Combatant as Mobile; if (combatant == null || combatant.Deleted || !combatant.Alive || combatant.IsDeadBondedPet || !m_Mobile.CanSee(combatant) || !m_Mobile.CanBeHarmful(combatant, false) || combatant.Map != m_Mobile.Map) @@ -522,7 +522,7 @@ public override bool Think() // Try to find another combatant if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) { - m_Mobile.Combatant = combatant = m_Mobile.FocusMob; + m_Mobile.Combatant = combatant = m_Mobile.FocusMob as Mobile; m_Mobile.FocusMob = null; } else @@ -535,7 +535,7 @@ public override bool Think() { if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) { - m_Mobile.Combatant = combatant = m_Mobile.FocusMob; + m_Mobile.Combatant = combatant = m_Mobile.FocusMob as Mobile; m_Mobile.FocusMob = null; } else if (!m_Mobile.InRange(combatant, 36)) diff --git a/Scripts/Services/High Seas/Mobiles/BaseSeaChampion.cs b/Scripts/Services/High Seas/Mobiles/BaseSeaChampion.cs index 58019ab23c..489048738e 100644 --- a/Scripts/Services/High Seas/Mobiles/BaseSeaChampion.cs +++ b/Scripts/Services/High Seas/Mobiles/BaseSeaChampion.cs @@ -164,7 +164,7 @@ public void TryDamageBoat() Mobile focusMob = m_Fisher; if (focusMob == null || !focusMob.Alive) - focusMob = Combatant; + focusMob = Combatant as Mobile; if (focusMob == null || focusMob.AccessLevel > AccessLevel.Player || !InRange(focusMob.Location, DamageRange) || BaseBoat.FindBoatAt(focusMob, focusMob.Map) == null) return; diff --git a/Scripts/Services/High Seas/Mobiles/Charybdis.cs b/Scripts/Services/High Seas/Mobiles/Charybdis.cs index 51a1bd078e..24ea1aadc6 100644 --- a/Scripts/Services/High Seas/Mobiles/Charybdis.cs +++ b/Scripts/Services/High Seas/Mobiles/Charybdis.cs @@ -109,7 +109,7 @@ public override void OnThink() public void DoTeleport() { - if (this.Combatant == null) + if (this.Combatant == null || !(Combatant is Mobile)) { m_NextTeleport = DateTime.UtcNow + TeleportRate; return; @@ -122,7 +122,7 @@ public void DoTeleport() this.Hidden = true; this.Internalize(); - DoAreaLightningAttack(Combatant); + DoAreaLightningAttack((Mobile)Combatant); Timer.DelayCall(TimeSpan.FromSeconds(3), new TimerStateCallback(FinishTeleport), new object[]{Combatant.Location,Combatant}); m_NextTeleport = DateTime.UtcNow + TeleportRate; diff --git a/Scripts/Services/High Seas/Quests/ProfessionalBountyQuest/Mobiles/BaseShipCaptain.cs b/Scripts/Services/High Seas/Quests/ProfessionalBountyQuest/Mobiles/BaseShipCaptain.cs index 378a874ae2..250953f114 100644 --- a/Scripts/Services/High Seas/Quests/ProfessionalBountyQuest/Mobiles/BaseShipCaptain.cs +++ b/Scripts/Services/High Seas/Quests/ProfessionalBountyQuest/Mobiles/BaseShipCaptain.cs @@ -304,7 +304,7 @@ public override void OnThink() public Mobile GetFocusMob() { - Mobile focus = Combatant; + Mobile focus = Combatant as Mobile; if (focus == null || focus.Deleted || !focus.Alive) { @@ -312,11 +312,11 @@ public Mobile GetFocusMob() foreach (Mobile mob in m_Crew) { - if (mob.Alive && mob.Combatant != null) + if (mob.Alive && mob.Combatant is Mobile) { if (focus == null || (int)focus.GetDistanceToSqrt(mob) < closest) { - focus = mob.Combatant; + focus = mob.Combatant as Mobile; closest = (int)focus.GetDistanceToSqrt(mob); } } diff --git a/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Beacon.cs b/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Beacon.cs index 1c2b45319c..7dda49bd0a 100644 --- a/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Beacon.cs +++ b/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Beacon.cs @@ -13,9 +13,6 @@ public class InvasionBeacon : DamageableItem [CommandProperty(AccessLevel.GameMaster)] public InvasionController Controller { get; set; } - [CommandProperty(AccessLevel.GameMaster)] - public bool CanBeDamaged { get { return Controller.BeaconVulnerable; } } - [CommandProperty(AccessLevel.GameMaster)] public BeaconItem Component { get; set; } @@ -35,16 +32,9 @@ public bool DoBlast public List Rubble { get; set; } - public override int PhysicalResistance { get { return 50; } } - public override int FireResistance { get { return 85; } } - public override int ColdResistance { get { return 99; } } - public override int PoisonResistance { get { return 99; } } - public override int EnergyResistance { get { return 70; } } - - public override DamagePlaceholder Placeholder { get { return new BeaconPlaceholder(this); } } - public override bool DeleteOnDestroy { get { return false; } } public override double IDChange { get { return 0.50; } } + public override bool CanDamage { get { return Controller == null || Controller.BeaconVulnerable; } } public InvasionBeacon(InvasionController controller) : base(18212, 39299, 1) @@ -53,11 +43,14 @@ public InvasionBeacon(InvasionController controller) Component = new BeaconItem(this); Name = "lighthouse"; - PlaceholderName = "lighthouse"; - Level = ItemLevel.Easy; // Hard + ResistBasePhys = 50; + ResistBaseFire = 85; + ResistBaseCold = 99; + ResistBasePoison = 99; + ResistBaseEnergy = 70; - ProvideEntity(); + Level = ItemLevel.Easy; // Hard } public override void OnLocationChange(Point3D oldlocation) @@ -105,7 +98,12 @@ public override bool OnBeforeDestroyed() DoEffects(); if (Component != null) + { Component.ItemID = 1; + Component.Visible = false; + } + + Visible = false; delete.Clear(); delete.TrimExcess(); @@ -167,7 +165,7 @@ private void DoEffects() public override void OnIDChange(int oldID) { - if (ItemID == IDHalfHits && oldID == IDStart && Link != null) + if (ItemID == IDHalfHits && oldID == IDStart) { AddRubble(new Static(6571), new Point3D(this.X, this.Y + 1, this.Z + 42)); AddRubble(new Static(3118), new Point3D(this.X - 1, this.Y + 1, this.Z)); @@ -175,9 +173,9 @@ public override void OnIDChange(int oldID) } } - public override void OnDamage(int amount, Mobile from, bool willKill) + public override void OnDamage(int amount, Mobile from, bool willkill) { - base.OnDamage(amount, from, willKill); + base.OnDamage(amount, from, willkill); if (this.ItemID == IDHalfHits && this.Hits <= (HitsMax * .25)) { @@ -203,6 +201,11 @@ public override void OnDamage(int amount, Mobile from, bool willKill) this.ItemID = 39300; } + + if (0.02 > Utility.RandomDouble()) + { + DoAreaAttack(); + } } private void AddRubble(Item i, Point3D p) @@ -220,7 +223,42 @@ public override void Delete() base.Delete(); if (Rubble != null) - Rubble.ForEach(i => i.Delete()); + { + List rubble = new List(Rubble); + + rubble.ForEach(i => i.Delete()); + rubble.ForEach(i => Rubble.Remove(i)); + + rubble.Clear(); + rubble.TrimExcess(); + } + } + + private void DoAreaAttack() + { + List list = new List(); + IPooledEnumerable eable = this.Map.GetMobilesInRange(this.Location, 8); + + foreach (Mobile m in eable) + { + if (m.AccessLevel > AccessLevel.Player) + continue; + + if (m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) + list.Add(m); + } + + list.ForEach(m => + { + m.BoltEffect(0); + AOS.Damage(m, null, Utility.RandomMinMax(80, 90), 0, 0, 0, 0, 100); + + if(m.NetState != null) + m.PrivateOverheadMessage(Server.Network.MessageType.Regular, 1154, 1154552, m.NetState); // *The beacon blasts a surge of energy at you!" + }); + + list.Clear(); + list.TrimExcess(); } public InvasionBeacon(Serial serial) @@ -234,7 +272,9 @@ public override void Serialize(GenericWriter writer) writer.Write(0); writer.Write(Component); + writer.Write(Rubble == null ? 0 : Rubble.Count); + if (Rubble != null) Rubble.ForEach(i => writer.Write(i)); } @@ -250,6 +290,7 @@ public override void Deserialize(GenericReader reader) Component.Beacon = this; int count = reader.ReadInt(); + for (int i = 0; i < count; i++) { Item item = reader.ReadItem(); @@ -301,44 +342,4 @@ public override void Deserialize(GenericReader reader) int version = reader.ReadInt(); } } - - public class BeaconPlaceholder : DamagePlaceholder - { - public override bool IsInvulnerable { get { return Link is InvasionBeacon && !((InvasionBeacon)Link).CanBeDamaged; } } - - public BeaconPlaceholder(DamageableItem parent) : base(parent) - { - } - - public override Poison PoisonImmune - { - get - { - return Poison.Lesser; - } - } - - /*public override void Damage(int amount, Mobile from, bool informMount, bool checkDisrupt) - { - if(Link is InvasionBeacon && ((InvasionBeacon)Link).CanBeDamaged) - base.Damage(amount, from, informMount, checkDisrupt); - }*/ - - public BeaconPlaceholder(Serial serial) - : base(serial) - { - } - - public override void Serialize(GenericWriter writer) - { - base.Serialize(writer); - writer.Write((int)0); - } - - public override void Deserialize(GenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } \ No newline at end of file diff --git a/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Creatures.cs b/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Creatures.cs index ffa27891c7..71ecb684f6 100644 --- a/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Creatures.cs +++ b/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/Creatures.cs @@ -29,6 +29,7 @@ public static SkillName RandomSpecialty() SkillName.Bushido, SkillName.Bushido, SkillName.Ninjitsu, + SkillName.Chivalry, SkillName.Necromancy, SkillName.Poisoning }; @@ -37,10 +38,12 @@ public static SkillName RandomSpecialty() private SkillName _Specialty; private bool _Sampire; + private DateTime _NextSpecial; public override bool AlwaysMurderer { get { return true; } } public override bool CanHeal { get { return AI == AIType.AI_Melee || AI == AIType.AI_Paladin; } } public override double WeaponAbilityChance { get { return AI == AIType.AI_Melee || AI == AIType.AI_Paladin ? 0.4 : 0.1; } } + public override WeaponAbility GetWeaponAbility() { BaseWeapon wep = Weapon as BaseWeapon; @@ -62,6 +65,8 @@ public override WeaponAbility GetWeaponAbility() public override int AuraBaseDamage { get { return 25; } } public override int AuraEnergyDamage { get { return 100; } } + public virtual bool CanDoSpecial { get { return SpellCaster; } } + public override void AuraEffect(Mobile m) { if (m.NetState != null) @@ -127,7 +132,7 @@ public Invader(SkillName specialty, InvasionType type) SetDex(SpellCaster ? 75 : 150); SetInt(SpellCaster ? 1800 : 500); - SetHits(500, 750); + SetHits(800, 1250); if (AI == AIType.AI_Melee) SetDamage(15, 28); @@ -143,11 +148,16 @@ public Invader(SkillName specialty, InvasionType type) SetSkills(); EquipSpecialty(); - Timer.DelayCall(TimeSpan.FromSeconds(1), () => - { - VampiricEmbraceSpell spell = new VampiricEmbraceSpell(this, null); - spell.Cast(); - }); + _NextSpecial = DateTime.UtcNow; + + if (_Sampire) + { + Timer.DelayCall(TimeSpan.FromSeconds(1), () => + { + VampiricEmbraceSpell spell = new VampiricEmbraceSpell(this, null); + spell.Cast(); + }); + } } public virtual void SetBody() @@ -224,7 +234,7 @@ public virtual void EquipSpecialty() { case SkillName.Chivalry: SetWearable(RandomSwordWeapon()); - StandardMeleeEquip(); + PaladinEquip(); break; case SkillName.Swords: SetWearable(RandomSwordWeapon()); @@ -270,6 +280,8 @@ public virtual void EquipSpecialty() if (_Sampire) w.WeaponAttributes.HitLeechHits = 100; + + SetSkill(SkillName.Parry, 120); break; case SkillName.Ninjitsu: SetWearable(RandomNinjaWeapon()); @@ -307,11 +319,24 @@ public virtual void EquipSpecialty() SetWearable(new LeatherLegs()); SetWearable(new LeatherGloves()); SetWearable(new LeatherGorget()); - break; } } + private void PaladinEquip() + { + SetWearable(Loot.Construct(new Type[] { typeof(Bascinet), typeof(Helmet), typeof(PlateHelm) }), 1153); + + SetWearable(new PlateChest()); + SetWearable(new PlateLegs()); + SetWearable(new PlateGloves()); + SetWearable(new PlateGorget()); + SetWearable(new PlateArms()); + SetWearable(new MetalKiteShield()); + + SetSkill(SkillName.Parry, 120); + } + private void StandardMeleeEquip() { SetWearable(Loot.Construct(new Type[] { typeof(Bascinet), typeof(Helmet), typeof(LeatherCap), typeof(RoyalCirclet) })); @@ -409,7 +434,13 @@ public override void OnThink() if (Combatant == null) return; - if (_Sampire) + if (CanDoSpecial && InRange(Combatant, 4) && 0.1 > Utility.RandomDouble() && _NextSpecial < DateTime.UtcNow) + { + DoSpecial(); + + _NextSpecial = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); + } + else if (_Sampire) { if (0.1 > Utility.RandomDouble() && Weapon is BaseWeapon && !(Weapon is Fists) && !((BaseWeapon)Weapon).Cursed) { @@ -424,6 +455,46 @@ public override void OnThink() } } + private void DoSpecial() + { + if (this.Map == null || this.Map == Map.Internal) + return; + + for (int i = 0; i < 4; i++) + { + Timer.DelayCall(TimeSpan.FromMilliseconds(i * 50), o => + { + Server.Misc.Geometry.Circle2D(this.Location, this.Map, (int)o, (pnt, map) => + { + Effects.SendLocationEffect(pnt, map, Utility.RandomBool() ? 14000 : 14013, 14, 20, 2018, 0); + }); + }, i); + } + + Timer.DelayCall(TimeSpan.FromMilliseconds(200), () => + { + List list = new List(); + IPooledEnumerable eable = this.Map.GetMobilesInRange(this.Location, 4); + + foreach (Mobile m in eable) + { + if (m.AccessLevel > AccessLevel.Player) + continue; + + if (m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile) && CanBeHarmful(m)) + list.Add(m); + } + + list.ForEach(m => + { + AOS.Damage(m, this, Utility.RandomMinMax(80, 90), 0, 0, 0, 0, 0, 100, 0); + }); + + list.Clear(); + list.TrimExcess(); + }); + } + public override void GenerateLoot() { this.AddLoot(LootPack.UltraRich, 2); @@ -452,6 +523,8 @@ public override void Deserialize(GenericReader reader) _Specialty = (SkillName)reader.ReadInt(); _InvasionType = (InvasionType)reader.ReadInt(); _Sampire = reader.ReadBool(); + + _NextSpecial = DateTime.UtcNow; } } @@ -469,7 +542,7 @@ public InvaderCaptain(InvasionType type) : base(type) SetDex(SpellCaster ? 150 : 200); SetInt(SpellCaster ? 1000 : 5000); - SetHits(6000, 8000); + SetHits(8000, 12000); if (AI == AIType.AI_Melee) SetDamage(22, 30); diff --git a/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/InvasionController.cs b/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/InvasionController.cs index 495958f630..cd3c22ccc2 100644 --- a/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/InvasionController.cs +++ b/Scripts/Services/Revamped Dungeons/BlackthornDungeon/InvasionSpawner/InvasionController.cs @@ -138,6 +138,8 @@ public void BeginInvasion() if (!Enabled) return; + RemoveSpawn(); + CurrentWave = 1; InvasionType newType; City newCity; @@ -263,7 +265,17 @@ public void OnDeath(BaseCreature bc) { Spawn.Remove(bc); - if (Spawn.Count == 0) + bool wavecomplete = true; + foreach (KeyValuePair> kvp in Spawn) + { + if (kvp.Key != null && kvp.Key.Alive) + { + wavecomplete = false; + break; + } + } + + if (wavecomplete) CompleteWave(); } else @@ -285,6 +297,9 @@ public void OnDeath(BaseCreature bc) public void CleanupSpawn() { + if (Spawn == null) + return; + List list = null; foreach (KeyValuePair> kvp in Spawn) @@ -310,7 +325,6 @@ private void CompleteWave() if(CurrentWave == MaxWaves) { DoMessage(); - OnEndInvasion(); } else { @@ -334,6 +348,8 @@ private void DoMessage() public void OnBeaconDestroyed() { + OnEndInvasion(); + Timer.DelayCall(TimeSpan.FromMinutes(2), () => { Cleanup(); @@ -343,30 +359,32 @@ public void OnBeaconDestroyed() public void OnEndInvasion() { - if (Beacon != null && Beacon.Link is BaseCreature) + if (Beacon != null) { - BaseCreature victim = Beacon.Link as BaseCreature; + List rights = Beacon.GetLootingRights(); - foreach (DamageStore ds in ((BaseCreature)Beacon.Link).GetLootingRights().Where(d => d.m_HasRight && d.m_Mobile.InRange(Beacon.Location, 10))) + if (rights != null) { - Mobile damager = ds.m_Mobile; - Item i = Loot.RandomArmorOrShieldOrWeaponOrJewelry(LootPackEntry.IsInTokuno(victim), LootPackEntry.IsMondain(victim), LootPackEntry.IsStygian(victim)); - - if (i != null) + foreach (Mobile damager in rights.Where(mob => mob.InRange(Beacon.Location, 12))) { - RunicReforging.GenerateRandomItem(i, damager, Math.Max(100, RunicReforging.GetDifficultyFor(victim)), RunicReforging.GetLuckForKiller(victim), ReforgedPrefix.None, ReforgedSuffix.Minax); - - damager.PlaySound(0x5B4); - damager.SendLocalizedMessage(1154554); // You recover an artifact bearing the crest of Minax from the rubble. + Item i = Loot.RandomArmorOrShieldOrWeaponOrJewelry(LootPackEntry.IsInTokuno(damager), LootPackEntry.IsMondain(damager), LootPackEntry.IsStygian(damager)); - if (!damager.PlaceInBackpack(i)) + if (i != null) { - if (damager.BankBox != null && damager.BankBox.TryDropItem(damager, i, false)) - damager.SendLocalizedMessage(1079730); // The item has been placed into your bank box. - else + RunicReforging.GenerateRandomItem(i, damager, Utility.RandomMinMax(700, 800), damager is PlayerMobile ? ((PlayerMobile)damager).RealLuck : damager.Luck, ReforgedPrefix.None, ReforgedSuffix.Minax); + + damager.PlaySound(0x5B4); + damager.SendLocalizedMessage(1154554); // You recover an artifact bearing the crest of Minax from the rubble. + + if (!damager.PlaceInBackpack(i)) { - damager.SendLocalizedMessage(1072523); // You find an artifact, but your backpack and bank are too full to hold it. - i.MoveToWorld(damager.Location, damager.Map); + if (damager.BankBox != null && damager.BankBox.TryDropItem(damager, i, false)) + damager.SendLocalizedMessage(1079730); // The item has been placed into your bank box. + else + { + damager.SendLocalizedMessage(1072523); // You find an artifact, but your backpack and bank are too full to hold it. + i.MoveToWorld(damager.Location, damager.Map); + } } } } @@ -382,6 +400,9 @@ public void Cleanup() public void RemoveSpawn() { + if (Spawn == null) + return; + Dictionary> copy = Spawn; Spawn = new Dictionary>(); @@ -482,11 +503,17 @@ public override void Deserialize(GenericReader reader) } } - if (Beacon != null && Beacon.Destroyed) + Timer.DelayCall(TimeSpan.FromSeconds(10), () => { - Cleanup(); - BeginInvasion(); - } + if (Beacon != null && Beacon.Destroyed) + { + Timer.DelayCall(TimeSpan.FromMinutes(2), () => + { + Cleanup(); + BeginInvasion(); + }); + } + }); } public static void Initialize() diff --git a/Scripts/Services/Revamped Dungeons/Covetous Void Spawn/Creatures/CovetousCreature.cs b/Scripts/Services/Revamped Dungeons/Covetous Void Spawn/Creatures/CovetousCreature.cs index 84395e64cc..69cee7d0db 100644 --- a/Scripts/Services/Revamped Dungeons/Covetous Void Spawn/Creatures/CovetousCreature.cs +++ b/Scripts/Services/Revamped Dungeons/Covetous Void Spawn/Creatures/CovetousCreature.cs @@ -126,7 +126,7 @@ public override void OnThink() protected virtual bool CheckCanTeleport() { - if (CurrentWayPoint == null || Frozen || Paralyzed || (Combatant != null && Combatant.InLOS(this))) + if (CurrentWayPoint == null || Frozen || Paralyzed || (Combatant is Mobile && ((Mobile)Combatant).InLOS(this))) return false; bool canTeleport = true; diff --git a/Scripts/Services/Revamped Dungeons/DespiseRevamped/AI.cs b/Scripts/Services/Revamped Dungeons/DespiseRevamped/AI.cs index 7b9f6353f4..6b68bf240b 100644 --- a/Scripts/Services/Revamped Dungeons/DespiseRevamped/AI.cs +++ b/Scripts/Services/Revamped Dungeons/DespiseRevamped/AI.cs @@ -26,7 +26,7 @@ public override bool DoOrderAttack() if (m_Creature.Orb == null) return base.DoOrderAttack(); - if (m_Creature.ControlTarget == null || m_Creature.ControlTarget.Deleted || m_Creature.ControlTarget.Map != m_Creature.Map || !m_Creature.ControlTarget.Alive || m_Creature.ControlTarget.IsDeadBondedPet) + if (m_Creature.ControlTarget == null || m_Creature.ControlTarget.Deleted || m_Creature.ControlTarget.Map != m_Creature.Map || !m_Creature.ControlTarget.Alive || (m_Creature.ControlTarget is Mobile && ((Mobile)m_Creature.ControlTarget).IsDeadBondedPet)) { m_Creature.DebugSay("I think he might be dead. He's not anywhere around here at least. That's cool. I'm glad he's dead."); @@ -82,7 +82,7 @@ public override bool DoOrderFollow() if (p == null) p = m_Creature; - Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant : null; + Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant as Mobile : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant as Mobile : null; if (combatant != null && combatant.GetDistanceToSqrt(p) <= length) { @@ -143,7 +143,7 @@ public override bool DoOrderNone() if (p == null) p = m_Creature; - Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant : m_Creature.ControlMaster != null ? m_Creature.ControlMaster.Combatant : null; + Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant as Mobile : m_Creature.ControlMaster != null ? m_Creature.ControlMaster.Combatant as Mobile : null; if (combatant != null && combatant.GetDistanceToSqrt(p) <= length) { @@ -198,7 +198,7 @@ public override bool DoActionWander() if (p == null) p = m_Creature; - Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant : null; + Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant as Mobile : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant as Mobile : null; if (combatant != null && combatant.GetDistanceToSqrt(p) <= length) { @@ -254,10 +254,10 @@ public override bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayer break; case Aggression.Defensive: { - Mobile focus = m_Creature.Combatant; + Mobile focus = m_Creature.Combatant as Mobile; if (focus == null) - focus = m_Creature.ControlMaster.Combatant; + focus = m_Creature.ControlMaster.Combatant as Mobile; if (focus != null) { @@ -345,7 +345,7 @@ public override bool DoOrderAttack() if (m_Creature.Orb == null) return base.DoOrderAttack(); - if (m_Creature.ControlTarget == null || m_Creature.ControlTarget.Deleted || m_Creature.ControlTarget.Map != m_Creature.Map || !m_Creature.ControlTarget.Alive || m_Creature.ControlTarget.IsDeadBondedPet) + if (m_Creature.ControlTarget == null || m_Creature.ControlTarget.Deleted || m_Creature.ControlTarget.Map != m_Creature.Map || !m_Creature.ControlTarget.Alive || (m_Creature.ControlTarget is Mobile && ((Mobile)m_Creature.ControlTarget).IsDeadBondedPet)) { m_Creature.DebugSay("I think he might be dead. He's not anywhere around here at least. That's cool. I'm glad he's dead."); @@ -401,7 +401,7 @@ public override bool DoOrderFollow() if (p == null) p = m_Creature.ControlMaster; - Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant : null; + Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant as Mobile : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant as Mobile : null; if (combatant != null && combatant.GetDistanceToSqrt(p) <= length) { @@ -462,7 +462,7 @@ public override bool DoOrderNone() if (p == null) p = m_Creature.ControlMaster; - Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant : m_Creature.ControlMaster != null ? m_Creature.ControlMaster.Combatant : null; + Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant as Mobile : m_Creature.ControlMaster != null ? m_Creature.ControlMaster.Combatant as Mobile : null; if (combatant != null && combatant.GetDistanceToSqrt(p) <= length) { @@ -518,7 +518,7 @@ public override bool DoActionWander() if (p == null) p = m_Creature.ControlMaster; - Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant : null; + Mobile combatant = m_Creature.Combatant != null ? m_Creature.Combatant as Mobile : m_Creature.ControlMaster.Combatant != null ? m_Creature.ControlMaster.Combatant as Mobile : null; if (combatant != null && combatant.GetDistanceToSqrt(p) <= length) { @@ -599,10 +599,10 @@ public override bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayer break; case Aggression.Defensive: { - Mobile focus = m_Creature.Combatant; + Mobile focus = m_Creature.Combatant as Mobile; if (focus == null) - focus = m_Creature.ControlMaster.Combatant; + focus = m_Creature.ControlMaster.Combatant as Mobile; if (focus != null) { diff --git a/Scripts/Services/RunicReforging/RunicReforging.cs b/Scripts/Services/RunicReforging/RunicReforging.cs index 25686b72c2..62c873e71c 100644 --- a/Scripts/Services/RunicReforging/RunicReforging.cs +++ b/Scripts/Services/RunicReforging/RunicReforging.cs @@ -1607,7 +1607,7 @@ public static int GetLuckForKiller(BaseCreature dead) if (highest != null) { - return highest.Luck + TenthAnniversarySculpture.GetLuckBonus(highest) + FountainOfFortune.GetLuckBonus(highest); + return highest is PlayerMobile ? ((PlayerMobile)highest).RealLuck : highest.Luck; } return 0; diff --git a/Scripts/Services/XmlSpawner/XMLSpawner Extras/XmlPoints/ChallengeGameRegion.cs b/Scripts/Services/XmlSpawner/XMLSpawner Extras/XmlPoints/ChallengeGameRegion.cs index 1f2a984346..e20f1a2c5a 100644 --- a/Scripts/Services/XmlSpawner/XMLSpawner Extras/XmlPoints/ChallengeGameRegion.cs +++ b/Scripts/Services/XmlSpawner/XMLSpawner Extras/XmlPoints/ChallengeGameRegion.cs @@ -18,12 +18,12 @@ public ChallengeGameRegion(string name, Map map, int priority, params Rectangle3 { } - public override bool AllowHarmful(Mobile from, Mobile target) + public override bool AllowHarmful(Mobile from, IDamageable target) { if (from == null || target == null) return false; // during a challenge games or 1-on-1 duels, restrict harmful acts to opponents - return XmlPoints.AreChallengers(from, target); + return target is Mobile && XmlPoints.AreChallengers(from, (Mobile)target); } diff --git a/Scripts/Skills/Hiding.cs b/Scripts/Skills/Hiding.cs index b4a903bd04..734650e4fc 100644 --- a/Scripts/Skills/Hiding.cs +++ b/Scripts/Skills/Hiding.cs @@ -65,7 +65,7 @@ public static TimeSpan OnUse(Mobile m) //int range = 18 - (int)(m.Skills[SkillName.Hiding].Value / 10); int range = Math.Min((int)((100 - m.Skills[SkillName.Hiding].Value) / 2) + 8, 18); //Cap of 18 not OSI-exact, intentional difference - bool badCombat = (!m_CombatOverride && m.Combatant != null && m.InRange(m.Combatant.Location, range) && m.Combatant.InLOS(m)); + bool badCombat = (!m_CombatOverride && m.Combatant is Mobile && m.InRange(m.Combatant.Location, range) && ((Mobile)m.Combatant).InLOS(m.Combatant)); bool ok = (!badCombat /*&& m.CheckSkill( SkillName.Hiding, 0.0 - bonus, 100.0 - bonus )*/); if (ok) diff --git a/Scripts/Spells/Base/Spell.cs b/Scripts/Spells/Base/Spell.cs index 65a5d71305..7a4c77e867 100644 --- a/Scripts/Spells/Base/Spell.cs +++ b/Scripts/Spells/Base/Spell.cs @@ -58,34 +58,33 @@ public abstract class Spell : ISpell //the possibility of stacking 'em. Note that a MA & an Explosion will stack, but //of course, two MA's won't. - public virtual bool CanDamageItems { get { return true; } } - private static readonly Dictionary m_ContextTable = new Dictionary(); private class DelayedDamageContextWrapper { - private readonly Dictionary m_Contexts = new Dictionary(); + private readonly Dictionary m_Contexts = new Dictionary(); - public void Add(Mobile m, Timer t) + public void Add(IDamageable d, Timer t) { Timer oldTimer; - if (m_Contexts.TryGetValue(m, out oldTimer)) + + if (m_Contexts.TryGetValue(d, out oldTimer)) { oldTimer.Stop(); - m_Contexts.Remove(m); + m_Contexts.Remove(d); } - m_Contexts.Add(m, t); + m_Contexts.Add(d, t); } - public void Remove(Mobile m) + public void Remove(IDamageable d) { - m_Contexts.Remove(m); + m_Contexts.Remove(d); } } - public void StartDelayedDamageContext(Mobile m, Timer t) + public void StartDelayedDamageContext(IDamageable d, Timer t) { if (DelayedDamageStacking) { @@ -100,10 +99,10 @@ public void StartDelayedDamageContext(Mobile m, Timer t) m_ContextTable.Add(GetType(), contexts); } - contexts.Add(m, t); + contexts.Add(d, t); } - public void RemoveDelayedDamageContext(Mobile m) + public void RemoveDelayedDamageContext(IDamageable d) { DelayedDamageContextWrapper contexts; @@ -112,15 +111,19 @@ public void RemoveDelayedDamageContext(Mobile m) return; } - contexts.Remove(m); + contexts.Remove(d); } - public void HarmfulSpell(Mobile m) + public void HarmfulSpell(IDamageable d) { - if (m is BaseCreature) + if (d is BaseCreature) { - ((BaseCreature)m).OnHarmfulSpell(m_Caster); + ((BaseCreature)d).OnHarmfulSpell(m_Caster); } + else if (d is IDamageableItem) + { + ((IDamageableItem)d).OnHarmfulSpell(m_Caster); + } } public Spell(Mobile caster, Item scroll, SpellInfo info) @@ -130,11 +133,11 @@ public Spell(Mobile caster, Item scroll, SpellInfo info) m_Info = info; } - public virtual int GetNewAosDamage(int bonus, int dice, int sides, Mobile singleTarget) + public virtual int GetNewAosDamage(int bonus, int dice, int sides, IDamageable singleTarget) { if (singleTarget != null) { - return GetNewAosDamage(bonus, dice, sides, (Caster.Player && singleTarget.Player), GetDamageScalar(singleTarget), singleTarget); + return GetNewAosDamage(bonus, dice, sides, (Caster.Player && singleTarget is PlayerMobile), GetDamageScalar(singleTarget as Mobile), singleTarget); } else { @@ -142,13 +145,15 @@ public virtual int GetNewAosDamage(int bonus, int dice, int sides, Mobile single } } - public virtual int GetNewAosDamage(int bonus, int dice, int sides, bool playerVsPlayer, Mobile target) + public virtual int GetNewAosDamage(int bonus, int dice, int sides, bool playerVsPlayer, IDamageable damageable) { - return GetNewAosDamage(bonus, dice, sides, playerVsPlayer, 1.0, target); + return GetNewAosDamage(bonus, dice, sides, playerVsPlayer, 1.0, damageable); } - public virtual int GetNewAosDamage(int bonus, int dice, int sides, bool playerVsPlayer, double scalar, Mobile target) + public virtual int GetNewAosDamage(int bonus, int dice, int sides, bool playerVsPlayer, double scalar, IDamageable damageable) { + Mobile target = damageable as Mobile; + int damage = Utility.Dice(dice, sides, bonus) * 100; int damageBonus = 0; @@ -300,8 +305,11 @@ public virtual void OnConnectionChanged() public virtual bool OnCasterMoving(Direction d) { - if (IsCasting && BlocksMovement) + if (IsCasting && BlocksMovement && (!(m_Caster is BaseCreature) || ((BaseCreature)m_Caster).FreezeOnCast)) { + if (m_Caster is BaseCreature) + m_Caster.Say("Trying to move..."); + m_Caster.SendLocalizedMessage(500111); // You are frozen and can not move. return false; } @@ -401,6 +409,9 @@ public virtual double GetDamageScalar(Mobile target) { double scalar = 1.0; + if (target == null) + return scalar; + if (!Core.AOS) //EvalInt stuff for AoS is handled elsewhere { double casterEI = m_Caster.Skills[DamageSkill].Value; @@ -636,7 +647,7 @@ public virtual void SayMantra() return; } - if (m_Info.Mantra != null && m_Info.Mantra.Length > 0 && m_Caster.Player) + if (m_Info.Mantra != null && m_Info.Mantra.Length > 0 && (m_Caster.Player || (m_Caster is BaseCreature && ((BaseCreature)m_Caster).ShowSpellMantra))) { m_Caster.PublicOverheadMessage(MessageType.Spell, m_Caster.SpeechHue, true, m_Info.Mantra, false); } @@ -1116,9 +1127,9 @@ public bool CheckBSequence(Mobile target, bool allowDead) } } - public bool CheckHSequence(Mobile target) + public bool CheckHSequence(IDamageable target) { - if (!target.Alive || (!CanDamageItems && target is DamagePlaceholder)) + if (!target.Alive || (target is IDamageableItem && !((IDamageableItem)target).CanDamage)) { m_Caster.SendLocalizedMessage(501857); // This spell won't work on that! return false; diff --git a/Scripts/Spells/Base/SpellHelper.cs b/Scripts/Spells/Base/SpellHelper.cs index 037b80a496..8040629ff3 100644 --- a/Scripts/Spells/Base/SpellHelper.cs +++ b/Scripts/Spells/Base/SpellHelper.cs @@ -1089,54 +1089,55 @@ public static void Damage(Spell spell, TimeSpan delay, Mobile target, Mobile fro } } - public static void Damage(Spell spell, Mobile target, double damage, int phys, int fire, int cold, int pois, int nrgy) + public static void Damage(Spell spell, IDamageable damageable, double damage, int phys, int fire, int cold, int pois, int nrgy) { TimeSpan ts = GetDamageDelayForSpell(spell); - Damage(spell, ts, target, spell.Caster, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard); + Damage(spell, ts, damageable, spell.Caster, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard); } - public static void Damage(Spell spell, Mobile target, double damage, int phys, int fire, int cold, int pois, int nrgy, DFAlgorithm dfa) + public static void Damage(Spell spell, IDamageable damageable, double damage, int phys, int fire, int cold, int pois, int nrgy, DFAlgorithm dfa) { TimeSpan ts = GetDamageDelayForSpell(spell); - Damage(spell, ts, target, spell.Caster, damage, phys, fire, cold, pois, nrgy, dfa); + Damage(spell, ts, damageable, spell.Caster, damage, phys, fire, cold, pois, nrgy, dfa); } - public static void Damage(Spell spell, Mobile target, double damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct) + public static void Damage(Spell spell, IDamageable damageable, double damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct) { TimeSpan ts = GetDamageDelayForSpell(spell); - Damage(spell, ts, target, spell.Caster, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard, chaos, direct); + Damage(spell, ts, damageable, spell.Caster, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard, chaos, direct); } - public static void Damage(TimeSpan delay, Mobile target, double damage, int phys, int fire, int cold, int pois, int nrgy) + public static void Damage(TimeSpan delay, IDamageable damageable, double damage, int phys, int fire, int cold, int pois, int nrgy) { - Damage(delay, target, null, damage, phys, fire, cold, pois, nrgy); + Damage(delay, damageable, null, damage, phys, fire, cold, pois, nrgy); } - public static void Damage(TimeSpan delay, Mobile target, double damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct) + public static void Damage(TimeSpan delay, IDamageable damageable, double damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct) { - Damage(null, delay, target, null, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard, chaos, direct); + Damage(null, delay, damageable, null, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard, chaos, direct); } - public static void Damage(TimeSpan delay, Mobile target, Mobile from, double damage, int phys, int fire, int cold, int pois, int nrgy) + public static void Damage(TimeSpan delay, IDamageable damageable, Mobile from, double damage, int phys, int fire, int cold, int pois, int nrgy) { - Damage(delay, target, from, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard); + Damage(delay, damageable, from, damage, phys, fire, cold, pois, nrgy, DFAlgorithm.Standard); } - public static void Damage(TimeSpan delay, Mobile target, Mobile from, double damage, int phys, int fire, int cold, int pois, int nrgy, DFAlgorithm dfa) + public static void Damage(TimeSpan delay, IDamageable damageable, Mobile from, double damage, int phys, int fire, int cold, int pois, int nrgy, DFAlgorithm dfa) { - Damage(null, delay, target, from, damage, phys, fire, cold, pois, nrgy, dfa); + Damage(null, delay, damageable, from, damage, phys, fire, cold, pois, nrgy, dfa); } - public static void Damage(Spell spell, TimeSpan delay, Mobile target, Mobile from, double damage, int phys, int fire, int cold, int pois, int nrgy, DFAlgorithm dfa, int chaos = 0, int direct = 0) + public static void Damage(Spell spell, TimeSpan delay, IDamageable damageable, Mobile from, double damage, int phys, int fire, int cold, int pois, int nrgy, DFAlgorithm dfa, int chaos = 0, int direct = 0) { + Mobile target = damageable as Mobile; int iDamage = (int)damage; if (delay == TimeSpan.Zero) { - if (from is BaseCreature) + if (from is BaseCreature && target != null) ((BaseCreature)from).AlterSpellDamageTo(target, ref iDamage); if (target is BaseCreature) @@ -1144,9 +1145,9 @@ public static void Damage(Spell spell, TimeSpan delay, Mobile target, Mobile fro WeightOverloading.DFA = dfa; - int damageGiven = AOS.Damage(target, from, iDamage, phys, fire, cold, pois, nrgy, chaos, direct); + int damageGiven = AOS.Damage(damageable, from, iDamage, phys, fire, cold, pois, nrgy, chaos, direct); - if (from != null) // sanity check + if (from != null && target != null) // sanity check { DoLeech(damageGiven, from, target); } @@ -1155,7 +1156,7 @@ public static void Damage(Spell spell, TimeSpan delay, Mobile target, Mobile fro } else { - new SpellDamageTimerAOS(spell, target, from, iDamage, phys, fire, cold, pois, nrgy, chaos, direct, delay, dfa).Start(); + new SpellDamageTimerAOS(spell, damageable, from, iDamage, phys, fire, cold, pois, nrgy, chaos, direct, delay, dfa).Start(); } if (target is BaseCreature && from != null && delay == TimeSpan.Zero) @@ -1254,7 +1255,7 @@ protected override void OnTick() private class SpellDamageTimerAOS : Timer { - private readonly Mobile m_Target; + private readonly IDamageable m_Target; private readonly Mobile m_From; @@ -1276,7 +1277,7 @@ private class SpellDamageTimerAOS : Timer private readonly DFAlgorithm m_DFA; private readonly Spell m_Spell; - public SpellDamageTimerAOS(Spell s, Mobile target, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, TimeSpan delay, DFAlgorithm dfa) + public SpellDamageTimerAOS(Spell s, IDamageable target, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, TimeSpan delay, DFAlgorithm dfa) : base(delay) { this.m_Target = target; @@ -1299,8 +1300,10 @@ public SpellDamageTimerAOS(Spell s, Mobile target, Mobile from, int damage, int protected override void OnTick() { - if (this.m_From is BaseCreature && this.m_Target != null) - ((BaseCreature)this.m_From).AlterSpellDamageTo(this.m_Target, ref this.m_Damage); + Mobile target = m_Target as Mobile; + + if (this.m_From is BaseCreature && target != null) + ((BaseCreature)this.m_From).AlterSpellDamageTo(target, ref this.m_Damage); if (this.m_Target is BaseCreature && this.m_From != null) ((BaseCreature)this.m_Target).AlterSpellDamageFrom(this.m_From, ref this.m_Damage); @@ -1309,9 +1312,9 @@ protected override void OnTick() int damageGiven = AOS.Damage(this.m_Target, this.m_From, this.m_Damage, this.m_Phys, this.m_Fire, this.m_Cold, this.m_Pois, this.m_Nrgy, this.m_Chaos, this.m_Direct); - if (this.m_From != null) // sanity check + if (this.m_From != null && target != null) // sanity check { - DoLeech(damageGiven, this.m_From, this.m_Target); + DoLeech(damageGiven, this.m_From, target); } WeightOverloading.DFA = DFAlgorithm.Standard; diff --git a/Scripts/Spells/Eighth/Earthquake.cs b/Scripts/Spells/Eighth/Earthquake.cs index 733e965cd0..07ab410032 100644 --- a/Scripts/Spells/Eighth/Earthquake.cs +++ b/Scripts/Spells/Eighth/Earthquake.cs @@ -37,44 +37,66 @@ public override void OnCast() { if (SpellHelper.CheckTown(this.Caster, this.Caster) && this.CheckSequence()) { - List targets = new List(); + List targets = new List(); Map map = this.Caster.Map; if (map != null) - foreach (Mobile m in this.Caster.GetMobilesInRange(1 + (int)(this.Caster.Skills[SkillName.Magery].Value / 15.0))) - if (this.Caster != m && SpellHelper.ValidIndirectTarget(this.Caster, m) && this.Caster.CanBeHarmful(m, false) && (!Core.AOS || this.Caster.InLOS(m))) - targets.Add(m); + { + IPooledEnumerable eable = this.Caster.GetObjectsInRange(1 + (int)(this.Caster.Skills[SkillName.Magery].Value / 15.0)); + + foreach (object o in eable) + { + IDamageable id = o as IDamageable; + + if (id == null || id is Mobile && (Mobile)id == this.Caster) + continue; + + if ((!(id is Mobile) || SpellHelper.ValidIndirectTarget(this.Caster, id as Mobile)) && this.Caster.CanBeHarmful(id, false)) + { + if (Core.AOS && !this.Caster.InLOS(id)) + continue; + + targets.Add(id); + } + } + + eable.Free(); + } this.Caster.PlaySound(0x220); for (int i = 0; i < targets.Count; ++i) { - Mobile m = targets[i]; + IDamageable id = targets[i]; + Mobile m = id as Mobile; int damage; if (Core.AOS) { - damage = m.Hits / 2; + damage = id.Hits / 2; - if (!m.Player) + if (m == null || !m.Player) damage = Math.Max(Math.Min(damage, 100), 15); damage += Utility.RandomMinMax(0, 15); } else { - damage = (m.Hits * 6) / 10; + damage = (id.Hits * 6) / 10; - if (!m.Player && damage < 10) + if ((m == null || !m.Player) && damage < 10) damage = 10; else if (damage > 75) damage = 75; } - this.Caster.DoHarmful(m); - SpellHelper.Damage(TimeSpan.Zero, m, this.Caster, damage, 100, 0, 0, 0, 0); + this.Caster.DoHarmful(id); + SpellHelper.Damage(TimeSpan.Zero, id, this.Caster, damage, 100, 0, 0, 0, 0); } + + targets.Clear(); + targets.TrimExcess(); } this.FinishSequence(); diff --git a/Scripts/Spells/Fifth/Paralyze.cs b/Scripts/Spells/Fifth/Paralyze.cs index a832f21f98..3f83f0ebf0 100644 --- a/Scripts/Spells/Fifth/Paralyze.cs +++ b/Scripts/Spells/Fifth/Paralyze.cs @@ -7,8 +7,6 @@ namespace Server.Spells.Fifth { public class ParalyzeSpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Paralyze", "An Ex Por", 218, diff --git a/Scripts/Spells/First/Clumsy.cs b/Scripts/Spells/First/Clumsy.cs index 792024c074..993f950058 100644 --- a/Scripts/Spells/First/Clumsy.cs +++ b/Scripts/Spells/First/Clumsy.cs @@ -5,8 +5,6 @@ namespace Server.Spells.First { public class ClumsySpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Clumsy", "Uus Jux", 212, diff --git a/Scripts/Spells/First/Feeblemind.cs b/Scripts/Spells/First/Feeblemind.cs index 44e6a386a9..4674692263 100644 --- a/Scripts/Spells/First/Feeblemind.cs +++ b/Scripts/Spells/First/Feeblemind.cs @@ -5,8 +5,6 @@ namespace Server.Spells.First { public class FeeblemindSpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Feeblemind", "Rel Wis", 212, diff --git a/Scripts/Spells/First/MagicArrow.cs b/Scripts/Spells/First/MagicArrow.cs index 9bfbe1c85e..7e2cc2f3a1 100644 --- a/Scripts/Spells/First/MagicArrow.cs +++ b/Scripts/Spells/First/MagicArrow.cs @@ -41,27 +41,30 @@ public override void OnCast() this.Caster.Target = new InternalTarget(this); } - public void Target(Mobile m) + public void Target(IDamageable d) { - if (!this.Caster.CanSee(m)) + Mobile m = d as Mobile; + + if (!this.Caster.CanSee(d)) { this.Caster.SendLocalizedMessage(500237); // Target can not be seen. } - else if (this.CheckHSequence(m)) + else if (this.CheckHSequence(d)) { Mobile source = this.Caster; - SpellHelper.Turn(source, m); + SpellHelper.Turn(source, d); - SpellHelper.CheckReflect((int)this.Circle, ref source, ref m); + if(m != null) + SpellHelper.CheckReflect((int)this.Circle, ref source, ref m); - double damage; + double damage = 0; if (Core.AOS) { - damage = this.GetNewAosDamage(10, 1, 4, m); + damage = this.GetNewAosDamage(10, 1, 4, d); } - else + else if (m != null) { damage = Utility.Random(4, 4); @@ -75,10 +78,13 @@ public void Target(Mobile m) damage *= this.GetDamageScalar(m); } - source.MovingParticles(m, 0x36E4, 5, 0, false, false, 3006, 0, 0); - source.PlaySound(0x1E5); + if (damage > 0) + { + source.MovingParticles(d, 0x36E4, 5, 0, false, false, 3006, 0, 0); + source.PlaySound(0x1E5); - SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + SpellHelper.Damage(this, d, damage, 0, 100, 0, 0, 0); + } } this.FinishSequence(); @@ -95,9 +101,9 @@ public InternalTarget(MagicArrowSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) + if (o is IDamageable) { - this.m_Owner.Target((Mobile)o); + this.m_Owner.Target((IDamageable)o); } } diff --git a/Scripts/Spells/First/Weaken.cs b/Scripts/Spells/First/Weaken.cs index 465816067f..28ffb82c42 100644 --- a/Scripts/Spells/First/Weaken.cs +++ b/Scripts/Spells/First/Weaken.cs @@ -5,8 +5,6 @@ namespace Server.Spells.First { public class WeakenSpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Weaken", "Des Mani", 212, diff --git a/Scripts/Spells/Fourth/Curse.cs b/Scripts/Spells/Fourth/Curse.cs index 148017f21e..f4db211533 100644 --- a/Scripts/Spells/Fourth/Curse.cs +++ b/Scripts/Spells/Fourth/Curse.cs @@ -6,8 +6,6 @@ namespace Server.Spells.Fourth { public class CurseSpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Curse", "Des Sanct", 227, diff --git a/Scripts/Spells/Fourth/Lightning.cs b/Scripts/Spells/Fourth/Lightning.cs index 9b25d7a9db..c3e2e5065e 100644 --- a/Scripts/Spells/Fourth/Lightning.cs +++ b/Scripts/Spells/Fourth/Lightning.cs @@ -35,8 +35,10 @@ public override void OnCast() this.Caster.Target = new InternalTarget(this); } - public void Target(Mobile m) + public void Target(IDamageable m) { + Mobile mob = m as Mobile; + if (!this.Caster.CanSee(m)) { this.Caster.SendLocalizedMessage(500237); // Target can not be seen. @@ -45,31 +47,35 @@ public void Target(Mobile m) { SpellHelper.Turn(this.Caster, m); - SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref m); + if(mob != null) + SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref mob); - double damage; + double damage = 0; if (Core.AOS) { damage = this.GetNewAosDamage(23, 1, 4, m); } - else + else if (mob != null) { damage = Utility.Random(12, 9); - if (this.CheckResisted(m)) + if (this.CheckResisted(mob)) { damage *= 0.75; - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + mob.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } - damage *= this.GetDamageScalar(m); + damage *= this.GetDamageScalar(mob); } - m.BoltEffect(0); + Effects.SendBoltEffect(m, true, 0); - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + if (damage > 0) + { + SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + } } this.FinishSequence(); @@ -86,8 +92,8 @@ public InternalTarget(LightningSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) - this.m_Owner.Target((Mobile)o); + if (o is IDamageable) + this.m_Owner.Target((IDamageable)o); } protected override void OnTargetFinish(Mobile from) diff --git a/Scripts/Spells/Fourth/ManaDrain.cs b/Scripts/Spells/Fourth/ManaDrain.cs index 22941e464a..c99e9f55db 100644 --- a/Scripts/Spells/Fourth/ManaDrain.cs +++ b/Scripts/Spells/Fourth/ManaDrain.cs @@ -6,8 +6,6 @@ namespace Server.Spells.Fourth { public class ManaDrainSpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Mana Drain", "Ort Rel", 215, diff --git a/Scripts/Spells/Mysticism/SpellDefinitions/MassSleepSpell.cs b/Scripts/Spells/Mysticism/SpellDefinitions/MassSleepSpell.cs index abc701c5ea..f7b5ba3b8d 100644 --- a/Scripts/Spells/Mysticism/SpellDefinitions/MassSleepSpell.cs +++ b/Scripts/Spells/Mysticism/SpellDefinitions/MassSleepSpell.cs @@ -12,7 +12,6 @@ namespace Server.Spells.Mystic public class MassSleepSpell : MysticSpell { public override SpellCircle Circle { get { return SpellCircle.Fifth; } } - public override bool CanDamageItems { get { return false; } } private static SpellInfo m_Info = new SpellInfo( "Mass Sleep", "Vas Zu", diff --git a/Scripts/Spells/Mysticism/SpellDefinitions/PurgeMagicSpell.cs b/Scripts/Spells/Mysticism/SpellDefinitions/PurgeMagicSpell.cs index f4bfe1a0f5..507b501283 100644 --- a/Scripts/Spells/Mysticism/SpellDefinitions/PurgeMagicSpell.cs +++ b/Scripts/Spells/Mysticism/SpellDefinitions/PurgeMagicSpell.cs @@ -29,7 +29,6 @@ public enum BuffType public class PurgeMagicSpell : MysticSpell { public override SpellCircle Circle { get { return SpellCircle.Second; } } - public override bool CanDamageItems { get { return false; } } private static SpellInfo m_Info = new SpellInfo( "Purge", "An Ort Sanct ", diff --git a/Scripts/Spells/Mysticism/SpellDefinitions/SleepSpell.cs b/Scripts/Spells/Mysticism/SpellDefinitions/SleepSpell.cs index 4529d54667..ef2c2cfe4a 100644 --- a/Scripts/Spells/Mysticism/SpellDefinitions/SleepSpell.cs +++ b/Scripts/Spells/Mysticism/SpellDefinitions/SleepSpell.cs @@ -11,7 +11,6 @@ namespace Server.Spells.Mystic { public class SleepSpell : MysticSpell { - public override bool CanDamageItems { get { return false; } } public override SpellCircle Circle { get { return SpellCircle.Third; } } private static SpellInfo m_Info = new SpellInfo( diff --git a/Scripts/Spells/Mysticism/SpellDefinitions/SpellPlague.cs b/Scripts/Spells/Mysticism/SpellDefinitions/SpellPlague.cs index 29dcdbc099..2ab7261f8d 100644 --- a/Scripts/Spells/Mysticism/SpellDefinitions/SpellPlague.cs +++ b/Scripts/Spells/Mysticism/SpellDefinitions/SpellPlague.cs @@ -9,7 +9,6 @@ namespace Server.Spells.Mystic { public class SpellPlagueSpell : MysticSpell { - public override bool CanDamageItems { get { return false; } } private static SpellInfo m_Info = new SpellInfo( "Spell Plague", "Vas Rel Jux Ort", 230, diff --git a/Scripts/Spells/Necromancy/BloodOathSpell.cs b/Scripts/Spells/Necromancy/BloodOathSpell.cs index 96262154aa..401d6efd80 100644 --- a/Scripts/Spells/Necromancy/BloodOathSpell.cs +++ b/Scripts/Spells/Necromancy/BloodOathSpell.cs @@ -7,8 +7,6 @@ namespace Server.Spells.Necromancy { public class BloodOathSpell : NecromancerSpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Blood Oath", "In Jux Mani Xen", 203, diff --git a/Scripts/Spells/Necromancy/CorpseSkin.cs b/Scripts/Spells/Necromancy/CorpseSkin.cs index f1642d5176..6abfbbf7a4 100644 --- a/Scripts/Spells/Necromancy/CorpseSkin.cs +++ b/Scripts/Spells/Necromancy/CorpseSkin.cs @@ -6,8 +6,6 @@ namespace Server.Spells.Necromancy { public class CorpseSkinSpell : NecromancerSpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Corpse Skin", "In Agle Corp Ylem", 203, diff --git a/Scripts/Spells/Necromancy/EvilOmen.cs b/Scripts/Spells/Necromancy/EvilOmen.cs index 07363d4e00..2dafb9b4be 100644 --- a/Scripts/Spells/Necromancy/EvilOmen.cs +++ b/Scripts/Spells/Necromancy/EvilOmen.cs @@ -7,8 +7,6 @@ namespace Server.Spells.Necromancy { public class EvilOmenSpell : NecromancerSpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Evil Omen", "Pas Tym An Sanct", 203, diff --git a/Scripts/Spells/Necromancy/MindRot.cs b/Scripts/Spells/Necromancy/MindRot.cs index 744f75056c..71c0e3d6c6 100644 --- a/Scripts/Spells/Necromancy/MindRot.cs +++ b/Scripts/Spells/Necromancy/MindRot.cs @@ -6,8 +6,6 @@ namespace Server.Spells.Necromancy { public class MindRotSpell : NecromancerSpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Mind Rot", "Wis An Ben", 203, diff --git a/Scripts/Spells/Necromancy/PainSpike.cs b/Scripts/Spells/Necromancy/PainSpike.cs index 7207e9e688..f95692ee68 100644 --- a/Scripts/Spells/Necromancy/PainSpike.cs +++ b/Scripts/Spells/Necromancy/PainSpike.cs @@ -6,8 +6,6 @@ namespace Server.Spells.Necromancy { public class PainSpikeSpell : NecromancerSpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Pain Spike", "In Sar", 203, diff --git a/Scripts/Spells/Necromancy/PoisonStrike.cs b/Scripts/Spells/Necromancy/PoisonStrike.cs index a8f935062d..a6fe04e1e8 100644 --- a/Scripts/Spells/Necromancy/PoisonStrike.cs +++ b/Scripts/Spells/Necromancy/PoisonStrike.cs @@ -51,10 +51,11 @@ public override void OnCast() this.Caster.Target = new InternalTarget(this); } - public void Target(Mobile m) + public void Target(IDamageable m) { if (this.CheckHSequence(m)) { + Mobile mob = m as Mobile; SpellHelper.Turn(this.Caster, m); /* Creates a blast of poisonous energy centered on the target. @@ -62,8 +63,6 @@ public void Target(Mobile m) * One tile from main target receives 50% damage, two tiles from target receives 33% damage. */ - //CheckResisted( m ); // Check magic resist for skill, but do not use return value //reports from OSI: Necro spells don't give Resist gain - Effects.SendLocationParticles(EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x36B0, 1, 14, 63, 7, 9915, 0); Effects.PlaySound(m.Location, m.Map, 0x229); @@ -96,31 +95,48 @@ public void Target(Mobile m) if (map != null) { - List targets = new List(); + List targets = new List(); if (this.Caster.CanBeHarmful(m, false)) targets.Add(m); - foreach (Mobile targ in m.GetMobilesInRange(2)) - if (!(this.Caster is BaseCreature && targ is BaseCreature)) - if ((targ != this.Caster && m != targ) && (SpellHelper.ValidIndirectTarget(this.Caster, targ) && this.Caster.CanBeHarmful(targ, false))) - targets.Add(targ); + IPooledEnumerable eable = m.Map.GetObjectsInRange(m.Location, 2); + + foreach (object o in eable) + { + IDamageable id = o as IDamageable; + + if (!(this.Caster is BaseCreature && id is BaseCreature)) + { + if ((id is Mobile && (Mobile)id == Caster) || id == m) + continue; + + if ((!(id is Mobile) || SpellHelper.ValidIndirectTarget(this.Caster, (Mobile)id)) && this.Caster.CanBeHarmful(id, false)) + targets.Add(id); + } + } + + eable.Free(); for (int i = 0; i < targets.Count; ++i) { - Mobile targ = targets[i]; + IDamageable id = targets[i]; + int num; - if (targ.InRange(m.Location, 0)) + if (Utility.InRange(id.Location, m.Location, 0)) num = 1; - else if (targ.InRange(m.Location, 1)) + else if (Utility.InRange(id.Location, m.Location, 1)) num = 2; else num = 3; - this.Caster.DoHarmful(targ); - SpellHelper.Damage(this, targ, ((m.Player && this.Caster.Player) ? pvpDamage : pvmDamage) / num, 0, 0, 0, 100, 0); + this.Caster.DoHarmful(id); + SpellHelper.Damage(this, id, ((id is PlayerMobile && this.Caster.Player) ? pvpDamage : pvmDamage) / num, 0, 0, 0, 100, 0); } + + targets.Clear(); + targets.TrimExcess(); } } @@ -138,8 +154,8 @@ public InternalTarget(PoisonStrikeSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) - this.m_Owner.Target((Mobile)o); + if (o is IDamageable) + this.m_Owner.Target((IDamageable)o); } protected override void OnTargetFinish(Mobile from) diff --git a/Scripts/Spells/Necromancy/Strangle.cs b/Scripts/Spells/Necromancy/Strangle.cs index 6dd5af9fef..781762b34f 100644 --- a/Scripts/Spells/Necromancy/Strangle.cs +++ b/Scripts/Spells/Necromancy/Strangle.cs @@ -6,8 +6,6 @@ namespace Server.Spells.Necromancy { public class StrangleSpell : NecromancerSpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Strangle", "In Bal Nox", 209, diff --git a/Scripts/Spells/Necromancy/Wither.cs b/Scripts/Spells/Necromancy/Wither.cs index 4c855ea24e..f693016a82 100644 --- a/Scripts/Spells/Necromancy/Wither.cs +++ b/Scripts/Spells/Necromancy/Wither.cs @@ -58,48 +58,67 @@ public override void OnCast() if (map != null) { - List targets = new List(); + List targets = new List(); BaseCreature cbc = this.Caster as BaseCreature; bool isMonster = (cbc != null && !cbc.Controlled && !cbc.Summoned); - foreach (Mobile m in this.Caster.GetMobilesInRange(Core.ML ? 4 : 5)) + IPooledEnumerable eable = this.Caster.GetObjectsInRange(Core.ML ? 4 : 5); + + foreach (object o in eable) { - if (this.Caster != m && this.Caster.InLOS(m) && (isMonster || SpellHelper.ValidIndirectTarget(this.Caster, m)) && this.Caster.CanBeHarmful(m, false)) + IDamageable id = o as IDamageable; + + if (id is Mobile && (Mobile)id == Caster) + continue; + + if (this.Caster.InLOS(id) && (!(id is Mobile) || isMonster || SpellHelper.ValidIndirectTarget(this.Caster, (Mobile)id)) && this.Caster.CanBeHarmful(id, false)) { if (isMonster) { - if (m is BaseCreature) + if (id is BaseCreature) { - BaseCreature bc = (BaseCreature)m; + BaseCreature bc = (BaseCreature)id; if (!bc.Controlled && !bc.Summoned && bc.Team == cbc.Team) continue; } - else if (!m.Player) + else if (!(id is PlayerMobile)) { continue; } } - targets.Add(m); + targets.Add(id); } } + eable.Free(); + Effects.PlaySound(this.Caster.Location, map, 0x1FB); Effects.PlaySound(this.Caster.Location, map, 0x10B); Effects.SendLocationParticles(EffectItem.Create(this.Caster.Location, map, EffectItem.DefaultDuration), 0x37CC, 1, 40, 97, 3, 9917, 0); for (int i = 0; i < targets.Count; ++i) { - Mobile m = targets[i]; + IDamageable id = targets[i]; + Mobile m = id as Mobile; + + this.Caster.DoHarmful(id); - this.Caster.DoHarmful(m); - m.FixedParticles(0x374A, 1, 15, 9502, 97, 3, (EffectLayer)255); + if (m != null) + { + m.FixedParticles(0x374A, 1, 15, 9502, 97, 3, (EffectLayer)255); + } + else + { + Effects.SendLocationParticles(id, 0x374A, 1, 30, 97, 3, 9502, 0); + } double damage = Utility.RandomMinMax(30, 35); + int karma = m != null ? m.Karma / 100 : 0; - damage *= (300 + (m.Karma / 100) + (this.GetDamageSkill(this.Caster) * 10)); + damage *= 300 + karma + (this.GetDamageSkill(this.Caster) * 10); damage /= 1000; int sdiBonus = AosAttributes.GetValue(this.Caster, AosAttribute.SpellDamage); @@ -120,7 +139,7 @@ public override void OnCast() sdiBonus += 3; } // PvP spell damage increase cap of 15% from an item’s magic property in Publish 33(SE) - if (Core.SE && m.Player && this.Caster.Player && sdiBonus > 15) + if (Core.SE && id is PlayerMobile && this.Caster.Player && sdiBonus > 15) sdiBonus = 15; damage *= (100 + sdiBonus); @@ -130,7 +149,7 @@ public override void OnCast() //if ( damage > 40 ) // damage = 40; - SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + SpellHelper.Damage(this, id, damage, 0, 0, 100, 0, 0); } } } diff --git a/Scripts/Spells/Ninjitsu/AnimalForm.cs b/Scripts/Spells/Ninjitsu/AnimalForm.cs index 334d15e2a0..4d0dba4647 100644 --- a/Scripts/Spells/Ninjitsu/AnimalForm.cs +++ b/Scripts/Spells/Ninjitsu/AnimalForm.cs @@ -624,10 +624,10 @@ protected override void OnTick() } else if (m_Body == 0x114) // Reptalon { - if (m_Mobile.Combatant != null && m_Mobile.Combatant != m_LastTarget) + if (m_Mobile.Combatant is Mobile && m_Mobile.Combatant != m_LastTarget) { m_Counter = 1; - m_LastTarget = m_Mobile.Combatant; + m_LastTarget = (Mobile)m_Mobile.Combatant; } if (m_Mobile.Warmode && m_LastTarget != null && m_LastTarget.Alive && !m_LastTarget.Deleted && m_Counter-- <= 0) diff --git a/Scripts/Spells/Second/Harm.cs b/Scripts/Spells/Second/Harm.cs index 1c0f07b929..1ead8c797c 100644 --- a/Scripts/Spells/Second/Harm.cs +++ b/Scripts/Spells/Second/Harm.cs @@ -40,8 +40,10 @@ public override double GetSlayerDamageScalar(Mobile target) return 1.0; //This spell isn't affected by slayer spellbooks } - public void Target(Mobile m) + public void Target(IDamageable m) { + Mobile mob = m as Mobile; + if (!this.Caster.CanSee(m)) { this.Caster.SendLocalizedMessage(500237); // Target can not be seen. @@ -50,45 +52,57 @@ public void Target(Mobile m) { SpellHelper.Turn(this.Caster, m); - SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref m); + if(mob != null) + SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref mob); - double damage; + double damage = 0; if (Core.AOS) { damage = this.GetNewAosDamage(17, 1, 5, m); } - else + else if (mob != null) { damage = Utility.Random(1, 15); - if (this.CheckResisted(m)) + if (this.CheckResisted(mob)) { damage *= 0.75; - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + mob.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } - damage *= this.GetDamageScalar(m); + damage *= this.GetDamageScalar(mob); } - if (!m.InRange(this.Caster, 2)) + if (!this.Caster.InRange(m, 2)) damage *= 0.25; // 1/4 damage at > 2 tile range - else if (!m.InRange(this.Caster, 1)) + else if (!this.Caster.InRange(m, 1)) damage *= 0.50; // 1/2 damage at 2 tile range if (Core.AOS) { - m.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist); - m.PlaySound(0x0FC); + if (mob != null) + { + mob.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist); + mob.PlaySound(0x0FC); + } + else + { + Effects.SendLocationParticles(m, 0x374A, 10, 30, 1153, 2, 5013, 0); + Effects.PlaySound(m.Location, m.Map, 0x0FC); + } } - else + else if (mob != null) { - m.FixedParticles(0x374A, 10, 15, 5013, EffectLayer.Waist); - m.PlaySound(0x1F1); + mob.FixedParticles(0x374A, 10, 15, 5013, EffectLayer.Waist); + mob.PlaySound(0x1F1); } - SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + if (damage > 0) + { + SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + } } this.FinishSequence(); @@ -105,9 +119,9 @@ public InternalTarget(HarmSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) + if (o is IDamageable) { - this.m_Owner.Target((Mobile)o); + this.m_Owner.Target((IDamageable)o); } } diff --git a/Scripts/Spells/Seventh/ChainLightning.cs b/Scripts/Spells/Seventh/ChainLightning.cs index 0d1e987fc2..8eb30eb2c3 100644 --- a/Scripts/Spells/Seventh/ChainLightning.cs +++ b/Scripts/Spells/Seventh/ChainLightning.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Server.Targeting; +using Server.Mobiles; namespace Server.Spells.Seventh { @@ -52,25 +53,27 @@ public void Target(IPoint3D p) if (p is Item) p = ((Item)p).GetWorldLocation(); - List targets = new List(); + List targets = new List(); Map map = this.Caster.Map; if (map != null) { - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), 2); + IPooledEnumerable eable = map.GetObjectsInRange(new Point3D(p), 2); - foreach (Mobile m in eable) + foreach (object o in eable) { - if (Core.AOS && m == this.Caster) + IDamageable id = o as IDamageable; + + if (id == null || (Core.AOS && id is Mobile && (Mobile)id == this.Caster)) continue; - if (SpellHelper.ValidIndirectTarget(this.Caster, m) && this.Caster.CanBeHarmful(m, false)) + if ((!(id is Mobile) || SpellHelper.ValidIndirectTarget(this.Caster, id as Mobile)) && this.Caster.CanBeHarmful(id, false)) { - if (Core.AOS && !this.Caster.InLOS(m)) + if (Core.AOS && !this.Caster.InLOS(id)) continue; - targets.Add(m); + targets.Add(id); } } @@ -83,10 +86,11 @@ public void Target(IPoint3D p) { for (int i = 0; i < targets.Count; ++i) { - Mobile m = targets[i]; + IDamageable id = targets[i]; + Mobile m = id as Mobile; if (Core.AOS) - damage = this.GetNewAosDamage(51, 1, 5, m.Player, m); + damage = this.GetNewAosDamage(51, 1, 5, id is PlayerMobile, id); else damage = Utility.Random(27, 22); @@ -95,24 +99,29 @@ public void Target(IPoint3D p) else if (!Core.AOS) damage /= targets.Count; - if (!Core.AOS && this.CheckResisted(m)) + if (!Core.AOS && m != null && this.CheckResisted(m)) { damage *= 0.5; m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } - damage *= this.GetDamageScalar(m); - this.Caster.DoHarmful(m); - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + if(m != null) + damage *= this.GetDamageScalar(m); + + this.Caster.DoHarmful(id); + SpellHelper.Damage(this, id, damage, 0, 0, 0, 0, 100); - m.BoltEffect(0); + Effects.SendBoltEffect(id, true, 0); } } else { this.Caster.PlaySound(0x29); } + + targets.Clear(); + targets.TrimExcess(); } this.FinishSequence(); diff --git a/Scripts/Spells/Seventh/FlameStrike.cs b/Scripts/Spells/Seventh/FlameStrike.cs index ef158c8eac..3ffa98aa17 100644 --- a/Scripts/Spells/Seventh/FlameStrike.cs +++ b/Scripts/Spells/Seventh/FlameStrike.cs @@ -35,8 +35,10 @@ public override void OnCast() this.Caster.Target = new InternalTarget(this); } - public void Target(Mobile m) + public void Target(IDamageable m) { + Mobile mob = m as Mobile; + if (!this.Caster.CanSee(m)) { this.Caster.SendLocalizedMessage(500237); // Target can not be seen. @@ -45,32 +47,44 @@ public void Target(Mobile m) { SpellHelper.Turn(this.Caster, m); - SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref m); + if(mob != null) + SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref mob); - double damage; + double damage = 0; if (Core.AOS) { damage = this.GetNewAosDamage(48, 1, 5, m); } - else + else if (mob != null) { damage = Utility.Random(27, 22); - if (this.CheckResisted(m)) + if (this.CheckResisted(mob)) { damage *= 0.6; - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + mob.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } - damage *= this.GetDamageScalar(m); + damage *= this.GetDamageScalar(mob); } - m.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot); - m.PlaySound(0x208); + if (mob != null) + { + mob.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot); + mob.PlaySound(0x208); + } + else + { + Effects.SendLocationParticles(m, 0x3709, 10, 30, 5052); + Effects.PlaySound(m.Location, m.Map, 0x208); + } - SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + if (damage > 0) + { + SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + } } this.FinishSequence(); @@ -87,9 +101,9 @@ public InternalTarget(FlameStrikeSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) + if (o is IDamageable) { - this.m_Owner.Target((Mobile)o); + this.m_Owner.Target((IDamageable)o); } } diff --git a/Scripts/Spells/Seventh/ManaVampire.cs b/Scripts/Spells/Seventh/ManaVampire.cs index 2f8e1d539e..3538a70e3c 100644 --- a/Scripts/Spells/Seventh/ManaVampire.cs +++ b/Scripts/Spells/Seventh/ManaVampire.cs @@ -5,8 +5,6 @@ namespace Server.Spells.Seventh { public class ManaVampireSpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Mana Vampire", "Ort Sanct", 221, diff --git a/Scripts/Spells/Seventh/MeteorSwarm.cs b/Scripts/Spells/Seventh/MeteorSwarm.cs index 36756528b4..63bb2095e1 100644 --- a/Scripts/Spells/Seventh/MeteorSwarm.cs +++ b/Scripts/Spells/Seventh/MeteorSwarm.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Server.Targeting; +using Server.Mobiles; namespace Server.Spells.Seventh { @@ -52,22 +53,27 @@ public void Target(IPoint3D p) if (p is Item) p = ((Item)p).GetWorldLocation(); - List targets = new List(); + List targets = new List(); Map map = this.Caster.Map; if (map != null) { - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), 2); + IPooledEnumerable eable = map.GetObjectsInRange(new Point3D(p), 2); - foreach (Mobile m in eable) + foreach (object o in eable) { - if (this.Caster != m && SpellHelper.ValidIndirectTarget(this.Caster, m) && this.Caster.CanBeHarmful(m, false)) + IDamageable id = o as IDamageable; + + if (id == null || (Core.AOS && id is Mobile && (Mobile)id == this.Caster)) + continue; + + if ((!(id is Mobile) || SpellHelper.ValidIndirectTarget(this.Caster, id as Mobile)) && this.Caster.CanBeHarmful(id, false)) { - if (Core.AOS && !this.Caster.InLOS(m)) + if (Core.AOS && !this.Caster.InLOS(id)) continue; - targets.Add(m); + targets.Add(id); } } @@ -82,10 +88,11 @@ public void Target(IPoint3D p) for (int i = 0; i < targets.Count; ++i) { - Mobile m = targets[i]; + IDamageable id = targets[i]; + Mobile m = id as Mobile; if (Core.AOS) - damage = this.GetNewAosDamage(51, 1, 5, m.Player, m); + damage = this.GetNewAosDamage(51, 1, 5, id is PlayerMobile, id); else damage = Utility.Random(27, 22); @@ -94,20 +101,25 @@ public void Target(IPoint3D p) else if (!Core.AOS) damage /= targets.Count; - if (!Core.AOS && this.CheckResisted(m)) + if (!Core.AOS && m != null && this.CheckResisted(m)) { damage *= 0.5; m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } - damage *= this.GetDamageScalar(m); - this.Caster.DoHarmful(m); - SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + if(m != null) + damage *= this.GetDamageScalar(m); - this.Caster.MovingParticles(m, 0x36D4, 7, 0, false, true, 9501, 1, 0, 0x100); + this.Caster.DoHarmful(id); + SpellHelper.Damage(this, id, damage, 0, 100, 0, 0, 0); + + this.Caster.MovingParticles(id, 0x36D4, 7, 0, false, true, 9501, 1, 0, 0x100); } } + + targets.Clear(); + targets.TrimExcess(); } this.FinishSequence(); diff --git a/Scripts/Spells/Sixth/EnergyBolt.cs b/Scripts/Spells/Sixth/EnergyBolt.cs index c17bf11080..c6b2ca1f55 100644 --- a/Scripts/Spells/Sixth/EnergyBolt.cs +++ b/Scripts/Spells/Sixth/EnergyBolt.cs @@ -35,8 +35,10 @@ public override void OnCast() this.Caster.Target = new InternalTarget(this); } - public void Target(Mobile m) + public void Target(IDamageable m) { + Mobile mob = m as Mobile; + if (!this.Caster.CanSee(m)) { this.Caster.SendLocalizedMessage(500237); // Target can not be seen. @@ -47,35 +49,39 @@ public void Target(Mobile m) SpellHelper.Turn(this.Caster, m); - SpellHelper.CheckReflect((int)this.Circle, ref source, ref m); + if(mob != null) + SpellHelper.CheckReflect((int)this.Circle, ref source, ref mob); - double damage; + double damage = 0; if (Core.AOS) { damage = this.GetNewAosDamage(40, 1, 5, m); } - else + else if (mob != null) { damage = Utility.Random(24, 18); - if (this.CheckResisted(m)) + if (this.CheckResisted(mob)) { damage *= 0.75; - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + mob.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } // Scale damage based on evalint and resist - damage *= this.GetDamageScalar(m); + damage *= this.GetDamageScalar(mob); } // Do the effects source.MovingParticles(m, 0x379F, 7, 0, false, true, 3043, 4043, 0x211); source.PlaySound(0x20A); - // Deal the damage - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + if (damage > 0) + { + // Deal the damage + SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + } } this.FinishSequence(); @@ -92,8 +98,8 @@ public InternalTarget(EnergyBoltSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) - this.m_Owner.Target((Mobile)o); + if (o is IDamageable) + this.m_Owner.Target((IDamageable)o); } protected override void OnTargetFinish(Mobile from) diff --git a/Scripts/Spells/Sixth/Explosion.cs b/Scripts/Spells/Sixth/Explosion.cs index ffdc8d8f49..18138bd105 100644 --- a/Scripts/Spells/Sixth/Explosion.cs +++ b/Scripts/Spells/Sixth/Explosion.cs @@ -42,21 +42,24 @@ public override void OnCast() this.Caster.Target = new InternalTarget(this); } - public void Target(Mobile m) + public void Target(IDamageable m) { + Mobile defender = m as Mobile; + if (!this.Caster.CanSee(m)) { this.Caster.SendLocalizedMessage(500237); // Target can not be seen. } else if (this.Caster.CanBeHarmful(m) && this.CheckSequence()) { - Mobile attacker = this.Caster, defender = m; + Mobile attacker = this.Caster; SpellHelper.Turn(this.Caster, m); - SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref m); + if(defender != null) + SpellHelper.CheckReflect((int)this.Circle, this.Caster, ref defender); - InternalTimer t = new InternalTimer(this, attacker, defender, m); + InternalTimer t = new InternalTimer(this, attacker, defender != null ? defender : m); t.Start(); } @@ -66,16 +69,15 @@ public void Target(Mobile m) private class InternalTimer : Timer { private readonly MagerySpell m_Spell; - private readonly Mobile m_Target; + private readonly IDamageable m_Target; private readonly Mobile m_Attacker; - private readonly Mobile m_Defender; - public InternalTimer(MagerySpell spell, Mobile attacker, Mobile defender, Mobile target) + + public InternalTimer(MagerySpell spell, Mobile attacker, IDamageable target) : base(TimeSpan.FromSeconds(Core.AOS ? 3.0 : 2.5)) { - this.m_Spell = spell; - this.m_Attacker = attacker; - this.m_Defender = defender; - this.m_Target = target; + m_Spell = spell; + m_Attacker = attacker; + m_Target = target; if (this.m_Spell != null) this.m_Spell.StartDelayedDamageContext(attacker, this); @@ -85,32 +87,45 @@ public InternalTimer(MagerySpell spell, Mobile attacker, Mobile defender, Mobile protected override void OnTick() { - if (this.m_Attacker.HarmfulCheck(this.m_Defender)) + Mobile defender = m_Target as Mobile; + + if (m_Attacker.HarmfulCheck(m_Target)) { - double damage; + double damage = 0; if (Core.AOS) { - damage = this.m_Spell.GetNewAosDamage(40, 1, 5, this.m_Defender); + damage = this.m_Spell.GetNewAosDamage(40, 1, 5, m_Target); } - else + else if (defender != null) { damage = Utility.Random(23, 22); - if (this.m_Spell.CheckResisted(this.m_Target)) + if (this.m_Spell.CheckResisted(defender)) { damage *= 0.75; - this.m_Target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + defender.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } - damage *= this.m_Spell.GetDamageScalar(this.m_Target); + damage *= this.m_Spell.GetDamageScalar(defender); } - this.m_Target.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - this.m_Target.PlaySound(0x307); + if (defender != null) + { + defender.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + defender.PlaySound(0x307); + } + else + { + Effects.SendLocationParticles(m_Target, 0x36BD, 20, 10, 5044); + Effects.PlaySound(m_Target.Location, m_Target.Map, 0x307); + } - SpellHelper.Damage(this.m_Spell, this.m_Target, damage, 0, 100, 0, 0, 0); + if (damage > 0) + { + SpellHelper.Damage(this.m_Spell, this.m_Target, damage, 0, 100, 0, 0, 0); + } if (this.m_Spell != null) this.m_Spell.RemoveDelayedDamageContext(this.m_Attacker); @@ -129,8 +144,8 @@ public InternalTarget(ExplosionSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) - this.m_Owner.Target((Mobile)o); + if (o is IDamageable) + this.m_Owner.Target((IDamageable)o); } protected override void OnTargetFinish(Mobile from) diff --git a/Scripts/Spells/Spellweaving/WordOfDeath.cs b/Scripts/Spells/Spellweaving/WordOfDeath.cs index 7b0ea46dcf..53e7674e65 100644 --- a/Scripts/Spells/Spellweaving/WordOfDeath.cs +++ b/Scripts/Spells/Spellweaving/WordOfDeath.cs @@ -6,8 +6,6 @@ namespace Server.Spells.Spellweaving { public class WordOfDeathSpell : ArcanistSpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo("Word of Death", "Nyraxle", -1); public WordOfDeathSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info) diff --git a/Scripts/Spells/Third/Fireball.cs b/Scripts/Spells/Third/Fireball.cs index 457a4b9783..9acbf270ea 100644 --- a/Scripts/Spells/Third/Fireball.cs +++ b/Scripts/Spells/Third/Fireball.cs @@ -34,7 +34,7 @@ public override void OnCast() this.Caster.Target = new InternalTarget(this); } - public void Target(Mobile m) + public void Target(IDamageable m) { if (!this.Caster.CanSee(m)) { @@ -43,35 +43,40 @@ public void Target(Mobile m) else if (this.CheckHSequence(m)) { Mobile source = this.Caster; + Mobile target = m as Mobile; SpellHelper.Turn(source, m); - SpellHelper.CheckReflect((int)this.Circle, ref source, ref m); + if(target != null) + SpellHelper.CheckReflect((int)this.Circle, ref source, ref target); - double damage; + double damage = 0; if (Core.AOS) { damage = this.GetNewAosDamage(19, 1, 5, m); } - else + else if (target != null) { damage = Utility.Random(10, 7); - if (this.CheckResisted(m)) + if (this.CheckResisted(target)) { damage *= 0.75; - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. } - damage *= this.GetDamageScalar(m); + damage *= this.GetDamageScalar(target); } - source.MovingParticles(m, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160); - source.PlaySound(Core.AOS ? 0x15E : 0x44B); + if (damage > 0) + { + source.MovingParticles(m, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160); + source.PlaySound(Core.AOS ? 0x15E : 0x44B); - SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + } } this.FinishSequence(); @@ -88,8 +93,8 @@ public InternalTarget(FireballSpell owner) protected override void OnTarget(Mobile from, object o) { - if (o is Mobile) - this.m_Owner.Target((Mobile)o); + if (o is IDamageable) + this.m_Owner.Target((IDamageable)o); } protected override void OnTargetFinish(Mobile from) diff --git a/Scripts/Spells/Third/Poison.cs b/Scripts/Spells/Third/Poison.cs index 1054fc8285..ea0d220828 100644 --- a/Scripts/Spells/Third/Poison.cs +++ b/Scripts/Spells/Third/Poison.cs @@ -5,8 +5,6 @@ namespace Server.Spells.Third { public class PoisonSpell : MagerySpell { - public override bool CanDamageItems { get { return false; } } - private static readonly SpellInfo m_Info = new SpellInfo( "Poison", "In Nox", 203, diff --git a/Server/Interfaces.cs b/Server/Interfaces.cs index 9df16bebd6..4866e642a0 100644 --- a/Server/Interfaces.cs +++ b/Server/Interfaces.cs @@ -56,8 +56,8 @@ public interface ICarvable public interface IWeapon { int MaxRange { get; } - void OnBeforeSwing(Mobile attacker, Mobile defender); - TimeSpan OnSwing(Mobile attacker, Mobile defender); + void OnBeforeSwing(Mobile attacker, IDamageable damageable); + TimeSpan OnSwing(Mobile attacker, IDamageable damageable); void GetStatusDamage(Mobile from, out int min, out int max); } @@ -103,8 +103,20 @@ public interface ISpawnable : IEntity ISpawner Spawner { get; set; } } - public interface IDamageableItem : IEntity + public interface IDamageable : IEntity { - Mobile Link { get; } + string Name { get; set; } + int Hits { get; set; } + int HitsMax { get; } + bool Alive { get; } + + int PhysicalResistance { get; } + int FireResistance { get; } + int ColdResistance { get; } + int PoisonResistance { get; } + int EnergyResistance { get; } + + void OnStatsQuery(Mobile from); + void Damage(int amount, Mobile from); } } \ No newline at end of file diff --git a/Server/Mobile.cs b/Server/Mobile.cs index 25a6c3019d..16565a685d 100644 --- a/Server/Mobile.cs +++ b/Server/Mobile.cs @@ -495,7 +495,7 @@ public MobileNotConnectedException(Mobile source, string message) public delegate bool AllowBeneficialHandler(Mobile from, Mobile target); - public delegate bool AllowHarmfulHandler(Mobile from, Mobile target); + public delegate bool AllowHarmfulHandler(Mobile from, IDamageable target); public delegate Container CreateCorpseHandler( Mobile from, HairInfo hair, FacialHairInfo facialhair, List initialContent, List equipedItems); @@ -507,7 +507,7 @@ public MobileNotConnectedException(Mobile source, string message) /// Base class representing players, npcs, and creatures. /// [System.Runtime.InteropServices.ComVisible(true)] - public class Mobile : IEntity, IHued, IComparable, ISerializable, ISpawnable + public class Mobile : IEntity, IHued, IComparable, ISerializable, ISpawnable, IDamageable { #region CompareTo(...) public int CompareTo(IEntity other) @@ -746,7 +746,7 @@ public bool Expired() private Prompt m_Prompt; private ContextMenu m_ContextMenu; private List m_Aggressors, m_Aggressed; - private Mobile m_Combatant; + private IDamageable m_Combatant; private List m_Stabled; private bool m_AutoPageNotify; private bool m_CanHearGhosts; @@ -2078,11 +2078,11 @@ protected override void OnTick() { if (Core.TickCount - m_Mobile.m_NextCombatTime >= 0) { - Mobile combatant = m_Mobile.Combatant; + IDamageable combatant = m_Mobile.Combatant; // If no combatant, wrong map, one of us is a ghost, or cannot see, or deleted, then stop combat - if (combatant == null || combatant.m_Deleted || m_Mobile.m_Deleted || combatant.m_Map != m_Mobile.m_Map || - !combatant.Alive || !m_Mobile.Alive || !m_Mobile.CanSee(combatant) || combatant.IsDeadBondedPet || + if (combatant == null || combatant.Deleted || m_Mobile.m_Deleted || combatant.Map != m_Mobile.m_Map || + !combatant.Alive || !m_Mobile.Alive || !m_Mobile.CanSee(combatant) || (combatant is Mobile && ((Mobile)combatant).IsDeadBondedPet) || m_Mobile.IsDeadBondedPet) { m_Mobile.Combatant = null; @@ -2096,12 +2096,12 @@ protected override void OnTick() return; } - if (m_Mobile.InLOS(combatant)) - { - weapon.OnBeforeSwing(m_Mobile, combatant); //OnBeforeSwing for checking in regards to being hidden and whatnot - m_Mobile.RevealingAction(); - m_Mobile.m_NextCombatTime = Core.TickCount + (int)weapon.OnSwing(m_Mobile, combatant).TotalMilliseconds; - } + if (m_Mobile.InLOS(combatant)) + { + weapon.OnBeforeSwing(m_Mobile, combatant); //OnBeforeSwing for checking in regards to being hidden and whatnot + m_Mobile.RevealingAction(); + m_Mobile.m_NextCombatTime = Core.TickCount + (int)weapon.OnSwing(m_Mobile, combatant).TotalMilliseconds; + } } } } @@ -2181,17 +2181,17 @@ protected override void OnTick() public bool ChangingCombatant { get { return (m_ChangingCombatant > 0); } } - public virtual void Attack(Mobile m) + public virtual void Attack(IDamageable e) { - if (CheckAttack(m)) + if (CheckAttack(e)) { - Combatant = m; + Combatant = e; } } - public virtual bool CheckAttack(Mobile m) + public virtual bool CheckAttack(IDamageable e) { - return (Utility.InUpdateRange(this, m) && CanSee(m) && InLOS(m)); + return (Utility.InUpdateRange(this, e.Location) && CanSee(e) && InLOS(e)); } /// @@ -2199,7 +2199,7 @@ public virtual bool CheckAttack(Mobile m) /// /// [CommandProperty(AccessLevel.GameMaster)] - public virtual Mobile Combatant + public virtual IDamageable Combatant { get { return m_Combatant; } set @@ -2211,7 +2211,7 @@ public virtual Mobile Combatant if (m_Combatant != value && value != this) { - Mobile old = m_Combatant; + IDamageable old = m_Combatant; ++m_ChangingCombatant; m_Combatant = value; @@ -2264,9 +2264,9 @@ public virtual Mobile Combatant { DoHarmful(m_Combatant); - if (m_Combatant != null) + if (m_Combatant is Mobile) { - m_Combatant.PlaySound(m_Combatant.GetAngerSound()); + ((Mobile)m_Combatant).PlaySound(((Mobile)m_Combatant).GetAngerSound()); } } @@ -7716,33 +7716,45 @@ public virtual bool BeneficialCheck(Mobile target) #endregion #region Harmful Checks/Actions - public virtual bool CanBeHarmful(Mobile target) + public virtual bool CanBeHarmful(IDamageable target) { return CanBeHarmful(target, true); } - public virtual bool CanBeHarmful(Mobile target, bool message) + public virtual bool CanBeHarmful(IDamageable target, bool message) { return CanBeHarmful(target, message, false); } - public virtual bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness) + public virtual bool CanBeHarmful(IDamageable target, bool message, bool ignoreOurBlessedness) { - if (target == null) + if (target == null) { return false; } - if (m_Deleted || (!ignoreOurBlessedness && m_Blessed) || target.m_Deleted || target.m_Blessed || !Alive || - IsDeadBondedPet || !target.Alive || target.IsDeadBondedPet) - { - if (message) - { - SendLocalizedMessage(1001018); // You can not perform negative acts on your target. - } + if (m_Deleted || (!ignoreOurBlessedness && m_Blessed) || !Alive || IsDeadBondedPet || target.Deleted) + { + if (message) + { + SendLocalizedMessage(1001018); // You can not perform negative acts on your target. + } - return false; - } + return false; + } + + if (target is Mobile) + { + if (((Mobile)target).m_Blessed || !((Mobile)target).Alive || ((Mobile)target).IsDeadBondedPet) + { + if (message) + { + SendLocalizedMessage(1001018); // You can not perform negative acts on your target. + } + + return false; + } + } if (target == this) { @@ -7764,7 +7776,7 @@ public virtual bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBles return true; } - public virtual bool IsHarmfulCriminal(Mobile target) + public virtual bool IsHarmfulCriminal(IDamageable target) { if (this == target) { @@ -7777,7 +7789,7 @@ public virtual bool IsHarmfulCriminal(Mobile target) /// /// Overridable. Event invoked when the Mobile does a harmful action. /// - public virtual void OnHarmfulAction(Mobile target, bool isCriminal) + public virtual void OnHarmfulAction(IDamageable target, bool isCriminal) { if (isCriminal) { @@ -7785,12 +7797,12 @@ public virtual void OnHarmfulAction(Mobile target, bool isCriminal) } } - public virtual void DoHarmful(Mobile target) + public virtual void DoHarmful(IDamageable target) { - DoHarmful(target, false); + DoHarmful(target, false); } - public virtual void DoHarmful(Mobile target, bool indirect) + public virtual void DoHarmful(IDamageable target, bool indirect) { if (target == null || m_Deleted) { @@ -7800,10 +7812,16 @@ public virtual void DoHarmful(Mobile target, bool indirect) bool isCriminal = IsHarmfulCriminal(target); OnHarmfulAction(target, isCriminal); - target.AggressiveAction(this, isCriminal); + + if(target is Mobile) + ((Mobile)target).AggressiveAction(this, isCriminal); Region.OnDidHarmful(this, target); - target.Region.OnGotHarmful(this, target); + + if(target is Mobile) + ((Mobile)target).Region.OnGotHarmful(this, target); + else if (target is Item) + Region.Find(target.Location, target.Map).OnGotHarmful(this, target); if (!indirect) { @@ -7822,7 +7840,7 @@ public virtual void DoHarmful(Mobile target, bool indirect) m_ExpireCombatant.Start(); } - public virtual bool HarmfulCheck(Mobile target) + public virtual bool HarmfulCheck(IDamageable target) { if (CanBeHarmful(target)) { diff --git a/Server/Network/PacketHandlers.cs b/Server/Network/PacketHandlers.cs index 8628e9bb02..6a745fed12 100644 --- a/Server/Network/PacketHandlers.cs +++ b/Server/Network/PacketHandlers.cs @@ -626,16 +626,16 @@ public static void RequestScrollWindow(NetState state, PacketReader pvSrc) int type = pvSrc.ReadByte(); } - public static void AttackReq(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - Mobile m = World.FindMobile(pvSrc.ReadInt32()); + public static void AttackReq(NetState state, PacketReader pvSrc) + { + Mobile from = state.Mobile; + Mobile m = World.FindMobile(pvSrc.ReadInt32()); - if (m != null) - { - from.Attack(m); - } - } + if (m != null) + { + from.Attack(m); + } + } public static void HuePickerResponse(NetState state, PacketReader pvSrc) { @@ -1313,9 +1313,6 @@ public static void TargetResponse(NetState state, PacketReader pvSrc) else if (serial.IsItem) { toTarget = World.FindItem(serial); - - if (toTarget is IDamageableItem && ((IDamageableItem)toTarget).Link != null && (t.Flags & TargetFlags.Harmful) != 0) - toTarget = ((IDamageableItem)toTarget).Link; } else { @@ -2227,38 +2224,78 @@ public static void MobileQuery(NetState state, PacketReader pvSrc) pvSrc.ReadInt32(); // 0xEDEDEDED int type = pvSrc.ReadByte(); - Mobile m = World.FindMobile(pvSrc.ReadInt32()); - if (m != null) - { - switch (type) - { - case 0x00: // Unknown, sent by godclient - { - if (VerifyGC(state)) - { - Console.WriteLine("God Client: {0}: Query 0x{1:X2} on {2} '{3}'", state, type, m.Serial, m.Name); - } - - break; - } - case 0x04: // Stats - { - m.OnStatsQuery(from); - break; - } - case 0x05: - { - m.OnSkillsQuery(from); - break; - } - default: - { - pvSrc.Trace(state); - break; - } - } - } + Serial serial = pvSrc.ReadInt32(); + + if (serial.IsMobile) + { + Mobile m = World.FindMobile(serial); + + if (m != null) + { + switch (type) + { + case 0x00: // Unknown, sent by godclient + { + if (VerifyGC(state)) + { + Console.WriteLine("God Client: {0}: Query 0x{1:X2} on {2} '{3}'", state, type, serial, m.Name); + } + + break; + } + case 0x04: // Stats + { + m.OnStatsQuery(from); + break; + } + case 0x05: + { + m.OnSkillsQuery(from); + break; + } + default: + { + pvSrc.Trace(state); + break; + } + } + } + } + else if (serial.IsItem) + { + IDamageable item = World.FindItem(serial) as IDamageable; + + if (item != null) + { + switch (type) + { + case 0x00: + { + if (VerifyGC(state)) + { + Console.WriteLine("God Client: {0}: Query 0x{1:X2} on {2} '{3}'", state, type, serial, item.Name); + } + + break; + } + case 0x04: // Stats + { + item.OnStatsQuery(from); + break; + } + case 0x05: + { + break; + } + default: + { + pvSrc.Trace(state); + break; + } + } + } + } } public delegate void PlayCharCallback(NetState state, bool val); diff --git a/Server/Network/Packets.cs b/Server/Network/Packets.cs index d9fc87c4e7..b80b4e3c28 100644 --- a/Server/Network/Packets.cs +++ b/Server/Network/Packets.cs @@ -87,10 +87,10 @@ public DamagePacketOld(Mobile m, int amount) public sealed class DamagePacket : Packet { - public DamagePacket(Mobile m, int amount) + public DamagePacket(IDamageable damageable, int amount) : base(0x0B, 7) { - m_Stream.Write(m.Serial); + m_Stream.Write(damageable.Serial); if (amount > 0xFFFF) { @@ -623,7 +623,7 @@ public ChangeUpdateRange(int range) public sealed class ChangeCombatant : Packet { - public ChangeCombatant(Mobile combatant) + public ChangeCombatant(IEntity combatant) : base(0xAA, 5) { m_Stream.Write(combatant != null ? combatant.Serial : Serial.Zero); @@ -1311,10 +1311,15 @@ public WorldItemHS(Item item) int itemID = item.ItemID; + if(item is BaseMulti) + m_Stream.Write((byte)0x02); + else if (item is IDamageable) + m_Stream.Write((byte)0x03); + else + m_Stream.Write((byte)0x00); + if (item is BaseMulti) { - m_Stream.Write((byte)0x02); - m_Stream.Write(item.Serial); itemID &= 0x3FFF; @@ -1322,16 +1327,9 @@ public WorldItemHS(Item item) m_Stream.Write((ushort)itemID); m_Stream.Write((byte)0); - /*} else if ( ) { - m_Stream.Write( (byte) 0x01 ); - m_Stream.Write( (int) item.Serial ); - m_Stream.Write( (ushort) itemID ); - m_Stream.Write( (byte) item.Direction );*/ } else { - m_Stream.Write((byte)0x00); - m_Stream.Write(item.Serial); itemID &= 0xFFFF; @@ -1366,9 +1364,15 @@ public WorldItemHS(Item item, PacketWriter stream) int itemID = item.ItemID; + if (item is BaseMulti) + m_Stream.Write((byte)0x02); + else if (item is IDamageable) + m_Stream.Write((byte)0x03); + else + m_Stream.Write((byte)0x00); + if (item is BaseMulti) { - stream.Write((byte)0x02); stream.Write((int)item.Serial); itemID &= 0x3FFF; stream.Write((ushort)itemID); @@ -1376,7 +1380,6 @@ public WorldItemHS(Item item, PacketWriter stream) } else { - stream.Write((byte)0x00); stream.Write((int)item.Serial); itemID &= 0xFFFF; stream.Write((ushort)itemID); @@ -2369,7 +2372,7 @@ public SetWarMode(bool mode) public sealed class Swing : Packet { - public Swing(int flag, Mobile attacker, Mobile defender) + public Swing(int flag, Mobile attacker, IDamageable defender) : base(0x2F, 10) { m_Stream.Write((byte)flag); @@ -3308,11 +3311,11 @@ public MobileHits(Mobile m) public sealed class MobileHitsN : Packet { - public MobileHitsN(Mobile m) + public MobileHitsN(IDamageable d) : base(0xA1, 9) { - m_Stream.Write(m.Serial); - AttributeNormalizer.Write(m_Stream, m.Hits, m.HitsMax); + m_Stream.Write(d.Serial); + AttributeNormalizer.Write(m_Stream, d.Hits, d.HitsMax); } } @@ -3449,21 +3452,17 @@ public NewMobileAnimation(Mobile m, int action, int frameCount, int delay) public sealed class MobileStatusCompact : Packet { - public MobileStatusCompact(bool canBeRenamed, Mobile m) + public MobileStatusCompact(bool canBeRenamed, IDamageable d) : base(0x11) { - string name = m.Name; - if (name == null) - { - name = ""; - } + string name = d.Name == null ? "" : d.Name; EnsureCapacity(43); - m_Stream.Write(m.Serial); + m_Stream.Write(d.Serial); m_Stream.WriteAsciiFixed(name, 30); - AttributeNormalizer.WriteReverse(m_Stream, m.Hits, m.HitsMax); + AttributeNormalizer.WriteReverse(m_Stream, d.Hits, d.HitsMax); m_Stream.Write(canBeRenamed); @@ -3574,131 +3573,131 @@ public MobileStatusExtended(Mobile m, NetState ns) } } - public sealed class MobileStatus : Packet - { - public MobileStatus(Mobile beholder, Mobile beheld) - : this(beholder, beheld, beheld.NetState) - { } + public sealed class MobileStatus : Packet + { + public MobileStatus(Mobile beholder, Mobile beheld) + : this(beholder, beheld, beheld.NetState) + { } - public MobileStatus(Mobile beholder, Mobile beheld, NetState ns) - : base(0x11) - { - string name = beheld.Name; - if (name == null) - { - name = ""; - } + public MobileStatus(Mobile beholder, Mobile beheld, NetState ns) + : base(0x11) + { + string name = beheld.Name; + if (name == null) + { + name = ""; + } - int type; + int type; - if (beholder != beheld) - { - type = 0; - EnsureCapacity(43); - } - else if (Core.HS && ns != null && ns.ExtendedStatus) - { - type = 6; - EnsureCapacity(121); - } - else if (Core.ML && ns != null && ns.SupportsExpansion(Expansion.ML)) - { - type = 5; - EnsureCapacity(91); - } - else - { - type = Core.AOS ? 4 : 3; - EnsureCapacity(88); - } + if (beholder != beheld) + { + type = 0; + EnsureCapacity(43); + } + else if (Core.HS && ns != null && ns.ExtendedStatus) + { + type = 6; + EnsureCapacity(121); + } + else if (Core.ML && ns != null && ns.SupportsExpansion(Expansion.ML)) + { + type = 5; + EnsureCapacity(91); + } + else + { + type = Core.AOS ? 4 : 3; + EnsureCapacity(88); + } - m_Stream.Write(beheld.Serial); + m_Stream.Write(beheld.Serial); - m_Stream.WriteAsciiFixed(name, 30); + m_Stream.WriteAsciiFixed(name, 30); - if (beholder == beheld) - { - WriteAttr(beheld.Hits, beheld.HitsMax); - } - else - { - WriteAttrNorm(beheld.Hits, beheld.HitsMax); - } + if (beholder == beheld) + { + WriteAttr(beheld.Hits, beheld.HitsMax); + } + else + { + WriteAttrNorm(beheld.Hits, beheld.HitsMax); + } - m_Stream.Write(beheld.CanBeRenamedBy(beholder)); + m_Stream.Write(beheld.CanBeRenamedBy(beholder)); - m_Stream.Write((byte)type); + m_Stream.Write((byte)type); - if (type > 0) - { - m_Stream.Write(beheld.Female); + if (type > 0) + { + m_Stream.Write(beheld.Female); - m_Stream.Write((short)beheld.Str); - m_Stream.Write((short)beheld.Dex); - m_Stream.Write((short)beheld.Int); + m_Stream.Write((short)beheld.Str); + m_Stream.Write((short)beheld.Dex); + m_Stream.Write((short)beheld.Int); - WriteAttr(beheld.Stam, beheld.StamMax); - WriteAttr(beheld.Mana, beheld.ManaMax); + WriteAttr(beheld.Stam, beheld.StamMax); + WriteAttr(beheld.Mana, beheld.ManaMax); - m_Stream.Write(beheld.TotalGold); - m_Stream.Write((short)(Core.AOS ? beheld.PhysicalResistance : (int)(beheld.ArmorRating + 0.5))); - m_Stream.Write((short)(Mobile.BodyWeight + beheld.TotalWeight)); + m_Stream.Write(beheld.TotalGold); + m_Stream.Write((short)(Core.AOS ? beheld.PhysicalResistance : (int)(beheld.ArmorRating + 0.5))); + m_Stream.Write((short)(Mobile.BodyWeight + beheld.TotalWeight)); - if (type >= 5) - { - m_Stream.Write((short)beheld.MaxWeight); - m_Stream.Write((byte)(beheld.Race.RaceID + 1)); // Would be 0x00 if it's a non-ML enabled account but... - } + if (type >= 5) + { + m_Stream.Write((short)beheld.MaxWeight); + m_Stream.Write((byte)(beheld.Race.RaceID + 1)); // Would be 0x00 if it's a non-ML enabled account but... + } - m_Stream.Write((short)beheld.StatCap); + m_Stream.Write((short)beheld.StatCap); - m_Stream.Write((byte)beheld.Followers); - m_Stream.Write((byte)beheld.FollowersMax); + m_Stream.Write((byte)beheld.Followers); + m_Stream.Write((byte)beheld.FollowersMax); - if (type >= 4) - { - m_Stream.Write((short)beheld.FireResistance); // Fire - m_Stream.Write((short)beheld.ColdResistance); // Cold - m_Stream.Write((short)beheld.PoisonResistance); // Poison - m_Stream.Write((short)beheld.EnergyResistance); // Energy - m_Stream.Write((short)beheld.Luck); // Luck + if (type >= 4) + { + m_Stream.Write((short)beheld.FireResistance); // Fire + m_Stream.Write((short)beheld.ColdResistance); // Cold + m_Stream.Write((short)beheld.PoisonResistance); // Poison + m_Stream.Write((short)beheld.EnergyResistance); // Energy + m_Stream.Write((short)beheld.Luck); // Luck - IWeapon weapon = beheld.Weapon; + IWeapon weapon = beheld.Weapon; - int min = 0, max = 0; + int min = 0, max = 0; - if (weapon != null) - { - weapon.GetStatusDamage(beheld, out min, out max); - } + if (weapon != null) + { + weapon.GetStatusDamage(beheld, out min, out max); + } - m_Stream.Write((short)min); // Damage min - m_Stream.Write((short)max); // Damage max + m_Stream.Write((short)min); // Damage min + m_Stream.Write((short)max); // Damage max - m_Stream.Write(beheld.TithingPoints); - } + m_Stream.Write(beheld.TithingPoints); + } - if (type >= 6) - { - for (int i = 0; i < 15; ++i) - { - m_Stream.Write((short)beheld.GetAOSStatus(i)); - } - } - } - } + if (type >= 6) + { + for (int i = 0; i < 15; ++i) + { + m_Stream.Write((short)beheld.GetAOSStatus(i)); + } + } + } + } - private void WriteAttr(int current, int maximum) - { - m_Stream.Write((short)current); - m_Stream.Write((short)maximum); - } + private void WriteAttr(int current, int maximum) + { + m_Stream.Write((short)current); + m_Stream.Write((short)maximum); + } - private void WriteAttrNorm(int current, int maximum) - { - AttributeNormalizer.WriteReverse(m_Stream, current, maximum); - } - } + private void WriteAttrNorm(int current, int maximum) + { + AttributeNormalizer.WriteReverse(m_Stream, current, maximum); + } + } public sealed class HealthbarPoison : Packet { diff --git a/Server/Notoriety.cs b/Server/Notoriety.cs index 40547beeb8..4062de2cc1 100644 --- a/Server/Notoriety.cs +++ b/Server/Notoriety.cs @@ -6,7 +6,7 @@ namespace Server { - public delegate int NotorietyHandler(Mobile source, Mobile target); + public delegate int NotorietyHandler(Mobile source, IDamageable target); public static class Notoriety { @@ -36,7 +36,7 @@ public static int GetHue(int noto) return m_Hues[noto]; } - public static int Compute(Mobile source, Mobile target) + public static int Compute(Mobile source, IDamageable target) { return m_Handler == null ? CanBeAttacked : m_Handler(source, target); } diff --git a/Server/Region.cs b/Server/Region.cs index ecc87acede..4aef32493c 100644 --- a/Server/Region.cs +++ b/Server/Region.cs @@ -647,7 +647,7 @@ public virtual void OnAggressed(Mobile aggressor, Mobile aggressed, bool crimina } } - public virtual void OnDidHarmful(Mobile harmer, Mobile harmed) + public virtual void OnDidHarmful(Mobile harmer, IDamageable harmed) { if (m_Parent != null) { @@ -655,7 +655,7 @@ public virtual void OnDidHarmful(Mobile harmer, Mobile harmed) } } - public virtual void OnGotHarmful(Mobile harmer, Mobile harmed) + public virtual void OnGotHarmful(Mobile harmer, IDamageable harmed) { if (m_Parent != null) { @@ -681,7 +681,7 @@ public virtual bool OnTarget(Mobile m, Target t, object o) return true; } - public virtual bool OnCombatantChange(Mobile m, Mobile Old, Mobile New) + public virtual bool OnCombatantChange(Mobile m, IDamageable Old, IDamageable New) { if (m_Parent != null) { @@ -731,7 +731,7 @@ public virtual bool OnDecay(Item item) return true; } - public virtual bool AllowHarmful(Mobile from, Mobile target) + public virtual bool AllowHarmful(Mobile from, IDamageable target) { if (m_Parent != null) {