using System; using System.Collections.Generic; using Server.Mobiles; using Server.Regions; using Server.Misc; using Server.Commands; namespace Server.EventSystem { public class TownInvasion : BaseEvent { public static TimeSpan m_TIEventRate = TimeSpan.FromHours( 12.0 ); #region Private Variables private int m_MinSpawnZ; private int m_MaxSpawnZ; private int m_LastMsg; private bool m_Broadcast = true; private bool m_FinalStage; private Point3D m_Top = new Point3D(4394, 1058, 30); private Point3D m_Bottom = new Point3D(4481, 1173, 0); private Map m_SpawnMap = Map.Felucca; private List m_Spawned; private TownMonsterType m_TownMonsterType = TownMonsterType.OrcsandRatmen; private TownChampionType m_TownChampionType = TownChampionType.Barracoon; private double m_ParagonChance = 0.05; private bool m_AlwaysMurderer = false; private bool m_IsRunning; private DateTime m_TimeNextScheduledEvent = DateTime.MinValue; private DateTime m_TimeLastEvent = DateTime.MinValue; private string m_TownInvaded = "Moonglow"; #endregion #region Public Variables [CommandProperty( AccessLevel.Administrator )] public int MinSpawnZ { get { return m_MinSpawnZ; } set { m_MinSpawnZ = value; } } [CommandProperty( AccessLevel.Administrator )] public int MaxSpawnZ { get { return m_MaxSpawnZ; } set { m_MaxSpawnZ = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool Broadcast { get { return m_Broadcast; } set { m_Broadcast = value; } } [CommandProperty( AccessLevel.Administrator )] public Point3D Top { get { return m_Top; } set { m_Top = value; } } [CommandProperty( AccessLevel.Administrator )] public Point3D Bottom { get { return m_Bottom; } set { m_Bottom = value; } } [CommandProperty( AccessLevel.Administrator )] public Map SpawnMap { get { return m_SpawnMap; } set { m_SpawnMap = value; } } public List Spawned { get { return m_Spawned; } set { m_Spawned = value; } } [CommandProperty( AccessLevel.GameMaster )] public TownMonsterType TownMonsterType { get { return m_TownMonsterType; } set { m_TownMonsterType = value; } } [CommandProperty( AccessLevel.GameMaster )] public TownChampionType TownChampionType { get { return m_TownChampionType; } set { m_TownChampionType = value; } } [CommandProperty( AccessLevel.GameMaster )] public double ParagonChance { get { return m_ParagonChance; } set { m_ParagonChance = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool AlwaysMurderer { get { return m_AlwaysMurderer; } set { m_AlwaysMurderer = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool IsRunning { get { return m_IsRunning; } set { m_IsRunning = value; } } [CommandProperty( AccessLevel.GameMaster, true )] public DateTime TimeNextScheduledEvent { get { return m_TimeNextScheduledEvent; } set { m_TimeNextScheduledEvent = value; } } [CommandProperty( AccessLevel.GameMaster, true )] public DateTime TimeLastEvent { get { return m_TimeLastEvent; } set { m_TimeLastEvent = value; } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan TIEventRate { get { return m_TIEventRate; } set { m_TIEventRate = value; } } [CommandProperty( AccessLevel.GameMaster )] public string TownInvaded { get { return m_TownInvaded; } set { m_TownInvaded = value; } } #endregion #region Property Overrides public override EventType EventType { get { return EventType.TownInvasion; } } public override string EventName { get { return "Town Invasion"; } } public override TimeSpan TimerFrequency { get { return TimeSpan.FromSeconds( 1.0 ); } } public override Map StartingMap { get { return Map.Felucca; } } public override Point3D StartingLocation { get { return new Point3D(6804, 2233, 0); } } #endregion #region Constructor public TownInvasion() { m_Spawned = new List(); } #endregion #region Method Overrides protected override void OnEnable() { } protected override void OnDisable() { } public override void OnStart() { if( !this.IsRunning ) { switch( Utility.Random(6) ) { /*case 0: //Britain Doesn't Get Invaded Anymore { this.Top = new Point3D(1426, 1554, 30); this.Bottom = new Point3D(1490, 1735, 0); this.MinSpawnZ = 0; this.MaxSpawnZ = 31; this.SpawnMap = Map.Felucca; this.TownInvaded = "Britain"; this.TownMonsterType = TownMonsterType.OrcsandRatmen; this.TownChampionType = TownChampionType.Barracoon; break; }*/ case 0: //Moonglow { this.Top = new Point3D(4394, 1058, 30); this.Bottom = new Point3D(4481, 1173, 0); this.MinSpawnZ = 0; this.MaxSpawnZ = 31; this.SpawnMap = Map.Felucca; this.TownInvaded = "Moonglow"; this.TownMonsterType = TownMonsterType.Abyss; this.TownChampionType = TownChampionType.Rikktor; break; } case 1: //Minoc { this.Top = new Point3D(2443, 420, 15); this.Bottom = new Point3D(2520, 539, 0); this.MinSpawnZ = 0; this.MaxSpawnZ = 16; this.SpawnMap = Map.Felucca; this.TownInvaded = "Minoc"; this.TownMonsterType = TownMonsterType.OreElementals; this.TownChampionType = TownChampionType.LordOaks; break; } case 2: //Delucia { this.Top = new Point3D(5171, 3980, 41); this.Bottom = new Point3D(5300, 4040, 39); this.MinSpawnZ = 39; this.MaxSpawnZ = 42; this.SpawnMap = Map.Felucca; this.TownInvaded = "Delucia"; this.TownMonsterType = TownMonsterType.Ophidian; this.TownChampionType = TownChampionType.Mephitis; break; } case 3: //Ocllo { this.Top = new Point3D(3617, 2482, 0); this.Bottom = new Point3D(3712, 2630, 20); this.MinSpawnZ = 0; this.MaxSpawnZ = 21; this.SpawnMap = Map.Felucca; this.TownInvaded = "Ocllo"; this.TownMonsterType = TownMonsterType.Elementals; this.TownChampionType = TownChampionType.Semidar; break; } case 4: //Skara Brae { this.Top = new Point3D(577, 2131, -90); this.Bottom = new Point3D(634, 2234, -90); this.MinSpawnZ = 0; this.MaxSpawnZ = 1; this.SpawnMap = Map.Felucca; this.TownInvaded = "Skara Brae"; this.TownMonsterType = TownMonsterType.Humanoid; this.TownChampionType = TownChampionType.Serado; break; } case 5: //Yew { this.Top = new Point3D(457, 913, 30); this.Bottom = new Point3D(662, 1117, 0); this.MinSpawnZ = 0; this.MaxSpawnZ = 0; this.SpawnMap = Map.Felucca; this.TownInvaded = "Yew"; this.TownMonsterType = TownMonsterType.OrcsandRatmen; this.TownChampionType = TownChampionType.Barracoon; break; } } foreach ( Region r in Region.Regions ) { if ( r is GuardedRegion && r.Name == this.TownInvaded ) { ((GuardedRegion)r).Disabled = true; } } Spawn(); this.m_TimeLastEvent = DateTime.Now; this.m_TimeNextScheduledEvent = DateTime.Now + TIEventRate; //World.Broadcast( 0x35, true, "{0} is being invaded! The guards have fled! Help save it's citzens!", this.m_TownInvaded); string bc = this.m_TownInvaded + " is being invaded! The guards have fled! Help save it's citizens!"; Server.Mobiles.InvasionAnnouncer.SetAnnouncement( bc ); this.IsRunning = true; } } protected override void OnStop() { Despawn(); foreach ( Region r in Region.Regions ) { if ( r is GuardedRegion && r.Name == this.TownInvaded ) { ((GuardedRegion)r).Disabled = false; } } Server.Mobiles.InvasionAnnouncer.DeleteAnnouncements(); this.IsRunning = false; //it's not running anymore } public override void OnTick( int ticks ) { int count = 0; for ( int i = 0; i < m_Spawned.Count; ++i ) if ( m_Spawned[i] != null && !m_Spawned[i].Deleted && m_Spawned[i].Alive ) ++count; if ( !m_FinalStage ) //Monsters { if ( count == 0 ) //All monsters have been slayed SpawnChamp(); } else //Champion { if ( count == 0 ) //Champion is dead { if ( m_Broadcast ) Announce( 1161, "The city of {0} has been saved and the guards have returned to their posts. The citizens of {1} thank you!", m_TownInvaded, m_TownInvaded ); Stop(); } } } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int)3 ); //version //v 3 writer.Write( m_Spawned, true ); // v 2 writer.Write( m_IsRunning ); // v 1 writer.Write( m_ParagonChance ); writer.Write( m_AlwaysMurderer ); writer.Write( m_TimeNextScheduledEvent ); writer.Write( m_TimeLastEvent ); writer.Write( m_TIEventRate ); // v 0 writer.Write( m_MinSpawnZ ); writer.Write( m_MaxSpawnZ ); writer.Write( m_Broadcast ); writer.Write( m_Top ); writer.Write( m_Bottom ); writer.Write( m_SpawnMap ); writer.WriteEncodedInt( (int)m_TownMonsterType ); writer.WriteEncodedInt( (int)m_TownChampionType ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 3: { m_Spawned = reader.ReadStrongMobileList(); goto case 2; } case 2: { m_IsRunning = reader.ReadBool(); goto case 1; } case 1: { m_ParagonChance = reader.ReadDouble(); m_AlwaysMurderer = reader.ReadBool(); m_TimeNextScheduledEvent = reader.ReadDateTime(); m_TimeLastEvent = reader.ReadDateTime(); m_TIEventRate = reader.ReadTimeSpan(); goto case 0; } case 0: { m_MinSpawnZ = reader.ReadInt(); m_MaxSpawnZ = reader.ReadInt(); m_Broadcast = reader.ReadBool(); m_Top = reader.ReadPoint3D(); m_Bottom = reader.ReadPoint3D(); m_SpawnMap = reader.ReadMap(); m_TownMonsterType = (TownMonsterType)reader.ReadEncodedInt(); m_TownChampionType = (TownChampionType)reader.ReadEncodedInt(); break; } } OnStop(); m_IsRunning = false; //m_Spawned = new List(); } #endregion #region Private Methods private void Spawn() { Despawn(); MonsterTownSpawnEntry[] entries = null; switch ( m_TownMonsterType ) { default: case TownMonsterType.Abyss: entries = MonsterTownSpawnEntry.Abyss; break; case TownMonsterType.Arachnid: entries = MonsterTownSpawnEntry.Arachnid; break; case TownMonsterType.DragonKind: entries = MonsterTownSpawnEntry.DragonKind; break; case TownMonsterType.Elementals: entries = MonsterTownSpawnEntry.Elementals; break; case TownMonsterType.Humanoid: entries = MonsterTownSpawnEntry.Humanoid; break; case TownMonsterType.Ophidian: entries = MonsterTownSpawnEntry.Ophidian; break; case TownMonsterType.OrcsandRatmen: entries = MonsterTownSpawnEntry.OrcsandRatmen; break; case TownMonsterType.OreElementals: entries = MonsterTownSpawnEntry.OreElementals; break; case TownMonsterType.Snakes: entries = MonsterTownSpawnEntry.Snakes; break; case TownMonsterType.Undead: entries = MonsterTownSpawnEntry.Undead; break; } for ( int i = 0; i < entries.Length; ++i ) for ( int count = 0; count < entries[i].Amount; ++count ) AddMonster( entries[i].Monster ); } private void Despawn() { foreach ( Mobile m in m_Spawned ) if ( m != null && !m.Deleted ) m.Delete(); m_Spawned.Clear(); m_FinalStage = false; } private Point3D FindSpawnLocation() { int x, y, z; do { x = Utility.Random( m_Top.X, ( m_Bottom.X - m_Top.X ) ); y = Utility.Random( m_Top.Y, ( m_Bottom.Y - m_Top.Y ) ); z = SpawnMap.GetAverageZ( x, y ); } while ( !SpawnMap.CanSpawnMobile( x, y, z ) ); return new Point3D( x, y, z ); } private void AddMonster( Type type ) { object monster = Activator.CreateInstance( type ); if ( monster != null && monster is Mobile ) { Point3D location = FindSpawnLocation(); Mobile from = (Mobile)monster; if ( m_FinalStage ) { Announce( 1161, "{0} has come to take over {1}! Please save it's citizens!", from.Name, m_TownInvaded ); //TODO: Pack Goodies } from.MoveToWorld( location, SpawnMap ); if ( from is BaseCreature ) { ( (BaseCreature)from ).Tamable = false; if ( !(from is BaseChampion) && !(from is Harrower) && !(from is BaseVendor) && !(from is BaseEscortable) && !(from is Clone) ) { //if( Utility.RandomDouble() < m_ParagonChance ) //( (BaseCreature)from ).IsParagon = true; if( m_AlwaysMurderer ) ( (BaseCreature)from ).Kills = 6; } } m_Spawned.Add( from ); } } public void SpawnChamp() { Despawn(); m_FinalStage = true; switch ( m_TownChampionType ) { default: case TownChampionType.Barracoon: AddMonster( typeof( Barracoon ) ); break; case TownChampionType.Harrower: AddMonster( typeof( Harrower ) ); break; case TownChampionType.LordOaks: AddMonster( typeof( LordOaks ) ); break; case TownChampionType.Mephitis: AddMonster( typeof( Mephitis ) ); break; case TownChampionType.Neira: AddMonster( typeof( Neira ) ); break; case TownChampionType.Rikktor: AddMonster( typeof( Rikktor ) ); break; case TownChampionType.Semidar: AddMonster( typeof( Semidar ) ); break; case TownChampionType.Serado: AddMonster( typeof( Serado ) ); break; } } #endregion } public class TIWorldTimer : Timer { public static void Initialize() { new TIWorldTimer().Start(); } public TIWorldTimer() : base( TownInvasion.m_TIEventRate, TownInvasion.m_TIEventRate ) { Priority = TimerPriority.OneMinute; } protected override void OnTick() { BaseEvent evnt = Server.EventSystem.EventCore.FindEvent( EventType.TownInvasion ); if( evnt != null ) //don't run a new one if one is running already. { evnt.Start(); } } } }