public void Fire(Mobile from)
        {
            BaseRanged bow  = from.Weapon as BaseRanged;
            BaseThrown trow = from.Weapon as BaseThrown;

            if (bow == null || trow == null)
            {
                this.SendLocalizedMessageTo(from, 500593); // You must practice with ranged weapons on this.
                return;
            }

            if (DateTime.UtcNow < (this.m_LastUse + UseDelay))
            {
                return;
            }

            Point3D worldLoc = this.GetWorldLocation();

            if (this.FacingEast ? from.X <= worldLoc.X : from.Y <= worldLoc.Y)
            {
                from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500596); // You would do better to stand in front of the archery butte.
                return;
            }

            if (this.FacingEast ? from.Y != worldLoc.Y : from.X != worldLoc.X)
            {
                from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500597); // You aren't properly lined up with the archery butte to get an accurate shot.
                return;
            }

            if (!from.InRange(worldLoc, 6))
            {
                from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500598); // You are too far away from the archery butte to get an accurate shot.
                return;
            }
            else if (from.InRange(worldLoc, 4))
            {
                from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500599); // You are too close to the target.
                return;
            }

            Container pack     = from.Backpack;
            Type      ammoType = bow.AmmoType;

            bool isArrow = (ammoType == typeof(Arrow));
            bool isBolt  = (ammoType == typeof(Bolt));
            bool isKnown = (isArrow || isBolt);

            if (from.Weapon != trow && (pack == null || !pack.ConsumeTotal(ammoType, 1)))
            {
                if (isArrow)
                {
                    from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500594); // You do not have any arrows with which to practice.
                }
                else if (isBolt)
                {
                    from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500595); // You do not have any crossbow bolts with which to practice.
                }
                else
                {
                    this.SendLocalizedMessageTo(from, 500593); // You must practice with ranged weapons on this.
                }
                return;
            }

            this.m_LastUse = DateTime.UtcNow;

            if (from.Weapon == trow)
            {
                from.MovingEffect(this, trow.EffectID, 18, 1, false, false);
                from.Direction = from.GetDirectionTo(this.GetWorldLocation());
                trow.PlaySwingAnimation(from);
            }

            else
            {
                from.Direction = from.GetDirectionTo(this.GetWorldLocation());
                bow.PlaySwingAnimation(from);
                from.MovingEffect(this, bow.EffectID, 18, 1, false, false);
            }

            ScoreEntry se = this.GetEntryFor(from);

            if (!from.CheckSkill(bow.Skill, this.m_MinSkill, this.m_MaxSkill))
            {
                from.PlaySound(bow.MissSound);

                this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 500604, from.Name); // You miss the target altogether.

                se.Record(0);

                if (se.Count == 1)
                {
                    this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062719, se.Total.ToString());
                }
                else
                {
                    this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1042683, String.Format("{0}\t{1}", se.Total, se.Count));
                }

                return;
            }

            else if (!from.CheckSkill(trow.Skill, this.m_MinSkill, this.m_MaxSkill))
            {
                from.PlaySound(trow.MissSound);

                this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 500604, from.Name); // You miss the target altogether.

                se.Record(0);

                if (se.Count == 1)
                {
                    this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062719, se.Total.ToString());
                }
                else
                {
                    this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1042683, String.Format("{0}\t{1}", se.Total, se.Count));
                }

                return;
            }
            Effects.PlaySound(this.Location, this.Map, 0x2B1);

            double rand = Utility.RandomDouble();

            int area, score, splitScore;

            if (0.10 > rand)
            {
                area       = 0; // bullseye
                score      = 50;
                splitScore = 100;
            }
            else if (0.25 > rand)
            {
                area       = 1; // inner ring
                score      = 10;
                splitScore = 20;
            }
            else if (0.50 > rand)
            {
                area       = 2; // middle ring
                score      = 5;
                splitScore = 15;
            }
            else
            {
                area       = 3; // outer ring
                score      = 2;
                splitScore = 5;
            }

            bool split = (isKnown && ((this.m_Arrows + this.m_Bolts) * 0.02) > Utility.RandomDouble());

            if (split)
            {
                this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1010027 + area, String.Format("{0}\t{1}", from.Name, isArrow ? "arrow" : "bolt"));
            }
            else
            {
                this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1010035 + area, from.Name);

                if (isArrow)
                {
                    ++this.m_Arrows;
                }
                else if (isBolt)
                {
                    ++this.m_Bolts;
                }
            }

            se.Record(split ? splitScore : score);

            if (se.Count == 1)
            {
                this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062719, se.Total.ToString());
            }
            else
            {
                this.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1042683, String.Format("{0}\t{1}", se.Total, se.Count));
            }
        }