using System; using System.Collections.Generic; using Server; using Server.ContextMenus; using Server.Engines.PartySystem; using Server.Gumps; using Server.Multis; using Server.Network; namespace Server.Items { public class TreasureMapChest : LockableContainer { public override int LabelNumber{ get{ return 3000541; } } private int m_Level; private DateTime m_DeleteTime; private Timer m_Timer; private Mobile m_Owner; private bool m_Temporary; private List m_Guardians; [CommandProperty( AccessLevel.GameMaster )] public int Level{ get{ return m_Level; } set{ m_Level = value; } } [CommandProperty( AccessLevel.GameMaster )] public Mobile Owner{ get{ return m_Owner; } set{ m_Owner = value; } } [CommandProperty( AccessLevel.GameMaster )] public DateTime DeleteTime{ get{ return m_DeleteTime; } } [CommandProperty( AccessLevel.GameMaster )] public bool Temporary{ get{ return m_Temporary; } set{ m_Temporary = value; } } public List Guardians { get { return m_Guardians; } } [Constructable] public TreasureMapChest( int level ) : this( null, level, false ) { } public TreasureMapChest( Mobile owner, int level, bool temporary ) : base( 0xE40 ) { m_Owner = owner; m_Level = level; m_DeleteTime = DateTime.Now + TimeSpan.FromHours( 3.0 ); m_Temporary = temporary; m_Guardians = new List(); m_Timer = new DeleteTimer( this, m_DeleteTime ); m_Timer.Start(); Fill( this, level ); } public static void Fill( LockableContainer cont, int level ) { cont.Movable = false; cont.Locked = true; int numberItems; if ( level == 0 ) { cont.LockLevel = 0; // Can't be unlocked cont.DropItem( new Gold( Utility.RandomMinMax( 50, 100 ) ) ); if ( Utility.RandomDouble() < 0.75 ) cont.DropItem( new TreasureMap( 0, Map.Britannia ) ); } else { cont.TrapType = TrapType.ExplosionTrap; cont.TrapPower = level * 25; cont.TrapLevel = level; switch ( level ) { case 1: cont.RequiredSkill = 36; break; case 2: cont.RequiredSkill = 76; break; case 3: cont.RequiredSkill = 84; break; case 4: cont.RequiredSkill = 92; break; case 5: cont.RequiredSkill = 100; break; case 6: cont.RequiredSkill = 100; break; } cont.LockLevel = cont.RequiredSkill - 10; cont.MaxLockLevel = cont.RequiredSkill + 40; cont.DropItem( new Gold( level * 1000 ) ); for ( int i = 0; i < level * 5; ++i ) cont.DropItem( Loot.RandomScroll( 0, 63, SpellbookType.Regular ) ); numberItems = level * 6; for ( int i = 0; i < numberItems; ++i ) { Item item = Loot.RandomArmorOrShieldOrWeapon(); if ( item is BaseWeapon ) { BaseWeapon weapon = (BaseWeapon)item; weapon.DamageLevel = (WeaponDamageLevel)Utility.Random( 6 ); weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random( 6 ); weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random( 6 ); cont.DropItem( item ); } else if ( item is BaseArmor ) { BaseArmor armor = (BaseArmor)item; armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random( 6 ); armor.Durability = (ArmorDurabilityLevel)Utility.Random( 6 ); cont.DropItem( item ); } else { cont.DropItem( item ); } } } int reagents; if ( level == 0 ) reagents = 12; else reagents = level * 3; for ( int i = 0; i < reagents; i++ ) { Item item = Loot.RandomReagent(); item.Amount = Utility.RandomMinMax( 40, 60 ); cont.DropItem( item ); } int gems; if ( level == 0 ) gems = 2; else gems = level * 3; for ( int i = 0; i < gems; i++ ) { Item item = Loot.RandomGem(); cont.DropItem( item ); } } public override bool CheckLocked( Mobile from ) { if ( !this.Locked ) return false; if ( this.Level == 0 && from.AccessLevel < AccessLevel.GameMaster ) { foreach ( Mobile m in this.Guardians ) { if ( m.Alive ) { from.SendLocalizedMessage( 1046448 ); // You must first kill the guardians before you may open this chest. return true; } } LockPick( from ); return false; } else { return base.CheckLocked( from ); } } private List m_Lifted = new List(); private bool CheckLoot( Mobile m, bool criminalAction ) { if ( m_Temporary ) return false; if ( m.AccessLevel >= AccessLevel.GameMaster || m_Owner == null || m == m_Owner ) return true; Party p = Party.Get( m_Owner ); if ( p != null && p.Contains( m ) ) return true; Map map = this.Map; if ( map != null && (map.Rules & MapRules.HarmfulRestrictions) == 0 ) { if ( criminalAction ) m.CriminalAction( true ); else m.SendLocalizedMessage( 1010630 ); // Taking someone else's treasure is a criminal offense! return true; } m.SendLocalizedMessage( 1010631 ); // You did not discover this chest! return false; } public override bool IsDecoContainer { get{ return false; } } public override bool CheckItemUse( Mobile from, Item item ) { return CheckLoot( from, item != this ) && base.CheckItemUse( from, item ); } public override bool CheckLift( Mobile from, Item item, ref LRReason reject ) { return CheckLoot( from, true ) && base.CheckLift( from, item, ref reject ); } public override void OnItemLifted( Mobile from, Item item ) { bool notYetLifted = !m_Lifted.Contains( item ); from.RevealingAction(); if ( notYetLifted ) { m_Lifted.Add( item ); if ( 0.1 >= Utility.RandomDouble() ) // 10% chance to spawn a new monster TreasureMap.Spawn( m_Level, GetWorldLocation(), Map, from, false ); } base.OnItemLifted( from, item ); } public override bool CheckHold( Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight ) { if ( m.AccessLevel < AccessLevel.GameMaster ) { m.SendLocalizedMessage( 1048122, "", 0x8A5 ); // The chest refuses to be filled with treasure again. return false; } return base.CheckHold( m, item, message, checkItems, plusItems, plusWeight ); } public TreasureMapChest( Serial serial ) : base( serial ) { } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 2 ); // version writer.Write( m_Guardians, true ); writer.Write( (bool) m_Temporary ); writer.Write( m_Owner ); writer.Write( (int) m_Level ); writer.WriteDeltaTime( m_DeleteTime ); writer.Write( m_Lifted, true ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 2: { m_Guardians = reader.ReadStrongMobileList(); m_Temporary = reader.ReadBool(); goto case 1; } case 1: { m_Owner = reader.ReadMobile(); goto case 0; } case 0: { m_Level = reader.ReadInt(); m_DeleteTime = reader.ReadDeltaTime(); m_Lifted = reader.ReadStrongItemList(); if ( version < 2 ) m_Guardians = new List(); break; } } if ( !m_Temporary ) { m_Timer = new DeleteTimer( this, m_DeleteTime ); m_Timer.Start(); } else { Delete(); } } public override void OnAfterDelete() { if ( m_Timer != null ) m_Timer.Stop(); m_Timer = null; base.OnAfterDelete(); } public override void GetContextMenuEntries( Mobile from, List list ) { base.GetContextMenuEntries( from, list ); if ( from.Alive ) list.Add( new RemoveEntry( from, this ) ); } public void BeginRemove( Mobile from ) { if ( !from.Alive ) return; from.CloseGump( typeof( RemoveGump ) ); from.SendGump( new RemoveGump( from, this ) ); } public void EndRemove( Mobile from ) { if ( Deleted || from != m_Owner || !from.InRange( GetWorldLocation(), 3 ) ) return; from.SendLocalizedMessage( 1048124, "", 0x8A5 ); // The old, rusted chest crumbles when you hit it. this.Delete(); } private class RemoveGump : Gump { private Mobile m_From; private TreasureMapChest m_Chest; public RemoveGump( Mobile from, TreasureMapChest chest ) : base( 15, 15 ) { m_From = from; m_Chest = chest; Closable = false; Disposable = false; AddPage( 0 ); AddBackground( 30, 0, 240, 240, 2620 ); AddHtmlLocalized( 45, 15, 200, 80, 1048125, 0xFFFFFF, false, false ); // When this treasure chest is removed, any items still inside of it will be lost. AddHtmlLocalized( 45, 95, 200, 60, 1048126, 0xFFFFFF, false, false ); // Are you certain you're ready to remove this chest? AddButton( 40, 153, 4005, 4007, 1, GumpButtonType.Reply, 0 ); AddHtmlLocalized( 75, 155, 180, 40, 1048127, 0xFFFFFF, false, false ); // Remove the Treasure Chest AddButton( 40, 195, 4005, 4007, 2, GumpButtonType.Reply, 0 ); AddHtmlLocalized( 75, 197, 180, 35, 1006045, 0xFFFFFF, false, false ); // Cancel } public override void OnResponse( NetState sender, RelayInfo info ) { if ( info.ButtonID == 1 ) m_Chest.EndRemove( m_From ); } } private class RemoveEntry : ContextMenuEntry { private Mobile m_From; private TreasureMapChest m_Chest; public RemoveEntry( Mobile from, TreasureMapChest chest ) : base( 6149, 3 ) { m_From = from; m_Chest = chest; Enabled = ( from == chest.Owner ); } public override void OnClick() { if ( m_Chest.Deleted || m_From != m_Chest.Owner || !m_From.CheckAlive() ) return; m_Chest.BeginRemove( m_From ); } } private class DeleteTimer : Timer { private Item m_Item; public DeleteTimer( Item item, DateTime time ) : base( time - DateTime.Now ) { m_Item = item; Priority = TimerPriority.OneMinute; } protected override void OnTick() { m_Item.Delete(); } } } }