using System; using System.Collections; using Server; using Server.Mobiles; /* ** TimedLever, TimedSwitch, and XmlLatch class and TimedSwitchableItem ** Version 1.01 ** updated 5/06/04 ** ArteGordon */ namespace Server.Items { public class XmlLatch : Item { private TimeSpan m_MinDelay; private TimeSpan m_MaxDelay; private DateTime m_End; private InternalTimer m_Timer; private int m_State = 0; private int m_ResetState = 0; [Constructable] public XmlLatch() : base( 0x1BBF ) { Movable = false; } public XmlLatch(int itemID) : base( itemID ) { } public XmlLatch( Serial serial ) : base( serial ) { } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan MinDelay { get { return m_MinDelay; } set { m_MinDelay = value; InvalidateProperties(); } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan MaxDelay { get { return m_MaxDelay; } set { m_MaxDelay = value; InvalidateProperties(); } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan TimeUntilReset { get { if ( m_Timer != null && m_Timer.Running ) return m_End - DateTime.UtcNow; else return TimeSpan.FromSeconds( 0 ); } set { DoTimer( value ); InvalidateProperties(); } } [CommandProperty( AccessLevel.GameMaster )] public virtual int ResetState { get{ return m_ResetState; } set { m_ResetState = value; if ( m_Timer != null && m_Timer.Running ) m_Timer.Stop(); InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public virtual int State { get{ return m_State; } set { m_State = value; StartTimer(); InvalidateProperties();} } public void StartTimer() { if(m_State != m_ResetState && (m_MinDelay > TimeSpan.Zero || m_MaxDelay > TimeSpan.Zero)) DoTimer(); else if ( m_Timer != null && m_Timer.Running ) m_Timer.Stop(); } public virtual void OnReset() { State = ResetState; } public void DoTimer() { int minSeconds = (int)m_MinDelay.TotalSeconds; int maxSeconds = (int)m_MaxDelay.TotalSeconds; TimeSpan delay = TimeSpan.FromSeconds( Utility.RandomMinMax( minSeconds, maxSeconds ) ); DoTimer( delay ); } public void DoTimer( TimeSpan delay ) { m_End = DateTime.UtcNow + delay; if ( m_Timer != null ) m_Timer.Stop(); m_Timer = new InternalTimer( this, delay ); m_Timer.Start(); } private class InternalTimer : Timer { private XmlLatch m_latch; public InternalTimer( XmlLatch xmllatch, TimeSpan delay ) : base( delay ) { Priority = TimerPriority.OneSecond; m_latch = xmllatch; } protected override void OnTick() { if(m_latch != null && !m_latch.Deleted) { Stop(); m_latch.OnReset(); } } } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); // version // version 0 writer.Write( this.m_State ); writer.Write( this.m_ResetState ); writer.Write( this.m_MinDelay ); writer.Write( this.m_MaxDelay ); bool running = (m_Timer != null && m_Timer.Running); writer.Write( running ); if ( m_Timer != null && m_Timer.Running ) writer.Write( this.m_End - DateTime.UtcNow ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 0: { // note this is redundant with the base class serialization, but it is there for older (pre 1.02) version compatibility // not needed this.m_State = reader.ReadInt(); this.m_ResetState = reader.ReadInt(); this.m_MinDelay = reader.ReadTimeSpan(); this.m_MaxDelay = reader.ReadTimeSpan(); bool running = reader.ReadBool(); if(running) { TimeSpan delay = reader.ReadTimeSpan(); this.DoTimer( delay ); } } break; } } } public class TimedLever : XmlLatch, ILinkable { public enum leverType { Two_State, Three_State} private leverType m_LeverType = leverType.Two_State; private int m_LeverSound = 936; private Item m_TargetItem0 = null; private string m_TargetProperty0 = null; private Item m_TargetItem1 = null; private string m_TargetProperty1 = null; private Item m_TargetItem2 = null; private string m_TargetProperty2 = null; private Item m_LinkedItem = null; private bool already_being_activated = false; private bool m_Disabled = false; [CommandProperty(AccessLevel.GameMaster)] public bool Disabled { set { m_Disabled = value; } get { return m_Disabled; } } [CommandProperty(AccessLevel.GameMaster)] public Item Link { set { m_LinkedItem = value; } get { return m_LinkedItem; } } [Constructable] public TimedLever() : base( 0x108C ) { Name = "A lever"; Movable = false; } public TimedLever( Serial serial ) : base( serial ) { } [CommandProperty(AccessLevel.GameMaster)] public override int State { get { return base.State; } set { // prevent infinite recursion if (!already_being_activated) { already_being_activated = true; Activate(null, value, null); already_being_activated = false; } InvalidateProperties(); } } public void Activate(Mobile from, int state, ArrayList links) { if (Disabled) return; string status_str = null; if (state < 0) state = 0; if (state > 1 && m_LeverType == leverType.Two_State) state = 1; if (state > 2) state = 2; // assign the latch state and start the timer base.State = state; // update the graphic SetLeverStatic(); // play the switching sound //if (from != null) //{ // from.PlaySound(m_LeverSound); //} try { Effects.PlaySound(Location, Map, m_LeverSound); } catch { } // if a target object has been specified then apply the property modification if (state == 0 && m_TargetItem0 != null && !m_TargetItem0.Deleted && m_TargetProperty0 != null && m_TargetProperty0.Length > 0) { BaseXmlSpawner.ApplyObjectStringProperties(null, m_TargetProperty0, m_TargetItem0, null, this, out status_str); } if (state == 1 && m_TargetItem1 != null && !m_TargetItem1.Deleted && m_TargetProperty1 != null && m_TargetProperty1.Length > 0) { BaseXmlSpawner.ApplyObjectStringProperties(null, m_TargetProperty1, m_TargetItem1, null, this, out status_str); } if (state == 2 && m_TargetItem2 != null && !m_TargetItem2.Deleted && m_TargetProperty2 != null && m_TargetProperty2.Length > 0) { BaseXmlSpawner.ApplyObjectStringProperties(null, m_TargetProperty2, m_TargetItem2, null, this, out status_str); } // if the switch is linked, then activate the link as well if (Link != null && Link is ILinkable) { if (links == null) { links = new ArrayList(); } // activate other linked objects if they have not already been activated if (!links.Contains(this)) { links.Add(this); ((ILinkable)Link).Activate(from, state, links); } } // report any problems to staff if (status_str != null && from != null && from.AccessLevel > AccessLevel.Player) { from.SendMessage("{0}", status_str); } } [CommandProperty( AccessLevel.GameMaster )] public int LeverSound { get{ return m_LeverSound; } set { m_LeverSound = value; InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public leverType LeverType { get{ return m_LeverType; } set { m_LeverType = value; State = 0; InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] new public virtual Direction Direction { get{ return base.Direction; } set { base.Direction = value; SetLeverStatic();InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public Item Target0Item { get{ return m_TargetItem0; } set { m_TargetItem0 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target0Property { get{ return m_TargetProperty0; } set { m_TargetProperty0 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target0ItemName { get{ if(m_TargetItem0 != null && !m_TargetItem0.Deleted) return m_TargetItem0.Name; else return null;} } [CommandProperty( AccessLevel.GameMaster )] public Item Target1Item { get{ return m_TargetItem1; } set { m_TargetItem1 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target1Property { get{ return m_TargetProperty1; } set { m_TargetProperty1 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target1ItemName { get{ if(m_TargetItem1 != null && !m_TargetItem1.Deleted) return m_TargetItem1.Name; else return null;} } [CommandProperty( AccessLevel.GameMaster )] public Item Target2Item { get{ return m_TargetItem2; } set { m_TargetItem2 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target2Property { get{ return m_TargetProperty2; } set { m_TargetProperty2 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target2ItemName { get{ if(m_TargetItem2 != null && !m_TargetItem2.Deleted) return m_TargetItem2.Name; else return null;} } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 2 ); // version // version 2 writer.Write(this.m_Disabled); // version 1 writer.Write(this.m_LinkedItem); // version 0 writer.Write( this.m_LeverSound ); writer.Write( (int)this.m_LeverType ); writer.Write( this.m_TargetItem0 ); writer.Write( this.m_TargetProperty0 ); writer.Write( this.m_TargetItem1 ); writer.Write( this.m_TargetProperty1 ); writer.Write( this.m_TargetItem2 ); writer.Write( this.m_TargetProperty2 ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 2: { m_Disabled = reader.ReadBool(); goto case 1; } case 1: { m_LinkedItem = reader.ReadItem(); goto case 0; } case 0: { this.m_LeverSound = reader.ReadInt(); int ltype = reader.ReadInt(); switch( ltype ) { case (int)leverType.Two_State: this.m_LeverType = leverType.Two_State; break; case (int)leverType.Three_State: this.m_LeverType = leverType.Three_State; break; } this.m_TargetItem0 = reader.ReadItem(); this.m_TargetProperty0 = reader.ReadString(); this.m_TargetItem1 = reader.ReadItem(); this.m_TargetProperty1 = reader.ReadString(); this.m_TargetItem2 = reader.ReadItem(); this.m_TargetProperty2 = reader.ReadString(); } break; } // refresh the lever static to reflect the state SetLeverStatic(); } public void SetLeverStatic() { switch(this.Direction) { case Direction.North: case Direction.South: case Direction.Right: case Direction.Up: if(m_LeverType == leverType.Two_State) this.ItemID = 0x108c+ State*2; else this.ItemID = 0x108c+ State; break; case Direction.East: case Direction.West: case Direction.Left: case Direction.Down: if(m_LeverType == leverType.Two_State) this.ItemID = 0x1093+ State*2; else this.ItemID = 0x1093+ State; break; default: break; } } public override void OnDoubleClick( Mobile from ) { if(from == null || Disabled) return; if ( !from.InRange( GetWorldLocation(), 2 ) || !from.InLOS(this)) { from.SendLocalizedMessage( 500446 ); // That is too far away. return; } // animate and change state int newstate = State+1; if(newstate > 1 && m_LeverType == leverType.Two_State) newstate = 0; if(newstate > 2) newstate = 0; // carry out the switch actions Activate(from, newstate, null); } } public class TimedSwitch : XmlLatch, ILinkable { private int m_SwitchSound = 939; private Item m_TargetItem0 = null; private string m_TargetProperty0 = null; private Item m_TargetItem1 = null; private string m_TargetProperty1 = null; private Item m_LinkedItem = null; private bool already_being_activated = false; private bool m_Disabled = false; [CommandProperty(AccessLevel.GameMaster)] public bool Disabled { set { m_Disabled = value; } get { return m_Disabled; } } [CommandProperty(AccessLevel.GameMaster)] public Item Link { set { m_LinkedItem = value; } get { return m_LinkedItem; } } [Constructable] public TimedSwitch() : base( 0x108F ) { Name = "A switch"; Movable = false; } public TimedSwitch( Serial serial ) : base( serial ) { } [CommandProperty( AccessLevel.GameMaster )] public override int State { get { return base.State; } set { // prevent infinite recursion if (!already_being_activated) { already_being_activated = true; Activate(null, value, null); already_being_activated = false; } InvalidateProperties(); } } public void Activate(Mobile from, int state, ArrayList links) { if (Disabled) return; string status_str = null; if (state < 0) state = 0; if (state > 1) state = 1; // assign the latch state and start the timer base.State = state; // update the graphic SetSwitchStatic(); // play the switching sound //if (from != null) //{ // from.PlaySound(m_SwitchSound); //} try { Effects.PlaySound(Location, Map, m_SwitchSound); } catch { } // if a target object has been specified then apply the property modification if (state == 0 && m_TargetItem0 != null && !m_TargetItem0.Deleted && m_TargetProperty0 != null && m_TargetProperty0.Length > 0) { BaseXmlSpawner.ApplyObjectStringProperties(null, m_TargetProperty0, m_TargetItem0, null, this, out status_str); } if (state == 1 && m_TargetItem1 != null && !m_TargetItem1.Deleted && m_TargetProperty1 != null && m_TargetProperty1.Length > 0) { BaseXmlSpawner.ApplyObjectStringProperties(null, m_TargetProperty1, m_TargetItem1, null, this, out status_str); } // if the switch is linked, then activate the link as well if (Link != null && Link is ILinkable) { if (links == null) { links = new ArrayList(); } // activate other linked objects if they have not already been activated if (!links.Contains(this)) { links.Add(this); ((ILinkable)Link).Activate(from, state, links); } } // report any problems to staff if (status_str != null && from != null && from.AccessLevel > AccessLevel.Player) { from.SendMessage("{0}", status_str); } } [CommandProperty( AccessLevel.GameMaster )] public int SwitchSound { get{ return m_SwitchSound; } set { m_SwitchSound = value; InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] new public virtual Direction Direction { get{ return base.Direction; } set { base.Direction = value; SetSwitchStatic();InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public Item Target0Item { get{ return m_TargetItem0; } set { m_TargetItem0 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target0Property { get{ return m_TargetProperty0; } set { m_TargetProperty0 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target0ItemName { get{ if(m_TargetItem0 != null && !m_TargetItem0.Deleted) return m_TargetItem0.Name; else return null;} } [CommandProperty( AccessLevel.GameMaster )] public Item Target1Item { get{ return m_TargetItem1; } set { m_TargetItem1 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target1Property { get{ return m_TargetProperty1; } set { m_TargetProperty1 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target1ItemName { get{ if(m_TargetItem1 != null && !m_TargetItem1.Deleted) return m_TargetItem1.Name; else return null;} } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 2 ); // version // version 2 writer.Write(this.m_Disabled); // version 1 writer.Write(this.m_LinkedItem); // version 0 writer.Write( this.m_SwitchSound ); writer.Write( this.m_TargetItem0 ); writer.Write( this.m_TargetProperty0 ); writer.Write( this.m_TargetItem1 ); writer.Write( this.m_TargetProperty1 ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 2: { m_Disabled = reader.ReadBool(); goto case 1; } case 1: { m_LinkedItem = reader.ReadItem(); goto case 0; } case 0: { this.m_SwitchSound = reader.ReadInt(); this.m_TargetItem0 = reader.ReadItem(); this.m_TargetProperty0 = reader.ReadString(); this.m_TargetItem1 = reader.ReadItem(); this.m_TargetProperty1 = reader.ReadString(); } break; } // refresh the lever static to reflect the state SetSwitchStatic(); } public void SetSwitchStatic() { switch(this.Direction) { case Direction.North: case Direction.South: case Direction.Right: case Direction.Up: this.ItemID = 0x108f+ State; break; case Direction.East: case Direction.West: case Direction.Left: case Direction.Down: this.ItemID = 0x1091+ State; break; default: this.ItemID = 0x108f+ State; break; } } public override void OnDoubleClick( Mobile from ) { if(from == null || Disabled) return; if ( !from.InRange( GetWorldLocation(), 2 ) || !from.InLOS(this)) { from.SendLocalizedMessage( 500446 ); // That is too far away. return; } // animate and change state int newstate = State+1; if(newstate > 1) newstate = 0; // carry out the switch actions Activate(from, newstate, null); } } public class TimedSwitchableItem : XmlLatch, ILinkable { private int m_SwitchSound = 939; private Item m_TargetItem0 = null; private string m_TargetProperty0 = null; private Item m_TargetItem1 = null; private string m_TargetProperty1 = null; private int m_ItemID0 = 0x108F; private int m_ItemID1 = 0x1090; private Item m_LinkedItem = null; private bool already_being_activated = false; private Point3D m_Offset = Point3D.Zero; private bool m_Disabled = false; private bool m_NoDoubleClick = false; [CommandProperty(AccessLevel.GameMaster)] public bool Disabled { set { m_Disabled = value; } get { return m_Disabled; } } [CommandProperty(AccessLevel.GameMaster)] public bool NoDoubleClick { set { m_NoDoubleClick = value; } get { return m_NoDoubleClick; } } [CommandProperty(AccessLevel.GameMaster)] public Point3D Offset { set { m_Offset = value; } get { return m_Offset; } } [CommandProperty(AccessLevel.GameMaster)] public Item Link { set { m_LinkedItem = value; } get { return m_LinkedItem; } } [Constructable] public TimedSwitchableItem() : base( 0x108F ) { Name = "A switchable item"; Movable = false; } public TimedSwitchableItem( Serial serial ) : base( serial ) { } [CommandProperty(AccessLevel.GameMaster)] public override int State { get { return base.State; } set { // prevent infinite recursion if (!already_being_activated) { already_being_activated = true; Activate(null, value, null); already_being_activated = false; } InvalidateProperties(); } } public void Activate(Mobile from, int state, ArrayList links) { if (Disabled) return; string status_str = null; if (state < 0) state = 0; if (state > 1) state = 1; if (base.State != state) { // apply the offset SetSwitchOffset(); } // assign the latch state and start the timer base.State = state; // update the graphic SetSwitchStatic(); // play the switching sound //if (from != null) //{ // from.PlaySound(m_SwitchSound); //} try { Effects.PlaySound(Location, Map, m_SwitchSound); } catch { } // if a target object has been specified then apply the property modification if (state == 0 && m_TargetItem0 != null && !m_TargetItem0.Deleted && m_TargetProperty0 != null && m_TargetProperty0.Length > 0) { BaseXmlSpawner.ApplyObjectStringProperties(null, m_TargetProperty0, m_TargetItem0, null, this, out status_str); } if (state == 1 && m_TargetItem1 != null && !m_TargetItem1.Deleted && m_TargetProperty1 != null && m_TargetProperty1.Length > 0) { BaseXmlSpawner.ApplyObjectStringProperties(null, m_TargetProperty1, m_TargetItem1, null, this, out status_str); } // if the switch is linked, then activate the link as well if (Link != null && Link is ILinkable) { if (links == null) { links = new ArrayList(); } // activate other linked objects if they have not already been activated if (!links.Contains(this)) { links.Add(this); ((ILinkable)Link).Activate(from, state, links); } } // report any problems to staff if (status_str != null && from != null && from.AccessLevel > AccessLevel.Player) { from.SendMessage("{0}", status_str); } } [CommandProperty( AccessLevel.GameMaster )] public int ItemID0 { get{ return m_ItemID0; } set { m_ItemID0 = value; // refresh the lever static to reflect the state SetSwitchStatic(); InvalidateProperties(); } } [CommandProperty( AccessLevel.GameMaster )] public int ItemID1 { get{ return m_ItemID1; } set { m_ItemID1 = value; // refresh the lever static to reflect the state SetSwitchStatic(); InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public int SwitchSound { get{ return m_SwitchSound; } set { m_SwitchSound = value; InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public Item Target0Item { get{ return m_TargetItem0; } set { m_TargetItem0 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target0Property { get{ return m_TargetProperty0; } set { m_TargetProperty0 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target0ItemName { get{ if(m_TargetItem0 != null && !m_TargetItem0.Deleted) return m_TargetItem0.Name; else return null;} } [CommandProperty( AccessLevel.GameMaster )] public Item Target1Item { get{ return m_TargetItem1; } set { m_TargetItem1 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target1Property { get{ return m_TargetProperty1; } set { m_TargetProperty1 = value;InvalidateProperties();} } [CommandProperty( AccessLevel.GameMaster )] public string Target1ItemName { get{ if(m_TargetItem1 != null && !m_TargetItem1.Deleted) return m_TargetItem1.Name; else return null;} } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 4 ); // version // version 4 writer.Write(this.m_NoDoubleClick); // version 3 writer.Write(this.m_Disabled); writer.Write(this.m_Offset); // version 2 writer.Write(this.m_LinkedItem); // version 1 writer.Write( this.m_ItemID0 ); writer.Write( this.m_ItemID1 ); // version 0 writer.Write( this.m_SwitchSound ); writer.Write( this.m_TargetItem0 ); writer.Write( this.m_TargetProperty0 ); writer.Write( this.m_TargetItem1 ); writer.Write( this.m_TargetProperty1 ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 4: { m_NoDoubleClick = reader.ReadBool(); goto case 3; } case 3: { m_Disabled = reader.ReadBool(); m_Offset = reader.ReadPoint3D(); goto case 2; } case 2: { m_LinkedItem = reader.ReadItem(); goto case 1; } case 1: { m_ItemID0 = reader.ReadInt(); m_ItemID1 = reader.ReadInt(); goto case 0; } case 0: { m_SwitchSound = reader.ReadInt(); m_TargetItem0 = reader.ReadItem(); m_TargetProperty0 = reader.ReadString(); m_TargetItem1 = reader.ReadItem(); m_TargetProperty1 = reader.ReadString(); } break; } // refresh the lever static to reflect the state SetSwitchStatic(); } public void SetSwitchStatic() { switch(State) { case 0: this.ItemID = ItemID0; break; case 1: this.ItemID = ItemID1; break; } } public void SetSwitchOffset() { switch (State) { case 0: Location = new Point3D(X - m_Offset.X, Y - m_Offset.Y, Z - m_Offset.Z); break; case 1: Location = new Point3D(X + m_Offset.X, Y + m_Offset.Y, Z + m_Offset.Z); break; } } public override void OnDoubleClick( Mobile from ) { if(from == null || Disabled || NoDoubleClick) return; if ( !from.InRange( GetWorldLocation(), 2 ) || !from.InLOS(this)) { from.SendLocalizedMessage( 500446 ); // That is too far away. return; } // animate and change state int newstate = State+1; if(newstate > 1) newstate = 0; // carry out the switch actions Activate(from, newstate, null); } } }