using System; using System.Collections.Generic; using System.Linq; using Server; using Server.Items; using Server.Engines.SeasonalEvents; using Server.Spells; namespace Server.Mobiles { [CorpseName("the corpse of krampus")] public class Krampus : BaseCreature { public override bool TeleportsTo { get { return true; } } public List SummonedHelpers { get; set; } public List InitialSpawn { get; set; } private DateTime _NextSpecial; public const int MaxSummons = 24; private DateTime _LastActivity; [CommandProperty(AccessLevel.GameMaster)] public Point3D SpawnLocation { get; set; } public bool IsKrampusEncounter { get { return KrampusEncounter.Encounter != null && KrampusEncounter.Encounter.Krampus == this; } } [Constructable] public Krampus() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { Name = "Krampus"; Body = 1484; SetStr(700, 750); SetDex(800, 900); SetInt(500, 600); SetHits(40000); SetDamage(28, 35); SetDamageType(ResistanceType.Physical, 50); SetDamageType(ResistanceType.Cold, 50); SetResistance(ResistanceType.Physical, 80, 90); SetResistance(ResistanceType.Fire, 70, 80); SetResistance(ResistanceType.Cold, 80, 90); SetResistance(ResistanceType.Poison, 70, 80); SetResistance(ResistanceType.Energy, 70, 80); SetSkill(SkillName.MagicResist, 150); SetSkill(SkillName.Tactics, 110, 120); SetSkill(SkillName.Wrestling, 120.0, 125.0); SetSkill(SkillName.DetectHidden, 60.0, 70.0); SetSkill(SkillName.Parry, 60, 70); Fame = 30000; Karma = -30000; switch (Utility.Random(3)) { case 0: SetMagicalAbility(MagicalAbility.Piercing); break; case 1: SetMagicalAbility(MagicalAbility.Bashing); break; case 2: SetMagicalAbility(MagicalAbility.Slashing); break; } _NextSpecial = DateTime.UtcNow; } public int TotalSummons() { if (SummonedHelpers == null) { return 0; } return SummonedHelpers.Where(bc => bc != null && bc.Alive).Count(); } public void Summon(Mobile target, bool initial = false) { if (target == null || (!initial && InitialSpawn != null && InitialSpawn.Count > 0)) return; var map = Map; if (map == null || TotalSummons() > MaxSummons) return; if (!initial) { MovingEffect(target, 0xA271, 10, 0, false, false, 0, 0); } Timer.DelayCall(TimeSpan.FromSeconds(initial ? 0.25 : 1.0), com => { if (!com.Alive) return; int count = Utility.RandomMinMax(3, 5); for (int i = 0; i < count; i++) { Point3D p = com.Location; for (int j = 0; j < 10; j++) { int x = Utility.RandomMinMax(p.X - 3, p.X + 3); int y = Utility.RandomMinMax(p.Y - 3, p.Y + 3); int z = map.GetAverageZ(x, y); if (map.CanSpawnMobile(x, y, z)) { p = new Point3D(x, y, z); break; } } BaseCreature spawn = new KrampusMinion(); if (spawn != null) { spawn.MoveToWorld(p, map); spawn.Home = p; spawn.RangeHome = 5; spawn.Team = this.Team; spawn.SummonMaster = this; if (!initial) { if (spawn.Combatant != null) { if (!(spawn.Combatant is PlayerMobile) || !((PlayerMobile)spawn.Combatant).HonorActive) spawn.Combatant = com; } else { spawn.Combatant = com; } } AddHelper(spawn, initial); } } if (initial) { Blessed = true; } }, target); _NextSpecial = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(20, 40)); } protected virtual void AddHelper(BaseCreature bc, bool initial) { if (initial) { if (InitialSpawn == null) InitialSpawn = new List(); if (!InitialSpawn.Contains(bc)) InitialSpawn.Add(bc); } else { if (SummonedHelpers == null) SummonedHelpers = new List(); if (!SummonedHelpers.Contains(bc)) SummonedHelpers.Add(bc); } } private Mobile _LastTeleported; public override void OnAfterTeleport(Mobile m) { m.SendLocalizedMessage(1072195); // Without warning, you are magically transported closer to your enemy! } public override void OnGaveMeleeAttack(Mobile defender) { base.OnGaveMeleeAttack(defender); if (defender == _LastTeleported) { BoneBreakerContext.CheckHit(this, defender); } _LastTeleported = null; } public override int GetIdleSound() { return 1589; } public override int GetAngerSound() { return 1586; } public override int GetHurtSound() { return 1588; } public override int GetDeathSound() { return 1587; } public Krampus(Serial serial) : base(serial) { } public override void GenerateLoot() { AddLoot(LootPack.SuperBoss, 5); } public override void OnThink() { base.OnThink(); if (Blessed) { if (InitialSpawn != null) { if (InitialSpawn.All(s => s.Deleted)) { ColUtility.Free(InitialSpawn); InitialSpawn = null; Blessed = false; } } else { Blessed = false; } } if (Combatant == null) { if (SpawnLocation != Point3D.Zero && _LastActivity > DateTime.MinValue && _LastActivity + TimeSpan.FromHours(2) < DateTime.UtcNow) { Delete(); } return; } _LastActivity = DateTime.UtcNow; if (_NextSpecial < DateTime.UtcNow && 0.25 > Utility.RandomDouble()) { if (Utility.RandomBool()) { var target = GetTeleportTarget(); if (target != null) { Summon(target); } } else { int baseDamage = 100; bool switched = false; PlaySound(0x20D); foreach (var m in SpellHelper.AcquireIndirectTargets(this, Location, Map, 10).OfType()) { var range = (int)GetDistanceToSqrt(m); if (range < 1) range = 1; if (range > 4) range = 4; m.PlaySound(0x20D); AOS.Damage(this, m, baseDamage / range, 0, 0, 0, 0, 0, 100, 0); if (!switched && 0.2 > Utility.RandomDouble()) { Combatant = m; switched = true; } } } _NextSpecial = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); } if (Map != null && SpawnLocation != Point3D.Zero && !Utility.InRange(Location, SpawnLocation, 25)) { MoveToWorld(SpawnLocation, Map); } } public override void OnDeath(Container c) { if (IsKrampusEncounter) { var rights = GetLootingRights(); foreach (var ds in rights.Where(s => s.m_Mobile is PlayerMobile && s.m_HasRight)) { var m = ds.m_Mobile as PlayerMobile; int ordersComplete = 0; if (KrampusEncounter.Encounter.CompleteTable.ContainsKey(m)) { ordersComplete = KrampusEncounter.Encounter.CompleteTable[m]; } if (ordersComplete >= 3 || Utility.RandomMinMax(0, 8) <= ordersComplete) { Item item = null; switch (Utility.Random(13)) { case 0: item = new KrampusCoinPurse(m.Karma); break; case 1: item = new CardOfSemidar(Utility.RandomMinMax(0, 6)); break; case 2: item = new NiceTitleDeed(); break; case 3: item = new NaughtyTitleDeed(); break; case 4: item = new PunisherTitleDeed(); break; case 5: item = new RecipeScroll(586); break; // minion hat case 6: item = new RecipeScroll(587); break; // minion boots case 7: item = new KrampusCoinPurse(463); break; // minion talons case 8: item = new KrampusCoinPurse(588); break; // minion earrings case 9: item = new KrampusPunishinList(m.Name); break; case 10: item = new SpikedWhip(); break; case 11: item = new BarbedWhip(); break; case 12: item = new BladedWhip(); break; } if (item != null) { m.SendLocalizedMessage(1156269); // For your valor in defeating your foe a specialty item has been awarded to you! if (m.Backpack == null || !m.Backpack.TryDropItem(m, item, false)) { m.BankBox.DropItem(item); } } } } } base.OnDeath(c); } public override void Delete() { base.Delete(); if (IsKrampusEncounter) { KrampusEncounter.Encounter.OnKrampusKilled(); } if (SummonedHelpers != null) { ColUtility.SafeDelete(SummonedHelpers); ColUtility.Free(SummonedHelpers); } if (InitialSpawn != null) { ColUtility.SafeDelete(InitialSpawn); ColUtility.Free(InitialSpawn); } } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write((int)0); writer.Write(SpawnLocation); writer.Write(SummonedHelpers == null ? 0 : SummonedHelpers.Count); if (SummonedHelpers != null) SummonedHelpers.ForEach(m => writer.Write(m)); writer.Write(InitialSpawn == null ? 0 : InitialSpawn.Count); if (InitialSpawn != null) InitialSpawn.ForEach(m => writer.Write(m)); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); SpawnLocation = reader.ReadPoint3D(); int count = reader.ReadInt(); if (count > 0) { for (int i = 0; i < count; i++) { BaseCreature summon = reader.ReadMobile() as BaseCreature; if (summon != null) { if (SummonedHelpers == null) SummonedHelpers = new List(); SummonedHelpers.Add(summon); } } } count = reader.ReadInt(); if (count > 0) { for (int i = 0; i < count; i++) { BaseCreature summon = reader.ReadMobile() as BaseCreature; if (summon != null) { if (InitialSpawn == null) InitialSpawn = new List(); InitialSpawn.Add(summon); } } } _NextSpecial = DateTime.UtcNow; } } }