Пример #1
0
        public static Vector3 GetAirToAirFireSolution(MissileBase missile, Vessel targetVessel)
        {
            if (!targetVessel)
            {
                return(missile.transform.position + (missile.GetForwardTransform() * 1000));
            }
            Vector3 targetPosition = targetVessel.transform.position;
            float   leadTime       = 0;
            float   targetDistance = Vector3.Distance(targetVessel.transform.position, missile.transform.position);


            Vector3 simMissileVel = 500 * (targetPosition - missile.transform.position).normalized;

            MissileLauncher launcher = missile as MissileLauncher;
            float           optSpeed = 400; //TODO: Add parameter

            if (launcher != null)
            {
                optSpeed = launcher.optimumAirspeed;
            }
            simMissileVel = optSpeed * (targetPosition - missile.transform.position).normalized;

            leadTime       = targetDistance / (float)(targetVessel.Velocity() - simMissileVel).magnitude;
            leadTime       = Mathf.Clamp(leadTime, 0f, 8f);
            targetPosition = targetPosition + (targetVessel.Velocity() * leadTime);

            if (targetVessel && targetDistance < 800)
            {
                targetPosition += (Vector3)targetVessel.acceleration * 0.05f * leadTime * leadTime;
            }

            return(targetPosition);
        }
Пример #2
0
        /// <summary>
        /// Gets the dynamic launch parameters.
        /// </summary>
        /// <returns>The dynamic launch parameters.</returns>
        /// <param name="launcherVelocity">Launcher velocity.</param>
        /// <param name="targetVelocity">Target velocity.</param>
        public static MissileLaunchParams GetDynamicLaunchParams(MissileBase missile, Vector3 targetVelocity, Vector3 targetPosition)
        {
            Vector3 launcherVelocity = missile.vessel.Velocity();
            float   launcherSpeed    = (float)missile.vessel.srfSpeed;
            float   minLaunchRange   = missile.minStaticLaunchRange;
            float   maxLaunchRange   = missile.maxStaticLaunchRange;

            float rangeAddMin = 0;
            float rangeAddMax = 0;
            float relSpeed;

            Vector3 relV           = targetVelocity - launcherVelocity;
            Vector3 vectorToTarget = targetPosition - missile.part.transform.position;
            Vector3 relVProjected  = Vector3.Project(relV, vectorToTarget);

            relSpeed = -Mathf.Sign(Vector3.Dot(relVProjected, vectorToTarget)) * relVProjected.magnitude;


            rangeAddMin += relSpeed * 2;
            rangeAddMax += relSpeed * 8;
            rangeAddMin += launcherSpeed * 2;
            rangeAddMax += launcherSpeed * 2;

            double diffAlt = missile.vessel.altitude - FlightGlobals.getAltitudeAtPos(targetPosition);

            rangeAddMax += (float)diffAlt;

            float min = Mathf.Clamp(minLaunchRange + rangeAddMin, 0, BDArmorySettings.MAX_ENGAGEMENT_RANGE);
            float max = Mathf.Clamp(maxLaunchRange + rangeAddMax, min + 100, BDArmorySettings.MAX_ENGAGEMENT_RANGE);

            return(new MissileLaunchParams(min, max));
        }
Пример #3
0
    IEnumerator Fire()
    {
        Vector3 direction = new Vector3(
            5f * Mathf.Cos((angle * Mathf.PI) / 180f) + transform.position.x,
            5f * Mathf.Sin((angle * Mathf.PI) / 180f) + transform.position.y,
            0
            );

        for (int i = 0; i < 3; i++)
        {
            yield return(new WaitForSeconds(0.05f));

            GameObject missile = GameObject.Instantiate(basicMissile, shotOriginPoint.transform.position, transform.rotation);
            Physics.IgnoreCollision(GetComponentInChildren <Collider>(), missile.GetComponentInChildren <Collider>());
            foreach (GameObject igo in ignoredObjects)
            {
                if (igo != null)
                {
                    Physics.IgnoreCollision(igo.GetComponentInChildren <Collider>(), missile.GetComponentInChildren <Collider>());
                }
            }

            Destroy(missile, 7);
            MissileBase missileBase = missile.GetComponent <MissileBase> ();
            missileBase.WithForce(direction);
            missileBase.Fire();
        }
    }
