RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Lucid's Archery -Won't fire from quiver

Okay, so I've been working on this system for a while, trying to perfect it. The problem I'm having is, the new arrows won't fire from the quiver. I'm not exactly sure where to look for this. I've already modified the basequiver to allow the other arrows, but I'm not sure where it pulls the arrows from the quiver. Here's the basequiver:
Code:
using System;
using Server.Network;
using Server.Engines.Craft;
 
namespace Server.Items
{
    public class BaseQuiver : Container, ICraftable
    {
        public override int DefaultGumpID{ get{ return 0x108; } }
        public override int DefaultMaxItems{ get{ return 1; } }
        public override int DefaultMaxWeight{ get{ return 50; } }
        public override double DefaultWeight{ get{ return 2.0; } }
 
        private AosAttributes m_Attributes;
        private int m_Capacity;
        private int m_LowerAmmoCost;
        private int m_WeightReduction;
        private int m_DamageIncrease;
 
        [CommandProperty( AccessLevel.GameMaster)]
        public AosAttributes Attributes
        {
            get{ return m_Attributes; }
            set{}
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int Capacity
        {
            get{ return m_Capacity; }
            set{ m_Capacity = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int LowerAmmoCost
        {
            get{ return m_LowerAmmoCost; }
            set{ m_LowerAmmoCost = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int WeightReduction
        {
            get{ return m_WeightReduction; }
            set{ m_WeightReduction = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int DamageIncrease
        {
            get{ return m_DamageIncrease; }
            set{ m_DamageIncrease = value; InvalidateProperties(); }
        }
 
        private Mobile m_Crafter;
        private ClothingQuality m_Quality;
 
        [CommandProperty( AccessLevel.GameMaster )]
        public Mobile Crafter
        {
            get{ return m_Crafter; }
            set{ m_Crafter = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public ClothingQuality Quality
        {
            get{ return m_Quality; }
            set{ m_Quality = value; InvalidateProperties(); }
        }
     
        public Item Ammo
        {
            get{ return Items.Count > 0 ? Items[ 0 ] : null; }
        }
 
        public BaseQuiver() : this( 0x2FB7 )
        {
        }
 
        public BaseQuiver( int itemID ) : base( itemID )
        {
            Weight = 2.0;
            Capacity = 500;
            Layer = Layer.Cloak;
 
            m_Attributes = new AosAttributes( this );
 
            DamageIncrease = 10;
        }
 
        public BaseQuiver( Serial serial ) : base( serial )
        {
        }
 
        public override void OnAfterDuped( Item newItem )
        {
            BaseQuiver quiver = newItem as BaseQuiver;
 
            if ( quiver == null )
                return;
 
            quiver.m_Attributes = new AosAttributes( newItem, m_Attributes );
        }
 
        public override void  UpdateTotal( Item sender, TotalType type, int delta )
        {
            InvalidateProperties();
 
            base.UpdateTotal(sender, type, delta);
        }
 
        public override int GetTotal( TotalType type )
        {
            int total = base.GetTotal( type );
 
            if ( type == TotalType.Weight )
                total -= total * m_WeightReduction / 100;
 
            return total;
        }
 
        private static Type[] m_Ammo = new Type[]
        {
            typeof( Arrow ), typeof( Bolt ), typeof( ArmorPiercingArrow ), typeof( ExplosiveArrow ), typeof( FreezeArrow ), typeof( LightningArrow ), typeof( PoisonArrow ), typeof( ArmorPiercingBolt ), typeof( ExplosiveBolt ), typeof( FreezeBolt ), typeof( LightningBolt ), typeof( PoisonBolt )
        };
 
        public bool CheckType( Item item )
        {
            Type type = item.GetType();
            Item ammo = Ammo;
 
            if ( ammo != null )
            {
                if ( ammo.GetType() == type )
                    return true;
            }
            else
            {
                for ( int i = 0; i < m_Ammo.Length; i++ )
                {
                    if ( type == m_Ammo[ i ] )
                        return true;
                }
            }
 
            return false;
        }
 
        public override bool CheckHold( Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight )
        {
            if ( !CheckType( item ) )
            {
                if ( message )
                    m.SendLocalizedMessage( 1074836 ); // The container can not hold that type of object.
 
                return false;
            }
 
            if ( Items.Count < DefaultMaxItems )
            {
                if ( item.Amount <= m_Capacity )
                    return base.CheckHold( m, item, message, checkItems, plusItems, plusWeight );
 
                return false;
            }
            else if ( checkItems )
                return false;
 
            Item ammo = Ammo;
 
            if ( ammo == null || ammo.Deleted )
                return false;
 
            if ( ammo.Amount + item.Amount <= m_Capacity )
                return true;
 
            return false;
        }
 
        public override void AddItem( Item dropped )
        {
            base.AddItem( dropped );
 
            InvalidateWeight();
        }
     
        public override void RemoveItem( Item dropped )
        {
            base.RemoveItem( dropped );
 
            InvalidateWeight();
        }
     
        public override void OnAdded( object parent )
        {
            if ( parent is Mobile )
            {
                Mobile mob = (Mobile) parent;
 
                m_Attributes.AddStatBonuses( mob );
            }
        }
     
        public override void OnRemoved( object parent )
        {
            if ( parent is Mobile )
            {
                Mobile mob = (Mobile) parent;
 
                m_Attributes.RemoveStatBonuses( mob );
            }
        }
 
        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties( list );
             
            if ( m_Crafter != null )
                list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~
 
            if ( m_Quality == ClothingQuality.Exceptional )
                list.Add( 1063341 ); // exceptional
 
            Item ammo = Ammo;
 
            if ( ammo != null )
            {
                if ( ammo is Arrow )
                    list.Add( 1075265, "{0}\t{1}", ammo.Amount, Capacity ); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows
                else if ( ammo is Bolt )
                    list.Add( 1075266, "{0}\t{1}", ammo.Amount, Capacity ); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ bolts
            }
            else
                list.Add( 1075265, "{0}\t{1}", 0, Capacity ); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows
 
            int prop;
 
            if ( (prop = m_DamageIncrease) != 0 )
                list.Add( 1074762, prop.ToString() ); // Damage modifier: ~1_PERCENT~%
         
            int phys, fire, cold, pois, nrgy, chaos, direct;
            phys = fire = cold = pois = nrgy = chaos = direct = 0;
 
            AlterBowDamage( ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct );
 
            if ( phys != 0 )
                list.Add( 1060403, phys.ToString() ); // physical damage ~1_val~%
 
            if ( fire != 0 )
                list.Add( 1060405, fire.ToString() ); // fire damage ~1_val~%
 
            if ( cold != 0 )
                list.Add( 1060404, cold.ToString() ); // cold damage ~1_val~%
 
            if ( pois != 0 )
                list.Add( 1060406, pois.ToString() ); // poison damage ~1_val~%
 
            if ( nrgy != 0 )
                list.Add( 1060407, nrgy.ToString() ); // energy damage ~1_val
 
            if ( chaos != 0 )
                list.Add( 1072846, chaos.ToString() ); // chaos damage ~1_val~%
 
            if ( direct != 0 )
                list.Add( 1079978, direct.ToString() ); // Direct Damage: ~1_PERCENT~%
 
            list.Add( 1075085 ); // Requirement: Mondain's Legacy
 
            if ( (prop = m_Attributes.DefendChance) != 0 )
                list.Add( 1060408, prop.ToString() ); // defense chance increase ~1_val~%
 
            if ( (prop = m_Attributes.BonusDex) != 0 )
                list.Add( 1060409, prop.ToString() ); // dexterity bonus ~1_val~
 
            if ( (prop = m_Attributes.EnhancePotions) != 0 )
                list.Add( 1060411, prop.ToString() ); // enhance potions ~1_val~%
 
            if ( (prop = m_Attributes.CastRecovery) != 0 )
                list.Add( 1060412, prop.ToString() ); // faster cast recovery ~1_val~
 
            if ( (prop = m_Attributes.CastSpeed) != 0 )
                list.Add( 1060413, prop.ToString() ); // faster casting ~1_val~
 
            if ( (prop = m_Attributes.AttackChance) != 0 )
                list.Add( 1060415, prop.ToString() ); // hit chance increase ~1_val~%
 
            if ( (prop = m_Attributes.BonusHits) != 0 )
                list.Add( 1060431, prop.ToString() ); // hit point increase ~1_val~
 
            if ( (prop = m_Attributes.BonusInt) != 0 )
                list.Add( 1060432, prop.ToString() ); // intelligence bonus ~1_val~
 
            if ( (prop = m_Attributes.LowerManaCost) != 0 )
                list.Add( 1060433, prop.ToString() ); // lower mana cost ~1_val~%
 
            if ( (prop = m_Attributes.LowerRegCost) != 0 )
                list.Add( 1060434, prop.ToString() ); // lower reagent cost ~1_val~% 
 
            if ( (prop = m_Attributes.Luck) != 0 )
                list.Add( 1060436, prop.ToString() ); // luck ~1_val~
 
            if ( (prop = m_Attributes.BonusMana) != 0 )
                list.Add( 1060439, prop.ToString() ); // mana increase ~1_val~
 
            if ( (prop = m_Attributes.RegenMana) != 0 )
                list.Add( 1060440, prop.ToString() ); // mana regeneration ~1_val~
 
            if ( (prop = m_Attributes.NightSight) != 0 )
                list.Add( 1060441 ); // night sight
 
            if ( (prop = m_Attributes.ReflectPhysical) != 0 )
                list.Add( 1060442, prop.ToString() ); // reflect physical damage ~1_val~%
 
            if ( (prop = m_Attributes.RegenStam) != 0 )
                list.Add( 1060443, prop.ToString() ); // stamina regeneration ~1_val~
 
            if ( (prop = m_Attributes.RegenHits) != 0 )
                list.Add( 1060444, prop.ToString() ); // hit point regeneration ~1_val~
 
            if ( (prop = m_Attributes.SpellDamage) != 0 )
                list.Add( 1060483, prop.ToString() ); // spell damage increase ~1_val~%
 
            if ( (prop = m_Attributes.BonusStam) != 0 )
                list.Add( 1060484, prop.ToString() ); // stamina increase ~1_val~
 
            if ( (prop = m_Attributes.BonusStr) != 0 )
                list.Add( 1060485, prop.ToString() ); // strength bonus ~1_val~
 
            if ( (prop = m_Attributes.WeaponSpeed) != 0 )
                list.Add( 1060486, prop.ToString() ); // swing speed increase ~1_val~%
 
            if ( (prop = m_LowerAmmoCost) > 0 )
                list.Add( 1075208, prop.ToString() ); // Lower Ammo Cost ~1_Percentage~%
 
            double weight = 0;
 
            if ( ammo != null )
                weight = ammo.Weight * ammo.Amount;
 
            list.Add( 1072241, "{0}\t{1}\t{2}\t{3}", Items.Count, DefaultMaxItems, (int) weight, DefaultMaxWeight ); // Contents: ~1_COUNT~/~2_MAXCOUNT items, ~3_WEIGHT~/~4_MAXWEIGHT~ stones
 
            if ( (prop = m_WeightReduction) != 0 )
                list.Add( 1072210, prop.ToString() ); // Weight reduction: ~1_PERCENTAGE~% 
        }
     
        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
        {
            None                = 0x00000000,
            Attributes            = 0x00000001,
            DamageModifier        = 0x00000002,
            LowerAmmoCost        = 0x00000004,
            WeightReduction        = 0x00000008,
            Crafter                = 0x00000010,
            Quality                = 0x00000020,
            Capacity            = 0x00000040,
            DamageIncrease        = 0x00000080
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( 0 ); // version
 
            SaveFlag flags = SaveFlag.None;
 
            SetSaveFlag( ref flags, SaveFlag.Attributes,        !m_Attributes.IsEmpty );
            SetSaveFlag( ref flags, SaveFlag.LowerAmmoCost,        m_LowerAmmoCost != 0 );
            SetSaveFlag( ref flags, SaveFlag.WeightReduction,    m_WeightReduction != 0 );
            SetSaveFlag( ref flags, SaveFlag.DamageIncrease,    m_DamageIncrease != 0 );
            SetSaveFlag( ref flags, SaveFlag.Crafter,            m_Crafter != null );
            SetSaveFlag( ref flags, SaveFlag.Quality,            true );
            SetSaveFlag( ref flags, SaveFlag.Capacity,            m_Capacity > 0 );
 
            writer.WriteEncodedInt( (int) flags );
 
            if ( GetSaveFlag( flags, SaveFlag.Attributes ) )
                m_Attributes.Serialize( writer );
 
            if ( GetSaveFlag( flags, SaveFlag.LowerAmmoCost ) )
                writer.Write( (int) m_LowerAmmoCost );
 
            if ( GetSaveFlag( flags, SaveFlag.WeightReduction ) )
                writer.Write( (int) m_WeightReduction );
 
            if ( GetSaveFlag( flags, SaveFlag.DamageIncrease ) )
                writer.Write( (int) m_DamageIncrease );
 
            if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
                writer.Write( (Mobile) m_Crafter );
 
            if ( GetSaveFlag( flags, SaveFlag.Quality ) )
                writer.Write( (int) m_Quality );
 
            if ( GetSaveFlag( flags, SaveFlag.Capacity ) )
                writer.Write( (int) m_Capacity );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            SaveFlag flags = (SaveFlag) reader.ReadEncodedInt();
 
            if ( GetSaveFlag( flags, SaveFlag.Attributes ) )
                m_Attributes = new AosAttributes( this, reader );
            else
                m_Attributes = new AosAttributes( this );
 
            if ( GetSaveFlag( flags, SaveFlag.LowerAmmoCost ) )
                m_LowerAmmoCost = reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.WeightReduction ) )
                m_WeightReduction = reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.DamageIncrease ) )
                m_DamageIncrease = reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
                m_Crafter = reader.ReadMobile();
 
            if ( GetSaveFlag( flags, SaveFlag.Quality ) )
                m_Quality = (ClothingQuality) reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.Capacity ) )
                m_Capacity = reader.ReadInt();
        }
 
        public virtual void AlterBowDamage( ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, ref int chaos, ref int direct )
        {
        }
 
        public void InvalidateWeight()
        {
            if ( RootParent is Mobile )
            {
                Mobile m = (Mobile) RootParent;
 
                m.UpdateTotals();
            }
        }
     
        #region ICraftable
        public virtual int OnCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue )
        {
            Quality = (ClothingQuality) quality;
 
            if ( makersMark )
                Crafter = from;
 
            return quality;
        }
        #endregion
    }
}
Here is the baserange:
Code:
using System;
using Server.Items;
using Server.Network;
using Server.Spells;
using Server.Mobiles;
using Server.Targeting;
using System.Collections;
using System.Collections.Generic;
using Server.Enums;
using Server.ACC.CM;
using Server.LucidNagual;
 
namespace Server.Items
{
    public abstract class BaseRanged : BaseMeleeWeapon
    {
        //--<<Advanced Archery Edit>>---------------------[Start 1/4]
        //SkillModule edit.
        private BaseRangedModule m_BaseRangedModule;
     
        [CommandProperty( AccessLevel.GameMaster )]
        public BaseRangedModule BaseRangedModule
        {
            get
            {
                BaseRangedModule existingModule = ( BaseRangedModule )CentralMemory.GetModule( this.Serial, typeof( BaseRangedModule ) );
             
                if ( existingModule == null )
                {
                    BaseRangedModule module = new BaseRangedModule( this.Serial );
                    CentralMemory.AppendModule( this.Serial, module, true );
                 
                    return ( m_BaseRangedModule = module as BaseRangedModule );
                }
                else
                {
                    if ( m_BaseRangedModule != null )
                        return m_BaseRangedModule;
                 
                    return ( m_BaseRangedModule = existingModule as BaseRangedModule );
                }
            }
        }
        //SkillModule edit.
     
