Beispiel #1
0
        public void ResolveCannon(ShipCannon shipCannon, Mobile from, Point3D targetLocation, Map map, bool hit)
        {
            if (hit)
            {
                ResolveCannonHit(from, targetLocation);
            }

            else
            {
                Splash(targetLocation, map);
            }
        }
Beispiel #2
0
        public static void PlaceShipCannon(BaseBoat boat, Point3D point, CannonType cannonType, CannonPosition cannonPosition)
        {
            if (boat == null)
            {
                return;
            }

            ShipCannon shipCannon = new ShipCannon();

            shipCannon.Visible = false;

            shipCannon.m_Boat           = boat;
            shipCannon.m_CannonType     = cannonType;
            shipCannon.m_CannonPosition = cannonPosition;
            shipCannon.m_xOffset        = point.X;
            shipCannon.m_yOffset        = point.Y;
            shipCannon.m_zOffset        = point.Z;

            Point3D cannonLocation = boat.GetRotatedLocation(point.X, point.Y, 0);

            shipCannon.MoveToWorld(new Point3D(boat.Location.X + cannonLocation.X, boat.Location.Y + cannonLocation.Y, boat.Location.Z + cannonLocation.Z), boat.Map);
            shipCannon.BoatFacingChange(boat.Facing);
            shipCannon.Z = boat.Location.Z + cannonLocation.Z + shipCannon.GetAdjustedCannonZOffset();

            shipCannon.Hue = boat.CannonHue;

            if (boat.MobileControlType != MobileControlType.Player)
            {
                shipCannon.Ammunition = shipCannon.GetMaxAmmunition();
            }

            shipCannon.Visible = true;

            boat.m_Cannons.Add(shipCannon);

            switch (cannonPosition)
            {
            case CannonPosition.Left: boat.m_LeftCannons.Add(shipCannon); break;

            case CannonPosition.Right: boat.m_RightCannons.Add(shipCannon); break;

            case CannonPosition.Front: boat.m_FrontCannons.Add(shipCannon); break;

            case CannonPosition.Rear: boat.m_RearCannons.Add(shipCannon); break;
            }
        }
Beispiel #3
0
        public void FireCannon(ShipCannon shipCannon, Mobile from, Point3D targetLocation, Map map, bool hit, bool showSmoke)
        {
            if (shipCannon == null)
            {
                return;
            }

            int cannonballItemID = 0xE73;
            int cannonballHue    = 0;
            int smokeHue         = 0;

            bool fixedDirection = false;

            double shotDelay = .04;
            int    shotSpeed = 6;

            Point3D smokeLocation = shipCannon.Location;

            switch (shipCannon.Facing)
            {
            case Direction.North: { } break;

            case Direction.East: { smokeLocation.X++; } break;

            case Direction.South: { smokeLocation.Y++; } break;

            case Direction.West: { smokeLocation.X--; } break;
            }

            if (m_Boat != null)
            {
                double gunsPercent   = (double)((float)m_Boat.GunPoints / (float)m_Boat.MaxGunPoints);
                double misfireChance = BaseBoat.CannonMaxMisfireChance * (1 - gunsPercent);

                double chance = Utility.RandomDouble();

                double distance     = Utility.GetDistanceToSqrt(shipCannon.Location, targetLocation);
                double flatDistance = Utility.GetDistance(shipCannon.Location, targetLocation);

                //Misfire
                if (chance < misfireChance)
                {
                    List <Mobile> m_MobilesOnBoat = m_Boat.GetMobilesOnBoat(true, true);

                    foreach (Mobile mobile in m_MobilesOnBoat)
                    {
                        if (m_Boat.IsOwner(mobile) || m_Boat.IsCoOwner(mobile) || m_Boat.IsFriend(mobile))
                        {
                            mobile.SendMessage("Misfire!");
                        }
                    }

                    Effects.SendLocationEffect(shipCannon.Location, map, 0x3735, 10);
                    Effects.PlaySound(shipCannon.Location, map, 0x475);

                    return;
                }

                if (m_Boat.MobileFactionType == MobileFactionType.Undead)
                {
                    cannonballItemID = Utility.RandomList(6880, 6881, 6882, 6883, 6884);
                    smokeHue         = 2630;
                }

                //Hit
                if (hit)
                {
                    m_Boat.LastCombatTime = DateTime.UtcNow;

                    Effects.PlaySound(shipCannon.Location, map, 0x664);

                    if (showSmoke)
                    {
                        Effects.SendLocationEffect(smokeLocation, map, 0x36CB, 10, smokeHue, 0);
                    }

                    SpellHelper.AdjustField(ref targetLocation, map, 12, false);

                    IEntity startLocation = new Entity(Serial.Zero, new Point3D(shipCannon.Location.X, shipCannon.Location.Y, shipCannon.Location.Z + 10), map);
                    IEntity endLocation   = new Entity(Serial.Zero, new Point3D(targetLocation.X, targetLocation.Y, targetLocation.Z + 5), map);

                    Effects.SendMovingEffect(startLocation, endLocation, cannonballItemID, shotSpeed, 0, fixedDirection, false, cannonballHue, 0);
                    double effectDelay = distance * shotDelay;

                    Timer.DelayCall(TimeSpan.FromSeconds(effectDelay), delegate
                    {
                        ResolveCannon(shipCannon, from, targetLocation, map, hit);
                    });
                }

                //Miss
                else
                {
                    int xOffset = 0;
                    int yOffset = 0;

                    double effectiveDistance = distance;

                    int distanceOffset = (int)(Math.Floor(effectiveDistance / 2));

                    if (distance >= 2)
                    {
                        xOffset = Utility.RandomMinMax(0, distanceOffset);

                        if (Utility.RandomDouble() > .5)
                        {
                            xOffset *= -1;
                        }

                        yOffset = Utility.RandomMinMax(0, distanceOffset);

                        if (Utility.RandomDouble() > .5)
                        {
                            yOffset *= -1;
                        }
                    }

                    Effects.PlaySound(shipCannon.Location, map, 0x664);
                    Effects.SendLocationEffect(smokeLocation, map, 0x36CB, 10, smokeHue, 0);

                    IEntity startLocation = new Entity(Serial.Zero, new Point3D(shipCannon.Location.X, shipCannon.Location.Y, shipCannon.Location.Z + 10), map);
                    IEntity endLocation   = new Entity(Serial.Zero, new Point3D(targetLocation.X + xOffset, targetLocation.Y + yOffset, targetLocation.Z + 5), map);

                    Effects.SendMovingEffect(startLocation, endLocation, cannonballItemID, shotSpeed, 0, fixedDirection, false, cannonballHue, 0);

                    Point3D splashLocation = new Point3D(targetLocation.X + xOffset, targetLocation.Y + yOffset, +targetLocation.Z);

                    double newDistance = from.GetDistanceToSqrt(splashLocation);
                    double effectDelay = newDistance * shotDelay;

                    Timer.DelayCall(TimeSpan.FromSeconds(effectDelay), delegate
                    {
                        ResolveCannon(shipCannon, from, splashLocation, map, hit);
                    });
                }
            }
        }
