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

daat99

Moderator
Staff member
Change the debug code as follows:
Code:
//NEWEST EDIT
          if ( quiver != null )
          {
              ///original debug code goes here
          }
          else
          {
              Console.WriteLine("the quiver is null");
          }
          //end of change
          if( attacker.Player &&
              ( quiver == null || !quiver.ConsumeTotal( AmmoType, 1 ) ) &&
              (  pack == null ||  !pack.ConsumeTotal( AmmoType, 1 ) ) )
                        Console.WriteLine("Returning false because not consuming");
                return false;
After this change, please post both the full file and the console output.
 
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 )
        {
                Console.WriteLine("OnFired started.");
            //--<<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." );
                        Console.WriteLine("Returning false because there is no 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 );
                        Console.WriteLine("Returning true because quiver.lowerammocost.");
                return true;
            }
//NEWEST EDIT
                  if ( quiver != null )
                  {
                            Item[] typedItems = quiver.FindItemsByType( typeof( LightningArrow ), 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);
                          }
                  }
                  else
                  {
                      Console.WriteLine("the quiver is null");
                  }
                  //end of change
                  if( attacker.Player &&
                      ( quiver == null || !quiver.ConsumeTotal( AmmoType, 1 ) ) &&
                      (  pack == null ||  !pack.ConsumeTotal( AmmoType, 1 ) ) )
                                Console.WriteLine("Returning false because not consuming");
                        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 && quiver.ConsumeTotal( AmmoType, 1 ) )
                        quiver.InvalidateWeight();
                    else if ( pack == null || !pack.ConsumeTotal( AmmoType, 1 ) )
            Console.WriteLine("returning false because quiver != null");
                        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
            Console.WriteLine("returning false because ammo");
                    return false;
                }
            }
 
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
                        Console.WriteLine("Returning true because Moving Effect");
 
            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;
            }
        }
    }
}

Output:
Code:
OnFired started.
the quiver is null
Returning false because not consuming
OnFired started.
the quiver is null
Returning false because not consuming
OnFired started.
the quiver is null
Returning false because not consuming
OnFired started.
the quiver is null
Returning false because not consuming
OnFired started.
the quiver is null
Returning false because not consuming
OnFired started.
the quiver is null
Returning false because not consuming

So, I assume that means it's not reading I have a quiver?
 
We had this line, saying a quiver was on you middle torso, when it is on the layer cloak. So I changed if from
Code:
BaseQuiver quiver = attacker.FindItemOnLayer( Layer.MiddleTorso ) as BaseQuiver;
To
Code:
BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) as BaseQuiver;
And then I get the console output of
Code:
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 473
The amount of the first item after consuming 1 is: 472
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 471
The amount of the first item after consuming 1 is: 470
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 469
The amount of the first item after consuming 1 is: 468
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 467
The amount of the first item after consuming 1 is: 466
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 465
The amount of the first item after consuming 1 is: 464
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 463
The amount of the first item after consuming 1 is: 462
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 461
The amount of the first item after consuming 1 is: 460
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 459
The amount of the first item after consuming 1 is: 458
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 457
The amount of the first item after consuming 1 is: 456
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 455
The amount of the first item after consuming 1 is: 454
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 453
The amount of the first item after consuming 1 is: 452
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 451
The amount of the first item after consuming 1 is: 450
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 449
The amount of the first item after consuming 1 is: 448
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 447
The amount of the first item after consuming 1 is: 446
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 445
The amount of the first item after consuming 1 is: 444
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 443
The amount of the first item after consuming 1 is: 442
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 441
The amount of the first item after consuming 1 is: 440
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 439
The amount of the first item after consuming 1 is: 438
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 437
The amount of the first item after consuming 1 is: 436
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 435
The amount of the first item after consuming 1 is: 434
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 433
The amount of the first item after consuming 1 is: 432
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 431
The amount of the first item after consuming 1 is: 430
OnFired started.
FindItemsByType was able to find 1 items.
The amount of the first item is: 429
The amount of the first item after consuming 1 is: 428
Here is the whole new 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 )
        {
                Console.WriteLine("OnFired started.");
            //--<<Advanced Archery Edit>>---------------------[Start 3/4]
            PlayerMobile a_pm = attacker as PlayerMobile;
            Container pack = attacker.Backpack;
            BaseQuiver quiver = attacker.FindItemOnLayer( Layer.Cloak ) 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." );
                        Console.WriteLine("Returning false because there is no 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 );
                        Console.WriteLine("Returning true because quiver.lowerammocost.");
                return true;
            }
//NEWEST EDIT
                  if ( quiver != null )
                  {
                            Item[] typedItems = quiver.FindItemsByType( typeof( LightningArrow ), 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: {0}", typedItems[0].Amount);
                          }
                  }
                  else
                  {
                      Console.WriteLine("the quiver is null");
                  }
                  //end of change
                  if( attacker.Player &&
                      ( quiver == null || !quiver.ConsumeTotal( AmmoType, 1 ) ) &&
                      (  pack == null ||  !pack.ConsumeTotal( AmmoType, 1 ) ) )
                                Console.WriteLine("Returning false because not consuming");
                        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 && quiver.ConsumeTotal( AmmoType, 1 ) )
                        quiver.InvalidateWeight();
                    else if ( pack == null || !pack.ConsumeTotal( AmmoType, 1 ) )
            Console.WriteLine("returning false because quiver != null");
                        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
            Console.WriteLine("returning false because ammo");
                    return false;
                }
            }
 
            attacker.MovingEffect( defender, EffectID, 18, 1, false, false );
                        Console.WriteLine("Returning true because Moving Effect");
 
            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'm very happy to see that you understood what we are doing and were able to fix the quiver issue, keep up the great work :)