Пример #4
0
        void Awake()
        {
            if (!vessel)
            {
                vessel = GetComponent <Vessel>();
            }

            if (!vessel)
            {
                //Debug.Log ("[BDArmory]: TargetInfo was added to a non-vessel");
                Destroy(this);
                return;
            }

            //destroy this if a target info is already attached to the vessel
            foreach (var otherInfo in vessel.gameObject.GetComponents <TargetInfo>())
            {
                if (otherInfo != this)
                {
                    Destroy(this);
                    return;
                }
            }

            Team = null;
            var mf = VesselModuleRegistry.GetMissileFire(vessel, true);

            if (mf != null)
            {
                Team          = mf.Team;
                weaponManager = mf;
            }
            else
            {
                var ml = VesselModuleRegistry.GetMissileBase(vessel, true);
                if (ml != null)
                {
                    isMissile         = true;
                    MissileBaseModule = ml;
                    Team = ml.Team;
                }
            }

            vessel.OnJustAboutToBeDestroyed += AboutToBeDestroyed;

            //add delegate to peace enable event
            BDArmorySetup.OnPeaceEnabled += OnPeaceEnabled;

            //lifeRoutine = StartCoroutine(LifetimeRoutine());              // TODO: CHECK BEHAVIOUR AND SIDE EFFECTS!

            if (!isMissile && Team != null)
            {
                GameEvents.onVesselPartCountChanged.Add(VesselModified);
                //massRoutine = StartCoroutine(MassRoutine());              // TODO: CHECK BEHAVIOUR AND SIDE EFFECTS!
            }
            UpdateTargetPartList();
            GameEvents.onVesselDestroy.Add(CleanFriendliesEngaging);
        }
Пример #5
0
        private void MakeDecisionAboutPitch(MissileBase missile, double missileAltitude)
        {
            _futureAltitude = CalculateFutureAltitude(_missile.CruisePredictionTime);

            PitchDecision futureDecision;

            if (this.GuidanceState != GuidanceState.Terminal &&
                (missileAltitude < 4d || CalculateFutureAltitude(1f) < 4d))
            {
                futureDecision = PitchDecision.EmergencyAscent;
            }
            else if (this.GuidanceState != GuidanceState.Terminal && CalculateFutureCollision(_missile.CruisePredictionTime))
            {
                futureDecision = PitchDecision.EmergencyAscent;
            }
            else if (_futureAltitude < missile.CruiseAltitude || missileAltitude < missile.CruiseAltitude)
            {
                futureDecision = PitchDecision.Ascent;
            }
            else if (_futureAltitude > missile.CruiseAltitude || missileAltitude > missile.CruiseAltitude)
            {
                futureDecision = PitchDecision.Descent;
            }
            else
            {
                futureDecision = PitchDecision.Hold;
            }


            switch (futureDecision)
            {
            case PitchDecision.EmergencyAscent:
                if (PitchDecision == futureDecision)
                {
                    _pitchAngle = Mathf.Clamp(_pitchAngle + 1f, 1.5f, 100f);
                }
                else
                {
                    _pitchAngle = 1.5f;
                }
                break;

            case PitchDecision.Ascent:
                _pitchAngle = Mathf.Clamp(_pitchAngle + 0.0055f, -1.5f, 1.5f);
                break;

            case PitchDecision.Descent:
                _pitchAngle = Mathf.Clamp(_pitchAngle - 0.0025f, -1.5f, 1.5f);
                break;

            case PitchDecision.Hold:
                break;
            }

            PitchDecision = futureDecision;
        }