        public static int PlayerFreezeTimer = 2;
        public static int NPCFreezeTimer = 2;     
     
        private bool m_IsLevelable;
     
        [CommandProperty( AccessLevel.GameMaster )]
        public ArrowType ArrowSelection    { get { return m_BaseRangedModule.ArrowSelection; } set { m_BaseRangedModule.ArrowSelection = value; } }
     
        [CommandProperty( AccessLevel.GameMaster )]
        public BoltType BoltSelection { get { return m_BaseRangedModule.BoltSelection; } set { m_BaseRangedModule.BoltSelection = value; } }
     
        [CommandProperty( AccessLevel.GameMaster )]
        public StringStrength StringStrengthSelection { get { return m_BaseRangedModule.StringStrengthSelection; } set { m_BaseRangedModule.StringStrengthSelection = value; } }
     
        [CommandProperty( AccessLevel.GameMaster )]
        public PoundsPerPull PullWeightSelection { get { return m_BaseRangedModule.PullWeightSelection; } set { m_BaseRangedModule.PullWeightSelection = value; } }
     
        [CommandProperty( AccessLevel.GameMaster )]
        public bool HasBowString { get{ return m_BaseRangedModule.HasBowString; } set{ m_BaseRangedModule.HasBowString = value; } }     
     
        [CommandProperty( AccessLevel.GameMaster )]
        public bool IsLevelable { get{ return m_IsLevelable; } set{ m_IsLevelable = value; } }     
             
     
        private static Mobile m_Mobile;
        private static BaseRanged BRanged;
     
        public static TimeSpan StringWarningDelay = TimeSpan.FromSeconds( 10.0 );
        public static DateTime m_NextStringWarning;
        public static TimeSpan AmmoWarningDelay = TimeSpan.FromSeconds( 10.0 );
        public static DateTime m_NextAmmoWarning;
        //--<<Advanced Archery Edit>>---------------------[End 1/4]
 
        public abstract int EffectID{ get; }
        public abstract Type AmmoType{ get; }
        public abstract Item Ammo{ get; }
 
        public override int DefHitSound{ get{ return 0x234; } }
        public override int DefMissSound{ get{ return 0x238; } }
 
        public override SkillName DefSkill{ get{ return SkillName.Archery; } }
        public override WeaponType DefType{ get{ return WeaponType.Ranged; } }
        public override WeaponAnimation DefAnimation{ get{ return WeaponAnimation.ShootXBow; } }
 
        public override SkillName AccuracySkill{ get{ return SkillName.Archery; } }
 
        private Timer m_RecoveryTimer; // so we don't start too many timers
        private bool m_Balanced;
        private int m_Velocity;
     
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Balanced
        {
            get{ return m_Balanced; }
            set{ m_Balanced = value; InvalidateProperties(); }
        }
     
        [CommandProperty( AccessLevel.GameMaster )]
        public int Velocity
        {
            get{ return m_Velocity; }
            set{ m_Velocity = value; InvalidateProperties(); }
        }
 
        public BaseRanged( int itemID ) : base( itemID )
        {
        }
 
        public BaseRanged( Serial serial ) : base( serial )
        {
        }
 
        public override TimeSpan OnSwing( Mobile attacker, Mobile defender )
        {
            WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker );
 
            // Make sure we've been standing still for .25/.5/1 second depending on Era
            if ( DateTime.Now > (attacker.LastMoveTime + TimeSpan.FromSeconds( Core.SE ? 0.25 : (Core.AOS ? 0.5 : 1.0) )) || (Core.AOS && WeaponAbility.GetCurrentAbility( attacker ) is MovingShot) )
            {
                bool canSwing = true;
 
                if ( Core.AOS )
                {
                    canSwing = ( !attacker.Paralyzed && !attacker.Frozen );
 
                    if ( canSwing )
                    {
                        Spell sp = attacker.Spell as Spell;
 
                        canSwing = ( sp == null || !sp.IsCasting || !sp.BlocksMovement );
                    }
                }
 
                #region Dueling
                if ( attacker is PlayerMobile )
                {
                    PlayerMobile pm = (PlayerMobile)attacker;
 
                    if ( pm.DuelContext != null && !pm.DuelContext.CheckItemEquip( attacker, this ) )
                        canSwing = false;
                }
                #endregion
 
                if ( canSwing && attacker.HarmfulCheck( defender ) )
                {
                    attacker.DisruptiveAction();
                    attacker.Send( new Swing( 0, attacker, defender ) );
 
                    if ( OnFired( attacker, defender ) )
                    {
                        if ( CheckHit( attacker, defender ) )
                            OnHit( attacker, defender );
                        else
                            OnMiss( attacker, defender );
                    }
                }
 
                attacker.RevealingAction();
 
                return GetDelay( attacker );
            }
            else
            {
                attacker.RevealingAction();
 
                return TimeSpan.FromSeconds( 0.25 );
            }
        }
 
        public override void OnHit( Mobile attacker, Mobile defender, double damageBonus )
        {
            //--<<Advanced Archery Edit>>---------------------[Start 2/4]
            if ( attacker == null || defender == null )
                return;
         
            MoreBaseRanged.CustomAmmoCheck( attacker, defender, AmmoType );
         
            if ( Ammo == null )
                attacker.SendMessage( "You are out of arrows, or may have to choose a different type of arrow by double clicking the bow." );
            //--<<Advanced Archery Edit>>---------------------[End 2/4]
         
            if ( attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) && 0.4 >= Utility.RandomDouble() )
                defender.AddToBackpack( Ammo );
 
            if ( Core.ML && m_Velocity > 0 )
            {
                int bonus = (int) attacker.GetDistanceToSqrt( defender );
 
                if ( bonus > 0 && m_Velocity > Utility.Random( 100 ) )
                {
                    AOS.Damage( defender, attacker, bonus * 3, 100, 0, 0, 0, 0 );
 
                    if ( attacker.Player )
                        attacker.SendLocalizedMessage( 1072794 ); // Your arrow hits its mark with velocity!
 
                    if ( defender.Player )
                        defender.SendLocalizedMessage( 1072795 ); // You have been hit by an arrow with velocity!
                }
            }
 
            base.OnHit( attacker, defender, damageBonus );
        }
 
        public override void OnMiss( Mobile attacker, Mobile defender )
        {
            if ( attacker.Player && 0.4 >= Utility.RandomDouble() )
            {
                if ( Core.SE )
                {
                    PlayerMobile p = attacker as PlayerMobile;
 
                    if ( p != null )
                    {
                        Type ammo = AmmoType;
 
                        if ( p.RecoverableAmmo.ContainsKey( ammo ) )
                            p.RecoverableAmmo[ ammo ]++;
                        else
                            p.RecoverableAmmo.Add( ammo, 1 );
 
                        if ( !p.Warmode )
                        {
                            if ( m_RecoveryTimer == null )
                                m_RecoveryTimer = Timer.DelayCall( TimeSpan.FromSeconds( 10 ), new TimerCallback( p.RecoverAmmo ) );
 
                            if ( !m_RecoveryTimer.Running )
                                m_RecoveryTimer.Start();
                        }
                    }
                } else {
                    Ammo.MoveToWorld( new Point3D( defender.X + Utility.RandomMinMax( -1, 1 ), defender.Y + Utility.RandomMinMax( -1, 1 ), defender.Z ), defender.Map );
                }
            }
 
            base.OnMiss( attacker, defender );
        }
 
        public virtual bool OnFired( Mobile attacker, Mobile defender )
        {
            //--<<Advanced Archery Edit>>---------------------[Start 3/4]
            PlayerMobile a_pm = attacker as PlayerMobile;
            Container pack = attacker.Backpack;
            BaseQuiver quiver = attacker.FindItemOnLayer( Layer.MiddleTorso ) as BaseQuiver;
            BaseRangedModule module = this.BaseRangedModule;
 
            if ( !module.HasBowString )
            {
                if ( DateTime.Now >= m_NextStringWarning )
                {
                    m_NextStringWarning = DateTime.Now + StringWarningDelay;
                    attacker.SendMessage( "You need a string to use this bow. See a local fletcher to apply the string." );
                    return false;
                }
                else
                    return false;
            }
         
            if ( Ammo == null )
            {
                if ( DateTime.Now >= m_NextAmmoWarning )
                {
                    m_NextAmmoWarning = DateTime.Now + AmmoWarningDelay;
                    attacker.SendMessage( "You are out of ammo." );
                    return false;
                }
                else
                    return false;
            }
         
            if( attacker.Player && quiver != null && quiver.LowerAmmoCost > Utility.Random( 100 ) )
            {
                attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
                return true;
            }
         
            if( attacker.Player &&
              ( quiver == null || !quiver.ConsumeTotal( AmmoType, 1 ) ) &&
              (  pack == null ||  !pack.ConsumeTotal( AmmoType, 1 ) ) )
                return false;
         
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
            return true;
            //--<<Advanced Archery Edit>>---------------------[End 3/4]
     
 
            if ( attacker.Player )
            {
                //BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) as BaseQuiver;
                //Container pack = attacker.Backpack;
 
                if ( quiver == null || Utility.Random( 100 ) >= quiver.LowerAmmoCost )
                {
                    // consume ammo
                    if ( quiver != null && quiver.ConsumeTotal( AmmoType, 1 ) )
                        quiver.InvalidateWeight();
                    else if ( pack == null || !pack.ConsumeTotal( AmmoType, 1 ) )
                        return false;
                }
                else if ( quiver.FindItemByType( AmmoType ) == null && ( pack == null || pack.FindItemByType( AmmoType ) == null ) )
                {
                    // lower ammo cost should not work when we have no ammo at all
                    return false;
                }
            }
 
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
 
            return true;
        }
     
        //--<<Advanced Archery Edit>>---------------------[Start 4/4]
        public override void OnDoubleClick( Mobile from )
        {
            BaseRangedModule module = this.BaseRangedModule;
         
            if ( IsChildOf( from.Backpack ) || Parent == from )
            {
                if ( module.HasBowString )
                {
                    if ( this is Bow || this is CompositeBow || this is ElvenCompositeLongbow ||
                        this is MagicalShortbow || this is Yumi )
                    {
                        from.SendMessage( "Please choose which type of arrows you wish to use." );
                        from.Target = new BowTarget( this );
                    }
                 
                    if ( this is Crossbow || this is HeavyCrossbow || this is RepeatingCrossbow )
                    {
                        from.SendMessage( "Please choose which type of bolts you wish to use." );
                        from.Target = new CrossbowTarget( this );
                    }
                }
                else
                {
                    from.SendMessage( "You must string your bow. Please select a bow stringer." );
                    from.Target = new StringerTarget( this );
                }
            }
         
            else
                return;
        }
     
        /*public override void OnDelete()
        {
            BaseRangedModule module = this.BaseRangedModule;
         
            if ( module != null )
                module.Delete();
         
            base.OnDelete();
        }*/
     
        public override bool OnEquip( Mobile from )
        {
            m_Mobile = from;
         
            return true;
        }
     
        public override bool CanEquip( Mobile from )
        {
            BaseRangedModule module = this.BaseRangedModule;
 
            if ( from != null && !module.HasBowString )
            {
                from.SendMessage( "You cannot use that without a string." );
                return false;
            }
         
            base.CanEquip( from );
         
            return true;
        }
     
        public virtual Item AmmoArrowSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
         
            switch ( module.m_ArrowType )
            {
                case ArrowType.Normal:
                    return new Arrow();
                case ArrowType.Poison:
                    return new PoisonArrow();
                case ArrowType.Explosive:
                    return new ExplosiveArrow();
                case ArrowType.ArmorPiercing:
                    return new ArmorPiercingArrow();
                case ArrowType.Freeze:
                    return new FreezeArrow();
                case ArrowType.Lightning:
                    return new LightningArrow();
                 
                default:
                    return new Arrow();
            }
        }
     
        public virtual Type GetArrowSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
         
            switch ( module.m_ArrowType )
            {
                case ArrowType.Normal:
                    return typeof( Arrow );
                case ArrowType.Poison:
                    return typeof( PoisonArrow );
                case ArrowType.Explosive:
                    return typeof( ExplosiveArrow );
                case ArrowType.ArmorPiercing:
                    return typeof( ArmorPiercingArrow );
                case ArrowType.Freeze:
                    return typeof( FreezeArrow );
                case ArrowType.Lightning:
                    return typeof( LightningArrow );
                 
                default:
                    return typeof( Arrow );
            }
        }
     
        public virtual Item AmmoBoltSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
         
            switch ( module.m_BoltType )
            {
                case BoltType.Normal:
                    return new Bolt();
                case BoltType.Poison:
                    return new PoisonBolt();
                case BoltType.Explosive:
                    return new ExplosiveBolt();
                case BoltType.ArmorPiercing:
                    return new ArmorPiercingBolt();
                case BoltType.Freeze:
                    return new FreezeBolt();
                case BoltType.Lightning:
                    return new LightningBolt();
                 
                default:
                    return new Bolt();
            }
        }
     
        public virtual Type GetBoltSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
         
            switch ( module.m_BoltType )
            {
                case BoltType.Normal:
                    return typeof( Bolt );
                case BoltType.Poison:
                    return typeof( PoisonBolt );
                case BoltType.Explosive:
                    return typeof( ExplosiveBolt );
                case BoltType.ArmorPiercing:
                    return typeof( ArmorPiercingBolt );
                case BoltType.Freeze:
                    return typeof( FreezeBolt );
                case BoltType.Lightning:
                    return typeof( LightningBolt );
                 
                default:
                    return typeof( Bolt );
            }
        }
     
        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties(list);
         
            BaseRangedModule module = this.BaseRangedModule;
         
            if ( module != null )
            {
                ArrayList strings = new ArrayList();
             
                strings.Add( ( "---------------" ) );
             
                if ( this is Bow || this is CompositeBow || this is ElvenCompositeLongbow ||
                    this is MagicalShortbow || this is Yumi )
                {
                    strings.Add( ( "Quiver Using: " + module.m_ArrowType ) );
                }
             
                if ( this is Crossbow || this is HeavyCrossbow || this is RepeatingCrossbow )
                {
                    strings.Add( ( "Quiver Using: " + module.m_BoltType ) );
                }
             
                strings.Add( ( "lbs per Pull: " + module.m_PullWeight ) );
                strings.Add( ( "String Str: "  + module.m_Strength ) );
             
                string toAdd = "";
                int amount = strings.Count;
                int current = 1;
             
                foreach ( string str in strings )
                {
                    toAdd += str;
                 
                    if ( current != amount )
                        toAdd += "\n";
                 
                    ++current;
                }
             
                if ( toAdd != "" )
                    list.Add( 1070722, toAdd );
            }
            else
            {
                return;
            }
        }
        //--<<Advanced Archery Edit>>---------------------[End 4/4]
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 3 ); // version
 
            writer.Write( (bool) m_Balanced );
            writer.Write( (int) m_Velocity );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            switch ( version )
            {
                case 3:
                {
                    m_Balanced = reader.ReadBool();
                    m_Velocity = reader.ReadInt();
 
                    goto case 2;
                }
                case 2:
                case 1:
                {
                    break;
                }
                case 0:
                {
                    /*m_EffectID =*/ reader.ReadInt();
                    break;
                }
            }
 
            if ( version < 2 )
            {
                WeaponAttributes.MageWeapon = 0;
                WeaponAttributes.UseBestSkill = 0;
            }
        }
    }
}
Thanks in advance!
 
