diff --git a/Projects/UOContent/Mobiles/Abilities/DestroyEquipment.cs b/Projects/UOContent/Mobiles/Abilities/DestroyEquipment.cs index e193add32..4c270efbb 100644 --- a/Projects/UOContent/Mobiles/Abilities/DestroyEquipment.cs +++ b/Projects/UOContent/Mobiles/Abilities/DestroyEquipment.cs @@ -14,7 +14,6 @@ public class DestroyEquipment : MonsterAbilitySingleTarget protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { - base.OnTarget(trigger, source, defender); using var queue = PooledRefQueue.Create(); for (var i = 0; i < defender.Items.Count; i++) @@ -47,6 +46,8 @@ public class DestroyEquipment : MonsterAbilitySingleTarget return; } + source.DoHarmful(defender); + var toDestroy = queue.PeekRandom(); var name = toDestroy.Name?.Trim().DefaultIfNullOrEmpty(toDestroy.ItemData.Name); diff --git a/Projects/UOContent/Mobiles/Abilities/DrainLifeAttack.cs b/Projects/UOContent/Mobiles/Abilities/DrainLifeAttack.cs new file mode 100644 index 000000000..a4b1bb309 --- /dev/null +++ b/Projects/UOContent/Mobiles/Abilities/DrainLifeAttack.cs @@ -0,0 +1,59 @@ +using System; + +namespace Server.Mobiles; + +public class DrainLifeAttack : MonsterAbilitySingleTargetDoT +{ + public override MonsterAbilityType AbilityType => MonsterAbilityType.DrainLife; + public override MonsterAbilityTrigger AbilityTrigger => MonsterAbilityTrigger.GiveMeleeDamage; + + public override TimeSpan MinDelay => TimeSpan.FromSeconds(1.0); + public override TimeSpan MaxDelay => TimeSpan.FromSeconds(1.0); + + protected override int GetCount(BaseCreature source, Mobile defender) => 5; + + public override double ChanceToTrigger => 0.5; + + protected override bool CanEffectTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) => + base.CanEffectTarget(trigger, source, defender) && defender.Mana > 14 && !IsUnderEffect(defender); + + protected override void OnBeforeTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) + { + if (RemoveEffect(source, defender)) + { + defender.SendLocalizedMessage(1070847); // The creature continues to steal your life force! + } + else + { + defender.SendLocalizedMessage(1070848); // You feel your life force being stolen away. + } + } + + protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) + { + base.OnTarget(trigger, source, defender); + + source.DoHarmful(defender); + defender.Mana -= 15; + + if (defender.Alive) + { + var damageGiven = AOS.Damage(defender, source, 5, 0, 0, 0, 0, 100); + source.Hits += damageGiven; + } + else + { + RemoveEffect(source, defender); + defender.SendLocalizedMessage(1070849); // The drain on your life force is gone. + } + } + + protected override void EndEffect(BaseCreature source, Mobile defender) + { + } + + protected override void OnEffectExpired(BaseCreature source, Mobile defender) + { + defender.SendLocalizedMessage(1070849); // The drain on your life force is gone. + } +} diff --git a/Projects/UOContent/Mobiles/Abilities/EnergyBoltCounter.cs b/Projects/UOContent/Mobiles/Abilities/EnergyBoltCounter.cs index a1d0b3491..ce735f147 100644 --- a/Projects/UOContent/Mobiles/Abilities/EnergyBoltCounter.cs +++ b/Projects/UOContent/Mobiles/Abilities/EnergyBoltCounter.cs @@ -10,8 +10,6 @@ public class EnergyBoltCounter : MonsterAbilitySingleTarget protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { - base.OnTarget(trigger, source, defender); - source.MovingParticles(defender, 0x379F, 7, 0, false, true, 0xBE3, 0xFCB, 0x211); defender.PlaySound(0x229); diff --git a/Projects/UOContent/Mobiles/Abilities/FanThrowCounter.cs b/Projects/UOContent/Mobiles/Abilities/FanThrowCounter.cs index fa93533da..5020014b7 100644 --- a/Projects/UOContent/Mobiles/Abilities/FanThrowCounter.cs +++ b/Projects/UOContent/Mobiles/Abilities/FanThrowCounter.cs @@ -8,8 +8,6 @@ public class FanThrowCounter : MonsterAbilitySingleTarget protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { - base.OnTarget(trigger, source, defender); - /* Fan Throw * Effect: * - To: "0x57D4F5B" @@ -35,6 +33,7 @@ public class FanThrowCounter : MonsterAbilitySingleTarget 0 ); + source.DoHarmful(defender); AOS.Damage(defender, source, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0); } diff --git a/Projects/UOContent/Mobiles/Abilities/FanningFire.cs b/Projects/UOContent/Mobiles/Abilities/FanningFire.cs index 4014acbe8..c9fdb71a5 100644 --- a/Projects/UOContent/Mobiles/Abilities/FanningFire.cs +++ b/Projects/UOContent/Mobiles/Abilities/FanningFire.cs @@ -8,8 +8,19 @@ public class FanningFire : MonsterAbilitySingleTargetDoT public const string Name = "FanningFire"; - protected override void StartEffect(BaseCreature source, Mobile defender) + protected override void OnBeforeTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { + // Renew the effects + RemoveEffect(source, defender); + + // The creature fans you with fire, reducing your resistance to fire attacks. + defender.SendLocalizedMessage(1070833); + } + + protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) + { + base.OnTarget(trigger, source, defender); + /** * Fanning Fire * Start cliloc: 1070833 @@ -38,11 +49,7 @@ public class FanningFire : MonsterAbilitySingleTargetDoT * - Unknown: "0x0" */ - RemoveEffect(source, defender); - - // The creature fans you with fire, reducing your resistance to fire attacks. - defender.SendLocalizedMessage(1070833); - + source.DoHarmful(defender); var effect = -(defender.FireResistance / 10); var mod = new ResistanceMod(ResistanceType.Fire, Name, effect); diff --git a/Projects/UOContent/Mobiles/Abilities/GraspingClaw.cs b/Projects/UOContent/Mobiles/Abilities/GraspingClaw.cs index d5b35bfe0..13aab5b2d 100644 --- a/Projects/UOContent/Mobiles/Abilities/GraspingClaw.cs +++ b/Projects/UOContent/Mobiles/Abilities/GraspingClaw.cs @@ -8,7 +8,7 @@ public class GraspingClaw : MonsterAbilitySingleTargetDoT private const string Name = "GraspingClaw"; - protected override void StartEffect(BaseCreature source, Mobile defender) + protected override void OnBeforeTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { if (RemoveEffect(source, defender)) { @@ -19,6 +19,11 @@ public class GraspingClaw : MonsterAbilitySingleTargetDoT // The blow from the creature's claws has made you more susceptible to physical attacks. defender.SendLocalizedMessage(1070836); } + } + + protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) + { + base.OnTarget(trigger, source, defender); /** * Grasping Claw @@ -39,6 +44,7 @@ public class GraspingClaw : MonsterAbilitySingleTargetDoT * - Explode: "False" */ + source.DoHarmful(defender); var mod = new ResistanceMod(ResistanceType.Physical, Name, -(defender.PhysicalResistance * 15 / 100)); defender.AddResistanceMod(mod); diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs index f9d6857c5..935241eea 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs @@ -40,7 +40,9 @@ public static class MonsterAbilities public static DestroyEquipment DestroyEquipment => new(); + // Life Drain public static DrainLifeAreaAttack DrainLifeAreaAttack => new(); + public static DrainLifeAttack DrainLifeAttack => new(); public static MagicalBarrier MagicalBarrier => new(); diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTarget.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTarget.cs index 54313d3bc..7cd173660 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTarget.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTarget.cs @@ -6,17 +6,19 @@ public abstract class MonsterAbilitySingleTarget : MonsterAbility { if (CanEffectTarget(trigger, source, target)) { + OnBeforeTarget(trigger, source, target); OnTarget(trigger, source, target); } base.Trigger(trigger, source, target); } - protected virtual void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) + protected virtual void OnBeforeTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { - source.DoHarmful(defender); } + protected abstract void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender); + protected virtual bool CanEffectTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) => defender.Alive && source.CanBeHarmful(defender); } diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTargetDoT.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTargetDoT.cs index 4d162a6a2..f862f985c 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTargetDoT.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbilitySingleTargetDoT.cs @@ -18,14 +18,10 @@ public abstract class MonsterAbilitySingleTargetDoT : MonsterAbilitySingleTarget var count = GetCount(source, defender); var timer = _table[defender] = new ExpireTimer(this, source, defender, duration, count); timer.Start(); - - StartEffect(source, defender); } protected virtual int GetCount(BaseCreature source, Mobile defender) => 1; - protected abstract void StartEffect(BaseCreature source, Mobile defender); - protected virtual void EffectTick(BaseCreature source, Mobile defender, out TimeSpan nextDelay) { nextDelay = Utility.RandomMinMax(MinDelay, MaxDelay); @@ -72,8 +68,11 @@ public abstract class MonsterAbilitySingleTargetDoT : MonsterAbilitySingleTarget _ability.EffectTick(_source, _defender, out var delay); Delay = delay; - _ability.RemoveEffect(_source, _defender); - _ability.OnEffectExpired(_source, _defender); + if (RemainingCount == 0) + { + _ability.RemoveEffect(_source, _defender); + _ability.OnEffectExpired(_source, _defender); + } } } } diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs index 365e37ac4..73e26e9aa 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs @@ -12,6 +12,7 @@ public enum MonsterAbilityType ThrowWeapon, DestroyEquipment, DeathExplosion, + DrainLife, MassDrainLife, MagicalBarrier, EnergyBoltCounter, diff --git a/Projects/UOContent/Mobiles/Abilities/PoisonGasCounter.cs b/Projects/UOContent/Mobiles/Abilities/PoisonGasCounter.cs index 8a3da763d..eed45701f 100644 --- a/Projects/UOContent/Mobiles/Abilities/PoisonGasCounter.cs +++ b/Projects/UOContent/Mobiles/Abilities/PoisonGasCounter.cs @@ -14,6 +14,7 @@ public class PoisonGasCounter : MonsterAbilitySingleTarget protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { source.Animate(10, 4, 1, true, false, 0); + source.DoHarmful(defender); AOS.Damage(defender, source, 50, 100, 0, 0, 0, 0, 0); defender.FixedParticles(0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255); diff --git a/Projects/UOContent/Mobiles/Abilities/RuneCorruption.cs b/Projects/UOContent/Mobiles/Abilities/RuneCorruption.cs index 552c5da26..2e68c61ce 100644 --- a/Projects/UOContent/Mobiles/Abilities/RuneCorruption.cs +++ b/Projects/UOContent/Mobiles/Abilities/RuneCorruption.cs @@ -8,7 +8,7 @@ public class RuneCorruption : MonsterAbilitySingleTargetDoT private const string Name = "RuneCorruption"; - protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) + protected override void OnBeforeTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { if (RemoveEffect(source, defender)) { @@ -18,12 +18,12 @@ public class RuneCorruption : MonsterAbilitySingleTargetDoT { defender.SendLocalizedMessage(1070846); // The creature magically corrupts your armor! } - - base.OnTarget(trigger, source, defender); } - protected override void StartEffect(BaseCreature source, Mobile defender) + protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { + base.OnTarget(trigger, source, defender); + /** * Rune Corruption * Start cliloc: 1070846 "The creature magically corrupts your armor!" @@ -31,6 +31,8 @@ public class RuneCorruption : MonsterAbilitySingleTargetDoT * End ASCII: "The corruption of your armor has worn off" */ + source.DoHarmful(defender); + if (Core.ML) { if (defender.PhysicalResistance > 0) diff --git a/Projects/UOContent/Mobiles/Abilities/ThrowHatchetCounter.cs b/Projects/UOContent/Mobiles/Abilities/ThrowHatchetCounter.cs index a64360737..f6d43beb8 100644 --- a/Projects/UOContent/Mobiles/Abilities/ThrowHatchetCounter.cs +++ b/Projects/UOContent/Mobiles/Abilities/ThrowHatchetCounter.cs @@ -11,6 +11,7 @@ public class ThrowHatchetCounter : MonsterAbilitySingleTarget protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) { source.MovingEffect(defender, 0xF43, 10, 0, false, false); + source.DoHarmful(defender); AOS.Damage(defender, source, 50, 100, 0, 0, 0, 0, 0); } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs index 01c6dd6e3..e6e7749dc 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs @@ -1,86 +1,72 @@ -namespace Server.Mobiles +namespace Server.Mobiles; + +public class Guile : Changeling { - public class Guile : Changeling + [Constructible] + public Guile() { - [Constructible] - public Guile() - { - IsParagon = true; + IsParagon = true; - Hue = DefaultHue; + Hue = DefaultHue; - SetStr(53, 214); - SetDex(243, 367); - SetInt(369, 586); + SetStr(53, 214); + SetDex(243, 367); + SetInt(369, 586); - SetHits(1013, 1058); - SetStam(243, 367); - SetMana(369, 586); + SetHits(1013, 1058); + SetStam(243, 367); + SetMana(369, 586); - SetDamage(14, 20); + SetDamage(14, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 43, 46); - SetResistance(ResistanceType.Cold, 42, 44); - SetResistance(ResistanceType.Poison, 42, 50); - SetResistance(ResistanceType.Energy, 47, 50); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 43, 46); + SetResistance(ResistanceType.Cold, 42, 44); + SetResistance(ResistanceType.Poison, 42, 50); + SetResistance(ResistanceType.Energy, 47, 50); - SetSkill(SkillName.Wrestling, 12.8, 16.7); - SetSkill(SkillName.Tactics, 102.6, 131.0); - SetSkill(SkillName.MagicResist, 141.2, 161.6); - SetSkill(SkillName.Magery, 108.4, 120.0); - SetSkill(SkillName.EvalInt, 108.4, 120.0); - SetSkill(SkillName.Meditation, 109.2, 120.0); + SetSkill(SkillName.Wrestling, 12.8, 16.7); + SetSkill(SkillName.Tactics, 102.6, 131.0); + SetSkill(SkillName.MagicResist, 141.2, 161.6); + SetSkill(SkillName.Magery, 108.4, 120.0); + SetSkill(SkillName.EvalInt, 108.4, 120.0); + SetSkill(SkillName.Meditation, 109.2, 120.0); - Fame = 21000; - Karma = -21000; - } + Fame = 21000; + Karma = -21000; + } - public Guile(Serial serial) - : base(serial) - { - } + public Guile(Serial serial) + : base(serial) + { + } - public override string CorpseName => "a Guile corpse"; - public override string DefaultName => "Guile"; - public override int DefaultHue => 0x3F; + public override string CorpseName => "a Guile corpse"; + public override string DefaultName => "Guile"; + public override int DefaultHue => 0x3F; + public override bool GivesMLMinorArtifact => true; - public override bool GivesMLMinorArtifact => true; + private static MonsterAbility[] _abilities = { MonsterAbilities.DrainLifeAttack }; + public override MonsterAbility[] GetMonsterAbilities() => _abilities; - public override void OnGaveMeleeAttack(Mobile defender, int damage) - { - base.OnGaveMeleeAttack(defender, damage); + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } - if (Utility.RandomBool()) - { - if (!Kappa.IsBeingDrained(defender) && Mana > 14) - { - defender.SendLocalizedMessage(1070848); // You feel your life force being stolen away. - Kappa.BeginLifeDrain(defender, this); - Mana -= 15; - } - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } + writer.Write(0); // version + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - } + var version = reader.ReadInt(); } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs b/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs index 37b92ee25..51681b3ad 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs @@ -100,7 +100,7 @@ namespace Server.Mobiles { if (Utility.RandomBool() && Mana > 14 && to != null) { - damage = damage + damage / 2; + damage += damage / 2; to.SendLocalizedMessage(1060091); // You take extra damage from the crushing attack! to.PlaySound(0x1E1); to.FixedParticles(0x377A, 1, 32, 0x26da, 0, 0, 0); diff --git a/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs b/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs index ee5746f9f..8cbb54d4f 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs @@ -1,208 +1,143 @@ using System; -using System.Collections.Generic; using Server.Engines.Plants; using Server.Items; -namespace Server.Mobiles +namespace Server.Mobiles; + +public class Kappa : BaseCreature { - public class Kappa : BaseCreature + [Constructible] + public Kappa() : base(AIType.AI_Melee) { - private static readonly Dictionary m_Table = new(); + Body = 240; - [Constructible] - public Kappa() : base(AIType.AI_Melee) + SetStr(186, 230); + SetDex(51, 75); + SetInt(41, 55); + + SetMana(30); + + SetHits(151, 180); + + SetDamage(6, 12); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 35, 50); + SetResistance(ResistanceType.Fire, 35, 50); + SetResistance(ResistanceType.Cold, 25, 50); + SetResistance(ResistanceType.Poison, 35, 50); + SetResistance(ResistanceType.Energy, 20, 30); + + SetSkill(SkillName.MagicResist, 60.1, 70.0); + SetSkill(SkillName.Tactics, 79.1, 89.0); + SetSkill(SkillName.Wrestling, 60.1, 70.0); + + Fame = 1700; + Karma = -1700; + + PackItem(new RawFishSteak(3)); + for (var i = 0; i < 2; i++) { - Body = 240; - - SetStr(186, 230); - SetDex(51, 75); - SetInt(41, 55); - - SetMana(30); - - SetHits(151, 180); - - SetDamage(6, 12); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 35, 50); - SetResistance(ResistanceType.Fire, 35, 50); - SetResistance(ResistanceType.Cold, 25, 50); - SetResistance(ResistanceType.Poison, 35, 50); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.MagicResist, 60.1, 70.0); - SetSkill(SkillName.Tactics, 79.1, 89.0); - SetSkill(SkillName.Wrestling, 60.1, 70.0); - - Fame = 1700; - Karma = -1700; - - PackItem(new RawFishSteak(3)); - for (var i = 0; i < 2; i++) + switch (Utility.Random(6)) { - switch (Utility.Random(6)) - { - case 0: + case 0: + { PackItem(new Gears()); break; - case 1: + } + case 1: + { PackItem(new Hinge()); break; - case 2: + } + case 2: + { PackItem(new Axle()); break; - } - } - - if (Core.ML && Utility.RandomDouble() < .33) - { - PackItem(Seed.RandomPeculiarSeed(4)); + } } } - public Kappa(Serial serial) : base(serial) + if (Core.ML && Utility.Random(3) == 0) { + PackItem(Seed.RandomPeculiarSeed(4)); } + } - public override string CorpseName => "a kappa corpse"; - public override string DefaultName => "a kappa"; + public Kappa(Serial serial) : base(serial) + { + } - public override void GenerateLoot() + public override string CorpseName => "a kappa corpse"; + public override string DefaultName => "a kappa"; + + private static MonsterAbility[] _abilities = { MonsterAbilities.DrainLifeAttack }; + public override MonsterAbility[] GetMonsterAbilities() => _abilities; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.Average); + } + + public override int GetAngerSound() => 0x50B; + + public override int GetIdleSound() => 0x50A; + + public override int GetAttackSound() => 0x509; + + public override int GetHurtSound() => 0x50C; + + public override int GetDeathSound() => 0x508; + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + // Acid Blood ability + if (from?.Map != null) { - AddLoot(LootPack.Meager); - AddLoot(LootPack.Average); - } - - public override int GetAngerSound() => 0x50B; - - public override int GetIdleSound() => 0x50A; - - public override int GetAttackSound() => 0x509; - - public override int GetHurtSound() => 0x50C; - - public override int GetDeathSound() => 0x508; - - public override void OnGaveMeleeAttack(Mobile defender, int damage) - { - base.OnGaveMeleeAttack(defender, damage); - - if (Utility.RandomBool()) + var amt = 0; + Mobile target = this; + var rand = Utility.Random(1, 100); + if (willKill) { - if (!IsBeingDrained(defender) && Mana > 14) + amt = ((rand % 5) >> 2) + 3; + } + + if (Hits < 100 && rand < 21) + { + target = rand % 2 < 1 ? this : from; + amt++; + } + + if (amt > 0) + { + SpillAcid(target, amt); + from.SendLocalizedMessage(1070820); // The creature spills a pool of acidic slime! + if (Mana > 14) { - defender.SendLocalizedMessage(1070848); // You feel your life force being stolen away. - BeginLifeDrain(defender, this); Mana -= 15; } } } - public static bool IsBeingDrained(Mobile m) => m_Table.ContainsKey(m); + base.OnDamage(amount, from, willKill); + } - public static void BeginLifeDrain(Mobile m, Mobile from) - { - m_Table.TryGetValue(m, out var timer); - timer?.Stop(); - m_Table[m] = timer = new InternalTimer(from, m); + public override Item NewHarmfulItem() => new PoolOfAcid(TimeSpan.FromSeconds(10), 5, 10) + { + Name = "slime" + }; - timer.Start(); - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + } - public static void DrainLife(Mobile m, Mobile from) - { - if (m.Alive) - { - var damageGiven = AOS.Damage(m, from, 5, 0, 0, 0, 0, 100); - from.Hits += damageGiven; - } - else - { - EndLifeDrain(m); - } - } - - public static void EndLifeDrain(Mobile m) - { - if (m_Table.Remove(m, out var timer)) - { - timer?.Stop(); - m.SendLocalizedMessage(1070849); // The drain on your life force is gone. - } - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (from?.Map != null) - { - var amt = 0; - Mobile target = this; - var rand = Utility.Random(1, 100); - if (willKill) - { - amt = ((rand % 5) >> 2) + 3; - } - - if (Hits < 100 && rand < 21) - { - target = rand % 2 < 1 ? this : from; - amt++; - } - - if (amt > 0) - { - SpillAcid(target, amt); - from.SendLocalizedMessage(1070820); - if (Mana > 14) - { - Mana -= 15; - } - } - } - - base.OnDamage(amount, from, willKill); - } - - public override Item NewHarmfulItem() => new PoolOfAcid(TimeSpan.FromSeconds(10), 5, 10) - { - Name = "slime" - }; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - var version = reader.ReadInt(); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_From; - private readonly Mobile m_Mobile; - private int m_Count; - - public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_From = from; - m_Mobile = m; - } - - protected override void OnTick() - { - DrainLife(m_Mobile, m_From); - - if (Running && ++m_Count == 5) - { - EndLifeDrain(m_Mobile); - } - } - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); } }