Пример #6
0
        private double CalculateFreeFallTime(MissileBase missile, int predictionTime = 10)
        {
            double vi = CalculateFutureVerticalSpeed(missile, predictionTime) * -1;
            double a  = 9.80665f * missile.BallisticOverShootFactor;
            double d  = missile.vessel.GetFutureAltitude(predictionTime);

            double time1 = (-vi + Math.Sqrt(Math.Pow(vi, 2) - 4 * (0.5f * a) * (-d))) / a;
            double time2 = (-vi - Math.Sqrt(Math.Pow(vi, 2) - 4 * (0.5f * a) * (-d))) / a;

            return(Math.Max(time1, time2));
        }
Пример #7
0
        public bool ProcessMessage(MissileFireEventArgs message)
        {
            if (message == null)
            {
                return(false);
            }

            Vessel vessel = FlightGlobals.VesselsLoaded.FirstOrDefault(v => v.id == message.VesselId);

            if (vessel == null || vessel.packed)
            {
                if (!LunaMultiplayerSystem.missileMessagePending.Contains(message))
                {
                    LunaMultiplayerSystem.missileMessagePending.Enqueue(message);
                }

                return(false);
            }
            else
            {
                if (!vessel.loaded)
                {
                    vessel.Load();
                }
            }

            MissileBase missile = vessel.FindPartModuleImplementing <MissileBase>();

            if (missile == null)
            {
                return(false);
            }

            if (BDArmorySettings.MULTIPLAYER_VESSELS_OWNED.Contains(message.VesselId))
            {
                return(true);
            }

            if (missile.SourceVessel != null && BDArmorySettings.MULTIPLAYER_VESSELS_OWNED.Contains(missile.SourceVessel.id))
            {
                return(true);
            }

            missile.Team = BDTeam.Get(message.TeamName);
            missile.ActivateMissileMultiplayer();

            return(true);
        }
Пример #8
0
        public static Vector3 GetAirToAirFireSolution(MissileBase missile, Vector3 targetPosition, Vector3 targetVelocity)
        {
            float leadTime       = 0;
            float targetDistance = Vector3.Distance(targetPosition, missile.transform.position);

            float           optSpeed = 400; //TODO: Add parameter
            MissileLauncher launcher = missile as MissileLauncher;

            if (launcher != null)
            {
                optSpeed = launcher.optimumAirspeed;
            }

            Vector3 simMissileVel = optSpeed * (targetPosition - missile.transform.position).normalized;

            leadTime = targetDistance / (targetVelocity - simMissileVel).magnitude;
            leadTime = Mathf.Clamp(leadTime, 0f, 8f);

            targetPosition = targetPosition + (targetVelocity * leadTime);

            return(targetPosition);
        }
Пример #9
0
        private void MakeDecisionAboutThrottle(MissileBase missile)
        {
            const double maxError = 10;

            _futureSpeed = CalculateFutureSpeed();


            var currentSpeedDelta = missile.vessel.horizontalSrfSpeed - _missile.CruiseSpeed;

            if (_futureSpeed > missile.CruiseSpeed)
            {
                ThrottleDecision = ThrottleDecision.Decrease;
            }
            else if (Math.Abs(_futureSpeed - _missile.CruiseSpeed) < maxError)
            {
                ThrottleDecision = ThrottleDecision.Hold;
            }
            else
            {
                ThrottleDecision = ThrottleDecision.Increase;
            }

            switch (ThrottleDecision)
            {
            case ThrottleDecision.Increase:
                missile.Throttle = Mathf.Clamp(missile.Throttle + 0.001f, 0, 1f);
                break;

            case ThrottleDecision.Decrease:
                missile.Throttle = Mathf.Clamp(missile.Throttle - 0.001f, 0, 1f);
                break;

            case ThrottleDecision.Hold:
                break;
            }

            _lastSpeedDelta = currentSpeedDelta;
        }