I hope you learned something new about how to use console output in order to debug code on run-time.

Debugging using console output is my favorite way to debug complex systems in my day-job (way more complex than RunUO) and you can achieve a lot with the correct output including debugging some advanced long multi-threading operations which are very hard to debug using normal debugging tools.


Back on topic:
According to the new code it looks like it's consuming the ammo as you wanted, am I correct?

Is there an issue with the latest code you want to address?
 
As it is, it's not shooting. It's consuming, but it's not shooting. Before I could use normal arrows, now it won't shoot at all. What could we have done to stop the bows from shooting?
 

daat99

Moderator
Staff member
Take a look at this code:
Code:
                  //end of change
                  if( attacker.Player &&
                      ( quiver == null || !quiver.ConsumeTotal( AmmoType, 1 ) ) &&
                      (  pack == null ||  !pack.ConsumeTotal( AmmoType, 1 ) ) )
                                Console.WriteLine("Returning false because not consuming");
                        return false;
Can you tell what happens in this code?
 

daat99

Moderator
Staff member
Let's go back to basics:
Code:
if ( condition == true )
    Console.WriteLine("condition is true");
    Console.WriteLine("2nd print");
Console.WriteLine("Done");
Without running the code!!!:
Can you tell me what will be printed on the screen when condition is true and when condition is false?
 

daat99

Moderator
Staff member
Let's go back to basics:
Code:
if ( condition == true )
    Console.WriteLine("condition is true");
    Console.WriteLine("2nd print");
Console.WriteLine("Done");
Without running the code!!!:
Can you tell me what will be printed on the screen when condition is true and when condition is false?
Forget about the code in our thread for a second, can you tell me what this code snippet will print to the console without running it?
Take a guess if you aren't sure :)
 
"Condition is true
2nd print
Done"
Right? It that order? And since there are no other statements, it shoul just play through those three without interruption if the condition is true?
 

daat99

Moderator
Staff member
That is correct.

Now to the tricky question:
What will be printed if the condition is false? (this is approximately 10% of the points you get in your first programming test).
 

daat99

Moderator
Staff member
True.
With that in mind what will it print on the console?
Code:
if ( condition == true )
    Console.WriteLine("condition is true");
    Console.WriteLine("2nd print");
Console.WriteLine("Done");
 
I don't know. When it's true the console should display
Code:
condition is true
2nd print
Done
and when it's false, it should skip that statement since there is no false statement. But, since I don't see the next statement, I have no idea what would happen next. Am I right, or is there something I'm missing?
 
Top