public static TargetSignatureData GetHeatTarget(Ray ray, float scanRadius, float highpassThreshold, bool allAspect, MissileFire mf = null, bool favorGroundTargets = false) { float minMass = 0.05f; //otherwise the RAMs have trouble shooting down incoming missiles TargetSignatureData finalData = TargetSignatureData.noTarget; float finalScore = 0; foreach (Vessel vessel in LoadedVessels) { if (!vessel || !vessel.loaded) { continue; } if (favorGroundTargets && !vessel.LandedOrSplashed) // for AGM heat guidance { continue; } TargetInfo tInfo = vessel.gameObject.GetComponent <TargetInfo>(); if (mf == null || !tInfo || !(mf && tInfo.isMissile && tInfo.team != BoolToTeam(mf.team) && (tInfo.MissileBaseModule.MissileState == MissileBase.MissileStates.Boost || tInfo.MissileBaseModule.MissileState == MissileBase.MissileStates.Cruise))) { if (vessel.GetTotalMass() < minMass) { continue; } } float angle = Vector3.Angle(vessel.CoM - ray.origin, ray.direction); if (angle < scanRadius) { if (RadarUtils.TerrainCheck(ray.origin, vessel.transform.position)) { continue; } if (!allAspect) { if (!Misc.Misc.CheckSightLineExactDistance(ray.origin, vessel.CoM + vessel.Velocity(), Vector3.Distance(vessel.CoM, ray.origin), 5, 5)) { continue; } } float score = GetVesselHeatSignature(vessel) * Mathf.Clamp01(15 / angle); score *= Mathf.Pow(1400, 2) / Mathf.Clamp((vessel.CoM - ray.origin).sqrMagnitude, 90000, 36000000); if (vessel.LandedOrSplashed && !favorGroundTargets) { score /= 4; } score *= Mathf.Clamp(Vector3.Angle(vessel.transform.position - ray.origin, -VectorUtils.GetUpDirection(ray.origin)) / 90, 0.5f, 1.5f); if (score > finalScore) { finalScore = score; finalData = new TargetSignatureData(vessel, score); } } } // see if there are flares decoying us: TargetSignatureData flareData = GetFlareTarget(ray, scanRadius, highpassThreshold, allAspect, finalScore); if (finalScore < highpassThreshold) { finalData = TargetSignatureData.noTarget; } // return matching flare if (!flareData.Equals(TargetSignatureData.noTarget)) { return(flareData); } //else return the target: return(finalData); }