If you're talking about this line:
MoreBaseRanged.CustomAmmoCheck( attacker, defender, AmmoType );
It's located in the "MoreBaseRanged." Here:
Code:
/*
    _________________________________
-=(_)_______________________________)=-
  /  .  .  . ____  . ___      _/
  /~ /    /  / /    / /  )2007 /
(~ (____(___/ (____ / /___/    (
  \ ----------------------------- \
  \    [email protected]    \
    \_    ===================      \
    \  -Owner of "The Conjuring"-  \
      \_    ===================    ~\
      )      Lucid's Mega Pack        )
      /~    The Mother Load v1.1    _/
    _/_______________________________/
-=(_)_______________________________)=-
 
*/
using System;
using Server;
using Server.Items;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
using Server.ACC.CM;
using Server.Enums;
using Server.LucidNagual;
using System.Collections;
//using Server.LevelSystem;
 
 
namespace Server.LucidNagual
{
    public class MoreBaseRanged
    {
        public static readonly TimeSpan PlayerFreezeDuration = TimeSpan.FromSeconds( BaseRanged.PlayerFreezeTimer );
        public static readonly TimeSpan NPCFreezeDuration = TimeSpan.FromSeconds( BaseRanged.NPCFreezeTimer );
       
        public static void CustomAmmoCheck( Mobile attacker, Mobile defender, Type AmmoType )
        {
            double archery = attacker.Skills[ SkillName.Archery ].Value;
            double dice = Utility.RandomDouble();
           
            //Poison ammo.
            if ( AmmoType == typeof( PoisonArrow ) || AmmoType == typeof( PoisonArrow ) )
            {
                if( archery >= 120 )
                {
                    if ( 0.20 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 4 );
 
                    if ( 0.40 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 3 );
                   
                    if ( 0.70 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 2 );
                }
               
                else if( archery >= 100 )
                {
                    if ( 0.10 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 4 );
 
                    if ( 0.30 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 3 );
                   
                    if ( 0.60 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 2 );
                }
               
                else if( archery >= 70 )
                {
                    if ( 0.10 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 3 );
                   
                    if ( 0.30 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 2 );
                   
                    if ( 0.60 > Utility.RandomDouble() )
                        DoPoisonEffect( defender, 1 );
                }
               
                else if( archery >= 50 )
                {
                    switch ( Utility.Random( 2 ) )
                    {
                            case 0: DoPoisonEffect( defender, 2 ); break;
                            case 1: DoPoisonEffect( defender, 1 ); break;
                    }
                }
               
                if( archery < 50 )
                    DoPoisonEffect( defender, 1 );
            }
           
            //Explosive ammo.
            if ( AmmoType == typeof( ExplosiveArrow ) || AmmoType == typeof( ExplosiveBolt ) )
            {
                if( archery >= 120 )
                    DoExplosiveEffect( attacker, defender, 20, 80 );
               
                if( archery >= 60 )
                    DoExplosiveEffect( attacker, defender, 10, 40 );
               
                if( attacker.Skills[SkillName.Archery].Value < 60 )
                    DoExplosiveEffect( attacker, defender, 5, 20 );
            }
           
            //Piercing ammo.
            if ( AmmoType == typeof( ArmorPiercingArrow ) || AmmoType == typeof( ArmorPiercingBolt ) )
            {
                if( archery >= 120 )
                    DoPiercingEffect( attacker, defender, 20, 80 );
               
                if( attacker.Skills[SkillName.Archery].Value >= 60 )
                    DoPiercingEffect( attacker, defender, 10, 40 );
               
                if( attacker.Skills[SkillName.Archery].Value < 60 )
                    DoPiercingEffect( attacker, defender, 5, 20 );
            }
 
            //Freeze ammo.
            if ( AmmoType == typeof( FreezeArrow ) || AmmoType == typeof( FreezeBolt ) )
            {
                if( archery >= 120 )
                    DoFreezeEffect( attacker, defender, 20, 80 );
               
                if( archery >= 60 )
                    DoFreezeEffect( attacker, defender, 10, 40 );
               
                if( archery < 60 )
                    DoFreezeEffect( attacker, defender, 5, 20 );
            }
 
            //Lightning ammo.
            if ( AmmoType == typeof( LightningArrow ) || AmmoType == typeof( LightningBolt ) )
            {
                if( archery >= 120 )
                    DoLightningEffect( attacker, defender, 20, 80 );
               
                if( archery >= 60 )
                    DoLightningEffect( attacker, defender, 10, 40 );
               
                if( archery < 60 )
                    DoLightningEffect( attacker, defender, 5, 20 );
            }
        }
       
        public static void DoPoisonEffect( Mobile defender, int code )
        {
            defender.FixedParticles( 0x3728, 200, 25, 69, EffectLayer.Waist );
           
            if ( code == 1 ) //Lesser.
                defender.ApplyPoison( defender, Poison.Lesser );
           
            if ( code == 2 ) //Regular.
                defender.ApplyPoison( defender, Poison.Regular );
           
            if ( code == 3 ) //Greater.
                defender.ApplyPoison( defender, Poison.Greater );
           
            if ( code == 4 ) //Deadly.
                defender.ApplyPoison( defender, Poison.Deadly );
        }
       
        public static void DoExplosiveEffect( Mobile attacker, Mobile defender, int min, int max )
        {
            defender.FixedParticles( 0x36BD, 20, 10, 5044, EffectLayer.Waist );
            defender.PlaySound( 0x307 );
            attacker.DoHarmful( defender );
            AOS.Damage( defender, attacker, Utility.RandomMinMax( min, max ), 0, 100, 0, 0, 0 );
        }
       
        public static void DoPiercingEffect( Mobile attacker, Mobile defender, int min, int max )
        {
            defender.FixedParticles( 0x3728, 200, 25, 9942, EffectLayer.Waist );
            defender.PlaySound( 0x56 );
            attacker.DoHarmful( defender );
            AOS.Damage( defender, attacker, Utility.RandomMinMax( min, max ), 100, 0, 0, 0, 0 );
        }
       
        public static void DoFreezeEffect( Mobile attacker, Mobile defender, int min, int max )
        {
            defender.PlaySound( 0x204 );
            defender.Freeze( defender.Player ? PlayerFreezeDuration : NPCFreezeDuration );
            defender.FixedEffect( 0x376A, 9, 32 );
            attacker.DoHarmful( defender );
            AOS.Damage( defender, attacker, Utility.RandomMinMax( min, max ), 0, 0, 100, 0, 0 );
        }
       
        public static void DoLightningEffect( Mobile attacker, Mobile defender, int min, int max )
        {
            defender.PlaySound( 1471 );
            defender.BoltEffect( 1153 );
            attacker.DoHarmful( defender );
            AOS.Damage( defender, attacker, Utility.RandomMinMax( min, max ), 0, 0, 0, 0, 100 );
        }
       
        public virtual void DoDamage( Mobile attacker, Mobile defender, int min, int max )
        {
            attacker.DoHarmful( defender );
            AOS.Damage( defender, attacker, Utility.RandomMinMax( min, max ), 100, 0, 0, 0, 0 );
        }
       
