using System; using Server.Items; namespace Server.Mobiles { public class ShadowKnight : BaseCreature { private bool m_HasTeleportedAway; private Timer m_SoundTimer; [Constructible] public ShadowKnight() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { Name = NameList.RandomName("shadow knight"); Title = "the Shadow Knight"; Body = 311; SetStr(250); SetDex(100); SetInt(100); SetHits(2000); SetDamage(20, 30); SetDamageType(ResistanceType.Physical, 60); SetDamageType(ResistanceType.Cold, 40); SetResistance(ResistanceType.Physical, 90); SetResistance(ResistanceType.Fire, 65); SetResistance(ResistanceType.Cold, 75); SetResistance(ResistanceType.Poison, 75); SetResistance(ResistanceType.Energy, 55); SetSkill(SkillName.Chivalry, 120.0); SetSkill(SkillName.DetectHidden, 80.0); SetSkill(SkillName.EvalInt, 100.0); SetSkill(SkillName.Magery, 100.0); SetSkill(SkillName.Meditation, 100.0); SetSkill(SkillName.MagicResist, 120.0); SetSkill(SkillName.Tactics, 100.0); SetSkill(SkillName.Wrestling, 100.0); Fame = 25000; Karma = -25000; VirtualArmor = 54; } public ShadowKnight(Serial serial) : base(serial) { } public override string CorpseName => "a shadow knight corpse"; public override bool IgnoreYoungProtection => Core.ML; public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; public override bool BardImmune => !Core.SE; public override bool Unprovokable => Core.SE; public override bool AreaPeaceImmune => Core.SE; public override Poison PoisonImmune => Poison.Lethal; public override int TreasureMapLevel => 1; public override WeaponAbility GetWeaponAbility() { return Utility.RandomBool() ? WeaponAbility.ConcussionBlow : WeaponAbility.CrushingBlow; } public override void GenerateLoot() { AddLoot(LootPack.UltraRich, 2); } public override void OnDeath(Container c) { base.OnDeath(c); if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) DemonKnight.DistributeArtifact(this); } public override int GetIdleSound() { return 0x2CE; } public override int GetDeathSound() { return 0x2C1; } public override int GetHurtSound() { return 0x2D1; } public override int GetAttackSound() { return 0x2C8; } public override void OnCombatantChange() { base.OnCombatantChange(); if (Hidden && Combatant != null) Combatant = null; } public virtual void SendTrackingSound() { if (Hidden) { Effects.PlaySound(Location, Map, 0x2C8); Combatant = null; } else { Frozen = false; m_SoundTimer?.Stop(); m_SoundTimer = null; } } public override void OnThink() { if (!m_HasTeleportedAway && Hits < HitsMax / 2) { Map map = Map; if (map != null) for (int i = 0; i < 10; ++i) { int x = X + Utility.RandomMinMax(5, 10) * (Utility.RandomBool() ? 1 : -1); int y = Y + Utility.RandomMinMax(5, 10) * (Utility.RandomBool() ? 1 : -1); int z = Z; if (!map.CanFit(x, y, z, 16, false, false)) continue; Point3D from = Location; Point3D to = new Point3D(x, y, z); if (!InLOS(to)) continue; Location = to; ProcessDelta(); Hidden = true; Combatant = null; Effects.SendLocationParticles(EffectItem.Create(from, map, EffectItem.DefaultDuration), 0x3728, 10, 10, 2023); Effects.SendLocationParticles(EffectItem.Create(to, map, EffectItem.DefaultDuration), 0x3728, 10, 10, 5023); Effects.PlaySound(to, map, 0x1FE); m_HasTeleportedAway = true; m_SoundTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(2.5), SendTrackingSound); Frozen = true; break; } } base.OnThink(); } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write(0); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); if (BaseSoundID == 357) BaseSoundID = -1; } } }