WorldPacketSA should not be used yet. There is much more work to be done and that version has not been looked at in quite some time.
1833 lines
No EOL
41 KiB
C#
1833 lines
No EOL
41 KiB
C#
/***************************************************************************
|
|
* Container.cs
|
|
* -------------------
|
|
* begin : May 1, 2002
|
|
* copyright : (C) The RunUO Software Team
|
|
* email : info@runuo.com
|
|
*
|
|
* $Id$
|
|
*
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
***************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using Server.Network;
|
|
|
|
namespace Server.Items
|
|
{
|
|
public delegate void OnItemConsumed( Item item, int amount );
|
|
public delegate int CheckItemGroup( Item a, Item b );
|
|
|
|
public delegate void ContainerSnoopHandler( Container cont, Mobile from );
|
|
|
|
public class Container : Item
|
|
{
|
|
private static ContainerSnoopHandler m_SnoopHandler;
|
|
|
|
public static ContainerSnoopHandler SnoopHandler
|
|
{
|
|
get{ return m_SnoopHandler; }
|
|
set{ m_SnoopHandler = value; }
|
|
}
|
|
|
|
private ContainerData m_ContainerData;
|
|
|
|
private int m_DropSound;
|
|
private int m_GumpID;
|
|
private int m_MaxItems;
|
|
|
|
private int m_TotalItems;
|
|
private int m_TotalWeight;
|
|
private int m_TotalGold;
|
|
|
|
private bool m_LiftOverride;
|
|
|
|
internal List<Item> m_Items;
|
|
|
|
public ContainerData ContainerData
|
|
{
|
|
get
|
|
{
|
|
if ( m_ContainerData == null )
|
|
UpdateContainerData();
|
|
|
|
return m_ContainerData;
|
|
}
|
|
set{ m_ContainerData = value; }
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public override int ItemID
|
|
{
|
|
get{ return base.ItemID; }
|
|
set
|
|
{
|
|
int oldID = this.ItemID;
|
|
|
|
base.ItemID = value;
|
|
|
|
if ( this.ItemID != oldID )
|
|
UpdateContainerData();
|
|
}
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public int GumpID
|
|
{
|
|
get{ return ( m_GumpID == -1 ? DefaultGumpID : m_GumpID ); }
|
|
set{ m_GumpID = value; }
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public int DropSound
|
|
{
|
|
get{ return ( m_DropSound == -1 ? DefaultDropSound : m_DropSound ); }
|
|
set{ m_DropSound = value; }
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public int MaxItems
|
|
{
|
|
get{ return ( m_MaxItems == -1 ? DefaultMaxItems : m_MaxItems ); }
|
|
set{ m_MaxItems = value; InvalidateProperties(); }
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public virtual int MaxWeight
|
|
{
|
|
get
|
|
{
|
|
if ( Parent is Container && ((Container)Parent).MaxWeight == 0 )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return DefaultMaxWeight;
|
|
}
|
|
}
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public bool LiftOverride
|
|
{
|
|
get{ return m_LiftOverride; }
|
|
set{ m_LiftOverride = value; }
|
|
}
|
|
|
|
public virtual void UpdateContainerData()
|
|
{
|
|
this.ContainerData = ContainerData.GetData( this.ItemID );
|
|
}
|
|
|
|
public virtual Rectangle2D Bounds{ get{ return ContainerData.Bounds; } }
|
|
public virtual int DefaultGumpID{ get{ return ContainerData.GumpID; } }
|
|
public virtual int DefaultDropSound{ get{ return ContainerData.DropSound; } }
|
|
|
|
public virtual int DefaultMaxItems{ get{ return m_GlobalMaxItems; } }
|
|
public virtual int DefaultMaxWeight{ get{ return m_GlobalMaxWeight; } }
|
|
|
|
public virtual bool IsDecoContainer
|
|
{
|
|
get{ return !Movable && !IsLockedDown && !IsSecure && Parent == null && !m_LiftOverride; }
|
|
}
|
|
|
|
public virtual int GetDroppedSound( Item item )
|
|
{
|
|
int dropSound = item.GetDropSound();
|
|
|
|
return dropSound != -1 ? dropSound : DropSound;
|
|
}
|
|
|
|
public override void OnSnoop( Mobile from )
|
|
{
|
|
if ( m_SnoopHandler != null )
|
|
m_SnoopHandler( this, from );
|
|
}
|
|
|
|
public override bool CheckLift( Mobile from, Item item, ref LRReason reject )
|
|
{
|
|
if ( from.AccessLevel < AccessLevel.GameMaster && IsDecoContainer )
|
|
{
|
|
reject = LRReason.CannotLift;
|
|
return false;
|
|
}
|
|
|
|
return base.CheckLift( from, item, ref reject );
|
|
}
|
|
|
|
public override bool CheckItemUse( Mobile from, Item item )
|
|
{
|
|
if ( item != this && from.AccessLevel < AccessLevel.GameMaster && IsDecoContainer )
|
|
{
|
|
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
|
|
return false;
|
|
}
|
|
|
|
return base.CheckItemUse( from, item );
|
|
}
|
|
|
|
public bool CheckHold( Mobile m, Item item, bool message )
|
|
{
|
|
return CheckHold( m, item, message, true, 0, 0 );
|
|
}
|
|
|
|
public bool CheckHold( Mobile m, Item item, bool message, bool checkItems )
|
|
{
|
|
return CheckHold( m, item, message, checkItems, 0, 0 );
|
|
}
|
|
|
|
public virtual bool CheckHold( Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight )
|
|
{
|
|
if ( m.AccessLevel < AccessLevel.GameMaster )
|
|
{
|
|
if ( IsDecoContainer )
|
|
{
|
|
if ( message )
|
|
SendCantStoreMessage( m, item );
|
|
|
|
return false;
|
|
}
|
|
|
|
int maxItems = this.MaxItems;
|
|
|
|
if ( checkItems && maxItems != 0 && (this.TotalItems + plusItems + item.TotalItems + (item.IsVirtualItem ? 0 : 1)) > maxItems )
|
|
{
|
|
if ( message )
|
|
SendFullItemsMessage( m, item );
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
int maxWeight = this.MaxWeight;
|
|
|
|
if ( maxWeight != 0 && (this.TotalWeight + plusWeight + item.TotalWeight + item.PileWeight) > maxWeight )
|
|
{
|
|
if ( message )
|
|
SendFullWeightMessage( m, item );
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
object parent = this.Parent;
|
|
|
|
while ( parent != null )
|
|
{
|
|
if ( parent is Container )
|
|
return ((Container)parent).CheckHold( m, item, message, checkItems, plusItems, plusWeight );
|
|
else if ( parent is Item )
|
|
parent = ((Item)parent).Parent;
|
|
else
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public virtual void SendFullItemsMessage( Mobile to, Item item )
|
|
{
|
|
to.SendMessage( "That container cannot hold more items." );
|
|
}
|
|
|
|
public virtual void SendFullWeightMessage( Mobile to, Item item )
|
|
{
|
|
to.SendMessage( "That container cannot hold more weight." );
|
|
}
|
|
|
|
public virtual void SendCantStoreMessage( Mobile to, Item item )
|
|
{
|
|
to.SendLocalizedMessage( 500176 ); // That is not your container, you can't store things here.
|
|
}
|
|
|
|
public virtual bool OnDragDropInto( Mobile from, Item item, Point3D p )
|
|
{
|
|
if ( !CheckHold( from, item, true, true ) )
|
|
return false;
|
|
|
|
item.Location = new Point3D( p.m_X, p.m_Y, 0 );
|
|
AddItem( item );
|
|
|
|
from.SendSound( GetDroppedSound( item ), GetWorldLocation() );
|
|
|
|
return true;
|
|
}
|
|
|
|
private class GroupComparer : IComparer
|
|
{
|
|
private CheckItemGroup m_Grouper;
|
|
|
|
public GroupComparer( CheckItemGroup grouper )
|
|
{
|
|
m_Grouper = grouper;
|
|
}
|
|
|
|
public int Compare( object x, object y )
|
|
{
|
|
Item a = (Item)x;
|
|
Item b = (Item)y;
|
|
|
|
return m_Grouper( a, b );
|
|
}
|
|
}
|
|
|
|
#region Consume[...]
|
|
|
|
public bool ConsumeTotalGrouped( Type type, int amount, bool recurse, OnItemConsumed callback, CheckItemGroup grouper )
|
|
{
|
|
if ( grouper == null )
|
|
throw new ArgumentNullException();
|
|
|
|
Item[] typedItems = FindItemsByType( type, recurse );
|
|
|
|
List<List<Item>> groups = new List<List<Item>>();
|
|
int idx = 0;
|
|
|
|
while ( idx < typedItems.Length )
|
|
{
|
|
Item a = typedItems[idx++];
|
|
List<Item> group = new List<Item>();
|
|
|
|
group.Add( a );
|
|
|
|
while ( idx < typedItems.Length )
|
|
{
|
|
Item b = typedItems[idx];
|
|
int v = grouper( a, b );
|
|
|
|
if ( v == 0 )
|
|
group.Add( b );
|
|
else
|
|
break;
|
|
|
|
++idx;
|
|
}
|
|
|
|
groups.Add( group );
|
|
}
|
|
|
|
Item[][] items = new Item[groups.Count][];
|
|
int[] totals = new int[groups.Count];
|
|
|
|
bool hasEnough = false;
|
|
|
|
for ( int i = 0; i < groups.Count; ++i )
|
|
{
|
|
items[i] = groups[i].ToArray();
|
|
//items[i] = (Item[])(((ArrayList)groups[i]).ToArray( typeof( Item ) ));
|
|
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
totals[i] += items[i][j].Amount;
|
|
|
|
if ( totals[i] >= amount )
|
|
hasEnough = true;
|
|
}
|
|
|
|
if ( !hasEnough )
|
|
return false;
|
|
|
|
for ( int i = 0; i < items.Length; ++i )
|
|
{
|
|
if ( totals[i] >= amount )
|
|
{
|
|
int need = amount;
|
|
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
{
|
|
Item item = items[i][j];
|
|
|
|
int theirAmount = item.Amount;
|
|
|
|
if ( theirAmount < need )
|
|
{
|
|
if ( callback != null )
|
|
callback( item, theirAmount );
|
|
|
|
item.Delete();
|
|
need -= theirAmount;
|
|
}
|
|
else
|
|
{
|
|
if ( callback != null )
|
|
callback( item, need );
|
|
|
|
item.Consume( need );
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public int ConsumeTotalGrouped( Type[] types, int[] amounts, bool recurse, OnItemConsumed callback, CheckItemGroup grouper )
|
|
{
|
|
if ( types.Length != amounts.Length )
|
|
throw new ArgumentException();
|
|
else if ( grouper == null )
|
|
throw new ArgumentNullException();
|
|
|
|
Item[][][] items = new Item[types.Length][][];
|
|
int[][] totals = new int[types.Length][];
|
|
|
|
for ( int i = 0; i < types.Length; ++i )
|
|
{
|
|
Item[] typedItems = FindItemsByType( types[i], recurse );
|
|
|
|
List<List<Item>> groups = new List<List<Item>>();
|
|
int idx = 0;
|
|
|
|
while ( idx < typedItems.Length )
|
|
{
|
|
Item a = typedItems[idx++];
|
|
List<Item> group = new List<Item>();
|
|
|
|
group.Add( a );
|
|
|
|
while ( idx < typedItems.Length )
|
|
{
|
|
Item b = typedItems[idx];
|
|
int v = grouper( a, b );
|
|
|
|
if ( v == 0 )
|
|
group.Add( b );
|
|
else
|
|
break;
|
|
|
|
++idx;
|
|
}
|
|
|
|
groups.Add( group );
|
|
}
|
|
|
|
items[i] = new Item[groups.Count][];
|
|
totals[i] = new int[groups.Count];
|
|
|
|
bool hasEnough = false;
|
|
|
|
for ( int j = 0; j < groups.Count; ++j )
|
|
{
|
|
items[i][j] = groups[j].ToArray();
|
|
//items[i][j] = (Item[])(((ArrayList)groups[j]).ToArray( typeof( Item ) ));
|
|
|
|
for ( int k = 0; k < items[i][j].Length; ++k )
|
|
totals[i][j] += items[i][j][k].Amount;
|
|
|
|
if ( totals[i][j] >= amounts[i] )
|
|
hasEnough = true;
|
|
}
|
|
|
|
if ( !hasEnough )
|
|
return i;
|
|
}
|
|
|
|
for ( int i = 0; i < items.Length; ++i )
|
|
{
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
{
|
|
if ( totals[i][j] >= amounts[i] )
|
|
{
|
|
int need = amounts[i];
|
|
|
|
for ( int k = 0; k < items[i][j].Length; ++k )
|
|
{
|
|
Item item = items[i][j][k];
|
|
|
|
int theirAmount = item.Amount;
|
|
|
|
if ( theirAmount < need )
|
|
{
|
|
if ( callback != null )
|
|
callback( item, theirAmount );
|
|
|
|
item.Delete();
|
|
need -= theirAmount;
|
|
}
|
|
else
|
|
{
|
|
if ( callback != null )
|
|
callback( item, need );
|
|
|
|
item.Consume( need );
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public int ConsumeTotalGrouped( Type[][] types, int[] amounts, bool recurse, OnItemConsumed callback, CheckItemGroup grouper )
|
|
{
|
|
if ( types.Length != amounts.Length )
|
|
throw new ArgumentException();
|
|
else if ( grouper == null )
|
|
throw new ArgumentNullException();
|
|
|
|
Item[][][] items = new Item[types.Length][][];
|
|
int[][] totals = new int[types.Length][];
|
|
|
|
for ( int i = 0; i < types.Length; ++i )
|
|
{
|
|
Item[] typedItems = FindItemsByType( types[i], recurse );
|
|
|
|
List<List<Item>> groups = new List<List<Item>>();
|
|
int idx = 0;
|
|
|
|
while ( idx < typedItems.Length )
|
|
{
|
|
Item a = typedItems[idx++];
|
|
List<Item> group = new List<Item>();
|
|
|
|
group.Add( a );
|
|
|
|
while ( idx < typedItems.Length )
|
|
{
|
|
Item b = typedItems[idx];
|
|
int v = grouper( a, b );
|
|
|
|
if ( v == 0 )
|
|
group.Add( b );
|
|
else
|
|
break;
|
|
|
|
++idx;
|
|
}
|
|
|
|
groups.Add( group );
|
|
}
|
|
|
|
items[i] = new Item[groups.Count][];
|
|
totals[i] = new int[groups.Count];
|
|
|
|
bool hasEnough = false;
|
|
|
|
for ( int j = 0; j < groups.Count; ++j )
|
|
{
|
|
items[i][j] = groups[j].ToArray();
|
|
|
|
for ( int k = 0; k < items[i][j].Length; ++k )
|
|
totals[i][j] += items[i][j][k].Amount;
|
|
|
|
if ( totals[i][j] >= amounts[i] )
|
|
hasEnough = true;
|
|
}
|
|
|
|
if ( !hasEnough )
|
|
return i;
|
|
}
|
|
|
|
for ( int i = 0; i < items.Length; ++i )
|
|
{
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
{
|
|
if ( totals[i][j] >= amounts[i] )
|
|
{
|
|
int need = amounts[i];
|
|
|
|
for ( int k = 0; k < items[i][j].Length; ++k )
|
|
{
|
|
Item item = items[i][j][k];
|
|
|
|
int theirAmount = item.Amount;
|
|
|
|
if ( theirAmount < need )
|
|
{
|
|
if ( callback != null )
|
|
callback( item, theirAmount );
|
|
|
|
item.Delete();
|
|
need -= theirAmount;
|
|
}
|
|
else
|
|
{
|
|
if ( callback != null )
|
|
callback( item, need );
|
|
|
|
item.Consume( need );
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public int ConsumeTotal( Type[][] types, int[] amounts )
|
|
{
|
|
return ConsumeTotal( types, amounts, true, null );
|
|
}
|
|
|
|
public int ConsumeTotal( Type[][] types, int[] amounts, bool recurse )
|
|
{
|
|
return ConsumeTotal( types, amounts, recurse, null );
|
|
}
|
|
|
|
public int ConsumeTotal( Type[][] types, int[] amounts, bool recurse, OnItemConsumed callback )
|
|
{
|
|
if ( types.Length != amounts.Length )
|
|
throw new ArgumentException();
|
|
|
|
Item[][] items = new Item[types.Length][];
|
|
int[] totals = new int[types.Length];
|
|
|
|
for ( int i = 0; i < types.Length; ++i )
|
|
{
|
|
items[i] = FindItemsByType( types[i], recurse );
|
|
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
totals[i] += items[i][j].Amount;
|
|
|
|
if ( totals[i] < amounts[i] )
|
|
return i;
|
|
}
|
|
|
|
for ( int i = 0; i < types.Length; ++i )
|
|
{
|
|
int need = amounts[i];
|
|
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
{
|
|
Item item = items[i][j];
|
|
|
|
int theirAmount = item.Amount;
|
|
|
|
if ( theirAmount < need )
|
|
{
|
|
if ( callback != null )
|
|
callback( item, theirAmount );
|
|
|
|
item.Delete();
|
|
need -= theirAmount;
|
|
}
|
|
else
|
|
{
|
|
if ( callback != null )
|
|
callback( item, need );
|
|
|
|
item.Consume( need );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public int ConsumeTotal( Type[] types, int[] amounts )
|
|
{
|
|
return ConsumeTotal( types, amounts, true, null );
|
|
}
|
|
|
|
public int ConsumeTotal( Type[] types, int[] amounts, bool recurse )
|
|
{
|
|
return ConsumeTotal( types, amounts, recurse, null );
|
|
}
|
|
|
|
public int ConsumeTotal( Type[] types, int[] amounts, bool recurse, OnItemConsumed callback )
|
|
{
|
|
if ( types.Length != amounts.Length )
|
|
throw new ArgumentException();
|
|
|
|
Item[][] items = new Item[types.Length][];
|
|
int[] totals = new int[types.Length];
|
|
|
|
for ( int i = 0; i < types.Length; ++i )
|
|
{
|
|
items[i] = FindItemsByType( types[i], recurse );
|
|
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
totals[i] += items[i][j].Amount;
|
|
|
|
if ( totals[i] < amounts[i] )
|
|
return i;
|
|
}
|
|
|
|
for ( int i = 0; i < types.Length; ++i )
|
|
{
|
|
int need = amounts[i];
|
|
|
|
for ( int j = 0; j < items[i].Length; ++j )
|
|
{
|
|
Item item = items[i][j];
|
|
|
|
int theirAmount = item.Amount;
|
|
|
|
if ( theirAmount < need )
|
|
{
|
|
if ( callback != null )
|
|
callback( item, theirAmount );
|
|
|
|
item.Delete();
|
|
need -= theirAmount;
|
|
}
|
|
else
|
|
{
|
|
if ( callback != null )
|
|
callback( item, need );
|
|
|
|
item.Consume( need );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public bool ConsumeTotal( Type type, int amount )
|
|
{
|
|
return ConsumeTotal( type, amount, true, null );
|
|
}
|
|
|
|
public bool ConsumeTotal( Type type, int amount, bool recurse )
|
|
{
|
|
return ConsumeTotal( type, amount, recurse, null );
|
|
}
|
|
|
|
public bool ConsumeTotal( Type type, int amount, bool recurse, OnItemConsumed callback )
|
|
{
|
|
Item[] items = FindItemsByType( type, recurse );
|
|
|
|
// First pass, compute total
|
|
int total = 0;
|
|
|
|
for( int i = 0; i < items.Length; ++i )
|
|
total += items[i].Amount;
|
|
|
|
if( total >= amount )
|
|
{
|
|
// We've enough, so consume it
|
|
|
|
int need = amount;
|
|
|
|
for( int i = 0; i < items.Length; ++i )
|
|
{
|
|
Item item = items[i];
|
|
|
|
int theirAmount = item.Amount;
|
|
|
|
if( theirAmount < need )
|
|
{
|
|
if( callback != null )
|
|
callback( item, theirAmount );
|
|
|
|
item.Delete();
|
|
need -= theirAmount;
|
|
}
|
|
else
|
|
{
|
|
if( callback != null )
|
|
callback( item, need );
|
|
|
|
item.Consume( need );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public int ConsumeUpTo( Type type, int amount )
|
|
{
|
|
return ConsumeUpTo( type, amount, true );
|
|
}
|
|
|
|
public int ConsumeUpTo( Type type, int amount, bool recurse )
|
|
{
|
|
int consumed = 0;
|
|
|
|
Queue<Item> toDelete = new Queue<Item>();
|
|
|
|
RecurseConsumeUpTo( this, type, amount, recurse, ref consumed, toDelete );
|
|
|
|
while( toDelete.Count > 0 )
|
|
toDelete.Dequeue().Delete();
|
|
|
|
return consumed;
|
|
}
|
|
|
|
private static void RecurseConsumeUpTo( Item current, Type type, int amount, bool recurse, ref int consumed, Queue<Item> toDelete )
|
|
{
|
|
if( current != null && current.Items.Count > 0 )
|
|
{
|
|
List<Item> list = current.Items;
|
|
|
|
for( int i = 0; i < list.Count; ++i )
|
|
{
|
|
Item item = list[i];
|
|
|
|
if( type.IsAssignableFrom( item.GetType() ) )
|
|
{
|
|
int need = amount - consumed;
|
|
int theirAmount = item.Amount;
|
|
|
|
if( theirAmount <= need )
|
|
{
|
|
toDelete.Enqueue( item );
|
|
consumed += theirAmount;
|
|
}
|
|
else
|
|
{
|
|
item.Amount -= need;
|
|
consumed += need;
|
|
|
|
return;
|
|
}
|
|
}
|
|
else if( recurse && item is Container )
|
|
{
|
|
RecurseConsumeUpTo( item, type, amount, recurse, ref consumed, toDelete );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Get[BestGroup]Amount
|
|
public int GetBestGroupAmount( Type type, bool recurse, CheckItemGroup grouper )
|
|
{
|
|
if( grouper == null )
|
|
throw new ArgumentNullException();
|
|
|
|
int best = 0;
|
|
|
|
Item[] typedItems = FindItemsByType( type, recurse );
|
|
|
|
List<List<Item>> groups = new List<List<Item>>();
|
|
int idx = 0;
|
|
|
|
while( idx < typedItems.Length )
|
|
{
|
|
Item a = typedItems[idx++];
|
|
List<Item> group = new List<Item>();
|
|
|
|
group.Add( a );
|
|
|
|
while( idx < typedItems.Length )
|
|
{
|
|
Item b = typedItems[idx];
|
|
int v = grouper( a, b );
|
|
|
|
if( v == 0 )
|
|
group.Add( b );
|
|
else
|
|
break;
|
|
|
|
++idx;
|
|
}
|
|
|
|
groups.Add( group );
|
|
}
|
|
|
|
for( int i = 0; i < groups.Count; ++i )
|
|
{
|
|
Item[] items = groups[i].ToArray();
|
|
|
|
//Item[] items = (Item[])(((ArrayList)groups[i]).ToArray( typeof( Item ) ));
|
|
int total = 0;
|
|
|
|
for( int j = 0; j < items.Length; ++j )
|
|
total += items[j].Amount;
|
|
|
|
if( total >= best )
|
|
best = total;
|
|
}
|
|
|
|
return best;
|
|
}
|
|
|
|
public int GetBestGroupAmount( Type[] types, bool recurse, CheckItemGroup grouper )
|
|
{
|
|
if( grouper == null )
|
|
throw new ArgumentNullException();
|
|
|
|
int best = 0;
|
|
|
|
Item[] typedItems = FindItemsByType( types, recurse );
|
|
|
|
List<List<Item>> groups = new List<List<Item>>();
|
|
int idx = 0;
|
|
|
|
while( idx < typedItems.Length )
|
|
{
|
|
Item a = typedItems[idx++];
|
|
List<Item> group = new List<Item>();
|
|
|
|
group.Add( a );
|
|
|
|
while( idx < typedItems.Length )
|
|
{
|
|
Item b = typedItems[idx];
|
|
int v = grouper( a, b );
|
|
|
|
if( v == 0 )
|
|
group.Add( b );
|
|
else
|
|
break;
|
|
|
|
++idx;
|
|
}
|
|
|
|
groups.Add( group );
|
|
}
|
|
|
|
for( int j = 0; j < groups.Count; ++j )
|
|
{
|
|
Item[] items = groups[j].ToArray();
|
|
//Item[] items = (Item[])(((ArrayList)groups[j]).ToArray( typeof( Item ) ));
|
|
int total = 0;
|
|
|
|
for( int k = 0; k < items.Length; ++k )
|
|
total += items[k].Amount;
|
|
|
|
if( total >= best )
|
|
best = total;
|
|
}
|
|
|
|
return best;
|
|
}
|
|
|
|
public int GetBestGroupAmount( Type[][] types, bool recurse, CheckItemGroup grouper )
|
|
{
|
|
if( grouper == null )
|
|
throw new ArgumentNullException();
|
|
|
|
int best = 0;
|
|
|
|
for( int i = 0; i < types.Length; ++i )
|
|
{
|
|
Item[] typedItems = FindItemsByType( types[i], recurse );
|
|
|
|
List<List<Item>> groups = new List<List<Item>>();
|
|
int idx = 0;
|
|
|
|
while( idx < typedItems.Length )
|
|
{
|
|
Item a = typedItems[idx++];
|
|
List<Item> group = new List<Item>();
|
|
|
|
group.Add( a );
|
|
|
|
while( idx < typedItems.Length )
|
|
{
|
|
Item b = typedItems[idx];
|
|
int v = grouper( a, b );
|
|
|
|
if( v == 0 )
|
|
group.Add( b );
|
|
else
|
|
break;
|
|
|
|
++idx;
|
|
}
|
|
|
|
groups.Add( group );
|
|
}
|
|
|
|
for( int j = 0; j < groups.Count; ++j )
|
|
{
|
|
Item[] items = groups[j].ToArray();
|
|
//Item[] items = (Item[])(((ArrayList)groups[j]).ToArray( typeof( Item ) ));
|
|
int total = 0;
|
|
|
|
for( int k = 0; k < items.Length; ++k )
|
|
total += items[k].Amount;
|
|
|
|
if( total >= best )
|
|
best = total;
|
|
}
|
|
}
|
|
|
|
return best;
|
|
}
|
|
|
|
public int GetAmount( Type type )
|
|
{
|
|
return GetAmount( type, true );
|
|
}
|
|
|
|
public int GetAmount( Type type, bool recurse )
|
|
{
|
|
Item[] items = FindItemsByType( type, recurse );
|
|
|
|
int amount = 0;
|
|
|
|
for ( int i = 0; i < items.Length; ++i )
|
|
amount += items[i].Amount;
|
|
|
|
return amount;
|
|
}
|
|
|
|
public int GetAmount( Type[] types )
|
|
{
|
|
return GetAmount( types, true );
|
|
}
|
|
|
|
public int GetAmount( Type[] types, bool recurse )
|
|
{
|
|
Item[] items = FindItemsByType( types, recurse );
|
|
|
|
int amount = 0;
|
|
|
|
for ( int i = 0; i < items.Length; ++i )
|
|
amount += items[i].Amount;
|
|
|
|
return amount;
|
|
}
|
|
#endregion
|
|
|
|
private static List<Item> m_FindItemsList = new List<Item>();
|
|
|
|
#region Non-Generic FindItem[s] by Type
|
|
public Item[] FindItemsByType( Type type )
|
|
{
|
|
return FindItemsByType( type, true );
|
|
}
|
|
|
|
public Item[] FindItemsByType( Type type, bool recurse )
|
|
{
|
|
if ( m_FindItemsList.Count > 0 )
|
|
m_FindItemsList.Clear();
|
|
|
|
RecurseFindItemsByType( this, type, recurse, m_FindItemsList );
|
|
|
|
return m_FindItemsList.ToArray();
|
|
}
|
|
|
|
private static void RecurseFindItemsByType( Item current, Type type, bool recurse, List<Item> list )
|
|
{
|
|
if ( current != null && current.Items.Count > 0 )
|
|
{
|
|
List<Item> items = current.Items;
|
|
|
|
for ( int i = 0; i < items.Count; ++i )
|
|
{
|
|
Item item = items[i];
|
|
|
|
if ( type.IsAssignableFrom( item.GetType() ) )// item.GetType().IsAssignableFrom( type ) )
|
|
list.Add( item );
|
|
|
|
if ( recurse && item is Container )
|
|
RecurseFindItemsByType( item, type, recurse, list );
|
|
}
|
|
}
|
|
}
|
|
|
|
public Item[] FindItemsByType( Type[] types )
|
|
{
|
|
return FindItemsByType( types, true );
|
|
}
|
|
|
|
public Item[] FindItemsByType( Type[] types, bool recurse )
|
|
{
|
|
if( m_FindItemsList.Count > 0 )
|
|
m_FindItemsList.Clear();
|
|
|
|
RecurseFindItemsByType( this, types, recurse, m_FindItemsList );
|
|
|
|
return m_FindItemsList.ToArray();
|
|
}
|
|
|
|
private static void RecurseFindItemsByType( Item current, Type[] types, bool recurse, List<Item> list )
|
|
{
|
|
if( current != null && current.Items.Count > 0 )
|
|
{
|
|
List<Item> items = current.Items;
|
|
|
|
for( int i = 0; i < items.Count; ++i )
|
|
{
|
|
Item item = items[i];
|
|
|
|
if( InTypeList( item, types ) )
|
|
list.Add( item );
|
|
|
|
if( recurse && item is Container )
|
|
RecurseFindItemsByType( item, types, recurse, list );
|
|
}
|
|
}
|
|
}
|
|
|
|
public Item FindItemByType( Type type )
|
|
{
|
|
return FindItemByType( type, true );
|
|
}
|
|
|
|
public Item FindItemByType( Type type, bool recurse )
|
|
{
|
|
return RecurseFindItemByType( this, type, recurse );
|
|
}
|
|
|
|
private static Item RecurseFindItemByType( Item current, Type type, bool recurse )
|
|
{
|
|
if( current != null && current.Items.Count > 0 )
|
|
{
|
|
List<Item> list = current.Items;
|
|
|
|
for( int i = 0; i < list.Count; ++i )
|
|
{
|
|
Item item = list[i];
|
|
|
|
if( type.IsAssignableFrom( item.GetType() ) )
|
|
{
|
|
return item;
|
|
}
|
|
else if( recurse && item is Container )
|
|
{
|
|
Item check = RecurseFindItemByType( item, type, recurse );
|
|
|
|
if( check != null )
|
|
return check;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public Item FindItemByType( Type[] types )
|
|
{
|
|
return FindItemByType( types, true );
|
|
}
|
|
|
|
public Item FindItemByType( Type[] types, bool recurse )
|
|
{
|
|
return RecurseFindItemByType( this, types, recurse );
|
|
}
|
|
|
|
private static Item RecurseFindItemByType( Item current, Type[] types, bool recurse )
|
|
{
|
|
if( current != null && current.Items.Count > 0 )
|
|
{
|
|
List<Item> list = current.Items;
|
|
|
|
for( int i = 0; i < list.Count; ++i )
|
|
{
|
|
Item item = list[i];
|
|
|
|
if( InTypeList( item, types ) )
|
|
{
|
|
return item;
|
|
}
|
|
else if( recurse && item is Container )
|
|
{
|
|
Item check = RecurseFindItemByType( item, types, recurse );
|
|
|
|
if( check != null )
|
|
return check;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Generic FindItem[s] by Type
|
|
public List<T> FindItemsByType<T>() where T : Item
|
|
{
|
|
return FindItemsByType<T>( true, null );
|
|
}
|
|
|
|
public List<T> FindItemsByType<T>( bool recurse ) where T : Item
|
|
{
|
|
return FindItemsByType<T>( recurse, null );
|
|
}
|
|
|
|
public List<T> FindItemsByType<T>( Predicate<T> predicate ) where T : Item
|
|
{
|
|
return FindItemsByType<T>( true, predicate );
|
|
}
|
|
|
|
public List<T> FindItemsByType<T>( bool recurse, Predicate<T> predicate ) where T : Item
|
|
{
|
|
if( m_FindItemsList.Count > 0 )
|
|
m_FindItemsList.Clear();
|
|
|
|
List<T> list = new List<T>();
|
|
|
|
RecurseFindItemsByType<T>( this, recurse, list, predicate );
|
|
|
|
return list;
|
|
}
|
|
|
|
private static void RecurseFindItemsByType<T>( Item current, bool recurse, List<T> list, Predicate<T> predicate ) where T : Item
|
|
{
|
|
if( current != null && current.Items.Count > 0 )
|
|
{
|
|
List<Item> items = current.Items;
|
|
|
|
for( int i = 0; i < items.Count; ++i )
|
|
{
|
|
Item item = items[i];
|
|
|
|
if( typeof( T ).IsAssignableFrom( item.GetType() ) )
|
|
{
|
|
T typedItem = (T)item;
|
|
|
|
if( predicate == null || predicate( typedItem ) )
|
|
list.Add( typedItem );
|
|
}
|
|
|
|
if( recurse && item is Container )
|
|
RecurseFindItemsByType<T>( item, recurse, list, predicate );
|
|
}
|
|
}
|
|
}
|
|
|
|
public T FindItemByType<T>() where T : Item
|
|
{
|
|
return FindItemByType<T>( true );
|
|
}
|
|
|
|
|
|
public T FindItemByType<T>( Predicate<T> predicate ) where T : Item
|
|
{
|
|
return FindItemByType<T>( true, predicate );
|
|
}
|
|
|
|
public T FindItemByType<T>( bool recurse ) where T : Item
|
|
{
|
|
return FindItemByType<T>( recurse, null );
|
|
}
|
|
|
|
public T FindItemByType<T>( bool recurse, Predicate<T> predicate ) where T : Item
|
|
{
|
|
return RecurseFindItemByType<T>( this, recurse, predicate );
|
|
}
|
|
|
|
private static T RecurseFindItemByType<T>( Item current, bool recurse, Predicate<T> predicate ) where T : Item
|
|
{
|
|
if( current != null && current.Items.Count > 0 )
|
|
{
|
|
List<Item> list = current.Items;
|
|
|
|
for( int i = 0; i < list.Count; ++i )
|
|
{
|
|
Item item = list[i];
|
|
|
|
if( typeof( T ).IsAssignableFrom( item.GetType() ) )
|
|
{
|
|
T typedItem = (T)item;
|
|
|
|
if( predicate == null || predicate( typedItem ) )
|
|
return typedItem;
|
|
}
|
|
else if( recurse && item is Container )
|
|
{
|
|
T check = RecurseFindItemByType<T>( item, recurse, predicate );
|
|
|
|
if( check != null )
|
|
return check;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
#endregion
|
|
|
|
|
|
private static bool InTypeList( Item item, Type[] types )
|
|
{
|
|
Type t = item.GetType();
|
|
|
|
for ( int i = 0; i < types.Length; ++i )
|
|
if ( types[i].IsAssignableFrom( t ) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
private static void SetSaveFlag( ref SaveFlag flags, SaveFlag toSet, bool setIf )
|
|
{
|
|
if ( setIf )
|
|
flags |= toSet;
|
|
}
|
|
|
|
private static bool GetSaveFlag( SaveFlag flags, SaveFlag toGet )
|
|
{
|
|
return ( (flags & toGet) != 0 );
|
|
}
|
|
|
|
[Flags]
|
|
private enum SaveFlag : byte
|
|
{
|
|
None = 0x00000000,
|
|
MaxItems = 0x00000001,
|
|
GumpID = 0x00000002,
|
|
DropSound = 0x00000004,
|
|
LiftOverride = 0x00000008
|
|
}
|
|
|
|
public override void Serialize( GenericWriter writer )
|
|
{
|
|
base.Serialize( writer );
|
|
|
|
writer.Write( (int) 2 ); // version
|
|
|
|
SaveFlag flags = SaveFlag.None;
|
|
|
|
SetSaveFlag( ref flags, SaveFlag.MaxItems, m_MaxItems != -1 );
|
|
SetSaveFlag( ref flags, SaveFlag.GumpID, m_GumpID != -1 );
|
|
SetSaveFlag( ref flags, SaveFlag.DropSound, m_DropSound != -1 );
|
|
SetSaveFlag( ref flags, SaveFlag.LiftOverride, m_LiftOverride );
|
|
|
|
writer.Write( (byte) flags );
|
|
|
|
if ( GetSaveFlag( flags, SaveFlag.MaxItems ) )
|
|
writer.WriteEncodedInt( (int) m_MaxItems );
|
|
|
|
if ( GetSaveFlag( flags, SaveFlag.GumpID ) )
|
|
writer.WriteEncodedInt( (int) m_GumpID );
|
|
|
|
if ( GetSaveFlag( flags, SaveFlag.DropSound ) )
|
|
writer.WriteEncodedInt( (int) m_DropSound );
|
|
}
|
|
|
|
public override void Deserialize( GenericReader reader )
|
|
{
|
|
base.Deserialize( reader );
|
|
|
|
int version = reader.ReadInt();
|
|
|
|
switch ( version )
|
|
{
|
|
case 2:
|
|
{
|
|
SaveFlag flags = (SaveFlag)reader.ReadByte();
|
|
|
|
if ( GetSaveFlag( flags, SaveFlag.MaxItems ) )
|
|
m_MaxItems = reader.ReadEncodedInt();
|
|
else
|
|
m_MaxItems = -1;
|
|
|
|
if ( GetSaveFlag( flags, SaveFlag.GumpID ) )
|
|
m_GumpID = reader.ReadEncodedInt();
|
|
else
|
|
m_GumpID = -1;
|
|
|
|
if ( GetSaveFlag( flags, SaveFlag.DropSound ) )
|
|
m_DropSound = reader.ReadEncodedInt();
|
|
else
|
|
m_DropSound = -1;
|
|
|
|
m_LiftOverride = GetSaveFlag( flags, SaveFlag.LiftOverride );
|
|
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
m_MaxItems = reader.ReadInt();
|
|
goto case 0;
|
|
}
|
|
case 0:
|
|
{
|
|
if ( version < 1 )
|
|
m_MaxItems = m_GlobalMaxItems;
|
|
|
|
m_GumpID = reader.ReadInt();
|
|
m_DropSound = reader.ReadInt();
|
|
|
|
if ( m_GumpID == DefaultGumpID )
|
|
m_GumpID = -1;
|
|
|
|
if ( m_DropSound == DefaultDropSound )
|
|
m_DropSound = -1;
|
|
|
|
if ( m_MaxItems == DefaultMaxItems )
|
|
m_MaxItems = -1;
|
|
|
|
//m_Bounds = new Rectangle2D( reader.ReadPoint2D(), reader.ReadPoint2D() );
|
|
reader.ReadPoint2D();
|
|
reader.ReadPoint2D();
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
UpdateContainerData();
|
|
}
|
|
|
|
private static int m_GlobalMaxItems = 125;
|
|
private static int m_GlobalMaxWeight = 400;
|
|
|
|
public static int GlobalMaxItems{ get{ return m_GlobalMaxItems; } set{ m_GlobalMaxItems = value; } }
|
|
public static int GlobalMaxWeight{ get{ return m_GlobalMaxWeight; } set{ m_GlobalMaxWeight = value; } }
|
|
|
|
public Container( int itemID ) : base( itemID )
|
|
{
|
|
m_GumpID = -1;
|
|
m_DropSound = -1;
|
|
m_MaxItems = -1;
|
|
|
|
UpdateContainerData();
|
|
}
|
|
|
|
public override int GetTotal( TotalType type )
|
|
{
|
|
switch ( type )
|
|
{
|
|
case TotalType.Gold:
|
|
return m_TotalGold;
|
|
|
|
case TotalType.Items:
|
|
return m_TotalItems;
|
|
|
|
case TotalType.Weight:
|
|
return m_TotalWeight;
|
|
}
|
|
|
|
return base.GetTotal( type );
|
|
}
|
|
|
|
public override void UpdateTotal( Item sender, TotalType type, int delta )
|
|
{
|
|
if ( sender != this && delta != 0 && !sender.IsVirtualItem )
|
|
{
|
|
switch ( type )
|
|
{
|
|
case TotalType.Gold:
|
|
m_TotalGold += delta;
|
|
break;
|
|
|
|
case TotalType.Items:
|
|
m_TotalItems += delta;
|
|
InvalidateProperties();
|
|
break;
|
|
|
|
case TotalType.Weight:
|
|
m_TotalWeight += delta;
|
|
InvalidateProperties();
|
|
break;
|
|
}
|
|
}
|
|
|
|
base.UpdateTotal( sender, type, delta );
|
|
}
|
|
|
|
public override void UpdateTotals()
|
|
{
|
|
m_TotalGold = 0;
|
|
m_TotalItems = 0;
|
|
m_TotalWeight = 0;
|
|
|
|
List<Item> items = m_Items;
|
|
|
|
if ( items == null )
|
|
return;
|
|
|
|
for ( int i = 0; i < items.Count; ++i )
|
|
{
|
|
Item item = items[i];
|
|
|
|
item.UpdateTotals();
|
|
|
|
if ( item.IsVirtualItem )
|
|
continue;
|
|
|
|
m_TotalGold += item.TotalGold;
|
|
m_TotalItems += item.TotalItems + 1;
|
|
m_TotalWeight += item.TotalWeight + item.PileWeight;
|
|
}
|
|
}
|
|
|
|
public Container( Serial serial ) : base( serial )
|
|
{
|
|
}
|
|
|
|
public virtual bool OnStackAttempt( Mobile from, Item stack, Item dropped )
|
|
{
|
|
if ( !CheckHold( from, dropped, true, false ) )
|
|
return false;
|
|
|
|
return stack.StackWith( from, dropped );
|
|
}
|
|
|
|
public override bool OnDragDrop( Mobile from, Item dropped )
|
|
{
|
|
if ( TryDropItem( from, dropped, true ) )
|
|
{
|
|
from.SendSound( GetDroppedSound( dropped ), GetWorldLocation() );
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public virtual bool TryDropItem( Mobile from, Item dropped, bool sendFullMessage )
|
|
{
|
|
if ( !CheckHold( from, dropped, sendFullMessage, true ) )
|
|
return false;
|
|
|
|
List<Item> list = this.Items;
|
|
|
|
for ( int i = 0; i < list.Count; ++i )
|
|
{
|
|
Item item = list[i];
|
|
|
|
if ( !(item is Container) && item.StackWith( from, dropped, false ) )
|
|
return true;
|
|
}
|
|
|
|
DropItem( dropped );
|
|
|
|
return true;
|
|
}
|
|
|
|
public virtual void Destroy()
|
|
{
|
|
Point3D loc = GetWorldLocation();
|
|
Map map = Map;
|
|
|
|
for ( int i = Items.Count - 1; i >= 0; --i )
|
|
{
|
|
if ( i < Items.Count )
|
|
{
|
|
Items[i].SetLastMoved();
|
|
Items[i].MoveToWorld( loc, map );
|
|
}
|
|
}
|
|
|
|
Delete();
|
|
}
|
|
|
|
public virtual void DropItem( Item dropped )
|
|
{
|
|
if ( dropped == null )
|
|
return;
|
|
|
|
AddItem( dropped );
|
|
|
|
Rectangle2D bounds = dropped.GetGraphicBounds();
|
|
Rectangle2D ourBounds = this.Bounds;
|
|
|
|
int x, y;
|
|
|
|
if ( bounds.Width >= ourBounds.Width )
|
|
x = (ourBounds.Width - bounds.Width) / 2;
|
|
else
|
|
x = Utility.Random( ourBounds.Width - bounds.Width );
|
|
|
|
if ( bounds.Height >= ourBounds.Height )
|
|
y = (ourBounds.Height - bounds.Height) / 2;
|
|
else
|
|
y = Utility.Random( ourBounds.Height - bounds.Height );
|
|
|
|
x += ourBounds.X;
|
|
x -= bounds.X;
|
|
|
|
y += ourBounds.Y;
|
|
y -= bounds.Y;
|
|
|
|
dropped.Location = new Point3D( x, y, 0 );
|
|
}
|
|
|
|
public override void OnDoubleClickSecureTrade( Mobile from )
|
|
{
|
|
if ( from.InRange( GetWorldLocation(), 2 ) )
|
|
{
|
|
DisplayTo( from );
|
|
|
|
SecureTradeContainer cont = GetSecureTradeCont();
|
|
|
|
if ( cont != null )
|
|
{
|
|
SecureTrade trade = cont.Trade;
|
|
|
|
if ( trade != null && trade.From.Mobile == from )
|
|
DisplayTo( trade.To.Mobile );
|
|
else if ( trade != null && trade.To.Mobile == from )
|
|
DisplayTo( trade.From.Mobile );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
from.SendLocalizedMessage( 500446 ); // That is too far away.
|
|
}
|
|
}
|
|
|
|
public virtual bool DisplaysContent{ get{ return true; } }
|
|
|
|
public virtual bool CheckContentDisplay( Mobile from )
|
|
{
|
|
if ( !DisplaysContent )
|
|
return false;
|
|
|
|
object root = this.RootParent;
|
|
|
|
if ( root == null || root is Item || root == from || from.AccessLevel > AccessLevel.Player )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public override void OnSingleClick( Mobile from )
|
|
{
|
|
base.OnSingleClick( from );
|
|
|
|
if ( CheckContentDisplay( from ) )
|
|
LabelTo( from, "({0} items, {1} stones)", TotalItems, TotalWeight );
|
|
}
|
|
|
|
private List<Mobile> m_Openers;
|
|
|
|
public List<Mobile> Openers
|
|
{
|
|
get{ return m_Openers; }
|
|
set{ m_Openers = value; }
|
|
}
|
|
|
|
public virtual bool IsPublicContainer{ get{ return false; } }
|
|
|
|
public override void OnDelete()
|
|
{
|
|
base.OnDelete();
|
|
|
|
m_Openers = null;
|
|
}
|
|
|
|
public virtual void DisplayTo( Mobile to )
|
|
{
|
|
ProcessOpeners( to );
|
|
|
|
to.Send( new ContainerDisplay( this ) );
|
|
|
|
if ( to.NetState != null && to.NetState.ContainerGridLines )
|
|
to.Send( new ContainerContent6017( to, this ) );
|
|
else
|
|
to.Send( new ContainerContent( to, this ) );
|
|
|
|
if ( ObjectPropertyList.Enabled )
|
|
{
|
|
List<Item> items = this.Items;
|
|
|
|
for ( int i = 0; i < items.Count; ++i )
|
|
to.Send( items[i].OPLPacket );
|
|
}
|
|
}
|
|
|
|
public void ProcessOpeners( Mobile opener )
|
|
{
|
|
if ( !IsPublicContainer )
|
|
{
|
|
bool contains = false;
|
|
|
|
if ( m_Openers != null )
|
|
{
|
|
Point3D worldLoc = GetWorldLocation();
|
|
Map map = this.Map;
|
|
|
|
for ( int i = 0; i < m_Openers.Count; ++i )
|
|
{
|
|
Mobile mob = m_Openers[i];
|
|
|
|
if ( mob == opener )
|
|
{
|
|
contains = true;
|
|
}
|
|
else
|
|
{
|
|
int range = GetUpdateRange( mob );
|
|
|
|
if ( mob.Map != map || !mob.InRange( worldLoc, range ) )
|
|
m_Openers.RemoveAt( i-- );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !contains )
|
|
{
|
|
if ( m_Openers == null )
|
|
{
|
|
m_Openers = new List<Mobile>();
|
|
}
|
|
|
|
m_Openers.Add( opener );
|
|
}
|
|
else if ( m_Openers != null && m_Openers.Count == 0 )
|
|
{
|
|
m_Openers = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void GetProperties( ObjectPropertyList list )
|
|
{
|
|
base.GetProperties( list );
|
|
|
|
if( DisplaysContent )//CheckContentDisplay( from ) )
|
|
{
|
|
if( Core.ML )
|
|
{
|
|
if( ParentsContain<BankBox>() ) //Root Parent is the Mobile. Parent could be another containter.
|
|
list.Add( 1073841, "{0}\t{1}\t{2}", TotalItems, MaxItems, TotalWeight ); // Contents: ~1_COUNT~/~2_MAXCOUNT~ items, ~3_WEIGHT~ stones
|
|
else
|
|
list.Add( 1072241, "{0}\t{1}\t{2}\t{3}", TotalItems, MaxItems, TotalWeight, MaxWeight ); // Contents: ~1_COUNT~/~2_MAXCOUNT~ items, ~3_WEIGHT~/~4_MAXWEIGHT~ stones
|
|
|
|
//TODO: Where do the other clilocs come into play? 1073839 & 1073840?
|
|
}
|
|
else
|
|
{
|
|
list.Add( 1050044, "{0}\t{1}", TotalItems, TotalWeight ); // ~1_COUNT~ items, ~2_WEIGHT~ stones
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnDoubleClick( Mobile from )
|
|
{
|
|
if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) )
|
|
DisplayTo( from );
|
|
else
|
|
from.SendLocalizedMessage( 500446 ); // That is too far away.
|
|
}
|
|
}
|
|
|
|
public class ContainerData
|
|
{
|
|
static ContainerData()
|
|
{
|
|
m_Table = new Dictionary<int, ContainerData>();
|
|
|
|
string path = Path.Combine( Core.BaseDirectory, "Data/containers.cfg" );
|
|
|
|
if ( !File.Exists( path ) )
|
|
{
|
|
m_Default = new ContainerData( 0x3C, new Rectangle2D( 44, 65, 142, 94 ), 0x48 );
|
|
return;
|
|
}
|
|
|
|
using ( StreamReader reader = new StreamReader( path ) )
|
|
{
|
|
string line;
|
|
|
|
while ( (line = reader.ReadLine()) != null )
|
|
{
|
|
line = line.Trim();
|
|
|
|
if ( line.Length == 0 || line.StartsWith( "#" ) )
|
|
continue;
|
|
|
|
try
|
|
{
|
|
string[] split = line.Split( '\t' );
|
|
|
|
if ( split.Length >= 3 )
|
|
{
|
|
int gumpID = Utility.ToInt32( split[0] );
|
|
|
|
string[] aRect = split[1].Split( ' ' );
|
|
if ( aRect.Length < 4 )
|
|
continue;
|
|
|
|
int x = Utility.ToInt32( aRect[0] );
|
|
int y = Utility.ToInt32( aRect[1] );
|
|
int width = Utility.ToInt32( aRect[2] );
|
|
int height = Utility.ToInt32( aRect[3] );
|
|
|
|
Rectangle2D bounds = new Rectangle2D( x, y, width, height );
|
|
|
|
int dropSound = Utility.ToInt32( split[2] );
|
|
|
|
ContainerData data = new ContainerData( gumpID, bounds, dropSound );
|
|
|
|
if ( m_Default == null )
|
|
m_Default = data;
|
|
|
|
if ( split.Length >= 4 )
|
|
{
|
|
string[] aIDs = split[3].Split( ',' );
|
|
|
|
for ( int i = 0; i < aIDs.Length; i++ )
|
|
{
|
|
int id = Utility.ToInt32( aIDs[i] );
|
|
|
|
if ( m_Table.ContainsKey( id ) )
|
|
{
|
|
Console.WriteLine( @"Warning: double ItemID entry in Data\containers.cfg" );
|
|
}
|
|
else
|
|
{
|
|
m_Table[id] = data;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( m_Default == null )
|
|
m_Default = new ContainerData( 0x3C, new Rectangle2D( 44, 65, 142, 94 ), 0x48 );
|
|
}
|
|
|
|
private static ContainerData m_Default;
|
|
private static Dictionary<int, ContainerData> m_Table;
|
|
|
|
public static ContainerData Default
|
|
{
|
|
get{ return m_Default; }
|
|
set{ m_Default = value; }
|
|
}
|
|
|
|
public static ContainerData GetData( int itemID )
|
|
{
|
|
ContainerData data = null;
|
|
m_Table.TryGetValue( itemID, out data );
|
|
|
|
if ( data != null )
|
|
return data;
|
|
else
|
|
return m_Default;
|
|
}
|
|
|
|
private int m_GumpID;
|
|
private Rectangle2D m_Bounds;
|
|
private int m_DropSound;
|
|
|
|
public int GumpID{ get{ return m_GumpID; } }
|
|
public Rectangle2D Bounds{ get{ return m_Bounds; } }
|
|
public int DropSound{ get{ return m_DropSound; } }
|
|
|
|
public ContainerData( int gumpID, Rectangle2D bounds, int dropSound )
|
|
{
|
|
m_GumpID = gumpID;
|
|
m_Bounds = bounds;
|
|
m_DropSound = dropSound;
|
|
}
|
|
}
|
|
} |