        public virtual bool CheckStringDamage( Mobile attacker, Mobile defender, BaseRanged ranged )
        {
            BaseRangedModule module = ranged.BaseRangedModule;
 
            if ( module.HasBowString )
            {
                if ( module.StringStrengthSelection == StringStrength.VeryWeak )
                {
                    if ( .05 > Utility.Random( 100 ) )
                    {
                        BonusDamage( attacker, defender, ranged );
                        return true;
                    }
                    if ( .10 > Utility.Random( 1000 ) ) //1 in a 100 chances of breaking.
                    {
                        module.HasBowString = false;
                        module.StringStrengthSelection = StringStrength.NoString;
                        attacker.SendMessage( "Your string just broke." );
                    }
                    return true;
                }
                else if ( module.StringStrengthSelection == StringStrength.Weak )
                {
                    if ( .10 > Utility.Random( 100 ) )
                    {
                        BonusDamage( attacker, defender, ranged );
                        return true;
                    }
                    if ( .09 > Utility.Random( 1000 ) ) //1 in a 110 chances of breaking.
                    {
                        module.HasBowString = false;
                        module.StringStrengthSelection = StringStrength.NoString;
                        attacker.SendMessage( "Your string just broke." );
                    }
                    return true;
                }
                else if ( module.StringStrengthSelection == StringStrength.Sturdy )
                {
                    if ( .15 > Utility.Random( 100 ) )
                    {
                        BonusDamage( attacker, defender, ranged );
                        return true;
                    }
                    if ( .08 > Utility.Random( 1000 ) ) //1 in a 125 chances of breaking.
                    {
                        module.HasBowString = false;
                        module.StringStrengthSelection = StringStrength.NoString;
                        attacker.SendMessage( "Your string just broke." );
                    }
                    return true;
                }
                else if ( module.StringStrengthSelection == StringStrength.Strong )
                {
                    if ( .20 > Utility.Random( 100 ) )
                    {
                        BonusDamage( attacker, defender, ranged );
                        return true;
                    }
                    if ( .05 > Utility.Random( 1000 ) ) //1 in a 200 chances of breaking.
                    {
                        module.HasBowString = false;
                        module.StringStrengthSelection = StringStrength.NoString;
                        attacker.SendMessage( "Your string just broke." );
                    }
                }
                else if ( module.StringStrengthSelection == StringStrength.Dependable )
                {
                    if ( .25 > Utility.Random( 100 ) )
                    {
                        BonusDamage( attacker, defender, ranged );
                        return true;
                    }
                    if ( .03 > Utility.Random( 1000 ) ) //1 in a 333 chances of breaking.
                    {
                        module.HasBowString = false;
                        module.StringStrengthSelection = StringStrength.NoString;
                        attacker.SendMessage( "Your string just broke." );
                    }
                    return true;
                }
                else if ( module.StringStrengthSelection == StringStrength.Indestructable )
                {
                    if ( .33 > Utility.Random( 100 ) )
                    {
                        BonusDamage( attacker, defender, ranged );
                        return true;
                    }
                    //No chance of breaking.
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
           
            return false;
        }
       
        public virtual bool BonusDamage( Mobile attacker, Mobile defender, BaseRanged ranged )
        {
            BaseRangedModule module = ranged.BaseRangedModule;
 
            attacker.SendMessage( "" );
            attacker.SendMessage( 0x35, "** Bonus Hit **" );
            attacker.SendMessage( "" );
            attacker.SendMessage( 0x35, "The strength of your bow and your immpecable skill have given you a perfect hit." );
            attacker.SendMessage( "" );
           
            defender.Say( "* Ouch, that hurt! *" );
            defender.PlaySound( 315 );
           
            if ( module.HasBowString )
            {
                if ( module.m_PullWeight == PoundsPerPull.Fourty )
                {
                    attacker.DoHarmful( defender );
                    AOS.Damage( defender, attacker, Utility.RandomMinMax( 2, 5 ), 100, 0, 0, 0, 0 );
                    return true;
                }
                else if ( module.m_PullWeight == PoundsPerPull.Sixty )
                {
                    attacker.DoHarmful( defender );
                    AOS.Damage( defender, attacker, Utility.RandomMinMax( 6, 10 ), 100, 0, 0, 0, 0 );
                    return true;
                }
                else if ( module.m_PullWeight == PoundsPerPull.Eighty )
                {
                    attacker.DoHarmful( defender );
                    AOS.Damage( defender, attacker, Utility.RandomMinMax( 11, 15 ), 100, 0, 0, 0, 0 );
                    return true;
                }
                else if ( module.m_PullWeight == PoundsPerPull.Hundred )
                {
                    attacker.DoHarmful( defender );
                    AOS.Damage( defender, attacker, Utility.RandomMinMax( 16, 20 ), 100, 0, 0, 0, 0 );
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
                return true;
        }
       
        public virtual void CheckStringCondition( Mobile from, BaseRanged ranged )
        {
            BaseRangedModule module = ranged.BaseRangedModule;
           
            if ( module.HasBowString && module.StringStrengthSelection == StringStrength.NoString )
            {
                module.HasBowString = false;
            }
           
            if ( !module.HasBowString )
            {
                if ( module.StringStrengthSelection == StringStrength.NoString )
                {
                    module.HasBowString = false;
                    //from.SendMessage( "You need a string to use this bow. See a local fletcher to apply the string." );
                }
                else
                {
                    module.StringStrengthSelection = StringStrength.NoString;
                }
            }
        }
       
        public static bool CheckForString( Mobile from, string errorMsg, BaseRanged ranged )
        {
            BaseRangedModule module = ranged.BaseRangedModule;
 
            if ( !module.HasBowString )
            {
                return true;
            }
            else
            {
                if ( module.HasBowString && module.StringStrengthSelection == StringStrength.NoString )
                {
                    from.SendMessage( "" );
                    from.SendMessage( 33, "--------------------" );
                    from.SendMessage( "" );
                    from.SendMessage( 33, "The bow has an internal error and is now being fixed..." );
                    from.SendMessage( "" );
                    from.SendMessage( 33, "--------------------" );
                    from.SendMessage( "" );
                    module.HasBowString = false;
                    return true;
                }
                else
                {
                    from.SendMessage( "{0}", errorMsg );
                    return false;
                }
            }
        }
       
        public static void CutString( Mobile from, BaseRanged ranged )
        {
            BaseRangedModule module = ranged.BaseRangedModule;
           
            module.StringStrengthSelection = StringStrength.NoString;
            module.PullWeightSelection = PoundsPerPull.Zero;
            module.HasBowString = false;
           
            from.PlaySound( 0x248 );
            from.SendMessage( "You have just removed the string from your bow." );
           
            ranged.InvalidateProperties();
        }
       
        public virtual void CheckStringError( Mobile from, BaseRanged ranged )
        {
            BaseRangedModule module = ranged.BaseRangedModule;
           
            if ( module.HasBowString && module.StringStrengthSelection == StringStrength.NoString )
            {
                from.SendMessage( "The bow has an internal error. The bow is now being fixed..." );
                module.HasBowString = false;
            }
        }
    }
}
 

daat99

Moderator
Staff member
That didn't help with the arrows from quiver but:
Code:
 if ( AmmoType == typeof( PoisonArrow ) || AmmoType == typeof( PoisonArrow ) )
I think one of those should be bolt, no?

Back on topic, lets add some debug information to OnFired in BaseRanged:
Every time you see:
Code:
else
    return false;
Change it to something like this (in this example I'm adding it inside the "Ammo == null" check):
Code:
else
{
    Console.WriteLine("Returning false because {0}", "Ammo is null");
    return false;
}
Just replace the "Ammo is null" string with something else which will tell you which line it is and why it is returning false.

Once you have that code in that please post the new code as well as what is written in the console when you try to fire the bow without it using the arrows from the quiver.
 
I was just looking through it, and was curious. I wasn't sure how to fix this, so I commented it out to get the script to compile. It worked, but I believe it may have something to do with this problem. How would I restate it to work correctly?
Code:
//BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) as BaseQuiver;
                //Container pack = attacker.Backpack;

And now, here are the edits I made, and the new error I got while trying to compile. I have no idea what I did.
Baseranged:
Code:
using System;
using Server.Items;
using Server.Network;
using Server.Spells;
using Server.Mobiles;
using Server.Targeting;
using System.Collections;
using System.Collections.Generic;
using Server.Enums;
using Server.ACC.CM;
using Server.LucidNagual;
 
namespace Server.Items
{
    public abstract class BaseRanged : BaseMeleeWeapon
    {
        //--<<Advanced Archery Edit>>---------------------[Start 1/4]
        //SkillModule edit.
        private BaseRangedModule m_BaseRangedModule;
       
        [CommandProperty( AccessLevel.GameMaster )]
        public BaseRangedModule BaseRangedModule
        {
            get
            {
                BaseRangedModule existingModule = ( BaseRangedModule )CentralMemory.GetModule( this.Serial, typeof( BaseRangedModule ) );
               
                if ( existingModule == null )
                {
                    BaseRangedModule module = new BaseRangedModule( this.Serial );
                    CentralMemory.AppendModule( this.Serial, module, true );
                   
                    return ( m_BaseRangedModule = module as BaseRangedModule );
                }
                else
                {
                    if ( m_BaseRangedModule != null )
                        return m_BaseRangedModule;
                   
                    return ( m_BaseRangedModule = existingModule as BaseRangedModule );
                }
            }
        }
        //SkillModule edit.
       
        public static int PlayerFreezeTimer = 2;
        public static int NPCFreezeTimer = 2;       
       
        private bool m_IsLevelable;
       
        [CommandProperty( AccessLevel.GameMaster )]
        public ArrowType ArrowSelection    { get { return m_BaseRangedModule.ArrowSelection; } set { m_BaseRangedModule.ArrowSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public BoltType BoltSelection { get { return m_BaseRangedModule.BoltSelection; } set { m_BaseRangedModule.BoltSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public StringStrength StringStrengthSelection { get { return m_BaseRangedModule.StringStrengthSelection; } set { m_BaseRangedModule.StringStrengthSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public PoundsPerPull PullWeightSelection { get { return m_BaseRangedModule.PullWeightSelection; } set { m_BaseRangedModule.PullWeightSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public bool HasBowString { get{ return m_BaseRangedModule.HasBowString; } set{ m_BaseRangedModule.HasBowString = value; } }       
       
        [CommandProperty( AccessLevel.GameMaster )]
        public bool IsLevelable { get{ return m_IsLevelable; } set{ m_IsLevelable = value; } }       
               
       
        private static Mobile m_Mobile;
        private static BaseRanged BRanged;
       
        public static TimeSpan StringWarningDelay = TimeSpan.FromSeconds( 10.0 );
        public static DateTime m_NextStringWarning;
        public static TimeSpan AmmoWarningDelay = TimeSpan.FromSeconds( 10.0 );
        public static DateTime m_NextAmmoWarning;
        //--<<Advanced Archery Edit>>---------------------[End 1/4]
 
        public abstract int EffectID{ get; }
        public abstract Type AmmoType{ get; }
        public abstract Item Ammo{ get; }
 
        public override int DefHitSound{ get{ return 0x234; } }
        public override int DefMissSound{ get{ return 0x238; } }
 
        public override SkillName DefSkill{ get{ return SkillName.Archery; } }
        public override WeaponType DefType{ get{ return WeaponType.Ranged; } }
        public override WeaponAnimation DefAnimation{ get{ return WeaponAnimation.ShootXBow; } }
 
        public override SkillName AccuracySkill{ get{ return SkillName.Archery; } }
 
        private Timer m_RecoveryTimer; // so we don't start too many timers
        private bool m_Balanced;
        private int m_Velocity;
       
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Balanced
        {
            get{ return m_Balanced; }
            set{ m_Balanced = value; InvalidateProperties(); }
        }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public int Velocity
        {
            get{ return m_Velocity; }
            set{ m_Velocity = value; InvalidateProperties(); }
        }
 
        public BaseRanged( int itemID ) : base( itemID )
        {
        }
 
        public BaseRanged( Serial serial ) : base( serial )
        {
        }
 
        public override TimeSpan OnSwing( Mobile attacker, Mobile defender )
        {
            WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker );
 
            // Make sure we've been standing still for .25/.5/1 second depending on Era
            if ( DateTime.Now > (attacker.LastMoveTime + TimeSpan.FromSeconds( Core.SE ? 0.25 : (Core.AOS ? 0.5 : 1.0) )) || (Core.AOS && WeaponAbility.GetCurrentAbility( attacker ) is MovingShot) )
            {
                bool canSwing = true;
 
                if ( Core.AOS )
                {
                    canSwing = ( !attacker.Paralyzed && !attacker.Frozen );
 
                    if ( canSwing )
                    {
                        Spell sp = attacker.Spell as Spell;
 
                        canSwing = ( sp == null || !sp.IsCasting || !sp.BlocksMovement );
                    }
                }
 
                #region Dueling
                if ( attacker is PlayerMobile )
                {
                    PlayerMobile pm = (PlayerMobile)attacker;
 
                    if ( pm.DuelContext != null && !pm.DuelContext.CheckItemEquip( attacker, this ) )
                        canSwing = false;
                }
                #endregion
 
                if ( canSwing && attacker.HarmfulCheck( defender ) )
                {
                    attacker.DisruptiveAction();
                    attacker.Send( new Swing( 0, attacker, defender ) );
 
                    if ( OnFired( attacker, defender ) )
                    {
                        if ( CheckHit( attacker, defender ) )
                            OnHit( attacker, defender );
                        else
                            OnMiss( attacker, defender );
                    }
                }
 
                attacker.RevealingAction();
 
                return GetDelay( attacker );
            }
            else
            {
                attacker.RevealingAction();
 
                return TimeSpan.FromSeconds( 0.25 );
            }
        }
 
        public override void OnHit( Mobile attacker, Mobile defender, double damageBonus )
        {
            //--<<Advanced Archery Edit>>---------------------[Start 2/4]
            if ( attacker == null || defender == null )
                return;
           
            MoreBaseRanged.CustomAmmoCheck( attacker, defender, AmmoType );
           
            if ( Ammo == null )
                attacker.SendMessage( "You are out of arrows, or may have to choose a different type of arrow by double clicking the bow." );
            //--<<Advanced Archery Edit>>---------------------[End 2/4]
           
            if ( attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) && 0.4 >= Utility.RandomDouble() )
                defender.AddToBackpack( Ammo );
 
            if ( Core.ML && m_Velocity > 0 )
            {
                int bonus = (int) attacker.GetDistanceToSqrt( defender );
 
                if ( bonus > 0 && m_Velocity > Utility.Random( 100 ) )
                {
                    AOS.Damage( defender, attacker, bonus * 3, 100, 0, 0, 0, 0 );
 
                    if ( attacker.Player )
                        attacker.SendLocalizedMessage( 1072794 ); // Your arrow hits its mark with velocity!
 
                    if ( defender.Player )
                        defender.SendLocalizedMessage( 1072795 ); // You have been hit by an arrow with velocity!
                }
            }
 
            base.OnHit( attacker, defender, damageBonus );
        }
 
        public override void OnMiss( Mobile attacker, Mobile defender )
        {
            if ( attacker.Player && 0.4 >= Utility.RandomDouble() )
            {
                if ( Core.SE )
                {
                    PlayerMobile p = attacker as PlayerMobile;
 
                    if ( p != null )
                    {
                        Type ammo = AmmoType;
 
                        if ( p.RecoverableAmmo.ContainsKey( ammo ) )
                            p.RecoverableAmmo[ ammo ]++;
                        else
                            p.RecoverableAmmo.Add( ammo, 1 );
 
                        if ( !p.Warmode )
                        {
                            if ( m_RecoveryTimer == null )
                                m_RecoveryTimer = Timer.DelayCall( TimeSpan.FromSeconds( 10 ), new TimerCallback( p.RecoverAmmo ) );
 
                            if ( !m_RecoveryTimer.Running )
                                m_RecoveryTimer.Start();
                        }
                    }
                } else {
                    Ammo.MoveToWorld( new Point3D( defender.X + Utility.RandomMinMax( -1, 1 ), defender.Y + Utility.RandomMinMax( -1, 1 ), defender.Z ), defender.Map );
                }
            }
 
            base.OnMiss( attacker, defender );
        }
 
        public virtual bool OnFired( Mobile attacker, Mobile defender )
        {
            //--<<Advanced Archery Edit>>---------------------[Start 3/4]
            PlayerMobile a_pm = attacker as PlayerMobile;
            Container pack = attacker.Backpack;
            BaseQuiver quiver = attacker.FindItemOnLayer( Layer.MiddleTorso ) as BaseQuiver;
            BaseRangedModule module = this.BaseRangedModule;
 
            if ( !module.HasBowString )
            {
                if ( DateTime.Now >= m_NextStringWarning )
                {
                    m_NextStringWarning = DateTime.Now + StringWarningDelay;
                    attacker.SendMessage( "You need a string to use this bow. See a local fletcher to apply the string." );
                    return false;
                }
                else
                {
                        Console.WriteLine("Returning false because {0}", "String is null");
                        return false;
                {
            }
           
            if ( Ammo == null )
            {
                if ( DateTime.Now >= m_NextAmmoWarning )
                {
                    m_NextAmmoWarning = DateTime.Now + AmmoWarningDelay;
                    attacker.SendMessage( "You are out of ammo." );
                    return false;
                }
                else
                {
                        Console.WriteLine("Returning false because {0}", "Ammo is null");
                        return false;
                }
            }
           
            if( attacker.Player && quiver != null && quiver.LowerAmmoCost > Utility.Random( 100 ) )
            {
                attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
                return true;
            }
           
            if( attacker.Player &&
              ( quiver == null || !quiver.ConsumeTotal( AmmoType, 1 ) ) &&
              (  pack == null ||  !pack.ConsumeTotal( AmmoType, 1 ) ) )
                return false;
           
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
            return true;
            //--<<Advanced Archery Edit>>---------------------[End 3/4]
       
 
            if ( attacker.Player )
            {
                //BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) as BaseQuiver;
                //Container pack = attacker.Backpack;
 
                if ( quiver == null || Utility.Random( 100 ) >= quiver.LowerAmmoCost )
                {
                    // consume ammo
                    if ( quiver != null && quiver.ConsumeTotal( AmmoType, 1 ) )
                        quiver.InvalidateWeight();
                    else if ( pack == null || !pack.ConsumeTotal( AmmoType, 1 ) )
                        return false;
                }
                else if ( quiver.FindItemByType( AmmoType ) == null && ( pack == null || pack.FindItemByType( AmmoType ) == null ) )
                {
                    // lower ammo cost should not work when we have no ammo at all
                    return false;
                }
            }
 
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
 
            return true;
        }
    }
}
       
        //--<<Advanced Archery Edit>>---------------------[Start 4/4]
        public override void OnDoubleClick( Mobile from )
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            if ( IsChildOf( from.Backpack ) || Parent == from )
            {
                if ( module.HasBowString )
                {
                    if ( this is Bow || this is CompositeBow || this is ElvenCompositeLongbow ||
                        this is MagicalShortbow || this is Yumi )
                    {
                        from.SendMessage( "Please choose which type of arrows you wish to use." );
                        from.Target = new BowTarget( this );
                    }
                   
                    if ( this is Crossbow || this is HeavyCrossbow || this is RepeatingCrossbow )
                    {
                        from.SendMessage( "Please choose which type of bolts you wish to use." );
                        from.Target = new CrossbowTarget( this );
                    }
                }
                else
                {
                    from.SendMessage( "You must string your bow. Please select a bow stringer." );
                    from.Target = new StringerTarget( this );
                }
            }
           
            else
                return;
        }
       
        /*public override void OnDelete()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            if ( module != null )
                module.Delete();
           
            base.OnDelete();
        }*/
       
        public override bool OnEquip( Mobile from )
        {
            m_Mobile = from;
           
            return true;
        }
       
        public override bool CanEquip( Mobile from )
        {
            BaseRangedModule module = this.BaseRangedModule;
 
            if ( from != null && !module.HasBowString )
            {
                from.SendMessage( "You cannot use that without a string." );
                return false;
            }
           
            base.CanEquip( from );
           
            return true;
        }
       
        public virtual Item AmmoArrowSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_ArrowType )
            {
                case ArrowType.Normal:
                    return new Arrow();
                case ArrowType.Poison:
                    return new PoisonArrow();
                case ArrowType.Explosive:
                    return new ExplosiveArrow();
                case ArrowType.ArmorPiercing:
                    return new ArmorPiercingArrow();
                case ArrowType.Freeze:
                    return new FreezeArrow();
                case ArrowType.Lightning:
                    return new LightningArrow();
                   
                default:
                    return new Arrow();
            }
        }
       
        public virtual Type GetArrowSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_ArrowType )
            {
                case ArrowType.Normal:
                    return typeof( Arrow );
                case ArrowType.Poison:
                    return typeof( PoisonArrow );
                case ArrowType.Explosive:
                    return typeof( ExplosiveArrow );
                case ArrowType.ArmorPiercing:
                    return typeof( ArmorPiercingArrow );
                case ArrowType.Freeze:
                    return typeof( FreezeArrow );
                case ArrowType.Lightning:
                    return typeof( LightningArrow );
                   
                default:
                    return typeof( Arrow );
            }
        }
       
        public virtual Item AmmoBoltSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_BoltType )
            {
                case BoltType.Normal:
                    return new Bolt();
                case BoltType.Poison:
                    return new PoisonBolt();
                case BoltType.Explosive:
                    return new ExplosiveBolt();
                case BoltType.ArmorPiercing:
                    return new ArmorPiercingBolt();
                case BoltType.Freeze:
                    return new FreezeBolt();
                case BoltType.Lightning:
                    return new LightningBolt();
                   
                default:
                    return new Bolt();
            }
        }
       
        public virtual Type GetBoltSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_BoltType )
            {
                case BoltType.Normal:
                    return typeof( Bolt );
                case BoltType.Poison:
                    return typeof( PoisonBolt );
                case BoltType.Explosive:
                    return typeof( ExplosiveBolt );
                case BoltType.ArmorPiercing:
                    return typeof( ArmorPiercingBolt );
                case BoltType.Freeze:
                    return typeof( FreezeBolt );
                case BoltType.Lightning:
                    return typeof( LightningBolt );
                   
                default:
                    return typeof( Bolt );
            }
        }
       
        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties(list);
           
            BaseRangedModule module = this.BaseRangedModule;
           
            if ( module != null )
            {
                ArrayList strings = new ArrayList();
               
                strings.Add( ( "---------------" ) );
               
                if ( this is Bow || this is CompositeBow || this is ElvenCompositeLongbow ||
                    this is MagicalShortbow || this is Yumi )
                {
                    strings.Add( ( "Quiver Using: " + module.m_ArrowType ) );
                }
               
                if ( this is Crossbow || this is HeavyCrossbow || this is RepeatingCrossbow )
                {
                    strings.Add( ( "Quiver Using: " + module.m_BoltType ) );
                }
               
                strings.Add( ( "lbs per Pull: " + module.m_PullWeight ) );
                strings.Add( ( "String Str: "  + module.m_Strength ) );
               
                string toAdd = "";
                int amount = strings.Count;
                int current = 1;
               
                foreach ( string str in strings )
                {
                    toAdd += str;
                   
                    if ( current != amount )
                        toAdd += "\n";
                   
                    ++current;
                }
               
                if ( toAdd != "" )
                    list.Add( 1070722, toAdd );
            }
            else
            {
                return;
            }
        }
        //--<<Advanced Archery Edit>>---------------------[End 4/4]
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 3 ); // version
 