Пример #10
0
        ///// <summary>
        ///// Gets the laser target painter with the least angle off boresight. Set the missileBase as the reference missilePosition.
        ///// </summary>
        ///// <returns>The laser target painter.</returns>
        ///// <param name="referenceTransform">Reference missilePosition.</param>
        ///// <param name="maxBoreSight">Max bore sight.</param>
        //public static ModuleTargetingCamera GetLaserTarget(MissileLauncher ml, bool parentOnly)
        //{
        //          return GetModuleTargeting(parentOnly, ml.transform.forward, ml.transform.position, ml.maxOffBoresight, ml.vessel, ml.SourceVessel);
        //      }

        //      public static ModuleTargetingCamera GetLaserTarget(BDModularGuidance ml, bool parentOnly)
        //      {
        //          float maxOffBoresight = 45;

        //          return GetModuleTargeting(parentOnly, ml.MissileReferenceTransform.forward, ml.MissileReferenceTransform.position, maxOffBoresight,ml.vessel,ml.SourceVessel);
        //      }

        /// <summary>
        /// Gets the laser target painter with the least angle off boresight. Set the missileBase as the reference missilePosition.
        /// </summary>
        /// <returns>The laser target painter.</returns>
        public static ModuleTargetingCamera GetLaserTarget(MissileBase ml, bool parentOnly)
        {
            return(GetModuleTargeting(parentOnly, ml.GetForwardTransform(), ml.MissileReferenceTransform.position, ml.maxOffBoresight, ml.vessel, ml.SourceVessel));
        }
Пример #11
0
        public static void DoExplosionRay(Ray ray, float power, float heat, float maxDistance, ref List <Part> ignoreParts, ref List <DestructibleBuilding> ignoreBldgs, Vessel sourceVessel = null)
        {
            RaycastHit rayHit;

            //KerbalEVA hitEVA = null;
            //if (Physics.Raycast(ray, out rayHit, maxDistance, 2228224))
            //{
            //    float sqrDist = (rayHit.point - ray.origin).sqrMagnitude;
            //    float sqrMaxDist = maxDistance * maxDistance;
            //    float distanceFactor = Mathf.Clamp01((sqrMaxDist - sqrDist) / sqrMaxDist);

            //    try
            //    {
            //        hitEVA = rayHit.collider.gameObject.GetComponentUpwards<KerbalEVA>();
            //        if (hitEVA != null)
            //            Debug.Log("[BDArmory]:Hit on kerbal confirmed!");
            //    }
            //    catch (System.NullReferenceException)
            //    {
            //        Debug.Log("[BDArmory]:Whoops ran amok of the exception handler");
            //    }

            //    Part part = hitEVA.part;
            //    Vessel missileSource = null;
            //    if (sourceVessel != null)
            //    {
            //        MissileBase ml = part.FindModuleImplementing<MissileBase>();
            //        if (ml)
            //        {
            //            missileSource = ml.SourceVessel;
            //        }
            //    }


            //    if (!ignoreParts.Contains(part) && part.physicalSignificance == Part.PhysicalSignificance.FULL &&
            //        (!sourceVessel || sourceVessel != missileSource))
            //    {
            //        ignoreParts.Add(part);
            //        Rigidbody rb = part.GetComponent<Rigidbody>();
            //        if (rb)
            //        {
            //            rb.AddForceAtPosition(ray.direction * power * distanceFactor * ExplosionImpulseMultiplier,
            //                rayHit.point, ForceMode.Impulse);
            //        }
            //        if (heat < 0)
            //        {
            //            heat = power;
            //        }
            //        float heatDamage = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * heat *
            //                           distanceFactor / part.crashTolerance;
            //        float excessHeat = Mathf.Max(0, (float)(part.temperature + heatDamage - part.maxTemp));
            //        part.AddDamage(heatDamage);
            //        if (BDArmorySettings.DRAW_DEBUG_LABELS)
            //            Debug.Log("[BDArmory]:====== Explosion ray hit part! Damage: " + heatDamage);
            //        if (excessHeat > 0 && part.parent)
            //        {
            //            part.parent.AddDamage(excessHeat);
            //        }
            //        return;
            //    }
            //}

            if (Physics.Raycast(ray, out rayHit, maxDistance, 688129))
            {
                float sqrDist        = (rayHit.point - ray.origin).sqrMagnitude;
                float sqrMaxDist     = maxDistance * maxDistance;
                float distanceFactor = Mathf.Clamp01((sqrMaxDist - sqrDist) / sqrMaxDist);
                //parts
                KerbalEVA eva  = rayHit.collider.gameObject.GetComponentUpwards <KerbalEVA>();
                Part      part = eva ? eva.part : rayHit.collider.GetComponentInParent <Part>();

                if (part)
                {
                    Vessel missileSource = null;
                    if (sourceVessel != null)
                    {
                        MissileBase ml = part.FindModuleImplementing <MissileBase>();
                        if (ml)
                        {
                            missileSource = ml.SourceVessel;
                        }
                    }


                    if (!ignoreParts.Contains(part) && part.physicalSignificance == Part.PhysicalSignificance.FULL &&
                        (!sourceVessel || sourceVessel != missileSource))
                    {
                        ignoreParts.Add(part);
                        Rigidbody rb = part.GetComponent <Rigidbody>();
                        if (rb)
                        {
                            rb.AddForceAtPosition(ray.direction * power * distanceFactor * ExplosionImpulseMultiplier,
                                                  rayHit.point, ForceMode.Impulse);
                        }
                        if (heat < 0)
                        {
                            heat = power;
                        }
                        float heatDamage = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * heat *
                                           distanceFactor / part.crashTolerance;
                        float excessHeat = Mathf.Max(0, (float)(part.temperature + heatDamage - part.maxTemp));
                        part.AddDamage(heatDamage);
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BDArmory]:====== Explosion ray hit part! Damage: " + heatDamage);
                        }
                        if (excessHeat > 0 && part.parent)
                        {
                            part.parent.AddDamage(excessHeat);
                        }
                        return;
                    }
                }

                //buildings
                DestructibleBuilding building = rayHit.collider.GetComponentInParent <DestructibleBuilding>();
                if (building && !ignoreBldgs.Contains(building))
                {
                    ignoreBldgs.Add(building);
                    float damageToBuilding = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * 0.00645f *
                                             power * distanceFactor;
                    if (damageToBuilding > building.impactMomentumThreshold / 10)
                    {
                        building.AddDamage(damageToBuilding);
                    }
                    if (building.Damage > building.impactMomentumThreshold)
                    {
                        building.Demolish();
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BDArmory]:== Explosion hit destructible building! Damage: " +
                                  (damageToBuilding).ToString("0.00") + ", total Damage: " + building.Damage);
                    }
                }
            }
        }
