using System; using System.Collections; using Server.Network; using Server.Targeting; using Server.Prompts; using Server.Misc; namespace Server.Items { public enum KeyType { Copper = 0x100E, Gold = 0x100F, Iron = 0x1010, Rusty = 0x1013 } public interface ILockable { bool Locked{ get; set; } uint KeyValue{ get; set; } } public class Key : Item { private string m_Description; private uint m_KeyVal; private Item m_Link; private int m_MaxRange; public static uint RandomValue() { return (uint)(0xFFFFFFFE * Utility.RandomDouble()) + 1; } public static void RemoveKeys( Mobile m, uint keyValue ) { if ( keyValue == 0 ) return; RemoveKeys( m.Backpack, keyValue ); RemoveKeys( m.InnBox, keyValue ); } public static void RemoveKeys( Container cont, uint keyValue ) { if ( cont == null || keyValue == 0 ) return; Item[] items = cont.FindItemsByType( new Type[] { typeof( Key ), typeof( KeyRing ) } ); foreach ( Item item in items ) { if ( item is Key ) { Key key = (Key) item; if ( key.KeyValue == keyValue ) key.Delete(); } else { KeyRing keyRing = (KeyRing) item; keyRing.RemoveKeys( keyValue ); } } } public static bool ContainsKey( Container cont, uint keyValue ) { if ( cont == null ) return false; Item[] items = cont.FindItemsByType( new Type[] { typeof( Key ), typeof( KeyRing ) } ); foreach ( Item item in items ) { if ( item is Key ) { Key key = (Key) item; if ( key.KeyValue == keyValue ) return true; } else { KeyRing keyRing = (KeyRing) item; if ( keyRing.ContainsKey( keyValue ) ) return true; } } return false; } [CommandProperty( AccessLevel.GameMaster )] public string Description { get { return m_Description; } set { m_Description = value; InvalidateProperties(); } } [CommandProperty( AccessLevel.GameMaster )] public int MaxRange { get { return m_MaxRange; } set { m_MaxRange = value; } } [CommandProperty( AccessLevel.GameMaster )] public uint KeyValue { get { return m_KeyVal; } set { m_KeyVal = value; InvalidateProperties(); } } [CommandProperty( AccessLevel.GameMaster )] public Item Link { get { return m_Link; } set { m_Link = value; } } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 2 ); // version writer.Write( (int) m_MaxRange ); writer.Write( (Item) m_Link ); writer.Write( (string) m_Description ); writer.Write( (uint) m_KeyVal ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 2: { m_MaxRange = reader.ReadInt(); goto case 1; } case 1: { m_Link = reader.ReadItem(); goto case 0; } case 0: { if ( version < 2 || m_MaxRange == 0 ) m_MaxRange = 3; m_Description = reader.ReadString(); m_KeyVal = reader.ReadUInt(); break; } } } [Constructable] public Key() : this( KeyType.Iron, 0 ) { } [Constructable] public Key( KeyType type ) : this( type, 0 ) { } [Constructable] public Key( uint val ) : this ( KeyType.Iron, val ) { } [Constructable] public Key( KeyType type, uint LockVal ) : this( type, LockVal, null ) { m_KeyVal = LockVal; } public Key( KeyType type, uint LockVal, Item link ) : base( (int)type ) { Weight = 1.0; m_MaxRange = 3; m_KeyVal = LockVal; m_Link = link; } public Key( Serial serial ) : base( serial ) { } public override void OnDoubleClick( Mobile from ) { if ( !this.IsChildOf( from.Backpack ) ) { from.SendLocalizedMessage( 501661 ); // That key is unreachable. return; } Target t; int number; if ( m_KeyVal != 0 ) { number = 501662; // What shall I use this key on? t = new UnlockTarget( this ); } else { number = 501663; // This key is a key blank. Which key would you like to make a copy of? t = new CopyTarget( this ); } from.SendLocalizedMessage( number ); from.Target = t; } public override void GetProperties( ObjectPropertyList list ) { base.GetProperties( list ); string desc; if ( m_KeyVal == 0 ) desc = "(blank)"; else if ( (desc = m_Description) == null || (desc = desc.Trim()).Length <= 0 ) desc = null; if ( desc != null ) list.Add( desc ); } public override void OnSingleClick( Mobile from ) { base.OnSingleClick( from ); string desc; if ( m_KeyVal == 0 ) desc = "(blank)"; else if ( (desc = m_Description) == null || (desc = desc.Trim()).Length <= 0 ) desc = ""; if ( desc.Length > 0 ) from.Send( new UnicodeMessage( Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", "", desc ) ); } public bool UseOn( Mobile from, ILockable o ) { if ( o.KeyValue == this.KeyValue ) { if ( o is BaseDoor && !((BaseDoor)o).UseLocks() ) { return false; } else { o.Locked = !o.Locked; if ( o is LockableContainer ) { LockableContainer cont = (LockableContainer)o; if ( cont.LockLevel == -255 ) cont.LockLevel = cont.RequiredSkill - 10; } if ( o is Item ) { Item item = (Item) o; if ( o.Locked ) item.SendLocalizedMessageTo( from, 1048000 ); // You lock it. else item.SendLocalizedMessageTo( from, 1048001 ); // You unlock it. if ( item is LockableContainer ) { LockableContainer cont = (LockableContainer) item; if ( cont.TrapType != TrapType.None && cont.TrapOnLockpick ) { if ( o.Locked ) item.SendLocalizedMessageTo( from, 501673 ); // You re-enable the trap. else item.SendLocalizedMessageTo( from, 501672 ); // You disable the trap temporarily. Lock it again to re-enable it. } } } return true; } } else { return false; } } private class RenamePrompt : Prompt { private Key m_Key; public RenamePrompt( Key key ) { m_Key = key; } public override void OnResponse( Mobile from, string text ) { if ( m_Key.Deleted || !m_Key.IsChildOf( from.Backpack ) ) { from.SendLocalizedMessage( 501661 ); // That key is unreachable. return; } m_Key.Description = Utility.FixHtml( text ); } } private class UnlockTarget : Target { private Key m_Key; public UnlockTarget( Key key ) : base( key.MaxRange, false, TargetFlags.None ) { m_Key = key; CheckLOS = false; } protected override void OnTarget( Mobile from, object targeted ) { if ( m_Key.Deleted || !m_Key.IsChildOf( from.Backpack ) ) { from.SendLocalizedMessage( 501661 ); // That key is unreachable. return; } int number; if ( targeted == m_Key ) { number = 501665; // Enter a description for this key. from.Prompt = new RenamePrompt( m_Key ); } else if ( targeted is ILockable ) { if ( m_Key.UseOn( from, (ILockable) targeted ) ) number = -1; else number = 501668; // This key doesn't seem to unlock that. } else { number = 501666; // You can't unlock that! } if ( number != -1 ) { from.SendLocalizedMessage( number ); } } } private class CopyTarget : Target { private Key m_Key; public CopyTarget( Key key ) : base( 3, false, TargetFlags.None ) { m_Key = key; } protected override void OnTarget( Mobile from, object targeted ) { if ( m_Key.Deleted || !m_Key.IsChildOf( from.Backpack ) ) { from.SendLocalizedMessage( 501661 ); // That key is unreachable. return; } int number; if ( targeted is Key ) { Key k = (Key)targeted; if ( k.m_KeyVal == 0 ) { number = 501675; // This key is also blank. } else if ( SkillCheck.TestTrade( from, Trades.Tinkering, 0, 75.0 ) ) { number = 501676; // You make a copy of the key. m_Key.Description = k.Description; m_Key.KeyValue = k.KeyValue; m_Key.Link = k.Link; m_Key.MaxRange = k.MaxRange; } else if ( Utility.RandomDouble() <= 0.1 ) // 10% chance to destroy the key { from.SendLocalizedMessage( 501677 ); // You fail to make a copy of the key. number = 501678; // The key was destroyed in the attempt. m_Key.Delete(); } else { number = 501677; // You fail to make a copy of the key. } } else { number = 501688; // Not a key. } from.SendLocalizedMessage( number ); } } } }