            writer.Write( (bool) m_Balanced );
            writer.Write( (int) m_Velocity );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            switch ( version )
            {
                case 3:
                {
                    m_Balanced = reader.ReadBool();
                    m_Velocity = reader.ReadInt();
 
                    goto case 2;
                }
                case 2:
                case 1:
                {
                    break;
                }
                case 0:
                {
                    /*m_EffectID =*/ reader.ReadInt();
                    break;
                }
            }
 
            if ( version < 2 )
            {
                WeaponAttributes.MageWeapon = 0;
                WeaponAttributes.UseBestSkill = 0;
            }
        }
    }
}

Error:
Code:
Errors:
+ Items/Weapons/Ranged/BaseRanged.cs:
    CS0161: Line 243: 'Server.Items.BaseRanged.OnFired(Server.Mobile, Server.Mob
ile)': not all code paths return a value
 

daat99

Moderator
Staff member
Like the error specified, not all code paths return a value in OnFired method.
What I did was:
1. Pasted your code in notepadd++.
2. Change the language of the file to "C#" in the language->C menu.
3. Pressed the "alt+0" hotkey (alt+zero - not numpad-zero) so it'll collapse all code blocks.
4. While everything is collapsed I did a search for "OnFired"
5. The 2nd search took me to the OnFired method.
6. I expanded the block of code in the OnFired method by clicking the + button on the left.

This was the result:
Code:
       public virtual bool OnFired( Mobile attacker, Mobile defender )
        {
            //--<<Advanced Archery Edit>>---------------------[Start 3/4]
            PlayerMobile a_pm = attacker as PlayerMobile;
            Container pack = attacker.Backpack;
            BaseQuiver quiver = attacker.FindItemOnLayer( Layer.MiddleTorso ) as BaseQuiver;
            BaseRangedModule module = this.BaseRangedModule;
 
            if ( !module.HasBowString )
            {
        }
As you can see there is no "return instruction" at the end of the method.

Furthermore you can see that all the code will be executed only if "module.HasBowString" will return false.

If you keep digging than you'll notice that you have an open bracket instead of a closing bracket in there (you probably just added a closing bracket at the end to fix the "missing }" error you had).
 

Hammerhand

Knight
2.3 doesnt seem to fire from the quiver either with the quiver equipped, but with the quiver in the pack it does... this is the OnFired method from 2.3, unmodified..
Code:
        public virtual bool OnFired( Mobile attacker, Mobile defender )
        {
            if ( attacker.Player )
            {
                BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) as BaseQuiver;
                Container pack = attacker.Backpack;
 
                if ( quiver == null || Utility.Random( 100 ) >= quiver.LowerAmmoCost )
                {
                    // consume ammo
                    if ( quiver != null && quiver.ConsumeTotal( AmmoType, 1 ) )
                        quiver.InvalidateWeight();
                    else if ( pack == null || !pack.ConsumeTotal( AmmoType, 1 ) )
                        return false;
                }
                else if ( quiver.FindItemByType( AmmoType ) == null && ( pack == null || pack.FindItemByType( AmmoType ) == null ) )
                {
                    // lower ammo cost should not work when we have no ammo at all
                    return false;
                }
            }
 
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
 
            return true;
        }
 

daat99

Moderator
Staff member
I need to see the code that is being executed by this method call:
Code:
quiver.ConsumeTotal( AmmoType, 1 )
Maybe if it'll be compared to a working copy you could see the bug and how to fix it.

This code should be either in BaseQuiver or in its parent class.
 

Hammerhand

Knight
Wonder if thats the whole issue right there.... Neither BaseQuiver.cs OR Container.cs have Consume anywhere in them.. Unmodified 2.3 scripts..
BaseQuiver.cs
Code:
using System;
using Server.Network;
using Server.Engines.Craft;
 
namespace Server.Items
{
    public class BaseQuiver : Container, ICraftable
    {
        public override int DefaultGumpID{ get{ return 0x108; } }
        public override int DefaultMaxItems{ get{ return 1; } }
        public override int DefaultMaxWeight{ get{ return 50; } }
        public override double DefaultWeight{ get{ return 2.0; } }
 
        private AosAttributes m_Attributes;
        private int m_Capacity;
        private int m_LowerAmmoCost;
        private int m_WeightReduction;
        private int m_DamageIncrease;
 
        [CommandProperty( AccessLevel.GameMaster)]
        public AosAttributes Attributes
        {
            get{ return m_Attributes; }
            set{}
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int Capacity
        {
            get{ return m_Capacity; }
            set{ m_Capacity = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int LowerAmmoCost
        {
            get{ return m_LowerAmmoCost; }
            set{ m_LowerAmmoCost = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int WeightReduction
        {
            get{ return m_WeightReduction; }
            set{ m_WeightReduction = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster)]
        public int DamageIncrease
        {
            get{ return m_DamageIncrease; }
            set{ m_DamageIncrease = value; InvalidateProperties(); }
        }
 
        private Mobile m_Crafter;
        private ClothingQuality m_Quality;
 
        [CommandProperty( AccessLevel.GameMaster )]
        public Mobile Crafter
        {
            get{ return m_Crafter; }
            set{ m_Crafter = value; InvalidateProperties(); }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public ClothingQuality Quality
        {
            get{ return m_Quality; }
            set{ m_Quality = value; InvalidateProperties(); }
        }
       
        public Item Ammo
        {
            get{ return Items.Count > 0 ? Items[ 0 ] : null; }
        }
 
        public BaseQuiver() : this( 0x2FB7 )
        {
        }
 
        public BaseQuiver( int itemID ) : base( itemID )
        {
            Weight = 2.0;
            Capacity = 500;
            Layer = Layer.Cloak;
 
            m_Attributes = new AosAttributes( this );
 
            DamageIncrease = 10;
        }
 
        public BaseQuiver( Serial serial ) : base( serial )
        {
        }
 
        public override void OnAfterDuped( Item newItem )
        {
            BaseQuiver quiver = newItem as BaseQuiver;
 
            if ( quiver == null )
                return;
 
            quiver.m_Attributes = new AosAttributes( newItem, m_Attributes );
        }
 
        public override void  UpdateTotal( Item sender, TotalType type, int delta )
        {
            InvalidateProperties();
 
            base.UpdateTotal(sender, type, delta);
        }
 
        public override int GetTotal( TotalType type )
        {
            int total = base.GetTotal( type );
 
            if ( type == TotalType.Weight )
                total -= total * m_WeightReduction / 100;
 
            return total;
        }
 
        private static Type[] m_Ammo = new Type[]
        {
            typeof( Arrow ), typeof( Bolt )
        };
 
        public bool CheckType( Item item )
        {
            Type type = item.GetType();
            Item ammo = Ammo;
 
            if ( ammo != null )
            {
                if ( ammo.GetType() == type )
                    return true;
            }
            else
            {
                for ( int i = 0; i < m_Ammo.Length; i++ )
                {
                    if ( type == m_Ammo[ i ] )
                        return true;
                }
            }
 
            return false;
        }
 
        public override bool CheckHold( Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight )
        {
            if ( !CheckType( item ) )
            {
                if ( message )
                    m.SendLocalizedMessage( 1074836 ); // The container can not hold that type of object.
 
                return false;
            }
 
            if ( Items.Count < DefaultMaxItems )
            {
                if ( item.Amount <= m_Capacity )
                    return base.CheckHold( m, item, message, checkItems, plusItems, plusWeight );
 
                return false;
            }
            else if ( checkItems )
                return false;
 
            Item ammo = Ammo;
 
            if ( ammo == null || ammo.Deleted )
                return false;
 
            if ( ammo.Amount + item.Amount <= m_Capacity )
                return true;
 
            return false;
        }
 
        public override void AddItem( Item dropped )
        {
            base.AddItem( dropped );
 
            InvalidateWeight();
        }
       
        public override void RemoveItem( Item dropped )
        {
            base.RemoveItem( dropped );
 
            InvalidateWeight();
        }
       
        public override void OnAdded( object parent )
        {
            if ( parent is Mobile )
            {
                Mobile mob = (Mobile) parent;
 
                m_Attributes.AddStatBonuses( mob );
            }
        }
       
        public override void OnRemoved( object parent )
        {
            if ( parent is Mobile )
            {
                Mobile mob = (Mobile) parent;
 
                m_Attributes.RemoveStatBonuses( mob );
            }
        }
 
        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties( list );
               
            if ( m_Crafter != null )
                list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~
 
            if ( m_Quality == ClothingQuality.Exceptional )
                list.Add( 1063341 ); // exceptional
 
            Item ammo = Ammo;
 
            if ( ammo != null )
            {
                if ( ammo is Arrow )
                    list.Add( 1075265, "{0}\t{1}", ammo.Amount, Capacity ); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows
                else if ( ammo is Bolt )
                    list.Add( 1075266, "{0}\t{1}", ammo.Amount, Capacity ); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ bolts
            }
            else
                list.Add( 1075265, "{0}\t{1}", 0, Capacity ); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows
 
            int prop;
 
            if ( (prop = m_DamageIncrease) != 0 )
                list.Add( 1074762, prop.ToString() ); // Damage modifier: ~1_PERCENT~%
           
            int phys, fire, cold, pois, nrgy, chaos, direct;
            phys = fire = cold = pois = nrgy = chaos = direct = 0;
 
            AlterBowDamage( ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct );
 
            if ( phys != 0 )
                list.Add( 1060403, phys.ToString() ); // physical damage ~1_val~%
 
            if ( fire != 0 )
                list.Add( 1060405, fire.ToString() ); // fire damage ~1_val~%
 
            if ( cold != 0 )
                list.Add( 1060404, cold.ToString() ); // cold damage ~1_val~%
 
            if ( pois != 0 )
                list.Add( 1060406, pois.ToString() ); // poison damage ~1_val~%
 
            if ( nrgy != 0 )
                list.Add( 1060407, nrgy.ToString() ); // energy damage ~1_val
 
            if ( chaos != 0 )
                list.Add( 1072846, chaos.ToString() ); // chaos damage ~1_val~%
 
            if ( direct != 0 )
                list.Add( 1079978, direct.ToString() ); // Direct Damage: ~1_PERCENT~%
 
            list.Add( 1075085 ); // Requirement: Mondain's Legacy
 
            if ( (prop = m_Attributes.DefendChance) != 0 )
                list.Add( 1060408, prop.ToString() ); // defense chance increase ~1_val~%
 
            if ( (prop = m_Attributes.BonusDex) != 0 )
                list.Add( 1060409, prop.ToString() ); // dexterity bonus ~1_val~
 
            if ( (prop = m_Attributes.EnhancePotions) != 0 )
                list.Add( 1060411, prop.ToString() ); // enhance potions ~1_val~%
 
            if ( (prop = m_Attributes.CastRecovery) != 0 )
                list.Add( 1060412, prop.ToString() ); // faster cast recovery ~1_val~
 
            if ( (prop = m_Attributes.CastSpeed) != 0 )
                list.Add( 1060413, prop.ToString() ); // faster casting ~1_val~
 
            if ( (prop = m_Attributes.AttackChance) != 0 )
                list.Add( 1060415, prop.ToString() ); // hit chance increase ~1_val~%
 
            if ( (prop = m_Attributes.BonusHits) != 0 )
                list.Add( 1060431, prop.ToString() ); // hit point increase ~1_val~
 
            if ( (prop = m_Attributes.BonusInt) != 0 )
                list.Add( 1060432, prop.ToString() ); // intelligence bonus ~1_val~
 
            if ( (prop = m_Attributes.LowerManaCost) != 0 )
                list.Add( 1060433, prop.ToString() ); // lower mana cost ~1_val~%
 
            if ( (prop = m_Attributes.LowerRegCost) != 0 )
                list.Add( 1060434, prop.ToString() ); // lower reagent cost ~1_val~%   
 
            if ( (prop = m_Attributes.Luck) != 0 )
                list.Add( 1060436, prop.ToString() ); // luck ~1_val~
 
            if ( (prop = m_Attributes.BonusMana) != 0 )
                list.Add( 1060439, prop.ToString() ); // mana increase ~1_val~
 
            if ( (prop = m_Attributes.RegenMana) != 0 )
                list.Add( 1060440, prop.ToString() ); // mana regeneration ~1_val~
 
            if ( (prop = m_Attributes.NightSight) != 0 )
                list.Add( 1060441 ); // night sight
 
            if ( (prop = m_Attributes.ReflectPhysical) != 0 )
                list.Add( 1060442, prop.ToString() ); // reflect physical damage ~1_val~%
 
            if ( (prop = m_Attributes.RegenStam) != 0 )
                list.Add( 1060443, prop.ToString() ); // stamina regeneration ~1_val~
 
            if ( (prop = m_Attributes.RegenHits) != 0 )
                list.Add( 1060444, prop.ToString() ); // hit point regeneration ~1_val~
 
            if ( (prop = m_Attributes.SpellDamage) != 0 )
                list.Add( 1060483, prop.ToString() ); // spell damage increase ~1_val~%
 
            if ( (prop = m_Attributes.BonusStam) != 0 )
                list.Add( 1060484, prop.ToString() ); // stamina increase ~1_val~
 
            if ( (prop = m_Attributes.BonusStr) != 0 )
                list.Add( 1060485, prop.ToString() ); // strength bonus ~1_val~
 
            if ( (prop = m_Attributes.WeaponSpeed) != 0 )
                list.Add( 1060486, prop.ToString() ); // swing speed increase ~1_val~%
 
            if ( (prop = m_LowerAmmoCost) > 0 )
                list.Add( 1075208, prop.ToString() ); // Lower Ammo Cost ~1_Percentage~%
 
            double weight = 0;
 
            if ( ammo != null )
                weight = ammo.Weight * ammo.Amount;
 
            list.Add( 1072241, "{0}\t{1}\t{2}\t{3}", Items.Count, DefaultMaxItems, (int) weight, DefaultMaxWeight ); // Contents: ~1_COUNT~/~2_MAXCOUNT items, ~3_WEIGHT~/~4_MAXWEIGHT~ stones
 
            if ( (prop = m_WeightReduction) != 0 )
                list.Add( 1072210, prop.ToString() ); // Weight reduction: ~1_PERCENTAGE~%   
        }
       
        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
        {
            None                = 0x00000000,
            Attributes            = 0x00000001,
            DamageModifier        = 0x00000002,
            LowerAmmoCost        = 0x00000004,
            WeightReduction        = 0x00000008,
            Crafter                = 0x00000010,
            Quality                = 0x00000020,
            Capacity            = 0x00000040,
            DamageIncrease        = 0x00000080
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( 0 ); // version
 
            SaveFlag flags = SaveFlag.None;
 
            SetSaveFlag( ref flags, SaveFlag.Attributes,        !m_Attributes.IsEmpty );
            SetSaveFlag( ref flags, SaveFlag.LowerAmmoCost,        m_LowerAmmoCost != 0 );
            SetSaveFlag( ref flags, SaveFlag.WeightReduction,    m_WeightReduction != 0 );
            SetSaveFlag( ref flags, SaveFlag.DamageIncrease,    m_DamageIncrease != 0 );
            SetSaveFlag( ref flags, SaveFlag.Crafter,            m_Crafter != null );
            SetSaveFlag( ref flags, SaveFlag.Quality,            true );
            SetSaveFlag( ref flags, SaveFlag.Capacity,            m_Capacity > 0 );
 
            writer.WriteEncodedInt( (int) flags );
 
            if ( GetSaveFlag( flags, SaveFlag.Attributes ) )
                m_Attributes.Serialize( writer );
 
            if ( GetSaveFlag( flags, SaveFlag.LowerAmmoCost ) )
                writer.Write( (int) m_LowerAmmoCost );
 
            if ( GetSaveFlag( flags, SaveFlag.WeightReduction ) )
                writer.Write( (int) m_WeightReduction );
 
            if ( GetSaveFlag( flags, SaveFlag.DamageIncrease ) )
                writer.Write( (int) m_DamageIncrease );
 
            if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
                writer.Write( (Mobile) m_Crafter );
 
            if ( GetSaveFlag( flags, SaveFlag.Quality ) )
                writer.Write( (int) m_Quality );
 
            if ( GetSaveFlag( flags, SaveFlag.Capacity ) )
                writer.Write( (int) m_Capacity );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            SaveFlag flags = (SaveFlag) reader.ReadEncodedInt();
 
            if ( GetSaveFlag( flags, SaveFlag.Attributes ) )
                m_Attributes = new AosAttributes( this, reader );
            else
                m_Attributes = new AosAttributes( this );
 
            if ( GetSaveFlag( flags, SaveFlag.LowerAmmoCost ) )
                m_LowerAmmoCost = reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.WeightReduction ) )
                m_WeightReduction = reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.DamageIncrease ) )
                m_DamageIncrease = reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
                m_Crafter = reader.ReadMobile();
 
            if ( GetSaveFlag( flags, SaveFlag.Quality ) )
                m_Quality = (ClothingQuality) reader.ReadInt();
 
            if ( GetSaveFlag( flags, SaveFlag.Capacity ) )
                m_Capacity = reader.ReadInt();
        }
 
        public virtual void AlterBowDamage( ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, ref int chaos, ref int direct )
        {
        }
 
        public void InvalidateWeight()
        {
            if ( RootParent is Mobile )
            {
                Mobile m = (Mobile) RootParent;
 
                m.UpdateTotals();
            }
        }
       
        #region ICraftable
        public virtual int OnCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue )
        {
            Quality = (ClothingQuality) quality;
 
            if ( makersMark )
                Crafter = from;
 
            return quality;
        }
        #endregion
    }
}
 