Пример #12
0
        public Vector3 GetDirection(MissileBase missile, Vector3 targetPosition, Vector3 targetVelocity)
        {
            //set up
            if (_missile.TimeIndex < 1)
            {
                return(_missile.vessel.CoM + _missile.vessel.Velocity() * 10);
            }

            upDirection = VectorUtils.GetUpDirection(_missile.vessel.CoM);

            planarDirectionToTarget =
                Vector3.ProjectOnPlane(targetPosition - _missile.vessel.CoM, upDirection).normalized;

            // Ascending
            _missile.debugString.Append("State=" + GuidanceState);
            _missile.debugString.Append(Environment.NewLine);

            var missileAltitude = GetCurrentAltitude(_missile.vessel);

            _missile.debugString.Append("Altitude=" + missileAltitude);
            _missile.debugString.Append(Environment.NewLine);

            _missile.debugString.Append("Apoapsis=" + _missile.vessel.orbit.ApA);
            _missile.debugString.Append(Environment.NewLine);

            _missile.debugString.Append("Future Altitude=" + _futureAltitude);
            _missile.debugString.Append(Environment.NewLine);

            _missile.debugString.Append("Pitch angle=" + _pitchAngle);
            _missile.debugString.Append(Environment.NewLine);

            _missile.debugString.Append("Pitch decision=" + PitchDecision);
            _missile.debugString.Append(Environment.NewLine);

            _missile.debugString.Append("lastVerticalSpeed=" + _lastVerticalSpeed);
            _missile.debugString.Append(Environment.NewLine);

            _missile.debugString.Append("verticalAcceleration=" + _verticalAcceleration);
            _missile.debugString.Append(Environment.NewLine);

            GetTelemetryData();

            switch (GuidanceState)
            {
            case GuidanceState.Ascending:
                UpdateThrottle();

                if (MissileWillReachAltitude(missileAltitude))
                {
                    _pitchAngle   = 0;
                    GuidanceState = GuidanceState.Cruising;

                    break;
                }

                CheckIfTerminal(missileAltitude, targetPosition, upDirection);

                return(_missile.vessel.CoM + (planarDirectionToTarget.normalized + upDirection.normalized) * 10f);

            case GuidanceState.Cruising:

                CheckIfTerminal(missileAltitude, targetPosition, upDirection);
                //Altitude control
                UpdatePitch(missileAltitude);
                UpdateThrottle();

                return(_missile.vessel.CoM + 10 * planarDirectionToTarget.normalized + _pitchAngle * upDirection);

            case GuidanceState.Terminal:

                _missile.debugString.Append($"Descending");
                _missile.debugString.Append(Environment.NewLine);

                _missile.Throttle = Mathf.Clamp((float)(_missile.vessel.atmDensity * 10f), 0.01f, 1f);

                if (_missile is BDModularGuidance)
                {
                    if (_missile.vessel.InVacuum())
                    {
                        return(_missile.vessel.CoM + _missile.vessel.Velocity() * 10);
                    }
                }

                return(MissileGuidance.GetAirToGroundTarget(targetPosition, targetVelocity, _missile.vessel, 1.85f));
            }

            return(_missile.vessel.CoM + _missile.vessel.Velocity() * 10);
        }
