using System; using System.Collections.Generic; using System.Linq; using Server.Items; using Server.Targeting; namespace Server.Mobiles { [CorpseName("the corpse of niporailem")] public class Niporailem : BaseSABoss { public override Type[] UniqueSAList { get { return new Type[] { typeof(HelmOfVillainousEpiphany), typeof(GorgetOfVillainousEpiphany), typeof(BreastplateOfVillainousEpiphany), typeof(ArmsOfVillainousEpiphany), typeof(GauntletsOfVillainousEpiphany), typeof(LegsOfVillainousEpiphany), typeof(KiltOfVillainousEpiphany), typeof(EarringsOfVillainousEpiphany), typeof(GargishBreastplateOfVillainousEpiphany), typeof(GargishArmsOfVillainousEpiphany), typeof(NecklaceOfVillainousEpiphany), typeof(GargishLegsOfVillainousEpiphany), typeof(HelmOfVirtuousEpiphany), typeof(GorgetOfVirtuousEpiphany), typeof(BreastplateOfVirtuousEpiphany), typeof(ArmsOfVirtuousEpiphany), typeof(GauntletsOfVirtuousEpiphany), typeof(LegsOfVirtuousEpiphany), typeof(KiltOfVirtuousEpiphany), typeof(EarringsOfVirtuousEpiphany), typeof(GargishBreastplateOfVirtuousEpiphany), typeof(GargishArmsOfVirtuousEpiphany), typeof(NecklaceOfVirtuousEpiphany), typeof(GargishLegsOfVirtuousEpiphany)}; } } public override Type[] SharedSAList { get { return new Type[] { typeof(BladeOfBattle), typeof(DemonBridleRing), typeof(GiantSteps), typeof(SwordOfShatteredHopes) }; } } [Constructable] public Niporailem() : base(AIType.AI_NecroMage, FightMode.Closest, 10, 1, 0.2, 0.4) { Name = "Niporailem"; Title = "the Thief"; Body = 722; SetStr(1000); SetDex(1200); SetInt(1200); SetHits(10000, 10500); SetDamage(15, 27); SetDamageType(ResistanceType.Physical, 20); SetDamageType(ResistanceType.Cold, 40); SetDamageType(ResistanceType.Energy, 40); SetResistance(ResistanceType.Physical, 34, 46); SetResistance(ResistanceType.Fire, 0); SetResistance(ResistanceType.Cold, 31, 49); SetResistance(ResistanceType.Poison, 100); SetResistance(ResistanceType.Energy, 31, 49); SetSkill(SkillName.Wrestling, 68.8, 85.0); SetSkill(SkillName.Tactics, 56.1, 90.0); SetSkill(SkillName.MagicResist, 87.7, 93.5); SetSkill(SkillName.EvalInt, 90.0, 100.0); SetSkill(SkillName.Meditation, 20.0, 30.0); SetSkill(SkillName.Necromancy, 120.0); SetSkill(SkillName.SpiritSpeak, 120.0); SetSkill(SkillName.Focus, 30.0, 40.0); PackNecroReg(12, 24); /// Stratics didn't specify Fame = 15000; Karma = -15000; } public override void GenerateLoot() { AddLoot(LootPack.FilthyRich, 6); AddLoot(LootPack.Gems, 6); } public override int Meat { get { return 1; } } public override bool AlwaysMurderer { get { return true; } } public override int GetIdleSound() { return 1609; } public override int GetAngerSound() { return 1606; } public override int GetHurtSound() { return 1608; } public override int GetDeathSound() { return 1607; } public Niporailem(Serial serial) : base(serial) { } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write((int)1); writer.WriteMobileList(Helpers, true); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); switch (version) { case 1: Helpers = reader.ReadStrongMobileList(); break; } } public List Helpers { get; set; } = new List(); private DateTime m_NextTreasure; private int m_Thrown; private DateTime m_NextSpawn; public override void OnGotMeleeAttack(Mobile attacker) { base.OnGotMeleeAttack(attacker); if (m_NextSpawn > DateTime.UtcNow || Helpers.Where(bc => bc.Deleted).Count() > 10) return; if (this.Hits > (this.HitsMax / 4)) { if (0.25 >= Utility.RandomDouble()) { SpawnSpectralArmour(attacker); } } else if (0.10 >= Utility.RandomDouble()) { SpawnSpectralArmour(attacker); } } public override void OnActionCombat() { Mobile combatant = Combatant as Mobile; if (combatant == null || combatant.Deleted || combatant.Map != Map || !InRange(combatant, 20) || !CanBeHarmful(combatant) || !InLOS(combatant)) return; if (DateTime.UtcNow >= m_NextTreasure) { ThrowTreasure(combatant); m_Thrown++; if (0.75 >= Utility.RandomDouble() && (m_Thrown % 2) == 1) // 75% chance to toss a second one m_NextTreasure = DateTime.UtcNow + TimeSpan.FromSeconds(3.0); else m_NextTreasure = DateTime.UtcNow + TimeSpan.FromSeconds(5.0 + (10.0 * Utility.RandomDouble())); // 5-15 seconds } } public void SpawnSpectralArmour(Mobile m) { Map map = this.Map; if (map == null) return; SpectralArmour spawned = new SpectralArmour(); spawned.Team = this.Team; spawned.SummonMaster = this; bool validLocation = false; Point3D loc = this.Location; for (int j = 0; !validLocation && j < 10; ++j) { int x = X + Utility.Random(3) - 1; int y = Y + Utility.Random(3) - 1; int z = map.GetAverageZ(x, y); if (validLocation = map.CanFit(x, y, this.Z, 16, false, false)) loc = new Point3D(x, y, Z); else if (validLocation = map.CanFit(x, y, z, 16, false, false)) loc = new Point3D(x, y, z); } spawned.MoveToWorld(loc, map); spawned.Combatant = m; spawned.SummonMaster = this; m_NextSpawn = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); Helpers.Add(spawned); } public void DeleteSpectralArmour(Mobile target) { foreach (var m in Helpers.Where(bc => bc != null && !bc.Deleted)) { m.Delete(); } ColUtility.Free(Helpers); } public override void OnDelete() { DeleteSpectralArmour(this); base.OnDelete(); } private void ThrowTreasure(Mobile m) { DoHarmful(m); this.MovingParticles(m, 0xEEF, 9, 0, false, true, 0, 0, 9502, 6014, 0x11D, EffectLayer.Waist, 0); Timer.DelayCall(TimeSpan.FromSeconds(1), () => { var treasure = new NiporailemsTreasure(this); m.PlaySound(0x033); m.AddToBackpack(treasure); m.SendLocalizedMessage(1112111); // To steal my gold? To give it freely! }); } } }