Hammerhand

Knight
Container.cs
Code:
using System;
using System.Collections.Generic;
using Server.Multis;
using Server.Mobiles;
using Server.Network;
using Server.ContextMenus;
 
namespace Server.Items
{
    public abstract class BaseContainer : Container
    {
        public override int DefaultMaxWeight
        {
            get
            {
                if ( IsSecure )
                    return 0;
 
                return base.DefaultMaxWeight;
            }
        }
 
        public BaseContainer( int itemID ) : base( itemID )
        {
        }
 
        public override bool IsAccessibleTo( Mobile m )
        {
            if ( !BaseHouse.CheckAccessible( m, this ) )
                return false;
 
            return base.IsAccessibleTo( m );
        }
 
        public override bool CheckHold( Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight )
        {
            if ( this.IsSecure && !BaseHouse.CheckHold( m, this, item, message, checkItems, plusItems, plusWeight ) )
                return false;
 
            return base.CheckHold( m, item, message, checkItems, plusItems, plusWeight );
        }
 
        public override bool CheckItemUse( Mobile from, Item item )
        {
            if ( IsDecoContainer && item is BaseBook )
                return true;
 
            return base.CheckItemUse( from, item );
        }
 
        public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
        {
            base.GetContextMenuEntries( from, list );
            SetSecureLevelEntry.AddTo( from, this, list );
        }
 
        public override bool TryDropItem( Mobile from, Item dropped, bool sendFullMessage )
        {
            if ( !CheckHold( from, dropped, sendFullMessage, true ) )
                return false;
 
            BaseHouse house = BaseHouse.FindHouseAt( this );
 
            if ( house != null && house.IsLockedDown( this ) )
            {
                if ( dropped is VendorRentalContract || ( dropped is Container && ((Container)dropped).FindItemByType( typeof( VendorRentalContract ) ) != null ) )
                {
                    from.SendLocalizedMessage( 1062492 ); // You cannot place a rental contract in a locked down container.
                    return false;
                }
 
                if ( !house.LockDown( from, dropped, false ) )
                    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 override bool OnDragDropInto( Mobile from, Item item, Point3D p )
        {
            if ( !CheckHold( from, item, true, true ) )
                return false;
 
            BaseHouse house = BaseHouse.FindHouseAt( this );
 
            if ( house != null && house.IsLockedDown( this ) )
            {
                if ( item is VendorRentalContract || ( item is Container && ((Container)item).FindItemByType( typeof( VendorRentalContract ) ) != null ) )
                {
                    from.SendLocalizedMessage( 1062492 ); // You cannot place a rental contract in a locked down container.
                    return false;
                }
 
                if ( !house.LockDown( from, item, false ) )
                    return false;
            }
 
            item.Location = new Point3D( p.X, p.Y, 0 );
            AddItem( item );
 
            from.SendSound( GetDroppedSound( item ), GetWorldLocation() );
 
            return true;
        }
 
        public override void UpdateTotal( Item sender, TotalType type, int delta )
        {
            base.UpdateTotal( sender, type, delta );
 
            if ( type == TotalType.Weight && RootParent is Mobile )
                ((Mobile) RootParent).InvalidateProperties();
        }
 
        public override void OnDoubleClick( Mobile from )
        {
            if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) || this.RootParent is PlayerVendor )
                Open( from );
            else
                from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
        }
 
        public virtual void Open( Mobile from )
        {
            DisplayTo( from );
        }
 
        public BaseContainer( Serial serial ) : base( serial )
        {
        }
 