Пример #13
0
 public CruiseGuidance(MissileBase missile)
 {
     _missile = missile;
 }
Пример #14
0
        /// <summary>
        /// Gets the dynamic launch parameters.
        /// </summary>
        /// <returns>The dynamic launch parameters.</returns>
        /// <param name="launcherVelocity">Launcher velocity.</param>
        /// <param name="targetVelocity">Target velocity.</param>
        public static MissileLaunchParams GetDynamicLaunchParams(MissileBase missile, Vector3 targetVelocity, Vector3 targetPosition)
        {
            Vector3 launcherVelocity = missile.vessel.Velocity();
            float   launcherSpeed    = (float)missile.vessel.srfSpeed;
            float   minLaunchRange   = missile.minStaticLaunchRange;
            float   maxLaunchRange   = missile.maxStaticLaunchRange;

            float bodyGravity = (float)PhysicsGlobals.GravitationalAcceleration * (float)missile.vessel.orbit.referenceBody.GeeASL; // Set gravity for calculations;

            float missileActiveTime = 2f;

            float rangeAddMin = 0;
            float rangeAddMax = 0;
            float relSpeed;

            // Calculate relative speed
            Vector3 relV           = targetVelocity - launcherVelocity;
            Vector3 vectorToTarget = targetPosition - missile.part.transform.position;
            Vector3 relVProjected  = Vector3.Project(relV, vectorToTarget);

            relSpeed = -Mathf.Sign(Vector3.Dot(relVProjected, vectorToTarget)) * relVProjected.magnitude;

            if (missile.GetComponent <BDModularGuidance>() == null)
            {
                // Basic time estimate for missile to drop and travel a safe distance from vessel assuming constant acceleration and firing vessel not accelerating
                MissileLauncher ml = missile.GetComponent <MissileLauncher>();
                float           maxMissileAccel = ml.thrust / missile.part.mass;
                float           blastRadius     = Mathf.Min(missile.GetBlastRadius(), 150f);                                                                  // Allow missiles with absurd blast ranges to still be launched if desired
                missileActiveTime = Mathf.Min((missile.vessel.LandedOrSplashed ? 0f : missile.dropTime) + Mathf.Sqrt(2 * blastRadius / maxMissileAccel), 2f); // Clamp at 2s for now

                // Rough range estimate of max missile G in a turn after launch, the following code is quite janky but works decently well in practice
                float maxEstimatedGForce = Mathf.Max(bodyGravity * ml.maxTorque, 15f); // Rough estimate of max G based on missile torque, use minimum of 15G to prevent some VLS parts from not working
                if (ml.aero)                                                           // If missile has aerodynamics, modify G force by AoA limit
                {
                    maxEstimatedGForce *= Mathf.Sin(ml.maxAoA * Mathf.Deg2Rad);
                }

                // Rough estimate of turning radius and arc length to travel
                float arcLength = 0;
                if ((!missile.vessel.LandedOrSplashed) && (missile.GetWeaponClass() != WeaponClasses.SLW)) // If the missile isn't a torpedo
                {
                    float   futureTime        = Mathf.Clamp((missile.vessel.LandedOrSplashed ? 0f : missile.dropTime), 0f, 2f);
                    Vector3 futureRelPosition = (targetPosition + targetVelocity * futureTime) - (missile.part.transform.position + launcherVelocity * futureTime);
                    float   missileTurnRadius = (ml.optimumAirspeed * ml.optimumAirspeed) / maxEstimatedGForce;
                    float   targetAngle       = Vector3.Angle(missile.GetForwardTransform(), futureRelPosition);
                    arcLength = Mathf.Deg2Rad * targetAngle * missileTurnRadius;
                }

                // Add additional range term for the missile to manuever to target at missileActiveTime
                rangeAddMin += arcLength;
            }

            float missileMaxRangeTime = 8f; // Placeholder value since this doesn't really matter much in BDA combat

            // Add to ranges
            rangeAddMin += relSpeed * missileActiveTime;
            rangeAddMax += relSpeed * missileMaxRangeTime;

            // Add altitude term to max
            double diffAlt = missile.vessel.altitude - FlightGlobals.getAltitudeAtPos(targetPosition);

            rangeAddMax += (float)diffAlt;

            float min = Mathf.Clamp(minLaunchRange + rangeAddMin, 0, BDArmorySettings.MAX_ENGAGEMENT_RANGE);
            float max = Mathf.Clamp(maxLaunchRange + rangeAddMax, min + 100, BDArmorySettings.MAX_ENGAGEMENT_RANGE);

            return(new MissileLaunchParams(min, max));
        }
