public void AimToTarget(Vector3 targetPosition, bool pitch = true, bool yaw = true) { if (!yawTransform) { return; } float deltaTime = Time.fixedDeltaTime; Vector3 localTargetYaw = yawTransform.parent.InverseTransformPoint(targetPosition - (yawTargetOffset * pitchTransform.right)); Vector3 targetYaw = Vector3.ProjectOnPlane(localTargetYaw, Vector3.up); float targetYawAngle = VectorUtils.SignedAngle(Vector3.forward, targetYaw, Vector3.right); targetYawAngle = Mathf.Clamp(targetYawAngle, -yawRange / 2, yawRange / 2); Quaternion currYawRot = yawTransform.localRotation; yawTransform.localRotation = Quaternion.Euler(0, targetYawAngle, 0); Vector3 localTargetPitch = pitchTransform.parent.InverseTransformPoint(targetPosition - (pitchTargetOffset * pitchTransform.up)); yawTransform.localRotation = currYawRot; localTargetPitch.z = Mathf.Abs(localTargetPitch.z); //prevents from aiming wonky if target is behind Vector3 targetPitch = Vector3.ProjectOnPlane(localTargetPitch, Vector3.right); float targetPitchAngle = VectorUtils.SignedAngle(Vector3.forward, targetPitch, Vector3.up); targetPitchAngle = Mathf.Clamp(targetPitchAngle, minPitch, maxPitch); float yawOffset = Vector3.Angle(yawTransform.parent.InverseTransformDirection(yawTransform.forward), targetYaw); float currentYawSign = Mathf.Sign(Vector3.Dot(yawTransform.localRotation * Vector3.forward, Vector3.right)); float pitchOffset = Vector3.Angle(pitchTransform.parent.InverseTransformDirection(pitchTransform.forward), targetPitch); float linPitchMult = yawOffset > 0 ? Mathf.Clamp01((pitchOffset / yawOffset) * (yawSpeedDPS / pitchSpeedDPS)) : 1; float linYawMult = pitchOffset > 0 ? Mathf.Clamp01((yawOffset / pitchOffset) * (pitchSpeedDPS / yawSpeedDPS)) : 1; float yawSpeed; float pitchSpeed; if (smoothRotation) { yawSpeed = Mathf.Clamp(yawOffset * smoothMultiplier, 1f, yawSpeedDPS) * deltaTime; pitchSpeed = Mathf.Clamp(pitchOffset * smoothMultiplier, 1f, pitchSpeedDPS) * deltaTime; } else { yawSpeed = yawSpeedDPS * deltaTime; pitchSpeed = pitchSpeedDPS * deltaTime; } yawSpeed *= linYawMult; pitchSpeed *= linPitchMult; if (yawRange < 360 && Mathf.Abs(targetYawAngle) > 90 && currentYawSign != Mathf.Sign(targetYawAngle)) { targetYawAngle = 5 * Mathf.Sign(targetYawAngle); } if (yaw) { yawTransform.localRotation = Quaternion.RotateTowards(yawTransform.localRotation, Quaternion.Euler(0, targetYawAngle, 0), yawSpeed); } if (pitch) { pitchTransform.localRotation = Quaternion.RotateTowards(pitchTransform.localRotation, Quaternion.Euler(-targetPitchAngle, 0, 0), pitchSpeed); } }
void FlyToPosition(FlightCtrlState s, Vector3 targetPosition) { if (!startedLanded) { targetPosition = FlightPosition(targetPosition, minAltitude); } Vector3d srfVel = vessel.srf_velocity; if (srfVel != Vector3d.zero) { velocityTransform.rotation = Quaternion.LookRotation(srfVel, -vesselTransform.forward); } velocityTransform.rotation = Quaternion.AngleAxis(90, velocityTransform.right) * velocityTransform.rotation; Vector3 localAngVel = vessel.angularVelocity; if (steerMode == SteerModes.NormalFlight) { float angleToTarget = Vector3.Angle(targetPosition - vesselTransform.position, vesselTransform.up); Vector3 dampedDirection = Vector3.RotateTowards(vesselTransform.up, targetPosition - vesselTransform.position, (angleToTarget / 2) * Mathf.Deg2Rad, 0).normalized; targetPosition = vesselTransform.position + (500 * dampedDirection); } if (BDArmorySettings.DRAW_DEBUG_LINES) { flyingToPosition = targetPosition; } Vector3 targetDirection; Vector3 targetDirectionYaw; float yawError; float pitchError; float postYawFactor; float postPitchFactor; if (steerMode == SteerModes.NormalFlight) { targetDirection = velocityTransform.InverseTransformDirection(targetPosition - velocityTransform.position).normalized; targetDirection = Vector3.RotateTowards(Vector3.up, targetDirection, 45 * Mathf.Deg2Rad, 0); targetDirectionYaw = vesselTransform.InverseTransformDirection(vessel.srf_velocity).normalized; targetDirectionYaw = Vector3.RotateTowards(Vector3.up, targetDirectionYaw, 45 * Mathf.Deg2Rad, 0); postYawFactor = 1; postPitchFactor = 1; } else //(steerMode == SteerModes.Aiming) { targetDirection = vesselTransform.InverseTransformDirection(targetPosition - vesselTransform.position).normalized; targetDirection = Vector3.RotateTowards(Vector3.up, targetDirection, 45 * Mathf.Deg2Rad, 0); targetDirectionYaw = targetDirection; if (command == PilotCommands.Follow) { postYawFactor = 1.5f; postPitchFactor = 1f; } else { postYawFactor = 1.6f; postPitchFactor = 2.4f; } } pitchError = VectorUtils.SignedAngle(Vector3.up, Vector3.ProjectOnPlane(targetDirection, Vector3.right), Vector3.back); yawError = VectorUtils.SignedAngle(Vector3.up, Vector3.ProjectOnPlane(targetDirectionYaw, Vector3.forward), Vector3.right); float finalMaxSteer = threatLevel * maxSteer; float steerPitch = (postPitchFactor * 0.015f * steerMult * pitchError) - (postPitchFactor * steerDamping * -localAngVel.x); float steerYaw = (postYawFactor * 0.022f * steerMult * yawError) - (postPitchFactor * steerDamping * -localAngVel.z); s.yaw = Mathf.Clamp(steerYaw, -finalMaxSteer, finalMaxSteer); s.pitch = Mathf.Clamp(steerPitch, Mathf.Min(-finalMaxSteer, -0.2f), finalMaxSteer); //roll Vector3 currentRoll = -vesselTransform.forward; Vector3 rollTarget; if (steerMode == SteerModes.Aiming || Vector3.Angle(vesselTransform.up, targetPosition - vesselTransform.position) > 2) { rollTarget = (targetPosition + ((steerMode == SteerModes.Aiming ? 10 : 45f) * upDirection)) - vesselTransform.position; } else { rollTarget = upDirection; } if (command == PilotCommands.Follow && useRollHint) { rollTarget = -commandLeader.vessel.ReferenceTransform.forward; } rollTarget = Vector3.ProjectOnPlane(rollTarget, vesselTransform.up); float rollError = Misc.SignedAngle(currentRoll, rollTarget, vesselTransform.right); debugString += "\nRoll offset: " + rollError; float steerRoll = (steerMult * 0.0015f * rollError); debugString += "\nSteerRoll: " + steerRoll; float rollDamping = (.10f * steerDamping * -localAngVel.y); steerRoll -= rollDamping; debugString += "\nRollDamping: " + rollDamping; float roll = Mathf.Clamp(steerRoll, -maxSteer, maxSteer); s.roll = roll; // }
IEnumerator CommandPosition(BDModulePilotAI wingman, BDModulePilotAI.PilotCommands command) { if (focusIndexes.Count == 0 && !commandSelf) { yield break; } DisplayScreenMessage("Select target coordinates.\nRight-click to cancel."); if (command == BDModulePilotAI.PilotCommands.FlyTo) { waitingForFlytoPos = true; } else if (command == BDModulePilotAI.PilotCommands.Attack) { waitingForAttackPos = true; } yield return(null); bool waitingForPos = true; drawMouseDiamond = true; while (waitingForPos) { if (Input.GetMouseButtonDown(1)) { break; } if (Input.GetMouseButtonDown(0)) { Vector3 mousePos = new Vector3(Input.mousePosition.x / Screen.width, Input.mousePosition.y / Screen.height, 0); Plane surfPlane = new Plane(vessel.upAxis, vessel.transform.position - (vessel.altitude * vessel.upAxis)); Ray ray = FlightCamera.fetch.mainCamera.ViewportPointToRay(mousePos); float dist; if (surfPlane.Raycast(ray, out dist)) { Vector3 worldPoint = ray.GetPoint(dist); Vector3d gps = VectorUtils.WorldPositionToGeoCoords(worldPoint, vessel.mainBody); if (command == BDModulePilotAI.PilotCommands.FlyTo) { wingman.CommandFlyTo(gps); } else if (command == BDModulePilotAI.PilotCommands.Attack) { wingman.CommandAttack(gps); } StartCoroutine(CommandPositionGUIRoutine(wingman, new GPSTargetInfo(gps, command.ToString()))); } break; } yield return(null); } waitingForAttackPos = false; waitingForFlytoPos = false; drawMouseDiamond = false; ScreenMessages.RemoveMessage(screenMessage); }
public static void UpdateRadarLock(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; } } } } }
void AutoPilot(FlightCtrlState s) { if (!vessel || !vessel.transform || vessel.packed || !vessel.mainBody) { return; } vesselTransform = vessel.ReferenceTransform; //default brakes off full throttle s.mainThrottle = 1; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, false); vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true); steerMode = SteerModes.NormalFlight; GetGuardTarget(); if (vessel.Landed && standbyMode && weaponManager && BDATargetManager.TargetDatabase[BDATargetManager.BoolToTeam(weaponManager.team)].Count == 0) { s.mainThrottle = 0; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); return; } //upDirection = -FlightGlobals.getGeeForceAtPosition(transform.position).normalized; upDirection = VectorUtils.GetUpDirection(vessel.transform.position); debugString = string.Empty; if (MissileGuidance.GetRadarAltitude(vessel) < minAltitude) { startedLanded = true; } if (startedLanded) { TakeOff(s); turningTimer = 0; } else { if (FlyAvoidCollision(s)) { turningTimer = 0; } else if (command != PilotCommands.Free) { UpdateCommand(s); } else { UpdateAI(s); } } //brake and cut throttle if exceeding max speed if (vessel.srfSpeed > maxSpeed) { vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); s.mainThrottle = 0; } debugString += "\nthreatLevel: " + threatLevel; }
protected void UpdateLaserTarget() { if (TargetAcquired) { if (lockedCamera && lockedCamera.groundStabilized && !lockedCamera.gimbalLimitReached && lockedCamera.surfaceDetected) //active laser target { TargetPosition = lockedCamera.groundTargetPosition; TargetVelocity = (TargetPosition - lastLaserPoint) / Time.fixedDeltaTime; TargetAcceleration = Vector3.zero; lastLaserPoint = TargetPosition; if (GuidanceMode == GuidanceModes.BeamRiding && TimeIndex > 0.25f && Vector3.Dot(GetForwardTransform(), part.transform.position - lockedCamera.transform.position) < 0) { TargetAcquired = false; lockedCamera = null; } } else //lost active laser target, home on last known position { if (CMSmoke.RaycastSmoke(new Ray(transform.position, lastLaserPoint - transform.position))) { //Debug.Log("Laser missileBase affected by smoke countermeasure"); float angle = VectorUtils.FullRangePerlinNoise(0.75f * Time.time, 10) * BDArmorySettings.SMOKE_DEFLECTION_FACTOR; TargetPosition = VectorUtils.RotatePointAround(lastLaserPoint, transform.position, VectorUtils.GetUpDirection(transform.position), angle); TargetVelocity = Vector3.zero; TargetAcceleration = Vector3.zero; lastLaserPoint = TargetPosition; } else { TargetPosition = lastLaserPoint; } } } else { ModuleTargetingCamera foundCam = null; bool parentOnly = (GuidanceMode == GuidanceModes.BeamRiding); foundCam = BDATargetManager.GetLaserTarget(this, parentOnly); if (foundCam != null && foundCam.cameraEnabled && foundCam.groundStabilized && BDATargetManager.CanSeePosition(foundCam.groundTargetPosition, vessel.transform.position, MissileReferenceTransform.position)) { Debug.Log("[BDArmory]: Laser guided missileBase actively found laser point. Enabling guidance."); lockedCamera = foundCam; TargetAcquired = true; } } }
/// <summary> /// Scans for targets in direction with field of view. /// Returns the direction scanned for debug /// </summary> /// <returns>The scan direction.</returns> /// <param name="myWpnManager">My wpn manager.</param> /// <param name="directionAngle">Direction angle.</param> /// <param name="referenceTransform">Reference transform.</param> /// <param name="fov">Fov.</param> /// <param name="results">Results.</param> /// <param name="maxDistance">Max distance.</param> public static Vector3 GuardScanInDirection(MissileFire myWpnManager, float directionAngle, Transform referenceTransform, float fov, out ViewScanResults results, float maxDistance) { fov *= 1.1f; results = new ViewScanResults(); results.foundMissile = false; results.foundHeatMissile = false; results.foundRadarMissile = false; results.foundAGM = false; results.firingAtMe = false; results.missileThreatDistance = float.MaxValue; results.threatVessel = null; results.threatWeaponManager = null; if (!myWpnManager || !referenceTransform) { return(Vector3.zero); } Vector3 position = referenceTransform.position; Vector3d geoPos = VectorUtils.WorldPositionToGeoCoords(position, FlightGlobals.currentMainBody); Vector3 forwardVector = referenceTransform.forward; Vector3 upVector = referenceTransform.up; Vector3 lookDirection = Quaternion.AngleAxis(directionAngle, upVector) * forwardVector; foreach (var vessel in BDATargetManager.LoadedVessels) { if (vessel == null) { continue; } if (vessel.loaded) { if (vessel == myWpnManager.vessel) { continue; //ignore self } Vector3 vesselProjectedDirection = Vector3.ProjectOnPlane(vessel.transform.position - position, upVector); Vector3 vesselDirection = vessel.transform.position - position; if (Vector3.Dot(vesselDirection, lookDirection) < 0) { continue; } float vesselDistance = (vessel.transform.position - position).magnitude; if (vesselDistance < maxDistance && Vector3.Angle(vesselProjectedDirection, lookDirection) < fov / 2 && Vector3.Angle(vessel.transform.position - position, -myWpnManager.transform.forward) < myWpnManager.guardAngle / 2) { //Debug.Log("Found vessel: " + vessel.vesselName); if (TerrainCheck(referenceTransform.position, vessel.transform.position)) { continue; //blocked by terrain } BDATargetManager.ReportVessel(vessel, myWpnManager); TargetInfo tInfo; if ((tInfo = vessel.GetComponent <TargetInfo>())) { if (tInfo.isMissile) { MissileBase missileBase; if (missileBase = tInfo.MissileBaseModule) { results.foundMissile = true; results.threatVessel = missileBase.vessel; Vector3 vectorFromMissile = myWpnManager.vessel.CoM - missileBase.part.transform.position; Vector3 relV = missileBase.vessel.srf_velocity - myWpnManager.vessel.srf_velocity; bool approaching = Vector3.Dot(relV, vectorFromMissile) > 0; if (missileBase.HasFired && missileBase.TimeIndex > 1 && approaching && (missileBase.TargetPosition - (myWpnManager.vessel.CoM + (myWpnManager.vessel.srf_velocity * Time.fixedDeltaTime))).sqrMagnitude < 3600) { if (missileBase.TargetingMode == MissileBase.TargetingModes.Heat) { results.foundHeatMissile = true; results.missileThreatDistance = Mathf.Min(results.missileThreatDistance, Vector3.Distance(missileBase.part.transform.position, myWpnManager.part.transform.position)); results.threatPosition = missileBase.transform.position; break; } else if (missileBase.TargetingMode == MissileBase.TargetingModes.Radar) { results.foundRadarMissile = true; results.missileThreatDistance = Mathf.Min(results.missileThreatDistance, Vector3.Distance(missileBase.part.transform.position, myWpnManager.part.transform.position)); results.threatPosition = missileBase.transform.position; } else if (missileBase.TargetingMode == MissileBase.TargetingModes.Laser) { results.foundAGM = true; results.missileThreatDistance = Mathf.Min(results.missileThreatDistance, Vector3.Distance(missileBase.part.transform.position, myWpnManager.part.transform.position)); break; } } else { break; } } } else { //check if its shooting guns at me //if(!results.firingAtMe) //more work, but we can't afford to be incorrect picking the closest threat //{ foreach (var weapon in vessel.FindPartModulesImplementing <ModuleWeapon>()) { if (!weapon.recentlyFiring) { continue; } if (Vector3.Dot(weapon.fireTransforms[0].forward, vesselDirection) > 0) { continue; } if (Vector3.Angle(weapon.fireTransforms[0].forward, -vesselDirection) < 6500 / vesselDistance && (!results.firingAtMe || (weapon.vessel.ReferenceTransform.position - position).magnitude < (results.threatPosition - position).magnitude)) { results.firingAtMe = true; results.threatPosition = weapon.vessel.transform.position; results.threatVessel = weapon.vessel; results.threatWeaponManager = weapon.weaponManager; break; } } //} } } } } } return(lookDirection); }
void Update() { if (HighLogic.LoadedSceneIsFlight) { if (cameraEnabled && !vessel.IsControllable) { DisableCamera(); } if (cameraEnabled && TargetingCamera.ReadyForUse && vessel.IsControllable) { if (delayedEnabling) { return; } if (!TargetingCamera.Instance || FlightGlobals.currentMainBody == null) { return; } if (activeCam == this) { if (zoomFovs != null) { TargetingCamera.Instance.SetFOV(fov); } } if (radarLock) { UpdateRadarLock(); } if (groundStabilized) { groundTargetPosition = VectorUtils.GetWorldSurfacePostion(bodyRelativeGTP, vessel.mainBody); //vessel.mainBody.GetWorldSurfacePosition(bodyRelativeGTP.x, bodyRelativeGTP.y, bodyRelativeGTP.z); Vector3 lookVector = groundTargetPosition - cameraParentTransform.position; cameraParentTransform.rotation = Quaternion.LookRotation(lookVector); } Vector3 lookDirection = cameraParentTransform.forward; if (Vector3.Angle(lookDirection, cameraParentTransform.parent.forward) > gimbalLimit) { lookDirection = Vector3.RotateTowards(cameraParentTransform.transform.parent.forward, lookDirection, gimbalLimit * Mathf.Deg2Rad, 0); gimbalLimitReached = true; } else { gimbalLimitReached = false; } cameraParentTransform.rotation = Quaternion.LookRotation(lookDirection, VectorUtils.GetUpDirection(transform.position)); if (eyeHolderTransform) { Vector3 projectedForward = Vector3.ProjectOnPlane(cameraParentTransform.forward, eyeHolderTransform.parent.up); if (projectedForward != Vector3.zero) { eyeHolderTransform.rotation = Quaternion.LookRotation(projectedForward, eyeHolderTransform.parent.up); } } UpdateControls(); } } }
void UpdateRadarLock() { if (weaponManager && weaponManager.radar && weaponManager.radar.locked) { Vector3 radarTargetPos = weaponManager.radar.lockedTarget.predictedPosition + (weaponManager.radar.lockedTarget.velocity * Time.fixedDeltaTime); Quaternion lookRotation = Quaternion.LookRotation(radarTargetPos - cameraParentTransform.position, VectorUtils.GetUpDirection(cameraParentTransform.position)); if (Vector3.Angle(radarTargetPos - cameraParentTransform.position, cameraParentTransform.forward) < 1.5f) { cameraParentTransform.rotation = lookRotation; GroundStabilize(); } else { if (groundStabilized) { ClearTarget(); } cameraParentTransform.rotation = Quaternion.RotateTowards(cameraParentTransform.rotation, lookRotation, 80 * Time.fixedDeltaTime); } } else { radarLock = false; } }
public IEnumerator PointToPositionRoutine(Vector3 position) { yield return(StopPTPRRoutine()); stopPTPR = false; slewingToPosition = true; radarLock = false; StopResetting(); ClearTarget(); while (!stopPTPR && Vector3.Angle(cameraParentTransform.transform.forward, position - (cameraParentTransform.transform.position + (part.rb.velocity * Time.fixedDeltaTime))) > 0.75f) { Vector3 newForward = Vector3.RotateTowards(cameraParentTransform.transform.forward, position - cameraParentTransform.transform.position, 60 * Mathf.Deg2Rad * Time.fixedDeltaTime, 0); cameraParentTransform.rotation = Quaternion.LookRotation(newForward, VectorUtils.GetUpDirection(transform.position)); yield return(new WaitForFixedUpdate()); if (gimbalLimitReached) { ClearTarget(); StartCoroutine("ResetCamera"); slewingToPosition = false; yield break; } } if (surfaceDetected && !stopPTPR) { cameraParentTransform.transform.rotation = Quaternion.LookRotation(position - cameraParentTransform.position, VectorUtils.GetUpDirection(transform.position)); GroundStabilize(); } slewingToPosition = false; yield break; }
// Update is called once per frame void Update() { if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && !vessel.packed && radarEnabled) { if (omnidirectional) { referenceTransform.position = vessel.transform.position; referenceTransform.rotation = Quaternion.LookRotation(VectorUtils.GetNorthVector(transform.position, vessel.mainBody), VectorUtils.GetUpDirection(transform.position)); } else { referenceTransform.position = vessel.transform.position; referenceTransform.rotation = Quaternion.LookRotation(part.transform.up, VectorUtils.GetUpDirection(referenceTransform.position)); } //UpdateInputs(); } drawGUI = (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && !vessel.packed && radarEnabled && vessel.isActiveVessel && BDArmorySettings.GAME_UI_ENABLED && !MapView.MapIsEnabled); //UpdateSlaveData(); }
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); }
IEnumerator DogfightCompetitionModeRoutine(float distance) { competitionStarting = true; competitionStatus = "Competition: Pilots are taking off."; Dictionary <BDArmorySettings.BDATeams, List <BDModulePilotAI> > pilots = new Dictionary <BDArmorySettings.BDATeams, List <BDModulePilotAI> >(); pilots.Add(BDArmorySettings.BDATeams.A, new List <BDModulePilotAI>()); pilots.Add(BDArmorySettings.BDATeams.B, new List <BDModulePilotAI>()); foreach (var v in BDATargetManager.LoadedVessels) { if (!v || !v.loaded) { continue; } BDModulePilotAI pilot = null; foreach (var p in v.FindPartModulesImplementing <BDModulePilotAI>()) { pilot = p; break; } if (!pilot || !pilot.weaponManager) { continue; } pilots[BDATargetManager.BoolToTeam(pilot.weaponManager.team)].Add(pilot); pilot.ActivatePilot(); pilot.standbyMode = false; if (pilot.weaponManager.guardMode) { pilot.weaponManager.ToggleGuardMode(); } } //clear target database so pilots don't attack yet BDATargetManager.ClearDatabase(); if (pilots[BDArmorySettings.BDATeams.A].Count == 0 || pilots[BDArmorySettings.BDATeams.B].Count == 0) { Debug.Log("[BDArmory]: Unable to start competition mode - one or more teams is empty"); competitionStatus = "Competition: Failed! One or more teams is empty."; yield return(new WaitForSeconds(2)); competitionStarting = false; yield break; } BDModulePilotAI aLeader = pilots[BDArmorySettings.BDATeams.A][0]; BDModulePilotAI bLeader = pilots[BDArmorySettings.BDATeams.B][0]; aLeader.weaponManager.wingCommander.CommandAllFollow(); bLeader.weaponManager.wingCommander.CommandAllFollow(); //wait till the leaders are airborne while (aLeader && bLeader && (aLeader.vessel.LandedOrSplashed || bLeader.vessel.LandedOrSplashed)) { yield return(null); } if (!aLeader || !bLeader) { StopCompetition(); } competitionStatus = "Competition: Sending pilots to start position."; Vector3 aDirection = Vector3.ProjectOnPlane(aLeader.vessel.CoM - bLeader.vessel.CoM, aLeader.vessel.upAxis).normalized; Vector3 bDirection = Vector3.ProjectOnPlane(bLeader.vessel.CoM - aLeader.vessel.CoM, bLeader.vessel.upAxis).normalized; Vector3 center = (aLeader.vessel.CoM + bLeader.vessel.CoM) / 2f; Vector3 aDestination = center + (aDirection * (distance + 1250f)); Vector3 bDestination = center + (bDirection * (distance + 1250f)); aDestination = VectorUtils.WorldPositionToGeoCoords(aDestination, FlightGlobals.currentMainBody); bDestination = VectorUtils.WorldPositionToGeoCoords(bDestination, FlightGlobals.currentMainBody); aLeader.CommandFlyTo(aDestination); bLeader.CommandFlyTo(bDestination); Vector3 centerGPS = VectorUtils.WorldPositionToGeoCoords(center, FlightGlobals.currentMainBody); //wait till everyone is in position bool waiting = true; while (waiting) { waiting = false; if (!aLeader || !bLeader) { StopCompetition(); } if (Vector3.Distance(aLeader.transform.position, bLeader.transform.position) < distance * 1.95f) { waiting = true; } else { foreach (var t in pilots.Keys) { foreach (var p in pilots[t]) { if (p.currentCommand == BDModulePilotAI.PilotCommands.Follow && Vector3.Distance(p.vessel.CoM, p.commandLeader.vessel.CoM) > 1000f) { competitionStatus = "Competition: Waiting for teams to get in position."; waiting = true; } } } } yield return(null); } //start the match foreach (var t in pilots.Keys) { foreach (var p in pilots[t]) { if (!p) { continue; } //enable guard mode if (!p.weaponManager.guardMode) { p.weaponManager.ToggleGuardMode(); } //report all vessels if (BDATargetManager.BoolToTeam(p.weaponManager.team) == BDArmorySettings.BDATeams.B) { BDATargetManager.ReportVessel(p.vessel, aLeader.weaponManager); } else { BDATargetManager.ReportVessel(p.vessel, bLeader.weaponManager); } //release command p.ReleaseCommand(); p.defaultOrbitCoords = centerGPS; } } competitionStatus = "Competition starting! Good luck!"; yield return(new WaitForSeconds(2)); competitionStarting = false; }
//public static TargetSignatureData GetHeatTarget(Ray ray, float scanRadius, float highpassThreshold, bool allAspect, MissileFire mf = null) public static TargetSignatureData GetHeatTarget(Ray ray, float scanRadius, float highpassThreshold, bool allAspect, MissileFire mf = null, bool favorGroundTargets = false) { float minScore = highpassThreshold; float minMass = 0.15f; //otherwise the RAMs have trouble shooting down incoming missiles TargetSignatureData finalData = TargetSignatureData.noTarget; float finalScore = 0; foreach (var vessel in BDATargetManager.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 != BDATargetManager.BoolToTeam(mf.team) && (tInfo.MissileBaseModule.MissileState == MissileBase.MissileStates.Boost || tInfo.MissileBaseModule.MissileState == MissileBase.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.srf_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 && !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); } } } 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); }