325 lines
10 KiB
C#
325 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Server.Events.Halloween;
|
|
using Server.Items;
|
|
using Server.Mobiles;
|
|
|
|
namespace Server.Engines.Events
|
|
{
|
|
public class HalloweenHauntings
|
|
{
|
|
private static readonly Rectangle2D[] m_Cemetaries = new Rectangle2D[]
|
|
{
|
|
new Rectangle2D(1272,3712,30,20), // Jhelom
|
|
new Rectangle2D(1337,1444,48,52), // Britain
|
|
new Rectangle2D(2424,1098,20,28), // Trinsic
|
|
new Rectangle2D(2728,840,54,54), // Vesper
|
|
new Rectangle2D(4528,1314,20,28), // Moonglow
|
|
new Rectangle2D(712,1104,30,22), // Yew
|
|
new Rectangle2D(5824,1464,22,6), // Fire Dungeon
|
|
new Rectangle2D(5224,3655,14,5), // T2A
|
|
|
|
new Rectangle2D(1272,3712,20,30), // Jhelom
|
|
new Rectangle2D(1337,1444,52,48), // Britain
|
|
new Rectangle2D(2424,1098,28,20), // Trinsic
|
|
new Rectangle2D(2728,840,54,54), // Vesper
|
|
new Rectangle2D(4528,1314,28,20), // Moonglow
|
|
new Rectangle2D(712,1104,22,30), // Yew
|
|
new Rectangle2D(5824,1464,6,22), // Fire Dungeon
|
|
new Rectangle2D(5224,3655,5,14), // T2A
|
|
};
|
|
private static Timer m_Timer;
|
|
private static Timer m_ClearTimer;
|
|
private static int m_TotalZombieLimit;
|
|
private static int m_DeathQueueLimit;
|
|
private static int m_QueueDelaySeconds;
|
|
private static int m_QueueClearIntervalSeconds;
|
|
private static Dictionary<PlayerMobile, ZombieSkeleton> m_ReAnimated;
|
|
private static List<PlayerMobile> m_DeathQueue;
|
|
public static Dictionary<PlayerMobile, ZombieSkeleton> ReAnimated
|
|
{
|
|
get
|
|
{
|
|
return m_ReAnimated;
|
|
}
|
|
set
|
|
{
|
|
m_ReAnimated = value;
|
|
}
|
|
}
|
|
public static void Initialize()
|
|
{
|
|
m_TotalZombieLimit = 200;
|
|
m_DeathQueueLimit = 200;
|
|
m_QueueDelaySeconds = 120;
|
|
m_QueueClearIntervalSeconds = 1800;
|
|
|
|
DateTime today = DateTime.UtcNow;
|
|
TimeSpan tick = TimeSpan.FromSeconds(m_QueueDelaySeconds);
|
|
TimeSpan clear = TimeSpan.FromSeconds(m_QueueClearIntervalSeconds);
|
|
|
|
m_ReAnimated = new Dictionary<PlayerMobile, ZombieSkeleton>();
|
|
m_DeathQueue = new List<PlayerMobile>();
|
|
|
|
if (today >= HolidaySettings.StartHalloween && today <= HolidaySettings.FinishHalloween)
|
|
{
|
|
m_Timer = Timer.DelayCall(tick, tick, new TimerCallback(Timer_Callback));
|
|
|
|
m_ClearTimer = Timer.DelayCall(clear, clear, new TimerCallback(Clear_Callback));
|
|
|
|
EventSink.PlayerDeath += new PlayerDeathEventHandler(EventSink_PlayerDeath);
|
|
}
|
|
}
|
|
|
|
public static void EventSink_PlayerDeath(PlayerDeathEventArgs e)
|
|
{
|
|
if (e.Mobile != null && !e.Mobile.Deleted) /* not sure .. better safe than sorry? */
|
|
{
|
|
if (e.Mobile is PlayerMobile)
|
|
{
|
|
PlayerMobile player = e.Mobile as PlayerMobile;
|
|
|
|
if (m_Timer.Running && !m_DeathQueue.Contains(player) && m_DeathQueue.Count < m_DeathQueueLimit)
|
|
{
|
|
m_DeathQueue.Add(player);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void Clear_Callback()
|
|
{
|
|
m_ReAnimated.Clear();
|
|
|
|
m_DeathQueue.Clear();
|
|
|
|
if (DateTime.UtcNow <= HolidaySettings.FinishHalloween)
|
|
{
|
|
m_ClearTimer.Stop();
|
|
}
|
|
}
|
|
|
|
private static void Timer_Callback()
|
|
{
|
|
PlayerMobile player = null;
|
|
|
|
if (DateTime.UtcNow <= HolidaySettings.FinishHalloween)
|
|
{
|
|
for (int index = 0; m_DeathQueue.Count > 0 && index < m_DeathQueue.Count; index++)
|
|
{
|
|
if (!m_ReAnimated.ContainsKey(m_DeathQueue[index]))
|
|
{
|
|
player = m_DeathQueue[index];
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (player != null && !player.Deleted && m_ReAnimated.Count < m_TotalZombieLimit)
|
|
{
|
|
Map map = Utility.RandomBool() ? Map.Trammel : Map.Felucca;
|
|
Point3D home = (GetRandomPointInRect(m_Cemetaries[Utility.Random(m_Cemetaries.Length)], map));
|
|
|
|
if (map.CanSpawnMobile(home))
|
|
{
|
|
ZombieSkeleton zombieskel = new ZombieSkeleton(player);
|
|
|
|
m_ReAnimated.Add(player, zombieskel);
|
|
zombieskel.Home = home;
|
|
zombieskel.RangeHome = 10;
|
|
|
|
zombieskel.MoveToWorld(home, map);
|
|
|
|
m_DeathQueue.Remove(player);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_Timer.Stop();
|
|
}
|
|
}
|
|
|
|
private static Point3D GetRandomPointInRect(Rectangle2D rect, Map map)
|
|
{
|
|
int x = Utility.Random(rect.X, rect.Width);
|
|
int y = Utility.Random(rect.Y, rect.Height);
|
|
|
|
return new Point3D(x, y, map.GetAverageZ(x, y));
|
|
}
|
|
}
|
|
|
|
public class PlayerBones : BaseContainer
|
|
{
|
|
[Constructable]
|
|
public PlayerBones(String name)
|
|
: base(Utility.RandomMinMax(0x0ECA, 0x0ED2))
|
|
{
|
|
this.Name = String.Format("{0}'s bones", name);
|
|
|
|
switch( Utility.Random(10) )
|
|
{
|
|
case 0:
|
|
this.Hue = 0xa09;
|
|
break;
|
|
case 1:
|
|
this.Hue = 0xa93;
|
|
break;
|
|
case 2:
|
|
this.Hue = 0xa47;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
public PlayerBones(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();
|
|
}
|
|
}
|
|
|
|
[CorpseName("a rotting corpse")]
|
|
public class ZombieSkeleton : BaseCreature
|
|
{
|
|
private static readonly string m_Name = "Zombie Skeleton";
|
|
private PlayerMobile m_DeadPlayer;
|
|
public ZombieSkeleton()
|
|
: this(null)
|
|
{
|
|
}
|
|
|
|
public ZombieSkeleton(PlayerMobile player)
|
|
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
|
|
{
|
|
this.m_DeadPlayer = player;
|
|
|
|
this.Name = (player != null) ? String.Format("{0}'s {1}", player.Name, m_Name) : m_Name;
|
|
|
|
this.Body = 0x93;
|
|
this.BaseSoundID = 0x1c3;
|
|
|
|
this.SetStr(500);
|
|
this.SetDex(500);
|
|
this.SetInt(500);
|
|
|
|
this.SetHits(2500);
|
|
this.SetMana(500);
|
|
this.SetStam(500);
|
|
|
|
this.SetDamage(8, 18);
|
|
|
|
this.SetDamageType(ResistanceType.Physical, 40);
|
|
this.SetDamageType(ResistanceType.Cold, 60);
|
|
|
|
this.SetResistance(ResistanceType.Fire, 50);
|
|
this.SetResistance(ResistanceType.Energy, 50);
|
|
this.SetResistance(ResistanceType.Physical, 50);
|
|
this.SetResistance(ResistanceType.Cold, 50);
|
|
this.SetResistance(ResistanceType.Poison, 50);
|
|
|
|
this.SetSkill(SkillName.MagicResist, 65.1, 80.0);
|
|
this.SetSkill(SkillName.Tactics, 95.1, 100);
|
|
this.SetSkill(SkillName.Wrestling, 85.1, 95);
|
|
|
|
this.Fame = 1000;
|
|
this.Karma = -1000;
|
|
|
|
this.VirtualArmor = 18;
|
|
}
|
|
|
|
public ZombieSkeleton(Serial serial)
|
|
: base(serial)
|
|
{
|
|
}
|
|
|
|
public override bool BleedImmune
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
public override Poison PoisonImmune
|
|
{
|
|
get
|
|
{
|
|
return Poison.Regular;
|
|
}
|
|
}
|
|
|
|
public override void GenerateLoot()
|
|
{
|
|
switch( Utility.Random(10) )
|
|
{
|
|
case 0:
|
|
this.PackItem(new LeftArm());
|
|
break;
|
|
case 1:
|
|
this.PackItem(new RightArm());
|
|
break;
|
|
case 2:
|
|
this.PackItem(new Torso());
|
|
break;
|
|
case 3:
|
|
this.PackItem(new Bone());
|
|
break;
|
|
case 4:
|
|
this.PackItem(new RibCage());
|
|
break;
|
|
case 5:
|
|
if (this.m_DeadPlayer != null && !this.m_DeadPlayer.Deleted)
|
|
{
|
|
this.PackItem(new PlayerBones(this.m_DeadPlayer.Name));
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
this.AddLoot(LootPack.Meager);
|
|
}
|
|
|
|
public override void OnDelete()
|
|
{
|
|
if (HalloweenHauntings.ReAnimated != null)
|
|
{
|
|
if (this.m_DeadPlayer != null && !this.m_DeadPlayer.Deleted)
|
|
{
|
|
if (HalloweenHauntings.ReAnimated.Count > 0 && HalloweenHauntings.ReAnimated.ContainsKey(this.m_DeadPlayer))
|
|
{
|
|
HalloweenHauntings.ReAnimated.Remove(this.m_DeadPlayer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Serialize(GenericWriter writer)
|
|
{
|
|
base.Serialize(writer);
|
|
writer.Write((int)0);
|
|
|
|
writer.WriteMobile(this.m_DeadPlayer);
|
|
}
|
|
|
|
public override void Deserialize(GenericReader reader)
|
|
{
|
|
base.Deserialize(reader);
|
|
int version = reader.ReadInt();
|
|
|
|
this.m_DeadPlayer = (PlayerMobile)reader.ReadMobile();
|
|
}
|
|
}
|
|
} |