Пример #15
0
 private double CalculateFutureHorizontalSpeed(MissileBase missile, int predictionTime = 10)
 {
     return(missile.vessel.horizontalSrfSpeed + (missile.HorizontalAcceleration / Time.fixedDeltaTime) * predictionTime);
 }
Пример #16
0
        void Awake()
        {
            if (!vessel)
            {
                vessel = GetComponent <Vessel>();
            }

            if (!vessel)
            {
                //Debug.Log ("[BDArmory]: TargetInfo was added to a non-vessel");
                Destroy(this);
                return;
            }

            //destroy this if a target info is already attached to the vessel
            IEnumerator otherInfo = vessel.gameObject.GetComponents <TargetInfo>().GetEnumerator();

            while (otherInfo.MoveNext())
            {
                if ((object)otherInfo.Current != this)
                {
                    Destroy(this);
                    return;
                }
            }

            Team = null;
            bool foundMf = false;

            List <MissileFire> .Enumerator mf = vessel.FindPartModulesImplementing <MissileFire>().GetEnumerator();
            while (mf.MoveNext())
            {
                foundMf       = true;
                Team          = mf.Current.Team;
                weaponManager = mf.Current;
                break;
            }
            mf.Dispose();

            if (!foundMf)
            {
                List <MissileBase> .Enumerator ml = vessel.FindPartModulesImplementing <MissileBase>().GetEnumerator();
                while (ml.MoveNext())
                {
                    isMissile         = true;
                    MissileBaseModule = ml.Current;
                    Team = ml.Current.Team;
                    break;
                }
                ml.Dispose();
            }

            vessel.OnJustAboutToBeDestroyed += AboutToBeDestroyed;

            //add delegate to peace enable event
            BDArmorySetup.OnPeaceEnabled += OnPeaceEnabled;

            //lifeRoutine = StartCoroutine(LifetimeRoutine());              // TODO: CHECK BEHAVIOUR AND SIDE EFFECTS!

            if (!isMissile && Team != null)
            {
                GameEvents.onVesselPartCountChanged.Add(VesselModified);
                //massRoutine = StartCoroutine(MassRoutine());              // TODO: CHECK BEHAVIOUR AND SIDE EFFECTS!
            }
        }
