예제 #1
0
        public virtual void Shoot(object cannoneer)
        {
            AmmoInfo ammo = AmmoInfo.GetAmmoInfo(AmmoType);

            if (ammo == null)
            {
                return;
            }

            Mobile shooter = null;

            if (cannoneer is Mobile)
            {
                shooter = (Mobile)cannoneer;
            }

            if (shooter != null && shooter.Player)
            {
                m_Hits -= Utility.RandomMinMax(0, 4);
            }

            DoShootEffects();
            AddAction(shooter, 1149691); //Fired successfully.

            int       xOffset = 0; int yOffset = 0;
            int       currentRange = 0;
            Point3D   pnt          = this.Location;
            Map       map          = this.Map;
            Direction d            = GetFacing();

            switch (d)
            {
            case Direction.North:
                xOffset = 0; yOffset = -1; break;

            case Direction.South:
                xOffset = 0; yOffset = 1; break;

            case Direction.West:
                xOffset = -1; yOffset = 0; break;

            case Direction.East:
                xOffset = 1; yOffset = 0; break;
            }

            int xo            = xOffset;
            int yo            = yOffset;
            int lateralOffset = 1;

            int latDist = ammo.LateralOffset;

            int  range = Range;
            bool hit   = false;

            while (currentRange++ <= range)
            {
                xOffset = xo;
                yOffset = yo;

                if (currentRange % latDist == 0)
                {
                    lateralOffset++;
                }

                TimeSpan delay = TimeSpan.FromSeconds((double)currentRange / 10.0);

                switch (AmmoType)
                {
                case AmmunitionType.Empty: break;

                case AmmunitionType.Cannonball:
                case AmmunitionType.FrostCannonball:
                case AmmunitionType.FlameCannonball:
                {
                    Point3D            newPoint    = pnt;
                    List <IEntity>     list        = new List <IEntity>();
                    List <IDamageable> damageables = new List <IDamageable>();

                    for (int i = -lateralOffset; i <= lateralOffset; i++)
                    {
                        if (xOffset == 0)
                        {
                            newPoint = new Point3D(pnt.X + (xOffset + i), pnt.Y + (yOffset * currentRange), pnt.Z);
                        }
                        else
                        {
                            newPoint = new Point3D(pnt.X + (xOffset * currentRange), pnt.Y + (yOffset + i), pnt.Z);
                        }

                        BaseGalleon g = FindValidBoatTarget(newPoint, map, ammo);

                        if (g != null && g != Galleon && g.IsEnemy(Galleon))
                        {
                            list.Add(g);
                        }

                        damageables.AddRange(FindDamageables(shooter, newPoint, map, false, false, false, true, true));
                    }

                    foreach (var m in damageables)
                    {
                        list.Add(m);
                    }

                    if (list.Count > 0)
                    {
                        IEntity toHit = list[Utility.Random(list.Count)];

                        if (toHit is Mobile)
                        {
                            Timer.DelayCall(delay, new TimerStateCallback(OnMobileHit), new object[] { (Mobile)toHit, newPoint, ammo, shooter });
                            hit = true;
                        }
                        else if (toHit is BaseGalleon)
                        {
                            Timer.DelayCall(delay, new TimerStateCallback(OnShipHit), new object[] { (BaseGalleon)toHit, newPoint, ammo, shooter });
                            hit = true;
                        }
                        else if (toHit is DamageableItem)
                        {
                            Timer.DelayCall(delay, new TimerStateCallback(OnDamageableItemHit), new object[] { (DamageableItem)toHit, newPoint, ammo, shooter });
                            hit = true;
                        }
                    }
                }
                break;

                case AmmunitionType.Grapeshot:
                {
                    Point3D       newPoint = pnt;
                    List <Mobile> mobiles  = new List <Mobile>();

                    for (int i = -lateralOffset; i <= lateralOffset; i++)
                    {
                        if (xOffset == 0)
                        {
                            newPoint = new Point3D(pnt.X + (xOffset + i), pnt.Y + (yOffset * currentRange), pnt.Z);
                        }
                        else
                        {
                            newPoint = new Point3D(pnt.X + (xOffset * currentRange), pnt.Y + (yOffset + i), pnt.Z);
                        }

                        mobiles.AddRange(FindDamageables(shooter, newPoint, map, true, true, true, true, false).OfType <Mobile>());
                    }

                    if (mobiles.Count > 0)
                    {
                        Timer.DelayCall(delay, new TimerStateCallback(OnMobileHit), new object[] { mobiles, newPoint, ammo, shooter });
                        hit = true;
                    }
                }
                break;
                }

                if (hit && ammo.SingleTarget)
                {
                    break;
                }
            }

            ClearCannon();
            InvalidateDamageState();

            if (shooter != null)
            {
                ResendGump(shooter);
            }
        }