296 lines
8.0 KiB
C#
296 lines
8.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Server;
|
|
using Server.Items;
|
|
using Server.Mobiles;
|
|
using Server.Regions;
|
|
using System.Xml;
|
|
using System.Linq;
|
|
using System.Collections;
|
|
|
|
namespace Server.Engines.Doom
|
|
{
|
|
public class DoomGuardianRegion : DungeonRegion
|
|
{
|
|
public static DoomGuardianRegion Instance { get; set; }
|
|
|
|
public static void Initialize()
|
|
{
|
|
if (Instance != null)
|
|
Instance.CheckDoors();
|
|
}
|
|
|
|
private Timer m_Timer;
|
|
|
|
public bool Active { get; set; }
|
|
public List<DarkGuardian> Guardians { get; set; }
|
|
public BaseDoor DoorOne { get; set; }
|
|
public BaseDoor DoorTwo { get; set; }
|
|
public DateTime NextActivate { get; set; }
|
|
|
|
public bool CanActivate { get { return NextActivate < DateTime.UtcNow; } }
|
|
|
|
private static Rectangle2D[] RegionBounds = new Rectangle2D[] { new Rectangle2D(355, 5, 20, 20) };
|
|
private static Rectangle2D PentagramBounds = new Rectangle2D(364, 14, 2, 2);
|
|
private static Point3D DoorOneLoc = new Point3D(355, 14, -1);
|
|
private static Point3D DoorTwoLoc = new Point3D(355, 15, -1);
|
|
private static Point3D KickLoc = new Point3D(344, 172, -1);
|
|
private static Point3D PentagramLoc = new Point3D(365, 15, -1);
|
|
|
|
public DoomGuardianRegion(XmlElement xml, Map map, Region parent)
|
|
: base(xml, map, parent)
|
|
{
|
|
Instance = this;
|
|
}
|
|
|
|
public override bool AllowHousing( Mobile from, Point3D p )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public override void OnLocationChanged( Mobile m, Point3D oldLocation )
|
|
{
|
|
base.OnLocationChanged( m, oldLocation );
|
|
|
|
if(!Active && CanActivate && m is PlayerMobile && m.AccessLevel == AccessLevel.Player && m.Alive)
|
|
{
|
|
for(int x = m.X - 3; x <= m.X + 3; x++)
|
|
{
|
|
for(int y = m.Y - 3; y <= m.Y + 3; y++)
|
|
{
|
|
if(!Active && PentagramBounds.Contains(new Point2D(x, y)))
|
|
{
|
|
Activate(m);
|
|
Active = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool CheckReset()
|
|
{
|
|
if (GetPlayerCount() == 0 || Guardians == null || Guardians.Count == 0 || !Guardians.Any(x => !x.Deleted))
|
|
{
|
|
Reset();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override void OnDeath( Mobile m )
|
|
{
|
|
if(Guardians != null && m is DarkGuardian && Guardians.Contains((DarkGuardian)m))
|
|
{
|
|
Guardians.Remove((DarkGuardian)m);
|
|
}
|
|
|
|
if(m is PlayerMobile && Active)
|
|
{
|
|
Timer.DelayCall<PlayerMobile>(TimeSpan.FromSeconds(3), MoveDeadPlayer, (PlayerMobile)m);
|
|
}
|
|
}
|
|
|
|
public void MoveDeadPlayer(PlayerMobile pm)
|
|
{
|
|
if (pm.Region == this)
|
|
{
|
|
BaseCreature.TeleportPets(pm, KickLoc, Map.Malas);
|
|
pm.MoveToWorld(KickLoc, Map.Malas);
|
|
|
|
if (pm.Corpse != null)
|
|
pm.Corpse.MoveToWorld(KickLoc, Map.Malas);
|
|
}
|
|
|
|
if (!GetEnumeratedMobiles().Any(mob => mob is PlayerMobile && mob.Alive))
|
|
{
|
|
Reset();
|
|
}
|
|
}
|
|
|
|
public void Activate(Mobile m)
|
|
{
|
|
if (Active)
|
|
return;
|
|
|
|
CheckDoors();
|
|
|
|
DoorOne.Open = false;
|
|
DoorTwo.Open = false;
|
|
DoorOne.Locked = true;
|
|
DoorTwo.Locked = true;
|
|
|
|
Effects.PlaySound(DoorOne.Location, DoorOne.Map, 0x241);
|
|
Effects.PlaySound(DoorTwo.Location, DoorTwo.Map, 0x241);
|
|
|
|
if (Guardians == null)
|
|
Guardians = new List<DarkGuardian>();
|
|
|
|
int count = 0;
|
|
foreach (var mob in this.GetEnumeratedMobiles().Where(mob => mob is PlayerMobile || (mob is BaseCreature && ((BaseCreature)mob).GetMaster() != null && !mob.IsDeadBondedPet)))
|
|
{
|
|
if (mob.NetState != null)
|
|
mob.SendLocalizedMessage(1050000, "", 365); // The locks on the door click loudly and you begin to hear a faint hissing near the walls.
|
|
|
|
if(mob.Alive)
|
|
count++;
|
|
}
|
|
|
|
count = Math.Max(1, count * 2);
|
|
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
DarkGuardian guardian = new DarkGuardian();
|
|
|
|
int x = Utility.RandomMinMax(PentagramBounds.X, PentagramBounds.X + PentagramBounds.Width);
|
|
int y = Utility.RandomMinMax(PentagramBounds.Y, PentagramBounds.Y + PentagramBounds.Height);
|
|
int z = Map.Malas.GetAverageZ(x, y);
|
|
|
|
guardian.MoveToWorld(new Point3D(x, y, z), Map.Malas);
|
|
Guardians.Add(guardian);
|
|
|
|
guardian.Combatant = m;
|
|
}
|
|
|
|
if (m_Timer != null)
|
|
{
|
|
m_Timer.Stop();
|
|
m_Timer = null;
|
|
}
|
|
|
|
m_Timer = new InternalTimer(this);
|
|
m_Timer.Start();
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
if (!Active)
|
|
return;
|
|
|
|
if (m_Timer != null)
|
|
{
|
|
m_Timer.Stop();
|
|
m_Timer = null;
|
|
}
|
|
|
|
DoorOne.Locked = false;
|
|
DoorTwo.Locked = false;
|
|
|
|
Active = false;
|
|
NextActivate = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(15, 60));
|
|
}
|
|
|
|
public void CheckDoors()
|
|
{
|
|
if(DoorOne == null || DoorOne.Deleted)
|
|
{
|
|
if(!CheckDoor(DoorOneLoc, 1))
|
|
{
|
|
DoorOne = new MetalDoor2(DoorFacing.NorthCW);
|
|
DoorOne.MoveToWorld(DoorOneLoc, Map.Malas);
|
|
DoorOne.KeyValue = 0;
|
|
}
|
|
}
|
|
|
|
if(DoorTwo == null || DoorTwo.Deleted)
|
|
{
|
|
if(!CheckDoor(DoorTwoLoc, 2))
|
|
{
|
|
DoorTwo = new MetalDoor2(DoorFacing.SouthCCW);
|
|
DoorTwo.MoveToWorld(DoorTwoLoc, Map.Malas);
|
|
DoorTwo.KeyValue = 0;
|
|
}
|
|
}
|
|
|
|
if(DoorOne != null && DoorOne.Link != DoorTwo)
|
|
DoorOne.Link = DoorTwo;
|
|
|
|
if(DoorTwo != null && DoorTwo.Link != DoorOne)
|
|
DoorTwo.Link = DoorOne;
|
|
|
|
CheckPentagram();
|
|
}
|
|
|
|
public bool CheckDoor(Point3D p, int door)
|
|
{
|
|
IPooledEnumerable eable = Map.Malas.GetItemsInRange(p, 0);
|
|
|
|
foreach(Item item in eable)
|
|
{
|
|
if(item is BaseDoor)
|
|
{
|
|
eable.Free();
|
|
|
|
if (door == 1)
|
|
DoorOne = item as BaseDoor;
|
|
else
|
|
DoorTwo = item as BaseDoor;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
eable.Free();
|
|
return false;
|
|
}
|
|
|
|
private void CheckPentagram()
|
|
{
|
|
IPooledEnumerable eable = Map.Malas.GetItemsInRange(PentagramLoc, 0);
|
|
|
|
foreach (Item item in eable)
|
|
{
|
|
if (item is PentagramAddon)
|
|
{
|
|
eable.Free();
|
|
return;
|
|
}
|
|
}
|
|
|
|
eable.Free();
|
|
|
|
var addon = new PentagramAddon();
|
|
addon.MoveToWorld(PentagramLoc, Map.Malas);
|
|
}
|
|
|
|
private class InternalTimer : Timer
|
|
{
|
|
public DoomGuardianRegion Region { get; private set; }
|
|
public DateTime NextGas { get; private set; }
|
|
|
|
public InternalTimer(DoomGuardianRegion reg)
|
|
: base(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500))
|
|
{
|
|
Region = reg;
|
|
NextGas = DateTime.UtcNow + TimeSpan.FromSeconds(3);
|
|
}
|
|
|
|
protected override void OnTick()
|
|
{
|
|
if (Region.CheckReset())
|
|
{
|
|
Region.Reset();
|
|
}
|
|
else if (NextGas < DateTime.UtcNow)
|
|
{
|
|
for (int i = 0; i < Utility.RandomMinMax(5, 12); i++)
|
|
{
|
|
Point3D p = Region.RandomSpawnLocation(0, true, false, Point3D.Zero, 0);
|
|
Effects.SendLocationEffect(p, Map.Malas, Utility.RandomList(0x113C, 0x1147, 0x11A8) - 2, 16, 3, 0, 0);
|
|
}
|
|
|
|
foreach (var m in Region.GetEnumeratedMobiles().Where(m => m is PlayerMobile && m.Alive && m.AccessLevel == AccessLevel.Player && m.Poison == null))
|
|
{
|
|
m.ApplyPoison(m, Poison.Deadly);
|
|
m.SendSound(0x231);
|
|
}
|
|
|
|
NextGas = DateTime.UtcNow + TimeSpan.FromSeconds(3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|