Пример #17
0
 private double CalculateFutureVerticalSpeed(MissileBase missile, int predictionTime = 10)
 {
     return(missile.vessel.verticalSpeed + (missile.VerticalAcceleration / Time.fixedDeltaTime) * predictionTime);
 }
Пример #18
0
        public Vector3 GetDirection(MissileBase missile, Vector3 targetPosition)
        {
            //set up
            if (_originalDistance == float.MinValue)
            {
                _startPoint       = missile.vessel.CoM;
                _originalDistance = Vector3.Distance(targetPosition, missile.vessel.CoM);
            }

            var surfaceDistanceVector = Vector3
                                        .Project((missile.vessel.CoM - _startPoint), (targetPosition - _startPoint).normalized);

            var pendingDistance = _originalDistance - surfaceDistanceVector.magnitude;

            if (missile.TimeIndex < 1)
            {
                return(missile.vessel.CoM + missile.vessel.Velocity() * 10);
            }

            Vector3 agmTarget;

            if (missile.vessel.verticalSpeed > 0 && pendingDistance > _originalDistance * 0.5)
            {
                missile.debugString.Append($"Ascending");
                missile.debugString.Append(Environment.NewLine);

                var freeFallTime = CalculateFreeFallTime(missile);
                missile.debugString.Append($"freeFallTime: {freeFallTime}");
                missile.debugString.Append(Environment.NewLine);

                var futureDistanceVector = Vector3
                                           .Project((missile.vessel.GetFuturePosition() - _startPoint), (targetPosition - _startPoint).normalized);

                var futureHorizontalSpeed = CalculateFutureHorizontalSpeed(missile);

                var horizontalTime = (_originalDistance - futureDistanceVector.magnitude) / futureHorizontalSpeed;


                missile.debugString.Append($"horizontalTime: {horizontalTime}");
                missile.debugString.Append(Environment.NewLine);

                if (freeFallTime >= horizontalTime)
                {
                    missile.debugString.Append($"Free fall achieved:");
                    missile.debugString.Append(Environment.NewLine);

                    missile.Throttle = Mathf.Clamp(missile.Throttle - 0.001f, 0.01f, 1f);
                }
                else
                {
                    missile.debugString.Append($"Free fall not achieved:");
                    missile.debugString.Append(Environment.NewLine);

                    missile.Throttle = Mathf.Clamp(missile.Throttle + 0.001f, 0.01f, 1f);
                }

                Vector3 dToTarget = targetPosition - missile.vessel.CoM;
                Vector3 direction = Quaternion.AngleAxis(Mathf.Clamp(missile.maxOffBoresight * 0.9f, 0, missile.BallisticAngle), Vector3.Cross(dToTarget, VectorUtils.GetUpDirection(missile.vessel.CoM))) * dToTarget;
                agmTarget = missile.vessel.CoM + direction;


                missile.debugString.Append($"Throttle: {missile.Throttle}");
                missile.debugString.Append(Environment.NewLine);
            }
            else
            {
                missile.debugString.Append($"Descending");
                missile.debugString.Append(Environment.NewLine);
                agmTarget = MissileGuidance.GetAirToGroundTarget(targetPosition, missile.vessel, 1.85f);

                missile.Throttle = Mathf.Clamp((float)(missile.vessel.atmDensity * 10f), 0.01f, 1f);
            }

            if (missile is BDModularGuidance)
            {
                if (missile.vessel.InVacuum())
                {
                    missile.vessel.Autopilot.SetMode(VesselAutopilot.AutopilotMode.Prograde);
                    agmTarget = missile.vessel.CoM + missile.vessel.Velocity() * 100;
                }
                else
                {
                    missile.vessel.Autopilot.SetMode(VesselAutopilot.AutopilotMode.StabilityAssist);
                }
            }
            return(agmTarget);
        }