Beispiel #4
0
        public void OnTarget(Mobile from, Point3D point, bool IsNPCShip, bool canHitCenter, bool canHitHold, bool canHitTillerman)
        {
            if (m_Boat == null)
            {
                return;
            }

            Map      map        = from.Map;
            BaseBoat targetBoat = BaseBoat.FindBoatAt(point, map);

            //For Player Ships
            if (m_Boat.MobileControlType == MobileControlType.Player)
            {
                if (!from.Player)
                {
                    return;
                }

                else if (!from.Alive)
                {
                    from.SendMessage("You must be alive to use this.");
                    return;
                }

                else if (!m_Boat.Contains(from))
                {
                    from.SendMessage("You are no longer on the boat.");
                    return;
                }

                else if (targetBoat == m_Boat)
                {
                    from.SendMessage("You may not fire onto your own ship!");
                    return;
                }

                else if (Ammunition == 0)
                {
                    from.SendMessage("At least one of your cannons must be loaded to fire a volley.");
                    return;
                }

                else if (DateTime.UtcNow < m_Boat.CannonCooldown)
                {
                    from.SendMessage("You must wait before firing another cannon volley.");
                    return;
                }
            }

            bool volleyValid = false;
            bool tooClose    = false;

            double cannonDelayTotal = 0;
            int    cannonsFiring    = 0;

            //Need At Least One Cannon With LOS to Target and In Range of Target For Volley To Be Valid
            foreach (ShipCannon shipCannon in m_Boat.m_Cannons)
            {
                //Cannon Has Ammunition and is on Correct Ship Side for Volley
                if (shipCannon.Ammunition > 0 && shipCannon.Facing == Facing)
                {
                    cannonDelayTotal += BaseBoat.CannonCooldownTime;
                    cannonsFiring++;

                    double modifiedRange = (double)BaseBoat.CannonMaxRange * m_Boat.CannonRangeScalar;

                    //Already Deterined to Be Valid Shot: NPC AI Ship
                    if (IsNPCShip)
                    {
                        volleyValid = true;
                        break;
                    }

                    //Cannon is in LOS and Within Range
                    if (shipCannon.InAngle(point) && Utility.GetDistanceToSqrt(shipCannon.Location, point) <= modifiedRange)
                    {
                        volleyValid = true;
                    }

                    //Cannon is too close
                    if (Utility.GetDistanceToSqrt(shipCannon.Location, point) < 2)
                    {
                        tooClose = true;
                    }
                }
            }

            //At Least One Cannon Was Too Close to Fire
            if (tooClose)
            {
                volleyValid = false;
            }

            //Can Fire Cannon Volley
            if (volleyValid)
            {
                if (m_Boat.TillerMan != null)
                {
                    m_Boat.TillerMan.Say("Firing cannons!");
                }

                m_Boat.LastCombatTime = DateTime.UtcNow;

                //Ship Cooldown Time (Average of Delay for Each Cannon Type that is Firing)
                double cooldown = cannonDelayTotal / cannonsFiring;

                m_Boat.CannonCooldown = DateTime.UtcNow + TimeSpan.FromSeconds(cooldown);
                m_Boat.StartCannonCooldown();

                List <ShipCannon> cannonsToFire = new List <ShipCannon>();

                foreach (ShipCannon shipCannon in m_Boat.m_Cannons)
                {
                    if (shipCannon.Ammunition > 0 && shipCannon.Facing == Facing)
                    {
                        cannonsToFire.Add(shipCannon);
                    }
                }

                int firingLoops = BaseBoat.CannonFiringLoops;

                int cannonCount = cannonsToFire.Count;

                for (int a = 0; a < firingLoops; a++)
                {
                    for (int b = 0; b < cannonCount; b++)
                    {
                        bool showSmoke  = false;
                        bool lastCannon = false;

                        int        cannonIndex = Utility.RandomMinMax(0, cannonsToFire.Count - 1);
                        ShipCannon shipCannon  = cannonsToFire[cannonIndex];

                        if (a == 0)
                        {
                            showSmoke = true;
                        }

                        if (a == (firingLoops - 1))
                        {
                            shipCannon.Ammunition--;
                            cannonsToFire.RemoveAt(cannonIndex);

                            if (b == cannonCount - 1)
                            {
                                lastCannon = true;
                            }
                        }

                        //Check Accuracy
                        double cannonAccuracy = BaseBoat.CannonAccuracy * m_Boat.CannonAccuracyModifer;

                        double opponentMovementPenalty = 0;
                        double movementAccuracyPenalty = 0;

                        //Own Ship Movement Penalty
                        TimeSpan timeStationary    = DateTime.UtcNow - m_Boat.TimeLastMoved;
                        double   secondsStationary = (double)timeStationary.TotalSeconds;

                        if (secondsStationary > BaseBoat.CannonMovementAccuracyCooldown)
                        {
                            secondsStationary = BaseBoat.CannonMovementAccuracyCooldown;
                        }

                        if (targetBoat != null)
                        {
                            TimeSpan timeTargetStationary      = DateTime.UtcNow - targetBoat.TimeLastMoved;
                            double   secondsOpponentStationary = (double)timeStationary.TotalSeconds;

                            if (secondsOpponentStationary > BaseBoat.CannonMovementAccuracyCooldown)
                            {
                                secondsOpponentStationary = BaseBoat.CannonMovementAccuracyCooldown;
                            }

                            opponentMovementPenalty = 1 - (BaseBoat.CannonTargetMovementMaxAccuracyPenalty * (1 - (secondsOpponentStationary / BaseBoat.CannonMovementAccuracyCooldown)));

                            //No Movement Penalty to Shoot a Ship That is in Reduced Speed Mode
                            if (targetBoat.ReducedSpeedMode)
                            {
                                opponentMovementPenalty = 1;
                            }
                        }

                        movementAccuracyPenalty = 1 - (BaseBoat.CannonMovementMaxAccuracyPenalty * (1 - (secondsStationary / BaseBoat.CannonMovementAccuracyCooldown)));

                        double finalAccuracy = cannonAccuracy * movementAccuracyPenalty * opponentMovementPenalty;

                        double chance = Utility.RandomDouble();

                        bool hit = false;

                        //Hit Target
                        if (chance <= finalAccuracy)
                        {
                            hit = true;
                        }

                        Point3D cannonEndLocation = point;

                        if (IsNPCShip && targetBoat != null)
                        {
                            if (canHitCenter)
                            {
                                cannonEndLocation = targetBoat.GetRandomEmbarkLocation(true);
                            }

                            else if (canHitHold && canHitTillerman)
                            {
                                if (Utility.RandomDouble() < .5)
                                {
                                    cannonEndLocation = targetBoat.Hold.Location;
                                }

                                else
                                {
                                    cannonEndLocation = targetBoat.TillerMan.Location;
                                }
                            }

                            else if (canHitHold && !canHitTillerman)
                            {
                                cannonEndLocation = targetBoat.Hold.Location;
                            }

                            else if (!canHitHold && canHitTillerman)
                            {
                                cannonEndLocation = targetBoat.TillerMan.Location;
                            }
                        }

                        double delay = (BaseBoat.CannonLoopDelay * (a + 1) / (double)firingLoops) * b;

                        Timer.DelayCall(TimeSpan.FromSeconds(delay), delegate
                        {
                            FireCannon(shipCannon, from, cannonEndLocation, map, hit, showSmoke);
                        });
                    }
                }
            }

            else
            {
                if (tooClose)
                {
                    from.SendMessage("Your target is too close to the ship to be fired upon.");
                }

                else
                {
                    from.SendMessage("At least one of your cannons must be within range of and in line of sight of your target in order to fire a cannon volley.");
                }
            }
        }
Beispiel #5
0
 public CannonTarget(ShipCannon shipCannon) : base(25, true, TargetFlags.Harmful)
 {
     m_ShipCannon = shipCannon;
 }