        /* Note: base class insertion; we cannot serialize anything here */
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
        }
    }
 
    public class CreatureBackpack : Backpack    //Used on BaseCreature
    {
        [Constructable]
        public CreatureBackpack( string name )
        {
            Name = name;
            Layer = Layer.Backpack;
            Hue = 5;
            Weight = 3.0;
        }
 
        public override void AddNameProperty( ObjectPropertyList list )
        {
            if ( Name != null )
                list.Add( 1075257, Name ); // Contents of ~1_PETNAME~'s pack.
            else
                base.AddNameProperty( list );
        }
 
        public override void OnItemRemoved( Item item )
        {
            if ( Items.Count == 0 )
                this.Delete();
 
            base.OnItemRemoved( item );
        }
 
        public override bool OnDragLift( Mobile from )
        {
            if ( from.AccessLevel > AccessLevel.Player )
                return true;
 
            from.SendLocalizedMessage( 500169 ); // You cannot pick that up.
            return false;
        }
 
        public override bool OnDragDropInto( Mobile from, Item item, Point3D p )
        {
            return false;
        }
 
        public override bool TryDropItem( Mobile from, Item dropped, bool sendFullMessage )
        {
            return false;
        }
 
        public CreatureBackpack( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 )
                Weight = 13.0;
        }
    }
 
    public class StrongBackpack : Backpack    //Used on Pack animals
    {
        [Constructable]
        public StrongBackpack()
        {
            Layer = Layer.Backpack;
            Weight = 13.0;
        }
 
        public override bool CheckHold( Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight )
        {
            return base.CheckHold( m, item, false, checkItems, plusItems, plusWeight );
        }
 
        public override int DefaultMaxWeight{ get{ return 1600; } }
 
        public override bool CheckContentDisplay( Mobile from )
        {
            object root = this.RootParent;
 
            if ( root is BaseCreature && ((BaseCreature)root).Controlled && ((BaseCreature)root).ControlMaster == from )
                return true;
 
            return base.CheckContentDisplay( from );
        }
 
        public StrongBackpack( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 )
                Weight = 13.0;
        }
    }
 
    public class Backpack : BaseContainer, IDyable
    {
        [Constructable]
        public Backpack() : base( 0xE75 )
        {
            Layer = Layer.Backpack;
            Weight = 3.0;
        }
 
        public override int DefaultMaxWeight {
            get {
                if ( Core.ML ) {
                    Mobile m = ParentEntity as Mobile;
                    if ( m != null && m.Player && m.Backpack == this ) {
                        return 550;
                    } else {
                        return base.DefaultMaxWeight;
                    }
                } else {
                    return base.DefaultMaxWeight;
                }
            }
        }
 
        public Backpack( Serial serial ) : base( serial )
        {
        }
 
        public bool Dye( Mobile from, DyeTub sender )
        {
            if ( Deleted ) return false;
 
            Hue = sender.DyedHue;
 
            return true;
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && ItemID == 0x9B2 )
                ItemID = 0xE75;
        }
    }
 
    public class Pouch : TrapableContainer
    {
        [Constructable]
        public Pouch() : base( 0xE79 )
        {
            Weight = 1.0;
        }
 
        public Pouch( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    public abstract class BaseBagBall : BaseContainer, IDyable
    {
        public BaseBagBall( int itemID ) : base( itemID )
        {
            Weight = 1.0;
        }
 
        public BaseBagBall( Serial serial ) : base( serial )
        {
        }
 
        public bool Dye( Mobile from, DyeTub sender )
        {
            if ( Deleted )
                return false;
 
            Hue = sender.DyedHue;
 
            return true;
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    public class SmallBagBall : BaseBagBall
    {
        [Constructable]
        public SmallBagBall() : base( 0x2256 )
        {
        }
 
        public SmallBagBall( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    public class LargeBagBall : BaseBagBall
    {
        [Constructable]
        public LargeBagBall() : base( 0x2257 )
        {
        }
 
        public LargeBagBall( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    public class Bag : BaseContainer, IDyable
    {
        [Constructable]
        public Bag() : base( 0xE76 )
        {
            Weight = 2.0;
        }
 
        public Bag( Serial serial ) : base( serial )
        {
        }
 
        public bool Dye( Mobile from, DyeTub sender )
        {
            if ( Deleted ) return false;
 
            Hue = sender.DyedHue;
 
            return true;
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    public class Barrel : BaseContainer
    {
        [Constructable]
        public Barrel() : base( 0xE77 )
        {
            Weight = 25.0;
        }
 
        public Barrel( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( Weight == 0.0 )
                Weight = 25.0;
        }
    }
 
    public class Keg : BaseContainer
    {
        [Constructable]
        public Keg() : base( 0xE7F )
        {
            Weight = 15.0;
        }
 
        public Keg( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    public class PicnicBasket : BaseContainer
    {
        [Constructable]
        public PicnicBasket() : base( 0xE7A )
        {
            Weight = 2.0; // Stratics doesn't know weight
        }
 
        public PicnicBasket( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    public class Basket : BaseContainer
    {
        [Constructable]
        public Basket() : base( 0x990 )
        {
            Weight = 1.0; // Stratics doesn't know weight
        }
 
        public Basket( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    [Furniture]
    [Flipable( 0x9AA, 0xE7D )]
    public class WoodenBox : LockableContainer
    {
        [Constructable]
        public WoodenBox() : base( 0x9AA )
        {
            Weight = 4.0;
        }
 
        public WoodenBox( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
 
    [Furniture]
    [Flipable( 0x9A9, 0xE7E )]
    public class SmallCrate : LockableContainer
    {
        [Constructable]
        public SmallCrate() : base( 0x9A9 )
        {
            Weight = 2.0;
        }
 
        public SmallCrate( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( Weight == 4.0 )
                Weight = 2.0;
        }
    }
 
    [Furniture]
    [Flipable( 0xE3F, 0xE3E )]
    public class MediumCrate : LockableContainer
    {
        [Constructable]
        public MediumCrate() : base( 0xE3F )
        {
            Weight = 2.0;
        }
 
        public MediumCrate( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( Weight == 6.0 )
                Weight = 2.0;
        }
    }
 
    [Furniture]
    [Flipable( 0xE3D, 0xE3C )]
    public class LargeCrate : LockableContainer
    {
        [Constructable]
        public LargeCrate() : base( 0xE3D )
        {
            Weight = 1.0;
        }
 
        public LargeCrate( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( Weight == 8.0 )
                Weight = 1.0;
        }
    }
 
    [DynamicFliping]
    [Flipable( 0x9A8, 0xE80 )]
    public class MetalBox : LockableContainer
    {
        [Constructable]
        public MetalBox() : base( 0x9A8 )
        {
        }
 
        public MetalBox( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 3 )
                Weight = -1;
        }
    }
 
    [DynamicFliping]
    [Flipable( 0x9AB, 0xE7C )]
    public class MetalChest : LockableContainer
    {
        [Constructable]
        public MetalChest() : base( 0x9AB )
        {
        }
 
        public MetalChest( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 25 )
                Weight = -1;
        }
    }
 
    [DynamicFliping]
    [Flipable( 0xE41, 0xE40 )]
    public class MetalGoldenChest : LockableContainer
    {
        [Constructable]
        public MetalGoldenChest() : base( 0xE41 )
        {
        }
 
        public MetalGoldenChest( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 25 )
                Weight = -1;
        }
    }
 
    [Furniture]
    [Flipable( 0xe43, 0xe42 )]
    public class WoodenChest : LockableContainer
    {
        [Constructable]
        public WoodenChest() : base( 0xe43 )
        {
            Weight = 2.0;
        }
 
        public WoodenChest( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( Weight == 15.0 )
                Weight = 2.0;
        }
    }
 
    [Furniture]
    [Flipable( 0x280B, 0x280C )]
    public class PlainWoodenChest : LockableContainer
    {
        [Constructable]
        public PlainWoodenChest() : base( 0x280B )
        {
        }
 
        public PlainWoodenChest( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 15 )
                Weight = -1;
        }
    }
 
    [Furniture]
    [Flipable( 0x280D, 0x280E )]
    public class OrnateWoodenChest : LockableContainer
    {
        [Constructable]
        public OrnateWoodenChest() : base( 0x280D )
        {
        }
 
        public OrnateWoodenChest( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 15 )
                Weight = -1;
        }
    }
 
    [Furniture]
    [Flipable( 0x280F, 0x2810 )]
    public class GildedWoodenChest : LockableContainer
    {
        [Constructable]
        public GildedWoodenChest() : base( 0x280F )
        {
        }
 
        public GildedWoodenChest( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 15 )
                Weight = -1;
        }
    }
 
    [Furniture]
    [Flipable( 0x2811, 0x2812 )]
    public class WoodenFootLocker : LockableContainer
    {
        [Constructable]
        public WoodenFootLocker() : base( 0x2811 )
        {
            GumpID = 0x10B;
        }
 
        public WoodenFootLocker( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 2 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 15 )
                Weight = -1;
           
            if ( version < 2 )
                GumpID = 0x10B;
        }
    }
 
    [Furniture]
    [Flipable( 0x2813, 0x2814 )]
    public class FinishedWoodenChest : LockableContainer
    {
        [Constructable]
        public FinishedWoodenChest() : base( 0x2813 )
        {
        }
 
        public FinishedWoodenChest( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 1 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            if ( version == 0 && Weight == 15 )
                Weight = -1;
        }
    }
}
 

daat99

Moderator
Staff member
If BaseQuiver doesn't have a ConsumeTotal method that this method is inherited from the parent.
In our case:
Code:
public class BaseQuiver : Container, ICraftable
BaseQuiver is inheriting the "Container" class (not "BaseContainer", just "Container") and implementing an interfacae called "ICraftable".

From the names and our familiarity with RunUO we know that the ICraftable interface only means players can craft it and has nothing to do with "Consuming" items.
So we need to look at the Container class.

This class might be located in the core and it doesn't have to be inside a file called "Container.cs" (although it'll be logical if it is).

I don't see this class in the code you posted so we'll need to keep looking for it someplace else.
 

Hammerhand

Knight
Container.cs from the 2.3 core.. Has a nice loooong Consume region.. This what you're looking for?
Code:
/***************************************************************************
*                              Container.cs
*                            -------------------
*  begin                : May 1, 2002
*  copyright            : (C) The RunUO Software Team
*  email                : [email protected]
*
*  $Id: Container.cs 564 2010-10-18 04:56:28Z asayre $
*
***************************************************************************/
 
/***************************************************************************
*
*  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 );
 
            NetState ns = to.NetState;
 
            if ( ns == null )
                return;
 
            if ( ns.HighSeas )
                to.Send( new ContainerDisplayHS( this ) );
            else
                to.Send( new ContainerDisplay( this ) );
           
            if ( ns.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;
        }
    }
}
 

daat99

Moderator
Staff member
Exactly.
As you can recall we called ConsumeTotal as follows:
Code:
quiver.ConsumeTotal( AmmoType, 1 )
We used 2 arguments, the first was a "Type" and the 2nd was a number (integer).
So we are looking for a ConsumeTotal method that accepts a type and a number (most likely integer, but not always).
We can find this method:
Code:
public bool ConsumeTotal( Type type, int amount )
        {
            return ConsumeTotal( type, amount, true, null );
        }
As we can see this calls another ConsumeTotal method, this time with 4 arguments: Type, int, bool (true) and some kind of an object (null).
Looking further we see this method:
Code:
public bool ConsumeTotal( Type type, int amount, bool recurse, OnItemConsumed callback )
Before we dive into this method lets remember the values of the arguments:
type: the arrow type we wanted to fire.
amount: 1
recurse: true
callback: null
Now lets dive into this method and see what can go wrong with the quiver here.
Code:
        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;
        }
First we are calling "FindItemsByType" using the arrow type and the value "true".
Lets try to understand what it does by looking for that method in the classes hierarchy starting from our quiver and going up.
As we can see only the Container class has that method so we know it'll be executed there.

At this point I'm going to "guess" that the FindItemsByType is working correctly so I'm not going through the code flow of that.
We need to remember that we didn't make sure though, so if we can't find anything else wrong we'll have to get back to this at a later attempt.

The FindItemsByType returns a list of items and we already assumed it returned the list with our arrows.
Considering our amount is "1" we know that we'll get to the "item.Consume(need);" line on the first iteration and then we'll return "true" indicating we consumed an arrow.

After reading the method we have 2 calls that may be problematic.
1. The FindItemsByType may not find the arrows in the quiver.
2. The Consume won't consume an arrow as expected.

Knowing that we can conduct an experiment.
Lets go back to where we started and add our own testing to the code.
Locate this code:
Code:
// consume ammo
if ( quiver != null && quiver.ConsumeTotal( AmmoType, 1 ) )
We'll add our testing code just above that line.
First we need to make sure we have a quiver so we'll add a quiver null check.
In this example I'm going to test this with "PoisonArrow" but you can use any kind of arrow instead.
I'm going to try and get a list of "PoisonArrow" items from the quiver, note that I'm passing "true" as the recurse variable because this is what we had in our code flow.
After that we need to check if the FindItemsByType managed to find any poison arrows so we'll print the Length (might be Count) of the typedItems array.
Code:
if ( quiver != null )
{
    Item[] typedItems = quiver.FindItemsByType( typeof( PoisonArrow ), true );
    Console.WriteLine("FindItemsByType was able to find {0} items.", typedItems.Length); //try Count if it doesn't compile
}
If the first test passed and returned at least a single item than we know that the FindItemsByType is working fine with our quiver so we continue on to test other stuff.
We'll start by printing the Amount the first item has because we know the code tries to consume the first item in the list:
Code:
if ( typedItems.Length > 0 )
{
    Console.WriteLine("The amount of the first item is: {0}", typedItems[0].Amount);
}
If this tells us that the amount of arrows is at least 1 than we need to continue and test the Consume method itself so we add:
Code:
    typedItems[0].Consume( 1 );
    Console.WriteLine("The amount of the first item after consuming 1 is: {1}", typedItems[0].Amount);

Our testing code should look like this:
Code:
if ( quiver != null )
{
    Item[] typedItems = quiver.FindItemsByType( typeof( PoisonArrow ), true );
    Console.WriteLine("FindItemsByType was able to find {0} items.", typedItems.Length); //try Count if it doesn't compile
    if ( typedItems.Length > 0 )
    {
        Console.WriteLine("The amount of the first item is: {0}", typedItems[0].Amount);
        typedItems[0].Consume( 1 );
        Console.WriteLine("The amount of the first item after consuming 1 is: {1}", typedItems[0].Amount);
    }
}

Try to test this code when you have PoisonArrow with "Amount > 10" in your quiver (I'm not sure if it'll crash when you have PoisonArrow with amount=1 so don't try it!).

Let me know what happened when you tested this code :)
 

Hammerhand

Knight
This is the OnFired method with the console writeline coding added in.. compiled fine, nothing appeared on the console when I tried firing a bow.. I tried it with 9 arrows & 90.. nada..
Code:
        public virtual bool OnFired( Mobile attacker, Mobile defender )
        {
            if ( attacker.Player )
            {
                BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) as BaseQuiver;
                Container pack = attacker.Backpack;
 
                if ( quiver == null || Utility.Random( 100 ) >= quiver.LowerAmmoCost )
                {
                    if (quiver != null)
                    {
                        Item[] typedItems = quiver.FindItemsByType(typeof(Arrow), true);
                        Console.WriteLine("FindItemsByType was able to find {0} items.", typedItems.Length); //try Count if it doesn't compile
                        if (typedItems.Length > 0)
                        {
                            Console.WriteLine("The amount of the first item is: {0}", typedItems[0].Amount);
                            typedItems[0].Consume(1);
                            Console.WriteLine("The amount of the first item after consuming 1 is: {1}", typedItems[0].Amount);
                        }
                    }
                    if ( quiver != null && quiver.ConsumeTotal( AmmoType, 1 ) )
                        quiver.InvalidateWeight();
                    else if ( pack == null || !pack.ConsumeTotal( AmmoType, 1 ) )
                        return false;
                }
                else if ( quiver.FindItemByType( AmmoType ) == null && ( pack == null || pack.FindItemByType( AmmoType ) == null ) )
                {
                    // lower ammo cost should not work when we have no ammo at all
                    return false;
                }
            }
 
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
 
            return true;
        }
Pic shows archery butte, response when trying to fire & paperdoll showing quiver & arrow amount of 9. Still no console writeline. Maybe I added it wrong or the thing just cant find the blasted quiver? You can place the quiver IN your backpack & fire from it, but not while its equipped.
 

Attachments

  • ScreenHunter_32 Apr. 03 08.45.jpg
    79.4 KB · Views: 3
I'm back now. I just fixed the base range with both what you said before and this new one you added. Nothing with the old one, but the new one gives me
Code:
Code making it to OnTarget.
Code making it to arrow check.
So, now we know the consume method is not working, correct? and here is my full baseranged, as a reference.
Code:
using System;
using Server.Items;
using Server.Network;
using Server.Spells;
using Server.Mobiles;
using Server.Targeting;
using System.Collections;
using System.Collections.Generic;
using Server.Enums;
using Server.ACC.CM;
using Server.LucidNagual;
 
namespace Server.Items
{
    public abstract class BaseRanged : BaseMeleeWeapon
    {
        //--<<Advanced Archery Edit>>---------------------[Start 1/4]
        //SkillModule edit.
        private BaseRangedModule m_BaseRangedModule;
       
        [CommandProperty( AccessLevel.GameMaster )]
        public BaseRangedModule BaseRangedModule
        {
            get
            {
                BaseRangedModule existingModule = ( BaseRangedModule )CentralMemory.GetModule( this.Serial, typeof( BaseRangedModule ) );
               
                if ( existingModule == null )
                {
                    BaseRangedModule module = new BaseRangedModule( this.Serial );
                    CentralMemory.AppendModule( this.Serial, module, true );
                   
                    return ( m_BaseRangedModule = module as BaseRangedModule );
                }
                else
                {
                    if ( m_BaseRangedModule != null )
                        return m_BaseRangedModule;
                   
                    return ( m_BaseRangedModule = existingModule as BaseRangedModule );
                }
            }
        }
        //SkillModule edit.
       
        public static int PlayerFreezeTimer = 2;
        public static int NPCFreezeTimer = 2;       
       
        private bool m_IsLevelable;
       
        [CommandProperty( AccessLevel.GameMaster )]
        public ArrowType ArrowSelection    { get { return m_BaseRangedModule.ArrowSelection; } set { m_BaseRangedModule.ArrowSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public BoltType BoltSelection { get { return m_BaseRangedModule.BoltSelection; } set { m_BaseRangedModule.BoltSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public StringStrength StringStrengthSelection { get { return m_BaseRangedModule.StringStrengthSelection; } set { m_BaseRangedModule.StringStrengthSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public PoundsPerPull PullWeightSelection { get { return m_BaseRangedModule.PullWeightSelection; } set { m_BaseRangedModule.PullWeightSelection = value; } }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public bool HasBowString { get{ return m_BaseRangedModule.HasBowString; } set{ m_BaseRangedModule.HasBowString = value; } }       
       
        [CommandProperty( AccessLevel.GameMaster )]
        public bool IsLevelable { get{ return m_IsLevelable; } set{ m_IsLevelable = value; } }       
               
       
        private static Mobile m_Mobile;
        private static BaseRanged BRanged;
       
        public static TimeSpan StringWarningDelay = TimeSpan.FromSeconds( 10.0 );
        public static DateTime m_NextStringWarning;
        public static TimeSpan AmmoWarningDelay = TimeSpan.FromSeconds( 10.0 );
        public static DateTime m_NextAmmoWarning;
        //--<<Advanced Archery Edit>>---------------------[End 1/4]
 
        public abstract int EffectID{ get; }
        public abstract Type AmmoType{ get; }
        public abstract Item Ammo{ get; }
 
        public override int DefHitSound{ get{ return 0x234; } }
        public override int DefMissSound{ get{ return 0x238; } }
 
        public override SkillName DefSkill{ get{ return SkillName.Archery; } }
        public override WeaponType DefType{ get{ return WeaponType.Ranged; } }
        public override WeaponAnimation DefAnimation{ get{ return WeaponAnimation.ShootXBow; } }
 
        public override SkillName AccuracySkill{ get{ return SkillName.Archery; } }
 
        private Timer m_RecoveryTimer; // so we don't start too many timers
        private bool m_Balanced;
        private int m_Velocity;
       
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Balanced
        {
            get{ return m_Balanced; }
            set{ m_Balanced = value; InvalidateProperties(); }
        }
       
        [CommandProperty( AccessLevel.GameMaster )]
        public int Velocity
        {
            get{ return m_Velocity; }
            set{ m_Velocity = value; InvalidateProperties(); }
        }
 
        public BaseRanged( int itemID ) : base( itemID )
        {
        }
 
        public BaseRanged( Serial serial ) : base( serial )
        {
        }
 
        public override TimeSpan OnSwing( Mobile attacker, Mobile defender )
        {
            WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker );
 
            // Make sure we've been standing still for .25/.5/1 second depending on Era
            if ( DateTime.Now > (attacker.LastMoveTime + TimeSpan.FromSeconds( Core.SE ? 0.25 : (Core.AOS ? 0.5 : 1.0) )) || (Core.AOS && WeaponAbility.GetCurrentAbility( attacker ) is MovingShot) )
            {
                bool canSwing = true;
 
                if ( Core.AOS )
                {
                    canSwing = ( !attacker.Paralyzed && !attacker.Frozen );
 
                    if ( canSwing )
                    {
                        Spell sp = attacker.Spell as Spell;
 
                        canSwing = ( sp == null || !sp.IsCasting || !sp.BlocksMovement );
                    }
                }
 
                #region Dueling
                if ( attacker is PlayerMobile )
                {
                    PlayerMobile pm = (PlayerMobile)attacker;
 
                    if ( pm.DuelContext != null && !pm.DuelContext.CheckItemEquip( attacker, this ) )
                        canSwing = false;
                }
                #endregion
 
                if ( canSwing && attacker.HarmfulCheck( defender ) )
                {
                    attacker.DisruptiveAction();
                    attacker.Send( new Swing( 0, attacker, defender ) );
 
                    if ( OnFired( attacker, defender ) )
                    {
                        if ( CheckHit( attacker, defender ) )
                            OnHit( attacker, defender );
                        else
                            OnMiss( attacker, defender );
                    }
                }
 
                attacker.RevealingAction();
 
                return GetDelay( attacker );
            }
            else
            {
                attacker.RevealingAction();
 
                return TimeSpan.FromSeconds( 0.25 );
            }
        }
 
        public override void OnHit( Mobile attacker, Mobile defender, double damageBonus )
        {
            //--<<Advanced Archery Edit>>---------------------[Start 2/4]
            if ( attacker == null || defender == null )
                return;
           
            MoreBaseRanged.CustomAmmoCheck( attacker, defender, AmmoType );
           
            if ( Ammo == null )
                attacker.SendMessage( "You are out of arrows, or may have to choose a different type of arrow by double clicking the bow." );
            //--<<Advanced Archery Edit>>---------------------[End 2/4]
           
            if ( attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) && 0.4 >= Utility.RandomDouble() )
                defender.AddToBackpack( Ammo );
 
            if ( Core.ML && m_Velocity > 0 )
            {
                int bonus = (int) attacker.GetDistanceToSqrt( defender );
 
                if ( bonus > 0 && m_Velocity > Utility.Random( 100 ) )
                {
                    AOS.Damage( defender, attacker, bonus * 3, 100, 0, 0, 0, 0 );
 
                    if ( attacker.Player )
                        attacker.SendLocalizedMessage( 1072794 ); // Your arrow hits its mark with velocity!
 
                    if ( defender.Player )
                        defender.SendLocalizedMessage( 1072795 ); // You have been hit by an arrow with velocity!
                }
            }
 
            base.OnHit( attacker, defender, damageBonus );
        }
 
        public override void OnMiss( Mobile attacker, Mobile defender )
        {
            if ( attacker.Player && 0.4 >= Utility.RandomDouble() )
            {
                if ( Core.SE )
                {
                    PlayerMobile p = attacker as PlayerMobile;
 
                    if ( p != null )
                    {
                        Type ammo = AmmoType;
 
                        if ( p.RecoverableAmmo.ContainsKey( ammo ) )
                            p.RecoverableAmmo[ ammo ]++;
                        else
                            p.RecoverableAmmo.Add( ammo, 1 );
 
                        if ( !p.Warmode )
                        {
                            if ( m_RecoveryTimer == null )
                                m_RecoveryTimer = Timer.DelayCall( TimeSpan.FromSeconds( 10 ), new TimerCallback( p.RecoverAmmo ) );
 
                            if ( !m_RecoveryTimer.Running )
                                m_RecoveryTimer.Start();
                        }
                    else
                        Ammo.MoveToWorld( new Point3D( defender.X + Utility.RandomMinMax( -1, 1 ), defender.Y + Utility.RandomMinMax( -1, 1 ), defender.Z ), defender.Map );
                    }
                }
            }
 
            base.OnMiss( attacker, defender );
        }
 
        public virtual bool OnFired( Mobile attacker, Mobile defender )
        {
            //--<<Advanced Archery Edit>>---------------------[Start 3/4]
            PlayerMobile a_pm = attacker as PlayerMobile;
            Container pack = attacker.Backpack;
            BaseQuiver quiver = attacker.FindItemOnLayer( Layer.MiddleTorso ) as BaseQuiver;
            BaseRangedModule module = this.BaseRangedModule;
 
            if ( !module.HasBowString )
            {
                if ( DateTime.Now >= m_NextStringWarning )
                {
                    m_NextStringWarning = DateTime.Now + StringWarningDelay;
                    attacker.SendMessage( "You need a string to use this bow. See a local fletcher to apply the string." );
                    return false;
                }
                else
                {
                        Console.WriteLine("Returning false because {0}", "String is null");
                        return false;
                }
            }
           
            if ( Ammo == null )
            {
                if ( DateTime.Now >= m_NextAmmoWarning )
                {
                    m_NextAmmoWarning = DateTime.Now + AmmoWarningDelay;
                    attacker.SendMessage( "You are out of ammo." );
                    return false;
                }
                else
                {
                        Console.WriteLine("Returning false because {0}", "Ammo is null");
                        return false;
                }
            }
           
            if( attacker.Player && quiver != null && quiver.LowerAmmoCost > Utility.Random( 100 ) )
            {
                attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
                return true;
            }
           
            if( attacker.Player &&
              ( quiver == null || !quiver.ConsumeTotal( AmmoType, 1 ) ) &&
              (  pack == null ||  !pack.ConsumeTotal( AmmoType, 1 ) ) )
                return false;
            //--<<Advanced Archery Edit>>---------------------[End 3/4]
       
 
            if ( attacker.Player )
            {
                //BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) as BaseQuiver;
                //Container pack = attacker.Backpack;
 
                if ( quiver == null || Utility.Random( 100 ) >= quiver.LowerAmmoCost )
                {
                    if ( quiver != null )
                    {
                        Item[] typedItems = quiver.FindItemsByType( typeof( PoisonArrow ), true );
                        Console.WriteLine("FindItemsByType was able to find {0} items.", typedItems.Length); //try Count if it doesn't compile
                        if ( typedItems.Length > 0 )
                        {
                            Console.WriteLine("The amount of the first item is: {0}", typedItems[0].Amount);
                            typedItems[0].Consume( 1 );
                            Console.WriteLine("The amount of the first item after consuming 1 is: {1}", typedItems[0].Amount);
                        }
                    }
 
                    // consume ammo
                    if ( quiver != null && quiver.ConsumeTotal( AmmoType, 1 ) )
                        quiver.InvalidateWeight();
                    else if ( pack == null || !pack.ConsumeTotal( AmmoType, 1 ) )
                        return false;
                }
                else if ( quiver.FindItemByType( AmmoType ) == null && ( pack == null || pack.FindItemByType( AmmoType ) == null ) )
                {
                    // lower ammo cost should not work when we have no ammo at all
                    return false;
                }
            }
           
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
            return true;
        }
       
        //--<<Advanced Archery Edit>>---------------------[Start 4/4]
        public override void OnDoubleClick( Mobile from )
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            if ( IsChildOf( from.Backpack ) || Parent == from )
            {
                if ( module.HasBowString )
                {
                    if ( this is Bow || this is CompositeBow || this is ElvenCompositeLongbow ||
                        this is MagicalShortbow || this is Yumi )
                    {
                        from.SendMessage( "Please choose which type of arrows you wish to use." );
                        from.Target = new BowTarget( this );
                    }
                   
                    if ( this is Crossbow || this is HeavyCrossbow || this is RepeatingCrossbow )
                    {
                        from.SendMessage( "Please choose which type of bolts you wish to use." );
                        from.Target = new CrossbowTarget( this );
                    }
                }
                else
                {
                    from.SendMessage( "You must string your bow. Please select a bow stringer." );
                    from.Target = new StringerTarget( this );
                }
            }
           
            else
                return;
        }
       
        /*public override void OnDelete()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            if ( module != null )
                module.Delete();
           
            base.OnDelete();
        }*/
       
        public override bool OnEquip( Mobile from )
        {
            m_Mobile = from;
           
            return true;
        }
       
        public override bool CanEquip( Mobile from )
        {
            BaseRangedModule module = this.BaseRangedModule;
 
            if ( from != null && !module.HasBowString )
            {
                from.SendMessage( "You cannot use that without a string." );
                return false;
            }
           
            base.CanEquip( from );
           
            return true;
        }
       
        public virtual Item AmmoArrowSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_ArrowType )
            {
                case ArrowType.Normal:
                    return new Arrow();
                case ArrowType.Poison:
                    return new PoisonArrow();
                case ArrowType.Explosive:
                    return new ExplosiveArrow();
                case ArrowType.ArmorPiercing:
                    return new ArmorPiercingArrow();
                case ArrowType.Freeze:
                    return new FreezeArrow();
                case ArrowType.Lightning:
                    return new LightningArrow();
                   
                default:
                    return new Arrow();
            }
        }
       
        public virtual Type GetArrowSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_ArrowType )
            {
                case ArrowType.Normal:
                    return typeof( Arrow );
                case ArrowType.Poison:
                    return typeof( PoisonArrow );
                case ArrowType.Explosive:
                    return typeof( ExplosiveArrow );
                case ArrowType.ArmorPiercing:
                    return typeof( ArmorPiercingArrow );
                case ArrowType.Freeze:
                    return typeof( FreezeArrow );
                case ArrowType.Lightning:
                    return typeof( LightningArrow );
                   
                default:
                    return typeof( Arrow );
            }
        }
       
        public virtual Item AmmoBoltSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_BoltType )
            {
                case BoltType.Normal:
                    return new Bolt();
                case BoltType.Poison:
                    return new PoisonBolt();
                case BoltType.Explosive:
                    return new ExplosiveBolt();
                case BoltType.ArmorPiercing:
                    return new ArmorPiercingBolt();
                case BoltType.Freeze:
                    return new FreezeBolt();
                case BoltType.Lightning:
                    return new LightningBolt();
                   
                default:
                    return new Bolt();
            }
        }
       
        public virtual Type GetBoltSelected()
        {
            BaseRangedModule module = this.BaseRangedModule;
           
            switch ( module.m_BoltType )
            {
                case BoltType.Normal:
                    return typeof( Bolt );
                case BoltType.Poison:
                    return typeof( PoisonBolt );
                case BoltType.Explosive:
                    return typeof( ExplosiveBolt );
                case BoltType.ArmorPiercing:
                    return typeof( ArmorPiercingBolt );
                case BoltType.Freeze:
                    return typeof( FreezeBolt );
                case BoltType.Lightning:
                    return typeof( LightningBolt );
                   
                default:
                    return typeof( Bolt );
            }
        }
       
        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties(list);
           
            BaseRangedModule module = this.BaseRangedModule;
           
            if ( module != null )
            {
                ArrayList strings = new ArrayList();
               
                strings.Add( ( "---------------" ) );
               
                if ( this is Bow || this is CompositeBow || this is ElvenCompositeLongbow ||
                    this is MagicalShortbow || this is Yumi )
                {
                    strings.Add( ( "Quiver Using: " + module.m_ArrowType ) );
                }
               
                if ( this is Crossbow || this is HeavyCrossbow || this is RepeatingCrossbow )
                {
                    strings.Add( ( "Quiver Using: " + module.m_BoltType ) );
                }
               
                strings.Add( ( "lbs per Pull: " + module.m_PullWeight ) );
                strings.Add( ( "String Str: "  + module.m_Strength ) );
               
                string toAdd = "";
                int amount = strings.Count;
                int current = 1;
               
                foreach ( string str in strings )
                {
                    toAdd += str;
                   
                    if ( current != amount )
                        toAdd += "\n";
                   
                    ++current;
                }
               
                if ( toAdd != "" )
                    list.Add( 1070722, toAdd );
            }
            else
            {
                return;
            }
        }
        //--<<Advanced Archery Edit>>---------------------[End 4/4]
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 3 ); // version
 
            writer.Write( (bool) m_Balanced );
            writer.Write( (int) m_Velocity );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            switch ( version )
            {
                case 3:
                {
                    m_Balanced = reader.ReadBool();
                    m_Velocity = reader.ReadInt();
 
                    goto case 2;
                }
                case 2:
                case 1:
                {
                    break;
                }
                case 0:
                {
                    /*m_EffectID =*/ reader.ReadInt();
                    break;
                }
            }
 
            if ( version < 2 )
            {
                WeaponAttributes.MageWeapon = 0;
                WeaponAttributes.UseBestSkill = 0;
            }
        }
    }
}
 

