IEnumerator LaunchWarningRoutine(TargetSignatureData data) { launchWarnings.Add(data); yield return(new WaitForSeconds(2)); launchWarnings.Remove(data); }
public void SetActiveLock(TargetSignatureData target) { for (int i = 0; i < lockedTargets.Count; i++) { if (target.vessel == lockedTargets[i].vessel) { lockedTargetIndex = i; return; } } }
public override void OnStart(StartState state) { if (HighLogic.LoadedSceneIsFlight) { pingsData = new TargetSignatureData[dataCount]; pingWorldPositions = new Vector3[dataCount]; TargetSignatureData.ResetTSDArray(ref pingsData); launchWarnings = new List <TargetSignatureData>(); rwrIconLabelStyle = new GUIStyle(); rwrIconLabelStyle.alignment = TextAnchor.MiddleCenter; rwrIconLabelStyle.normal.textColor = Color.green; rwrIconLabelStyle.fontSize = 12; rwrIconLabelStyle.border = new RectOffset(0, 0, 0, 0); rwrIconLabelStyle.clipping = TextClipping.Overflow; rwrIconLabelStyle.wordWrap = false; rwrIconLabelStyle.fontStyle = FontStyle.Bold; audioSource = gameObject.AddComponent <AudioSource>(); audioSource.minDistance = 500; audioSource.maxDistance = 1000; audioSource.spatialBlend = 1; audioSource.dopplerLevel = 0; audioSource.loop = false; UpdateVolume(); BDArmorySettings.OnVolumeChange += UpdateVolume; float size = displayRect.height + 20; if (!windowRectInitialized) { windowRect = new Rect(40, Screen.height - size - 20, size, size + 20); windowRectInitialized = true; } foreach (var mf in vessel.FindPartModulesImplementing <MissileFire>()) { mf.rwr = this; if (!weaponManager) { weaponManager = mf; } } if (rwrEnabled) { EnableRWR(); } } }
public void ReceiveContactData(TargetSignatureData contactData, bool _locked) { if (vesselRadarData) { vesselRadarData.AddRadarContact(this, contactData, _locked); } foreach (var vrd in linkedToVessels) { if (vrd && vrd.canReceiveRadarData && vrd.vessel != contactData.vessel) { vrd.AddRadarContact(this, contactData, _locked); } } }
public void UpdateLockedTargetInfo(TargetSignatureData newData) { int index = -1; for (int i = 0; i < lockedTargets.Count; i++) { if (lockedTargets[i].vessel == newData.vessel) { index = i; break; } } if (index >= 0) { lockedTargets[index] = newData; } }
void ReceivePing(Vessel v, Vector3 source, RWRThreatTypes type, float persistTime) { if (rwrEnabled && vessel && v == vessel) { if (type == RWRThreatTypes.MissileLaunch) { StartCoroutine(LaunchWarningRoutine(new TargetSignatureData(Vector3.zero, RadarUtils.WorldToRadar(source, referenceTransform, displayRect, rwrDisplayRange), Vector3.zero, true, (float)type))); PlayWarningSound(type); return; } else if (type == RWRThreatTypes.MissileLock) { if (!BDArmorySettings.ALLOW_LEGACY_TARGETING && weaponManager && weaponManager.guardMode) { weaponManager.FireChaff(); } } int openIndex = -1; for (int i = 0; i < dataCount; i++) { if (pingsData[i].exists && ((Vector2)pingsData[i].position - RadarUtils.WorldToRadar(source, referenceTransform, displayRect, rwrDisplayRange)).sqrMagnitude < Mathf.Pow(20, 2)) { break; } if (!pingsData[i].exists && openIndex == -1) { openIndex = i; } } if (openIndex >= 0) { referenceTransform.rotation = Quaternion.LookRotation(vessel.ReferenceTransform.up, VectorUtils.GetUpDirection(transform.position)); pingsData[openIndex] = new TargetSignatureData(Vector3.zero, RadarUtils.WorldToRadar(source, referenceTransform, displayRect, rwrDisplayRange), Vector3.zero, true, (float)type); pingWorldPositions[openIndex] = source; StartCoroutine(PingLifeRoutine(openIndex, persistTime)); PlayWarningSound(type); } } }
protected void UpdateHeatTarget() { if (lockFailTimer > 1) { legacyTargetVessel = null; TargetAcquired = false; return; } if (heatTarget.exists && lockFailTimer < 0) { lockFailTimer = 0; } if (lockFailTimer >= 0) { Ray lookRay = new Ray(transform.position, heatTarget.position + (heatTarget.velocity * Time.fixedDeltaTime) - transform.position); heatTarget = BDATargetManager.GetHeatTarget(lookRay, lockedSensorFOV / 2, heatThreshold, allAspect); if (heatTarget.exists) { TargetAcquired = true; TargetPosition = heatTarget.position + (2 * heatTarget.velocity * Time.fixedDeltaTime); TargetVelocity = heatTarget.velocity; TargetAcceleration = heatTarget.acceleration; lockFailTimer = 0; } else { TargetAcquired = false; if (FlightGlobals.ready) { lockFailTimer += Time.fixedDeltaTime; } } } }
public static void ScanInDirection(MissileFire myWpnManager, float directionAngle, Transform referenceTransform, float fov, Vector3 position, float minSignature, ref TargetSignatureData[] dataArray, float dataPersistTime, bool pingRWR, RadarWarningReceiver.RWRThreatTypes rwrType, bool radarSnapshot) { Vector3d geoPos = VectorUtils.WorldPositionToGeoCoords(position, FlightGlobals.currentMainBody); Vector3 forwardVector = referenceTransform.forward; Vector3 upVector = referenceTransform.up; //VectorUtils.GetUpDirection(position); Vector3 lookDirection = Quaternion.AngleAxis(directionAngle, upVector) * forwardVector; int dataIndex = 0; foreach (var vessel in BDATargetManager.LoadedVessels) { if (vessel == null) { continue; } if (!vessel.loaded) { continue; } if (myWpnManager) { if (vessel == myWpnManager.vessel) { continue; //ignore self } } else if ((vessel.transform.position - position).sqrMagnitude < 3600) { continue; } Vector3 vesselDirection = Vector3.ProjectOnPlane(vessel.CoM - position, upVector); if (Vector3.Angle(vesselDirection, lookDirection) < fov / 2) { if (TerrainCheck(referenceTransform.position, vessel.transform.position)) { continue; //blocked by terrain } float sig = float.MaxValue; if (radarSnapshot && minSignature > 0) { sig = GetModifiedSignature(vessel, position); } RadarWarningReceiver.PingRWR(vessel, position, rwrType, dataPersistTime); float detectSig = sig; VesselECMJInfo vesselJammer = vessel.GetComponent <VesselECMJInfo>(); if (vesselJammer) { sig *= vesselJammer.rcsReductionFactor; detectSig += vesselJammer.jammerStrength; } if (detectSig > minSignature) { if (vessel.vesselType == VesselType.Debris) { vessel.gameObject.AddComponent <TargetInfo>(); } else if (myWpnManager != null) { BDATargetManager.ReportVessel(vessel, myWpnManager); } while (dataIndex < dataArray.Length - 1) { if ((dataArray[dataIndex].exists && Time.time - dataArray[dataIndex].timeAcquired > dataPersistTime) || !dataArray[dataIndex].exists) { break; } dataIndex++; } if (dataIndex >= dataArray.Length) { break; } dataArray[dataIndex] = new TargetSignatureData(vessel, sig); dataIndex++; if (dataIndex >= dataArray.Length) { break; } } } } }
public static void ScanInDirection(Ray ray, float fov, float minSignature, ref TargetSignatureData[] dataArray, float dataPersistTime, bool pingRWR, RadarWarningReceiver.RWRThreatTypes rwrType, bool radarSnapshot) { int dataIndex = 0; foreach (var vessel in BDATargetManager.LoadedVessels) { if (vessel == null) { continue; } if (!vessel.loaded) { continue; } if (vessel.Landed) { continue; } Vector3 vectorToTarget = vessel.transform.position - ray.origin; if ((vectorToTarget).sqrMagnitude < 10) { continue; //ignore self } if (Vector3.Dot(vectorToTarget, ray.direction) < 0) { continue; //ignore behind ray } if (Vector3.Angle(vessel.CoM - ray.origin, ray.direction) < fov / 2) { if (TerrainCheck(ray.origin, vessel.transform.position)) { continue; //blocked by terrain } float sig = float.MaxValue; if (radarSnapshot) { sig = GetModifiedSignature(vessel, ray.origin); } if (pingRWR && sig > minSignature * 0.66f) { RadarWarningReceiver.PingRWR(vessel, ray.origin, rwrType, dataPersistTime); } if (sig > minSignature) { while (dataIndex < dataArray.Length - 1) { if ((dataArray[dataIndex].exists && Time.time - dataArray[dataIndex].timeAcquired > dataPersistTime) || !dataArray[dataIndex].exists) { break; } dataIndex++; } if (dataIndex >= dataArray.Length) { break; } dataArray[dataIndex] = new TargetSignatureData(vessel, sig); dataIndex++; if (dataIndex >= dataArray.Length) { break; } } } } }
void UpdateLock(int index) { TargetSignatureData lockedTarget = lockedTargets[index]; Vector3 targetPlanarDirection = Vector3.ProjectOnPlane(lockedTarget.predictedPosition - referenceTransform.position, referenceTransform.up); float lookAngle = Vector3.Angle(targetPlanarDirection, referenceTransform.forward); if (referenceTransform.InverseTransformPoint(lockedTarget.predictedPosition).x < 0) { lookAngle = -lookAngle; } if (omnidirectional) { if (lookAngle < 0) { lookAngle += 360; } } lockScanAngle = lookAngle + currentAngleLock; if (!canTrackWhileScan && index == lockedTargetIndex) { currentAngle = lockScanAngle; } float angleDelta = lockRotationSpeed * Time.fixedDeltaTime; float lockedSignalPersist = lockRotationAngle / lockRotationSpeed; //RadarUtils.ScanInDirection(lockScanAngle, referenceTransform, angleDelta, referenceTransform.position, minLockedSignalThreshold, ref attemptedLocks, lockedSignalPersist); bool radarSnapshot = (snapshotTicker > 30); if (radarSnapshot) { snapshotTicker = 0; } else { snapshotTicker++; } //RadarUtils.ScanInDirection (new Ray (referenceTransform.position, lockedTarget.predictedPosition - referenceTransform.position), lockRotationAngle * 2, minLockedSignalThreshold, ref attemptedLocks, lockedSignalPersist, true, rwrType, radarSnapshot); if ( Vector3.Angle(lockedTarget.position - referenceTransform.position, this.lockedTarget.position - referenceTransform.position) > multiLockFOV / 2) { UnlockTargetAt(index, true); return; } RadarUtils.UpdateRadarLock( new Ray(referenceTransform.position, lockedTarget.predictedPosition - referenceTransform.position), lockedTarget.predictedPosition, lockRotationAngle * 2, minLockedSignalThreshold, this, true, radarSnapshot, lockedSignalPersist, true, index, lockedTarget.vessel); /* * TargetSignatureData prevLock = lockedTarget; * lockedTarget = TargetSignatureData.noTarget; * for(int i = 0; i < attemptedLocks.Length; i++) * { * if(attemptedLocks[i].exists && (attemptedLocks[i].predictedPosition-prevLock.predictedPosition).sqrMagnitude < Mathf.Pow(20,2) && attemptedLocks[i].age < 2*lockedSignalPersist) * { * lockedTarget = attemptedLocks[i]; * break; * } * } * * if(!lockedTarget.exists) //if failed to maintain lock, get lock data from linked radar * { * if(linked && linkedRadar && linkedRadar.locked && (linkedRadar.lockedTarget.predictedPosition-prevLock.predictedPosition).sqrMagnitude < Mathf.Pow(20,2)) * { * lockedTarget = linkedRadar.lockedTarget; * //if(lockedTarget.exists) return; * } * } */ //if still failed or out of FOV, unlock. if (!lockedTarget.exists || (!omnidirectional && Vector3.Angle(lockedTarget.position - referenceTransform.position, transform.up) > directionalFieldOfView / 2)) { //UnlockAllTargets(); UnlockTargetAt(index, true); return; } //unlock if over-jammed if (lockedTarget.vesselJammer && lockedTarget.vesselJammer.lockBreakStrength > lockedTarget.signalStrength * lockedTarget.vesselJammer.rcsReductionFactor) { //UnlockAllTargets(); UnlockTargetAt(index, true); return; } //cycle scan direction if (index == lockedTargetIndex) { currentAngleLock += lockScanDirection * angleDelta; if (Mathf.Abs(currentAngleLock) > lockRotationAngle / 2) { currentAngleLock = Mathf.Sign(currentAngleLock) * lockRotationAngle / 2; lockScanDirection = -lockScanDirection; } } }
public override void OnStart(StartState state) { base.OnStart(state); if (HighLogic.LoadedSceneIsFlight) { myVesselID = vessel.id.ToString(); RadarUtils.SetupRadarCamera(); if (string.IsNullOrEmpty(radarName)) { radarName = part.partInfo.title; } linkedToVessels = new List <VesselRadarData>(); //rIncrements = Misc.ParseToFloatArray(rangeIncrements); //rangeIndex = Mathf.Clamp(rangeIndex, 0, rIncrements.Length-1); //maxRange = rIncrements[rIncrements.Length-1]; signalPersistTime = omnidirectional ? 360 / (scanRotationSpeed + 5) : directionalFieldOfView / (scanRotationSpeed + 5); if (rotationTransformName != string.Empty) { rotationTransform = part.FindModelTransform(rotationTransformName); } //lockedTarget = TargetSignatureData.noTarget; attemptedLocks = new TargetSignatureData[3]; TargetSignatureData.ResetTSDArray(ref attemptedLocks); lockedTargets = new List <TargetSignatureData>(); referenceTransform = (new GameObject()).transform; referenceTransform.parent = transform; referenceTransform.localPosition = Vector3.zero; foreach (var tur in part.FindModulesImplementing <ModuleTurret>()) { if (tur.turretID == turretID) { lockingTurret = tur; break; } } rwrType = (RadarWarningReceiver.RWRThreatTypes)rwrThreatType; foreach (var wm in vessel.FindPartModulesImplementing <MissileFire>()) { wm.radars.Add(this); } GameEvents.onVesselGoOnRails.Add(OnGoOnRails); EnsureVesselRadarData(); StartCoroutine(StartUpRoutine()); } if (HighLogic.LoadedSceneIsEditor) { foreach (var tur in part.FindModulesImplementing <ModuleTurret>()) { if (tur.turretID == turretID) { lockingTurret = tur; break; } } if (lockingTurret) { lockingTurret.Fields["minPitch"].guiActiveEditor = false; lockingTurret.Fields["maxPitch"].guiActiveEditor = false; lockingTurret.Fields["yawRange"].guiActiveEditor = false; } } }
public static TargetSignatureData GetHeatTarget(Ray ray, float scanRadius, float highpassThreshold, bool allAspect, MissileFire mf = null) { float minScore = highpassThreshold; float minMass = 0.5f; TargetSignatureData finalData = TargetSignatureData.noTarget; float finalScore = 0; foreach (var vessel in BDATargetManager.LoadedVessels) { if (!vessel || !vessel.loaded) { continue; } TargetInfo tInfo = vessel.gameObject.GetComponent <TargetInfo>(); if (mf == null || !tInfo || !(mf && tInfo.isMissile && tInfo.team != BDATargetManager.BoolToTeam(mf.team) && (tInfo.missileModule.MissileState == MissileLauncher.MissileStates.Boost || tInfo.missileModule.MissileState == MissileLauncher.MissileStates.Cruise))) { if (vessel.GetTotalMass() < minMass) { continue; } } if (RadarUtils.TerrainCheck(ray.origin, vessel.transform.position)) { continue; } float angle = Vector3.Angle(vessel.CoM - ray.origin, ray.direction); if (angle < scanRadius) { float score = 0; foreach (var part in vessel.Parts) { if (!part) { continue; } if (!allAspect) { if (!Misc.CheckSightLineExactDistance(ray.origin, part.transform.position + vessel.rb_velocity, Vector3.Distance(part.transform.position, ray.origin), 5, 5)) { continue; } } float thisScore = (float)(part.thermalInternalFluxPrevious + part.skinTemperature) * (15 / Mathf.Max(15, angle)); thisScore *= Mathf.Pow(1400, 2) / Mathf.Clamp((vessel.CoM - ray.origin).sqrMagnitude, 90000, 36000000); score = Mathf.Max(score, thisScore); } if (vessel.LandedOrSplashed) { 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); } } } heatScore = finalScore; //DEBUG flareScore = 0; //DEBUG foreach (var flare in BDArmorySettings.Flares) { if (!flare) { continue; } float angle = Vector3.Angle(flare.transform.position - ray.origin, ray.direction); if (angle < scanRadius) { float score = flare.thermal * Mathf.Clamp01(15 / angle); score *= Mathf.Pow(1400, 2) / Mathf.Clamp((flare.transform.position - ray.origin).sqrMagnitude, 90000, 36000000); score *= Mathf.Clamp(Vector3.Angle(flare.transform.position - ray.origin, -VectorUtils.GetUpDirection(ray.origin)) / 90, 0.5f, 1.5f); if (score > finalScore) { flareScore = score; //DEBUG finalScore = score; finalData = new TargetSignatureData(flare, score); } } } if (finalScore < minScore) { finalData = TargetSignatureData.noTarget; } return(finalData); }
protected void UpdateRadarTarget() { TargetAcquired = false; float angleToTarget = Vector3.Angle(radarTarget.predictedPosition - transform.position, GetForwardTransform()); if (radarTarget.exists) { if (!ActiveRadar && ((radarTarget.predictedPosition - transform.position).sqrMagnitude > Mathf.Pow(activeRadarRange, 2) || angleToTarget > maxOffBoresight * 0.75f)) { if (vrd) { TargetSignatureData t = TargetSignatureData.noTarget; List <TargetSignatureData> possibleTargets = vrd.GetLockedTargets(); for (int i = 0; i < possibleTargets.Count; i++) { if (possibleTargets[i].vessel == radarTarget.vessel) { t = possibleTargets[i]; } } if (t.exists) { TargetAcquired = true; radarTarget = t; TargetPosition = radarTarget.predictedPosition; TargetVelocity = radarTarget.velocity; TargetAcceleration = radarTarget.acceleration; _radarFailTimer = 0; return; } else { if (_radarFailTimer > maxRadarFailTime) { Debug.Log("[BDArmory]: Semi-Active Radar guidance failed. Parent radar lost target."); radarTarget = TargetSignatureData.noTarget; legacyTargetVessel = null; return; } else { if (_radarFailTimer == 0) { Debug.Log("[BDArmory]: Semi-Active Radar guidance failed - waiting for data"); } _radarFailTimer += Time.fixedDeltaTime; radarTarget.timeAcquired = Time.time; radarTarget.position = radarTarget.predictedPosition; TargetPosition = radarTarget.predictedPosition; TargetVelocity = radarTarget.velocity; TargetAcceleration = Vector3.zero; TargetAcquired = true; } } } else { Debug.Log("[BDArmory]: Semi-Active Radar guidance failed. Out of range and no data feed."); radarTarget = TargetSignatureData.noTarget; legacyTargetVessel = null; return; } } else { vrd = null; if (angleToTarget > maxOffBoresight) { Debug.Log("[BDArmory]: Radar guidance failed. Target is out of active seeker gimbal limits."); radarTarget = TargetSignatureData.noTarget; legacyTargetVessel = null; return; } else { if (scannedTargets == null) { scannedTargets = new TargetSignatureData[5]; } TargetSignatureData.ResetTSDArray(ref scannedTargets); Ray ray = new Ray(transform.position, radarTarget.predictedPosition - transform.position); bool pingRWR = Time.time - lastRWRPing > 0.4f; if (pingRWR) { lastRWRPing = Time.time; } bool radarSnapshot = (snapshotTicker > 20); if (radarSnapshot) { snapshotTicker = 0; } else { snapshotTicker++; } RadarUtils.UpdateRadarLock(ray, lockedSensorFOV, activeRadarMinThresh, ref scannedTargets, 0.4f, pingRWR, RadarWarningReceiver.RWRThreatTypes.MissileLock, radarSnapshot); float sqrThresh = radarLOALSearching ? Mathf.Pow(500, 2) : Mathf.Pow(40, 2); if (radarLOAL && radarLOALSearching && !radarSnapshot) { //only scan on snapshot interval } else { for (int i = 0; i < scannedTargets.Length; i++) { if (scannedTargets[i].exists && (scannedTargets[i].predictedPosition - radarTarget.predictedPosition).sqrMagnitude < sqrThresh) { radarTarget = scannedTargets[i]; TargetAcquired = true; radarLOALSearching = false; TargetPosition = radarTarget.predictedPosition + (radarTarget.velocity * Time.fixedDeltaTime); TargetVelocity = radarTarget.velocity; TargetAcceleration = radarTarget.acceleration; _radarFailTimer = 0; if (!ActiveRadar && Time.time - TimeFired > 1) { if (locksCount == 0) { RadarWarningReceiver.PingRWR(ray, lockedSensorFOV, RadarWarningReceiver.RWRThreatTypes.MissileLaunch, 2f); Debug.Log("[BDArmory]: Pitbull! Radar missileBase has gone active. Radar sig strength: " + radarTarget.signalStrength.ToString("0.0")); } else if (locksCount > 2) { guidanceActive = false; checkMiss = true; if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory]: Radar missileBase reached max re-lock attempts."); } } locksCount++; } ActiveRadar = true; return; } } } if (radarLOAL) { radarLOALSearching = true; TargetAcquired = true; TargetPosition = radarTarget.predictedPosition + (radarTarget.velocity * Time.fixedDeltaTime); TargetVelocity = radarTarget.velocity; TargetAcceleration = Vector3.zero; ActiveRadar = false; } else { radarTarget = TargetSignatureData.noTarget; } } } } else if (radarLOAL && radarLOALSearching) { if (scannedTargets == null) { scannedTargets = new TargetSignatureData[5]; } TargetSignatureData.ResetTSDArray(ref scannedTargets); Ray ray = new Ray(transform.position, GetForwardTransform()); bool pingRWR = Time.time - lastRWRPing > 0.4f; if (pingRWR) { lastRWRPing = Time.time; } bool radarSnapshot = (snapshotTicker > 6); if (radarSnapshot) { snapshotTicker = 0; } else { snapshotTicker++; } RadarUtils.UpdateRadarLock(ray, lockedSensorFOV * 3, activeRadarMinThresh * 2, ref scannedTargets, 0.4f, pingRWR, RadarWarningReceiver.RWRThreatTypes.MissileLock, radarSnapshot); float sqrThresh = Mathf.Pow(300, 2); float smallestAngle = 360; TargetSignatureData lockedTarget = TargetSignatureData.noTarget; for (int i = 0; i < scannedTargets.Length; i++) { if (scannedTargets[i].exists && (scannedTargets[i].predictedPosition - radarTarget.predictedPosition).sqrMagnitude < sqrThresh) { float angle = Vector3.Angle(scannedTargets[i].predictedPosition - transform.position, GetForwardTransform()); if (angle < smallestAngle) { lockedTarget = scannedTargets[i]; smallestAngle = angle; } ActiveRadar = true; return; } } if (lockedTarget.exists) { radarTarget = lockedTarget; TargetAcquired = true; radarLOALSearching = false; TargetPosition = radarTarget.predictedPosition + (radarTarget.velocity * Time.fixedDeltaTime); TargetVelocity = radarTarget.velocity; TargetAcceleration = radarTarget.acceleration; if (!ActiveRadar && Time.time - TimeFired > 1) { RadarWarningReceiver.PingRWR(new Ray(transform.position, radarTarget.predictedPosition - transform.position), lockedSensorFOV, RadarWarningReceiver.RWRThreatTypes.MissileLaunch, 2f); Debug.Log("[BDArmory]: Pitbull! Radar missileBase has gone active. Radar sig strength: " + radarTarget.signalStrength.ToString("0.0")); } return; } else { TargetAcquired = true; TargetPosition = transform.position + (startDirection * 500); TargetVelocity = Vector3.zero; TargetAcceleration = Vector3.zero; radarLOALSearching = true; return; } } if (!radarTarget.exists) { legacyTargetVessel = null; } }
public static TargetSignatureData GetHeatTarget(Ray ray, float scanRadius, float highpassThreshold, bool allAspect) { float minScore = highpassThreshold; float minMass = 0.5f; TargetSignatureData finalData = TargetSignatureData.noTarget; float finalScore = 0; foreach (var vessel in BDATargetManager.LoadedVessels) { if (!vessel || !vessel.loaded) { continue; } if (vessel.GetTotalMass() < minMass) { continue; } if (RadarUtils.TerrainCheck(ray.origin, vessel.transform.position)) { continue; } float angle = Vector3.Angle(vessel.CoM - ray.origin, ray.direction); if (angle < scanRadius) { float score = 0; foreach (var part in vessel.Parts) { if (!part) { continue; } if (!allAspect) { if (!Misc.CheckSightLine(ray.origin, part.transform.position, 10000, 5, 5)) { continue; } } float thisScore = (float)(part.thermalInternalFluxPrevious + part.skinTemperature) * Mathf.Clamp01(15 / angle); thisScore *= Mathf.Pow(1400, 2) / Mathf.Clamp((vessel.CoM - ray.origin).sqrMagnitude, 90000, 36000000); score = Mathf.Max(score, thisScore); } if (vessel.LandedOrSplashed) { 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); } } } heatScore = finalScore; //DEBUG flareScore = 0; //DEBUG foreach (var flare in BDArmorySettings.Flares) { if (!flare) { continue; } float angle = Vector3.Angle(flare.transform.position - ray.origin, ray.direction); if (angle < scanRadius) { float score = flare.thermal * Mathf.Clamp01(15 / angle); score *= Mathf.Pow(1400, 2) / Mathf.Clamp((flare.transform.position - ray.origin).sqrMagnitude, 90000, 36000000); score *= Mathf.Clamp(Vector3.Angle(flare.transform.position - ray.origin, -VectorUtils.GetUpDirection(ray.origin)) / 90, 0.5f, 1.5f); if (score > finalScore) { flareScore = score; //DEBUG finalScore = score; finalData = new TargetSignatureData(flare, score); } } } if (finalScore < minScore) { finalData = TargetSignatureData.noTarget; } return(finalData); }