void BoresightScan() { if (locked) { boresightScan = false; return; } currentAngle = Mathf.Lerp(currentAngle, 0, 0.08f); RadarUtils.UpdateRadarLock(new Ray(transform.position, transform.up), boresightFOV, minLockedSignalThreshold, ref attemptedLocks, Time.fixedDeltaTime, true, rwrType, true); for (int i = 0; i < attemptedLocks.Length; i++) { if (attemptedLocks[i].exists && attemptedLocks[i].age < 0.1f) { TryLockTarget(attemptedLocks[i].predictedPosition); /* * locked = true; * //lockedTarget = attemptedLocks[i]; * lockedTargets = new List<TargetSignatureData>(); * lockedTargets.Add(attemptedLocks[i]); * lockedTargetIndex = 0; * Debug.Log ("- Acquired lock on target."); */ boresightScan = false; return; } } }
void ReceiveLaunchWarning(Vector3 source, Vector3 direction) { if (referenceTransform == null) { return; } if (part == null) { return; } if (weaponManager == null) { return; } float sqrDist = (part.transform.position - source).sqrMagnitude; if (sqrDist < Mathf.Pow(5000, 2) && sqrDist > Mathf.Pow(100, 2) && Vector3.Angle(direction, part.transform.position - source) < 15) { StartCoroutine( LaunchWarningRoutine(new TargetSignatureData(Vector3.zero, RadarUtils.WorldToRadar(source, referenceTransform, displayRect, rwrDisplayRange), Vector3.zero, true, (float)RWRThreatTypes.MissileLaunch))); PlayWarningSound(RWRThreatTypes.MissileLaunch); if (weaponManager && weaponManager.guardMode) { weaponManager.FireAllCountermeasures(UnityEngine.Random.Range(2, 4)); weaponManager.incomingThreatPosition = source; } } }
public bool TryLockTarget(Vector3 position) { if (!canLock) { return(false); } Debug.Log("[BDArmory]: Trying to radar lock target"); if (currentLocks == maxLocks) { Debug.Log("[BDArmory]: This radar (" + radarName + ") already has the maximum allowed targets locked."); return(false); } Vector3 targetPlanarDirection = Vector3.ProjectOnPlane(position - referenceTransform.position, referenceTransform.up); float angle = Vector3.Angle(targetPlanarDirection, referenceTransform.forward); if (referenceTransform.InverseTransformPoint(position).x < 0) { angle = -angle; } //TargetSignatureData.ResetTSDArray(ref attemptedLocks); RadarUtils.UpdateRadarLock(weaponManager, angle, referenceTransform, lockAttemptFOV, referenceTransform.position, minLockedSignalThreshold, ref attemptedLocks, signalPersistTime, true, rwrType, true); for (int i = 0; i < attemptedLocks.Length; i++) { if (attemptedLocks[i].exists && (attemptedLocks[i].predictedPosition - position).sqrMagnitude < 40 * 40) { if (!locked && !omnidirectional) { float targetAngle = VectorUtils.SignedAngle(referenceTransform.forward, Vector3.ProjectOnPlane(attemptedLocks[i].position - referenceTransform.position, referenceTransform.up), referenceTransform.right); currentAngle = targetAngle; } lockedTargets.Add(attemptedLocks[i]); currLocks = lockedTargets.Count; Debug.Log("[BDArmory]: - Acquired lock on target."); vesselRadarData.AddRadarContact(this, lockedTarget, true); vesselRadarData.UpdateLockedTargets(); return(true); } } Debug.Log("[BDArmory]: - Failed to lock on target."); return(false); }
void Scan() { float angleDelta = scanRotationSpeed * Time.fixedDeltaTime; //RadarUtils.ScanInDirection(weaponManager, currentAngle, referenceTransform, angleDelta, vessel.transform.position, minSignalThreshold, ref contacts, signalPersistTime, true, rwrType, true); RadarUtils.UpdateRadarLock(weaponManager, currentAngle, referenceTransform, angleDelta, vessel.transform.position, minSignalThreshold, this, true, rwrType, true); if (omnidirectional) { currentAngle = Mathf.Repeat(currentAngle + angleDelta, 360); } else { currentAngle += radialScanDirection * angleDelta; if (locked) { float targetAngle = VectorUtils.SignedAngle(referenceTransform.forward, Vector3.ProjectOnPlane(lockedTarget.position - referenceTransform.position, referenceTransform.up), referenceTransform.right); leftLimit = Mathf.Clamp(targetAngle - (multiLockFOV / 2), -directionalFieldOfView / 2, directionalFieldOfView / 2); rightLimit = Mathf.Clamp(targetAngle + (multiLockFOV / 2), -directionalFieldOfView / 2, directionalFieldOfView / 2); if (radialScanDirection < 0 && currentAngle < leftLimit) { currentAngle = leftLimit; radialScanDirection = 1; } else if (radialScanDirection > 0 && currentAngle > rightLimit) { currentAngle = rightLimit; radialScanDirection = -1; } } else { if (Mathf.Abs(currentAngle) > directionalFieldOfView / 2) { currentAngle = Mathf.Sign(currentAngle) * directionalFieldOfView / 2; radialScanDirection = -radialScanDirection; } } } }
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); } } }
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); }