Esempio n. 1
0
        private void TryFireCannons()
        {
            //if (_ai.TimeUntilReloaded > 0 && false)
            {
                //    return;
            }

            // Check that we aren't at too extreme an angle to fire (e.g. don't fire off the bow of the ship)
            float angleTowardsPlayer = Util.AngleTowards(_h.SelfPos, _h.TargetPos);
            float relativeAngle      = Util.Clamp180(angleTowardsPlayer - _h.Heading);

            // Angle will be the following:
            // * 0: Front
            // * 180: Back
            // * 0 to 180: Right
            // * -180 to 0: Left
            if (Mathf.Abs(relativeAngle) < _h.Settings.MaxFiringAngle || Mathf.Abs(relativeAngle) > 180 - _h.Settings.MaxFiringAngle)
            {
                return;
            }

            // Check if we are in range, then if necessary, fire
            float sqrDistance = _h.SqrDistanceTo(_h.TargetPos);

            if (sqrDistance <= _h.Settings.CannonRange * _h.Settings.CannonRange)
            {
                int cannonIndex = relativeAngle <= 0 ?
                                  _ai._Caravel.GetNextLeftCannonIndex() :
                                  _ai._Caravel.GetNextRightCannonIndex();
                var cannon = _ai._Caravel.GetCannon(cannonIndex);

                if (Time.time - cannon.LastFireTime < _ai._AiSettings.ReloadTime ||
                    Time.time - _ai._lastFireTime < _ai._AiSettings.FireInterval)
                {
                    return;
                }
                cannon.LastFireTime = Time.time;
                _ai._lastFireTime   = Time.time;

                Vector3 spawnPos = cannon.SpawnPos.transform.position;

                // Basic velocity prediction
                // Predict how long a cannonball would take to land, if it was shot directly to where the target is right
                // now.
                // Then shoot the cannonball to where the target will be in that amount of time
                // This isn't perfect because technically the amount of time for the cannonball to land is dependent on the
                // distance to the target, so if we're changing the distance, we'll get a slightly different answer for where
                // it will land.
                // To solve this, we run multiple iterations of the prediction and cross our fingers it's close enough

                Vector3 predictedTargetPos = Vector3.zero; // will be initialized in the for-loop
                float   predictedTime      = _ai.PredictCannonballTime(spawnPos, _h.TargetPos, _h.Settings.CannonballSpeed, _h.Settings.CannonballGravity);
                for (int i = 0; i < 25; i++)
                {
                    predictedTargetPos = _h.TargetPos + predictedTime * _h.TargetVelocity;
                    predictedTime      = _ai.PredictCannonballTime(spawnPos, predictedTargetPos, _h.Settings.CannonballSpeed, _h.Settings.CannonballGravity);
                }

                // TODO AI cannonballs inherit AI ship velocity, and update prediction to take this into account
                GameObject instantiated = Instantiate(_ai._CannonballPrefab, spawnPos, Quaternion.identity);
                Cannonball cannonball   = instantiated.GetComponent <Cannonball>();
                cannonball.Gravity          = _h.Settings.CannonballGravity;
                cannonball.Velocity         = CalculateCannonballTrajectory(spawnPos, predictedTargetPos, _h.Settings.CannonballSpeed, _h.Settings.CannonballGravity);
                cannonball.IgnoreCollisions = _h.Self;

                _ai._Caravel.PlayCannonEffects(cannonIndex);
            }
        }