daat99

Moderator
Staff member
I don't see the code that writes those console output anywhere in the file you posted :(

Can you post the new code you have as well as the exact console output please?
 
Oops, gues that wasn't one of the edits. That part is from
Bowtarget.cs
Code:
using System;
using Server.Items;
using Server.Network;
using Server.Spells;
using Server.Mobiles;
using System.Collections;
using Server.Enums;
using Server.ACC.CM;
using Server.LucidNagual;
 
 
namespace Server.Targeting
{
    public class BowTarget : Target
    {
        private BaseRanged it_Ranged;
       
        public BowTarget( BaseRanged ranged ) : base( 1, false, TargetFlags.None )
        {
            it_Ranged = ranged;
        }
       
        protected override void OnTarget( Mobile from, object targeted )
        {
            Console.WriteLine( "Code making it to OnTarget." );
            BaseRanged rang = it_Ranged as BaseRanged;
            BaseRangedModule module = rang.BaseRangedModule;
           
            if ( targeted is Item && targeted is Arrow )
            {
                Console.WriteLine( "Code making it to arrow check." );
                Item item = ( Item )targeted;
               
                string errorMsg = "You cannot arm a bow that does not have a string.";
               
                if ( !module.HasBowString )
                {
                    from.SendMessage( "{0}", errorMsg );
                    return;
                }
               
                if ( item.GetType() == typeof( Arrow ) )
                {
                    module.ArrowSelection = ArrowType.Normal;
                    rang.InvalidateProperties();
                }
               
                if ( item.GetType() == typeof( PoisonArrow ) )
                {
                    module.ArrowSelection = ArrowType.Poison;
                    rang.InvalidateProperties();
                }
               
                if ( item.GetType() == typeof( ExplosiveArrow ) )
                {
                    module.ArrowSelection = ArrowType.Explosive;
                    rang.InvalidateProperties();
                }
               
                if ( item.GetType() == typeof( ArmorPiercingArrow ) )
                {
                    module.ArrowSelection = ArrowType.ArmorPiercing;
                    rang.InvalidateProperties();
                }
               
                if ( item.GetType() == typeof( FreezeArrow ) )
                {
                    module.ArrowSelection = ArrowType.Freeze;
                    rang.InvalidateProperties();
                }
               
                if ( item.GetType() == typeof( LightningArrow ) )
                {
                    module.ArrowSelection = ArrowType.Lightning;
                    rang.InvalidateProperties();
                }
            }
            else
            {
                from.SendMessage( "You can only target an arrow." );
            }
        }
    }
}
I'm lost. It said nothing on the console that we added. :/
 

Hammerhand

Knight
Got the console writeline to work when attempting to shoot a live target.... and got a crash in the process.. Got same result with just 9 arrows in quiver.
Console report from crash:
Code:
RunUO - [www.runuo.com] Version 2.3, Build 4923.14297
Core: Running on .NET Framework Version 2.0.50727
Core: Running with arguments: -debug
Core: Optimizing for 6 64-bit processors
Scripts: Compiling C# scripts...done (0 errors, 0 warnings)
Scripts: Skipping VB.NET Scripts...done (use -vb to enable)
Scripts: Verifying...done (2923 items, 599 mobiles) (0.99 seconds)
Regions: Loading...done
World: Loading...done (34 items, 1 mobiles) (0.40 seconds)
Listening: ***.**.**.***:2593
Listening: 127.0.0.1:2593
Client: 127.0.0.1: Connected. [1 Online]
Login: 127.0.0.1: Valid credentials for 'magnus'
Client: 127.0.0.1: Connected. [2 Online]
Login: 127.0.0.1: Account 'magnus' at character list
Client: 127.0.0.1: Disconnected. [1 Online] [Magnus]
FindItemsByType was able to find 1 items.
The amount of the first item is: 99
Error:
System.FormatException: Index (zero based) must be greater than or equal to zero
and less than the size of the argument list.
  at System.Text.StringBuilder.AppendFormat(IFormatProvider provider, String fo
rmat, Object[] args)
  at System.String.Format(IFormatProvider provider, String format, Object[] arg
s)
  at System.IO.TextWriter.WriteLine(String format, Object arg0)
  at System.IO.TextWriter.SyncTextWriter.WriteLine(String format, Object arg0)
  at Server.Items.BaseRanged.OnFired(Mobile attacker, Mobile defender) in d:\Ru
nUO 2.3\Scripts\Items\Weapons\Ranged\BaseRanged.cs:line 186
  at Server.Items.BaseRanged.OnSwing(Mobile attacker, Mobile defender) in d:\Ru
nUO 2.3\Scripts\Items\Weapons\Ranged\BaseRanged.cs:line 88
  at Server.Mobile.CombatTimer.OnTick()
  at Server.Timer.Slice()
  at Server.Core.Main(String[] args)
Crash: Generating report...done
Crash: Backing up...done
This exception is fatal, press return to exit
Crash report itself:
Code:
Server Crash Report
===================
 
RunUO Version 2.3, Build 4923.14297
Operating System: Microsoft Windows NT 6.1.7601 Service Pack 1
.NET Framework: 2.0.50727.5477
Time: 4/6/2014 6:02:48 PM
Mobiles: 2
Items: 39
Exception:
System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
  at System.Text.StringBuilder.AppendFormat(IFormatProvider provider, String format, Object[] args)
  at System.String.Format(IFormatProvider provider, String format, Object[] args)
  at System.IO.TextWriter.WriteLine(String format, Object arg0)
  at System.IO.TextWriter.SyncTextWriter.WriteLine(String format, Object arg0)
  at Server.Items.BaseRanged.OnFired(Mobile attacker, Mobile defender) in d:\RunUO 2.3\Scripts\Items\Weapons\Ranged\BaseRanged.cs:line 186
  at Server.Items.BaseRanged.OnSwing(Mobile attacker, Mobile defender) in d:\RunUO 2.3\Scripts\Items\Weapons\Ranged\BaseRanged.cs:line 88
  at Server.Mobile.CombatTimer.OnTick()
  at Server.Timer.Slice()
  at Server.Core.Main(String[] args)
 
Clients:
- Count: 1
+ 127.0.0.1: (account = Magnus) (mobile = 0x1 'Magnus')
Line 88 area in BaseRanged.cs
Code:
                if (canSwing && attacker.HarmfulCheck(defender))
                {
                    attacker.DisruptiveAction();
                    attacker.Send(new Swing(0, attacker, defender));
 
                    if (OnFired(attacker, defender))  //<<< line 88
                    {
                        if (CheckHit(attacker, defender))
                            OnHit(attacker, defender);
                        else
                            OnMiss(attacker, defender);
                    }
                }
Line 186
Code:
                if (quiver == null || Utility.Random(100) >= quiver.LowerAmmoCost)
                {
                    if (quiver != null) //
                    {
                        Item[] typedItems = quiver.FindItemsByType(typeof(Arrow), true);
                        Console.WriteLine("FindItemsByType was able to find {0} items.", typedItems.Length); //try Count if it doesn't compile
                        if (typedItems.Length > 0)
                        {
                            Console.WriteLine("The amount of the first item is: {0}", typedItems[0].Amount);
                            typedItems[0].Consume(1);
                            Console.WriteLine("The amount of the first item after consuming 1 is: {1}", typedItems[0].Amount); //<< 186
                        }
                    } //
*Edit* removed the console writeline coding, worked fine.
 

Mikey

Sorceror
If you were curious why it crashed:
Console.WriteLine("The amount of the first item after consuming 1 is: {1}", typedItems[0].Amount);
The {1} should be {0}, there is no {1} argument.
 
Top