void RegainEnergy(FlightCtrlState s) { debugString += "\nRegaining energy"; steerMode = SteerModes.Aiming; Vector3 planarDirection = Vector3.ProjectOnPlane(vessel.srf_velocity, upDirection); float angle = (Mathf.Clamp(MissileGuidance.GetRadarAltitude(vessel) - minAltitude, 0, 1500) / 1500) * 90; angle = Mathf.Clamp(angle, 0, 55) * Mathf.Deg2Rad; Vector3 targetDirection = Vector3.RotateTowards(planarDirection, -upDirection, angle, 0).normalized; AdjustThrottle(maxSpeed, false); FlyToPosition(s, vesselTransform.position + (targetDirection * 100)); }
void TakeOff(FlightCtrlState s) { threatLevel = 1; debugString += "\nTaking off/Gaining altitude"; if (vessel.Landed && vessel.srfSpeed < takeOffSpeed) { defaultOrbitCoords = VectorUtils.WorldPositionToGeoCoords(vessel.transform.position, vessel.mainBody); return; } steerMode = SteerModes.Aiming; float radarAlt = MissileGuidance.GetRadarAltitude(vessel); Vector3 forwardPoint = vessel.transform.position + Vector3.ProjectOnPlane(vesselTransform.up * 100, upDirection); float terrainDiff = MissileGuidance.GetRaycastRadarAltitude(forwardPoint) - radarAlt; terrainDiff = Mathf.Max(terrainDiff, 0); float rise = Mathf.Clamp((float)vessel.srfSpeed * 0.3f, 5, 100); if (radarAlt > 70) { vessel.ActionGroups.SetGroup(KSPActionGroup.Gear, false); } else { vessel.ActionGroups.SetGroup(KSPActionGroup.Gear, true); } FlyToPosition(s, forwardPoint + (upDirection * (rise + terrainDiff))); if (radarAlt > minAltitude) { startedLanded = false; } }
void FlyToTargetVessel(FlightCtrlState s, Vessel v) { Vector3 target = v.CoM; MissileLauncher missile = null; Vector3 vectorToTarget = v.transform.position - vesselTransform.position; float distanceToTarget = vectorToTarget.magnitude; if(weaponManager) { missile = weaponManager.currentMissile; if(missile != null) { if(missile.GetWeaponClass() == WeaponClasses.Missile) { if(missile.targetingMode == MissileLauncher.TargetingModes.Heat && !weaponManager.heatTarget.exists) { target += v.srf_velocity.normalized * 10; } else { target = MissileGuidance.GetAirToAirFireSolution(missile, v); } if(Vector3.Angle(target - vesselTransform.position, vesselTransform.forward) < 20f) { steerMode = SteerModes.Aiming; } } else //bombing { if(Vector3.Angle(target - vesselTransform.position, vesselTransform.up) < 45f) { /* target = GetSurfacePosition(target) + (vessel.upAxis * vessel.altitude); Vector3 fixedTDir = Quaternion.FromToRotation(Vector3.ProjectOnPlane(vessel.srf_velocity, vessel.upAxis), target - vesselTransform.position) * (target - vesselTransform.position); target = FlightPosition(vesselTransform.position + fixedTDir, Mathf.Max(defaultAltitude - 500f, minAltitude)); */ target = target+(Mathf.Max(defaultAltitude - 500f, minAltitude)*upDirection); Vector3 tDir = (target-vesselTransform.position).normalized; tDir = (1000 * tDir) - (vessel.srf_velocity.normalized * 600); target = vesselTransform.position + tDir; } else { target = target+(Mathf.Max(defaultAltitude - 500f, minAltitude)*upDirection); } } } else { ModuleWeapon weapon = weaponManager.currentGun; if(weapon!=null) { //target -= 1.30f*weapon.GetLeadOffset(); Vector3 leadOffset = weapon.GetLeadOffset(); float targetAngVel = 1.65f * Vector3.Angle(v.transform.position - vessel.transform.position, v.transform.position + (vessel.srf_velocity) - vessel.transform.position); debugString += "\ntargetAngVel: " + targetAngVel; float magnifier = Mathf.Clamp(targetAngVel, 1.25f, 3); magnifier += (0.5f * Mathf.Sin(Time.time / 2)); target -= magnifier * leadOffset; float angleToLead = Vector3.Angle(vesselTransform.up, target - vesselTransform.position); if(distanceToTarget < weaponManager.gunRange && angleToLead < 20) { steerMode = SteerModes.Aiming; //steer to aim } if(v.LandedOrSplashed) { if(distanceToTarget > defaultAltitude * 2.2f) { target = FlightPosition(target, defaultAltitude); } else { steerMode = SteerModes.Aiming; } } else if(distanceToTarget > weaponManager.gunRange * 1.5f || Vector3.Dot(target-vesselTransform.position, vesselTransform.up) < 0) { target = v.CoM; } } } } float targetDot = Vector3.Dot(vesselTransform.up, v.transform.position-vessel.transform.position); //manage speed when close to enemy float finalMaxSpeed = maxSpeed; if(targetDot > 0) { finalMaxSpeed = Mathf.Max((distanceToTarget - 100) / 8, 0) + (float)v.srfSpeed; finalMaxSpeed = Mathf.Max(finalMaxSpeed, minSpeed); } AdjustThrottle(finalMaxSpeed, true); if((targetDot < 0 && vessel.srfSpeed > finalMaxSpeed) && distanceToTarget < 300 && vessel.srfSpeed < v.srfSpeed * 1.25f && Vector3.Dot(vessel.srf_velocity, v.srf_velocity) > 0) //distance is less than 800m { debugString += ("\nEnemy on tail. Braking"); AdjustThrottle(minSpeed, true); } if(missile!=null && targetDot > 0 && distanceToTarget < 300 && vessel.srfSpeed > 130) { extending = true; lastTargetPosition = v.transform.position; } FlyToPosition(s, target); }
void FlyToPosition(FlightCtrlState s, Vector3 targetPosition) { if(!startedLanded) { targetPosition = FlightPosition(targetPosition, minAltitude); targetPosition = vesselTransform.position + ((targetPosition - vesselTransform.position).normalized * 100); } 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(BDArmorySettings.DRAW_DEBUG_LINES) { flyingToPosition = targetPosition; } //test poststall float AoA = Vector3.Angle(vessel.ReferenceTransform.up, vessel.srf_velocity); if(AoA > 30f) { steerMode = SteerModes.Aiming; } //slow down for tighter turns float velAngleToTarget = Vector3.Angle(targetPosition-vesselTransform.position, vessel.srf_velocity); float normVelAngleToTarget = Mathf.Clamp(velAngleToTarget, 0, 90)/90; float speedReductionFactor = 1.25f; float finalSpeed = Mathf.Min(speedController.targetSpeed, Mathf.Clamp(maxSpeed - (speedReductionFactor * normVelAngleToTarget), idleSpeed, maxSpeed)); debugString += "\nFinal Target Speed: " + finalSpeed.ToString("0.0"); AdjustThrottle(finalSpeed, useBrakes, useAB); 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 = 0.5f; postPitchFactor = 1; } else//(steerMode == SteerModes.Aiming) { targetDirection = vesselTransform.InverseTransformDirection(targetPosition-vesselTransform.position).normalized; targetDirection = Vector3.RotateTowards(Vector3.up, targetDirection, 25 * Mathf.Deg2Rad, 0); targetDirectionYaw = targetDirection; if(command == PilotCommands.Follow) { postYawFactor = 0.45f; postPitchFactor = 1f; } else { postYawFactor = 1.75f; postPitchFactor = 2f; } } 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.020f * steerMult * yawError) - (postYawFactor * steerDamping * 0.6f * -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 || angleToTarget > 2) //{ rollTarget = (targetPosition + ((steerMode == SteerModes.Aiming ? 10f : 25f) * 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; // }
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); AdjustThrottle(maxSpeed, true); useAB = true; useBrakes = true; vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true); steerMode = SteerModes.NormalFlight; GetGuardTarget(); if(vessel.LandedOrSplashed && standbyMode && weaponManager && (BDATargetManager.TargetDatabase[BDATargetManager.BoolToTeam(weaponManager.team)].Count == 0||BDArmorySettings.PEACE_MODE)) { //s.mainThrottle = 0; //vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); AdjustThrottle(0, true); return; } //upDirection = -FlightGlobals.getGeeForceAtPosition(transform.position).normalized; upDirection = VectorUtils.GetUpDirection(vessel.transform.position); debugString = string.Empty; CalculateAccelerationAndTurningCircle(); if (MissileGuidance.GetRadarAltitude(vessel) < MinAltitudeNeeded()) { startedLanded = true; } if (startedLanded) { if(command != PilotCommands.Follow) { currentStatus = "Gain Alt."; } TakeOff(s); turningTimer = 0; } else { if(FlyAvoidCollision(s)) { turningTimer = 0; } else if(command != PilotCommands.Free) { UpdateCommand(s); } else { UpdateAI(s); } } UpdateGAndAoALimits(s); AdjustPitchForGAndAoALimits(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; }
void UpdateFollowCommand(FlightCtrlState s) { threatLevel = 1; steerMode = SteerModes.NormalFlight; //s.mainThrottle = 1; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, false); commandSpeed = commandLeader.vessel.srfSpeed; commandHeading = commandLeader.vessel.srf_velocity.normalized; //formation position commandPosition = GetFormationPosition(); float distanceToPos = Vector3.Distance(vesselTransform.position, commandPosition); //if(distanceToPos > 100) //{ float dotToPos = Vector3.Dot(vesselTransform.up, commandPosition - vesselTransform.position); Vector3 flyPos; useRollHint = false; float ctrlModeThresh = 1000; if(distanceToPos < ctrlModeThresh) { flyPos = commandPosition + (ctrlModeThresh * commandHeading); Vector3 vectorToFlyPos = flyPos - vessel.ReferenceTransform.position; Vector3 projectedPosOffset = Vector3.ProjectOnPlane(commandPosition - vessel.ReferenceTransform.position, commandHeading); float posOffsetMag = projectedPosOffset.magnitude; float adjustAngle = (Mathf.Clamp(posOffsetMag * 0.27f, 0, 25)); Vector3 projVel = Vector3.Project(vessel.srf_velocity - commandLeader.vessel.srf_velocity, projectedPosOffset); adjustAngle -= Mathf.Clamp(Mathf.Sign(Vector3.Dot(projVel, projectedPosOffset)) * projVel.magnitude * 0.12f, -10, 10); adjustAngle *= Mathf.Deg2Rad; vectorToFlyPos = Vector3.RotateTowards(vectorToFlyPos, projectedPosOffset, adjustAngle, 0); flyPos = vessel.ReferenceTransform.position + vectorToFlyPos; if(distanceToPos < 400) { steerMode = SteerModes.Aiming; } else { steerMode = SteerModes.NormalFlight; } /* if(dotToPos < 0) { flyPos = commandPosition + (315 * commandHeading); s.mainThrottle = 0; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); steerMode = SteerModes.NormalFlight; } */ if(distanceToPos < 10) { useRollHint = true; } } else { steerMode = SteerModes.NormalFlight; flyPos = commandPosition; } double finalMaxSpeed = commandSpeed; if(dotToPos > 0) { finalMaxSpeed += (distanceToPos / 8); } else { finalMaxSpeed -= (distanceToPos / 2); } AdjustThrottle((float)finalMaxSpeed, true); FlyToPosition(s, flyPos); }
void TakeOff(FlightCtrlState s) { threatLevel = 1; debugString += "\nTaking off/Gaining altitude"; if(vessel.LandedOrSplashed && vessel.srfSpeed < takeOffSpeed) { defaultOrbitCoords = VectorUtils.WorldPositionToGeoCoords(vessel.transform.position, vessel.mainBody); return; } steerMode = SteerModes.Aiming; float radarAlt = MissileGuidance.GetRadarAltitude(vessel); Vector3 forwardPoint = vessel.transform.position + Vector3.ProjectOnPlane(vesselTransform.up * 100, upDirection); float terrainDiff = MissileGuidance.GetRaycastRadarAltitude(forwardPoint) - radarAlt; terrainDiff = Mathf.Max(terrainDiff, 0); float rise = Mathf.Clamp((float)vessel.srfSpeed * 0.3f, 5, 100); if(radarAlt > 70) { vessel.ActionGroups.SetGroup(KSPActionGroup.Gear, false); } else { vessel.ActionGroups.SetGroup(KSPActionGroup.Gear, true); } FlyToPosition(s, forwardPoint + (upDirection * (rise+terrainDiff))); if(radarAlt > minAltitude) { startedLanded = false; } }
void RegainEnergy(FlightCtrlState s) { debugString += "\nRegaining energy"; steerMode = SteerModes.Aiming; Vector3 planarDirection = Vector3.ProjectOnPlane(vessel.srf_velocity, upDirection); float angle = (Mathf.Clamp(MissileGuidance.GetRadarAltitude(vessel) - minAltitude, 0, 1500) / 1500) * 90; angle = Mathf.Clamp(angle, 0, 55) * Mathf.Deg2Rad; Vector3 targetDirection = Vector3.RotateTowards(planarDirection, -upDirection, angle, 0).normalized; AdjustThrottle(maxSpeed, false); FlyToPosition(s, vesselTransform.position + (targetDirection*100)); }
void FlyToTargetVessel(FlightCtrlState s, Vessel v) { Vector3 target = v.CoM; MissileLauncher missile = null; Vector3 vectorToTarget = v.transform.position - vesselTransform.position; float distanceToTarget = vectorToTarget.magnitude; if (weaponManager) { missile = weaponManager.currentMissile; if (missile != null) { if (missile.targetingMode == MissileLauncher.TargetingModes.Heat && !weaponManager.heatTarget.exists) { target += v.srf_velocity.normalized * 10; } else { target = MissileGuidance.GetAirToAirFireSolution(missile, v); } if (Vector3.Angle(target - vesselTransform.position, vesselTransform.forward) < 15) { steerMode = SteerModes.Aiming; } } else { ModuleWeapon weapon = weaponManager.currentGun; if (weapon != null) { //target -= 1.30f*weapon.GetLeadOffset(); Vector3 leadOffset = weapon.GetLeadOffset(); float targetAngVel = 1.65f * Vector3.Angle(v.transform.position - vessel.transform.position, v.transform.position + (vessel.srf_velocity) - vessel.transform.position); debugString += "\ntargetAngVel: " + targetAngVel; float magnifier = Mathf.Clamp(targetAngVel, 1.25f, 5); target -= magnifier * leadOffset; float angleToLead = Vector3.Angle(vesselTransform.up, target - vesselTransform.position); if (distanceToTarget < 1600 && angleToLead < 20) { steerMode = SteerModes.Aiming; //steer to aim } } } } float targetDot = Vector3.Dot(vesselTransform.up, v.transform.position - vessel.transform.position); //manage speed when close to enemy float finalMaxSpeed = ((distanceToTarget - 100) / 8) + (float)v.srfSpeed; AdjustThrottle(finalMaxSpeed, true); if ((targetDot < 0 || vessel.srfSpeed > finalMaxSpeed) && distanceToTarget < 800) //distance is less than 800m { debugString += ("\nEnemy on tail. Braking"); AdjustThrottle(minSpeed, true); } if (missile != null && targetDot > 0 && distanceToTarget < 300 && vessel.srfSpeed > 130) { extending = true; lastTargetPosition = v.transform.position; } FlyToPosition(s, target); }
void UpdateFollowCommand(FlightCtrlState s) { threatLevel = 1; steerMode = SteerModes.NormalFlight; //s.mainThrottle = 1; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, false); commandSpeed = commandLeader.vessel.srfSpeed; commandHeading = commandLeader.vessel.srf_velocity.normalized; //formation position commandPosition = GetFormationPosition(); float distanceToPos = Vector3.Distance(vesselTransform.position, commandPosition); //if(distanceToPos > 100) //{ float dotToPos = Vector3.Dot(vesselTransform.up, commandPosition - vesselTransform.position); Vector3 flyPos; useRollHint = false; float ctrlModeThresh = 1000; if (distanceToPos < ctrlModeThresh) { flyPos = commandPosition + (ctrlModeThresh * commandHeading); Vector3 vectorToFlyPos = flyPos - vessel.ReferenceTransform.position; Vector3 projectedPosOffset = Vector3.ProjectOnPlane(commandPosition - vessel.ReferenceTransform.position, commandHeading); float posOffsetMag = projectedPosOffset.magnitude; float adjustAngle = (Mathf.Clamp(posOffsetMag * 0.27f, 0, 25)); Vector3 projVel = Vector3.Project(vessel.srf_velocity - commandLeader.vessel.srf_velocity, projectedPosOffset); adjustAngle -= Mathf.Clamp(Mathf.Sign(Vector3.Dot(projVel, projectedPosOffset)) * projVel.magnitude * 0.12f, -10, 10); adjustAngle *= Mathf.Deg2Rad; vectorToFlyPos = Vector3.RotateTowards(vectorToFlyPos, projectedPosOffset, adjustAngle, 0); flyPos = vessel.ReferenceTransform.position + vectorToFlyPos; if (distanceToPos < 400) { steerMode = SteerModes.Aiming; } else { steerMode = SteerModes.NormalFlight; } /* * if(dotToPos < 0) * { * flyPos = commandPosition + (315 * commandHeading); * s.mainThrottle = 0; * vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); * * steerMode = SteerModes.NormalFlight; * } */ if (distanceToPos < 15) { useRollHint = true; } } else { steerMode = SteerModes.NormalFlight; flyPos = commandPosition; } double finalMaxSpeed = commandSpeed; if (dotToPos > 0) { finalMaxSpeed += (distanceToPos / 8); } else { finalMaxSpeed -= (distanceToPos / 2); } AdjustThrottle((float)finalMaxSpeed, true); FlyToPosition(s, flyPos); }
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); AdjustThrottle(maxSpeed, true); useAB = true; useBrakes = true; 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); AdjustThrottle(0, 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; }
void Evasive(FlightCtrlState s) { currentStatus = "Evading"; debugString += "\nEvasive"; debugString += "\n Threat Distance: " + weaponManager.incomingMissileDistance; collisionDetectionTicker += 2; if(weaponManager) { if(weaponManager.isFlaring) { useAB = vessel.srfSpeed < minSpeed; useBrakes = false; float targetSpeed = minSpeed; if(weaponManager.isChaffing) { targetSpeed = maxSpeed; } AdjustThrottle(targetSpeed, false, useAB); } if((weaponManager.isChaffing || weaponManager.isFlaring) && (weaponManager.incomingMissileDistance > 2000)) { debugString += "\nBreaking from missile threat!"; Vector3 axis = -Vector3.Cross(vesselTransform.up, threatRelativePosition); Vector3 breakDirection = Quaternion.AngleAxis(90, axis) * threatRelativePosition; //Vector3 breakTarget = vesselTransform.position + breakDirection; RegainEnergy(s, breakDirection); return; } else if(weaponManager.underFire) { debugString += "\nDodging gunfire"; float threatDirectionFactor = Vector3.Dot(vesselTransform.up, threatRelativePosition.normalized); //Vector3 axis = -Vector3.Cross(vesselTransform.up, threatRelativePosition); Vector3 breakTarget = threatRelativePosition * 2f; //for the most part, we want to turn _towards_ the threat in order to increase the rel ang vel and get under its guns if (threatDirectionFactor > 0.9f) //within 28 degrees in front { breakTarget += Vector3.Cross(threatRelativePosition.normalized, Mathf.Sign(Mathf.Sin((float)vessel.missionTime / 2)) * vessel.upAxis); debugString += " from directly ahead!"; } else if (threatDirectionFactor < -0.9) //within ~28 degrees behind { float threatDistance = threatRelativePosition.magnitude; if(threatDistance > 400) { breakTarget = vesselTransform.position + vesselTransform.up * 1500 - 500 * vessel.upAxis; breakTarget += Mathf.Sin((float)vessel.missionTime / 2) * vesselTransform.right * 1000 - Mathf.Cos((float)vessel.missionTime / 2) * vesselTransform.forward * 1000; if(threatDistance > 800) debugString += " from behind afar; engaging barrel roll"; else { debugString += " from behind moderate distance; engaging aggressvie barrel roll and braking"; steerMode = SteerModes.Aiming; AdjustThrottle(minSpeed, true, false); } } else { breakTarget = threatRelativePosition; if (evasiveTimer < 1.5f) breakTarget += Mathf.Sin((float)vessel.missionTime * 2) * vesselTransform.right * 500; else breakTarget += -Math.Sign(Mathf.Sin((float)vessel.missionTime * 2)) * vesselTransform.right * 150; debugString += " from directly behind and close; breaking hard"; steerMode = SteerModes.Aiming; } } else { float threatDistance = threatRelativePosition.magnitude; if(threatDistance < 400) { breakTarget += Mathf.Sin((float)vessel.missionTime * 2) * vesselTransform.right * 100; debugString += " from the side; breaking in"; steerMode = SteerModes.Aiming; } else { breakTarget = vesselTransform.position + vesselTransform.up * 1500; breakTarget += Mathf.Sin((float)vessel.missionTime / 2) * vesselTransform.right * 1000 - Mathf.Cos((float)vessel.missionTime / 2) * vesselTransform.forward * 1000; debugString += " from far side; engaging barrel roll"; } } float threatAltitudeDiff = Vector3.Dot(threatRelativePosition, vessel.upAxis); if (threatAltitudeDiff > 500) breakTarget += threatAltitudeDiff * vessel.upAxis; //if it's trying to spike us from below, don't go crazy trying to dive below it else breakTarget += - 150 * vessel.upAxis; //dive a bit to escape FlyToPosition(s, breakTarget); return; } else if(weaponManager.incomingMissileVessel) { float mSqrDist = Vector3.SqrMagnitude(weaponManager.incomingMissileVessel.transform.position - vesselTransform.position); if(mSqrDist < 810000) //900m { debugString += "\nMissile about to impact! pull away!"; AdjustThrottle(maxSpeed, false, false); Vector3 cross = Vector3.Cross(weaponManager.incomingMissileVessel.transform.position - vesselTransform.position, vessel.srf_velocity).normalized; if(Vector3.Dot(cross, -vesselTransform.forward) < 0) { cross = -cross; } FlyToPosition(s, vesselTransform.position +(50*vessel.srf_velocity/vessel.srfSpeed)+ (100 * cross)); return; } } } Vector3 target = (vessel.srfSpeed < 200) ? FlightPosition(vessel.transform.position, minAltitude) : vesselTransform.position; float angleOff = Mathf.Sin(Time.time * 0.75f) * 180; angleOff = Mathf.Clamp(angleOff, -45, 45); target += (Quaternion.AngleAxis(angleOff, upDirection) * Vector3.ProjectOnPlane(vesselTransform.up * 500, upDirection)); //+ (Mathf.Sin (Time.time/3) * upDirection * minAltitude/3); FlyToPosition(s, target); }
void FlyToTargetVessel(FlightCtrlState s, Vessel v) { Vector3 target = v.CoM; MissileLauncher missile = null; Vector3 vectorToTarget = v.transform.position - vesselTransform.position; float distanceToTarget = vectorToTarget.magnitude; float planarDistanceToTarget = Vector3.ProjectOnPlane(vectorToTarget, upDirection).magnitude; float angleToTarget = Vector3.Angle(target - vesselTransform.position, vesselTransform.up); if(weaponManager) { missile = weaponManager.currentMissile; if(missile != null) { if(missile.GetWeaponClass() == WeaponClasses.Missile) { if(distanceToTarget > 5500f) { finalMaxSteer = GetSteerLimiterForSpeedAndPower(); } if(missile.targetingMode == MissileLauncher.TargetingModes.Heat && !weaponManager.heatTarget.exists) { debugString += "\nAttempting heat lock"; target += v.srf_velocity.normalized * 10; } else { target = MissileGuidance.GetAirToAirFireSolution(missile, v); } if(angleToTarget < 20f) { steerMode = SteerModes.Aiming; } } else //bombing { if(distanceToTarget > 4500f) { finalMaxSteer = GetSteerLimiterForSpeedAndPower(); } if(angleToTarget < 45f) { /* target = GetSurfacePosition(target) + (vessel.upAxis * vessel.altitude); Vector3 fixedTDir = Quaternion.FromToRotation(Vector3.ProjectOnPlane(vessel.srf_velocity, vessel.upAxis), target - vesselTransform.position) * (target - vesselTransform.position); target = FlightPosition(vesselTransform.position + fixedTDir, Mathf.Max(defaultAltitude - 500f, minAltitude)); */ target = target + (Mathf.Max(defaultAltitude - 500f, minAltitude) * upDirection); Vector3 tDir = (target - vesselTransform.position).normalized; tDir = (1000 * tDir) - (vessel.srf_velocity.normalized * 600); target = vesselTransform.position + tDir; } else { target = target + (Mathf.Max(defaultAltitude - 500f, minAltitude) * upDirection); } } } else if(weaponManager.currentGun) { ModuleWeapon weapon = weaponManager.currentGun; if(weapon != null) { Vector3 leadOffset = weapon.GetLeadOffset(); float targetAngVel = Vector3.Angle(v.transform.position - vessel.transform.position, v.transform.position + (vessel.srf_velocity) - vessel.transform.position); debugString += "\ntargetAngVel: " + targetAngVel; float magnifier = Mathf.Clamp(targetAngVel, 1f, 2f); magnifier += ((magnifier-1f) * Mathf.Sin(Time.time *0.75f)); target -= magnifier * leadOffset; angleToTarget = Vector3.Angle(vesselTransform.up, target - vesselTransform.position); if(distanceToTarget < weaponManager.gunRange && angleToTarget < 20) { steerMode = SteerModes.Aiming; //steer to aim } else { if(distanceToTarget > 3500f || vessel.srfSpeed < takeOffSpeed) { finalMaxSteer = GetSteerLimiterForSpeedAndPower(); } else { //figuring how much to lead the target's movement to get there after its movement assuming we can manage a constant speed turn //this only runs if we're not aiming and not that far from the target float curVesselMaxAccel = Math.Min(maxDynPresGRecorded * (float)vessel.dynamicPressurekPa, maxAllowedGForce * 9.81f); if (curVesselMaxAccel > 0) { float timeToTurn = (float)vessel.srfSpeed * angleToTarget * Mathf.Deg2Rad / curVesselMaxAccel; target += v.srf_velocity * timeToTurn; //target += 0.5f * v.acceleration * timeToTurn * timeToTurn; } } } if(v.LandedOrSplashed) { if(distanceToTarget > defaultAltitude * 2.2f) { target = FlightPosition(target, defaultAltitude); } else { steerMode = SteerModes.Aiming; } } else if(distanceToTarget > weaponManager.gunRange * 1.5f || Vector3.Dot(target - vesselTransform.position, vesselTransform.up) < 0) { target = v.CoM; } } } else if(planarDistanceToTarget > weaponManager.gunRange * 1.25f && (vessel.altitude < targetVessel.altitude || MissileGuidance.GetRadarAltitude(vessel) < defaultAltitude)) //climb to target vessel's altitude if lower and still too far for guns { finalMaxSteer = GetSteerLimiterForSpeedAndPower(); target = vesselTransform.position + GetLimitedClimbDirectionForSpeed(vectorToTarget); } else { finalMaxSteer = GetSteerLimiterForSpeedAndPower(); } } float targetDot = Vector3.Dot(vesselTransform.up, v.transform.position-vessel.transform.position); //manage speed when close to enemy float finalMaxSpeed = maxSpeed; if(targetDot > 0) { finalMaxSpeed = Mathf.Max((distanceToTarget - 100) / 8, 0) + (float)v.srfSpeed; finalMaxSpeed = Mathf.Max(finalMaxSpeed, minSpeed+25f); } AdjustThrottle(finalMaxSpeed, true); if((targetDot < 0 && vessel.srfSpeed > finalMaxSpeed) && distanceToTarget < 300 && vessel.srfSpeed < v.srfSpeed * 1.25f && Vector3.Dot(vessel.srf_velocity, v.srf_velocity) > 0) //distance is less than 800m { debugString += ("\nEnemy on tail. Braking"); AdjustThrottle(minSpeed, true); } if(missile!=null && targetDot > 0 && distanceToTarget < MissileLaunchParams.GetDynamicLaunchParams(missile, v.srf_velocity, v.transform.position).minLaunchRange && vessel.srfSpeed > idleSpeed) { //extending = true; //lastTargetPosition = v.transform.position; RequestExtend(lastTargetPosition); } if(regainEnergy && angleToTarget > 30f) { RegainEnergy(s, target - vesselTransform.position); return; } else { useVelRollTarget = true; FlyToPosition(s, target); return; } }
void FlyToPosition(FlightCtrlState s, Vector3 targetPosition) { if(!belowMinAltitude) { if(weaponManager && Time.time - weaponManager.timeBombReleased < 1.5f) { targetPosition = vessel.transform.position + vessel.srf_velocity; } targetPosition = FlightPosition(targetPosition, minAltitude); targetPosition = vesselTransform.position + ((targetPosition - vesselTransform.position).normalized * 100); } 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; //ang vel Vector3 localAngVel = vessel.angularVelocity; //test Vector3 currTargetDir = (targetPosition-vesselTransform.position).normalized; if(steerMode == SteerModes.NormalFlight) { float gRotVel = ((10f * maxAllowedGForce) / ((float)vessel.srfSpeed)); //currTargetDir = Vector3.RotateTowards(prevTargetDir, currTargetDir, gRotVel*Mathf.Deg2Rad, 0); } Vector3 targetAngVel = Vector3.Cross(prevTargetDir, currTargetDir)/Time.fixedDeltaTime; Vector3 localTargetAngVel = vesselTransform.InverseTransformVector(targetAngVel); prevTargetDir = currTargetDir; targetPosition = vessel.transform.position + (currTargetDir * 100); if(BDArmorySettings.DRAW_DEBUG_LINES) { flyingToPosition = targetPosition; } //test poststall float AoA = Vector3.Angle(vessel.ReferenceTransform.up, vessel.srf_velocity); if(AoA > 30f) { steerMode = SteerModes.Aiming; } //slow down for tighter turns float velAngleToTarget = Vector3.Angle(targetPosition-vesselTransform.position, vessel.srf_velocity); float normVelAngleToTarget = Mathf.Clamp(velAngleToTarget, 0, 90)/90; float speedReductionFactor = 1.25f; float finalSpeed = Mathf.Min(speedController.targetSpeed, Mathf.Clamp(maxSpeed - (speedReductionFactor * normVelAngleToTarget), idleSpeed, maxSpeed)); debugString += "\nFinal Target Speed: " + finalSpeed.ToString("0.0"); AdjustThrottle(finalSpeed, useBrakes, useAB); if(steerMode == SteerModes.Aiming) { localAngVel -= localTargetAngVel; } 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 = 0.25f; //postPitchFactor = 0.8f; } else//(steerMode == SteerModes.Aiming) { targetDirection = vesselTransform.InverseTransformDirection(targetPosition-vesselTransform.position).normalized; targetDirection = Vector3.RotateTowards(Vector3.up, targetDirection, 25 * Mathf.Deg2Rad, 0); targetDirectionYaw = targetDirection; /* if(command == PilotCommands.Follow) { postYawFactor = 0.45f; postPitchFactor = 1f; } else { postYawFactor = 1f; postPitchFactor = 1.2f; } */ } pitchError = VectorUtils.SignedAngle(Vector3.up, Vector3.ProjectOnPlane(targetDirection, Vector3.right), Vector3.back); yawError = VectorUtils.SignedAngle(Vector3.up, Vector3.ProjectOnPlane(targetDirectionYaw, Vector3.forward), Vector3.right); //test debugString += "\n finalMaxSteer: " + finalMaxSteer; //roll Vector3 currentRoll = -vesselTransform.forward; float rollUp = (steerMode == SteerModes.Aiming ? 5f : 10f); if(steerMode == SteerModes.NormalFlight) { rollUp += (1 - finalMaxSteer) * 10f; } rollTarget = (targetPosition + (rollUp * upDirection)) - vesselTransform.position; //test if(steerMode == SteerModes.Aiming && !belowMinAltitude) { angVelRollTarget = -140 * vesselTransform.TransformVector(Quaternion.AngleAxis(90f, Vector3.up) * localTargetAngVel); rollTarget += angVelRollTarget; } if(command == PilotCommands.Follow && useRollHint) { rollTarget = -commandLeader.vessel.ReferenceTransform.forward; } // if(belowMinAltitude) { rollTarget = vessel.upAxis * 100; } if(useVelRollTarget && !belowMinAltitude) { rollTarget = Vector3.ProjectOnPlane(rollTarget, vessel.srf_velocity); currentRoll = Vector3.ProjectOnPlane(currentRoll, vessel.srf_velocity); } else { rollTarget = Vector3.ProjectOnPlane(rollTarget, vesselTransform.up); } //v/q float dynamicAdjustment = Mathf.Clamp(16*(float)(vessel.srfSpeed/vessel.dynamicPressurekPa), 0, 1.2f); float rollError = Misc.SignedAngle(currentRoll, rollTarget, vesselTransform.right); float steerRoll = (steerMult * 0.0015f * rollError); float rollDamping = (.10f * steerDamping * -localAngVel.y); steerRoll -= rollDamping; steerRoll *= dynamicAdjustment; if(steerMode == SteerModes.NormalFlight) { //premature dive fix pitchError = pitchError * Mathf.Clamp01((21 - Mathf.Exp(Mathf.Abs(rollError) / 30)) / 20); } float steerPitch = (0.015f * steerMult * pitchError) - (steerDamping * -localAngVel.x); float steerYaw = (0.005f * steerMult * yawError) - (steerDamping * 0.2f * -localAngVel.z); pitchIntegral += pitchError; steerPitch *= dynamicAdjustment; steerYaw *= dynamicAdjustment; float pitchKi = 0.1f * (pitchKiAdjust/5); //This is what should be allowed to be tweaked by the player, just like the steerMult, it is very low right now pitchIntegral = Mathf.Clamp(pitchIntegral, -0.2f / (pitchKi * dynamicAdjustment), 0.2f / (pitchKi * dynamicAdjustment)); //0.2f is the limit of the integral variable, making it bigger increases overshoot steerPitch += pitchIntegral * pitchKi * dynamicAdjustment; //Adds the integral component to the mix float roll = Mathf.Clamp(steerRoll, -maxSteer, maxSteer); s.roll = roll; s.yaw = Mathf.Clamp(steerYaw, -finalMaxSteer, finalMaxSteer); s.pitch = Mathf.Clamp(steerPitch, Mathf.Min(-finalMaxSteer, -0.2f), finalMaxSteer); }
void FlyToPosition(FlightCtrlState s, Vector3 targetPosition) { if(!belowMinAltitude) { if(weaponManager && Time.time - weaponManager.timeBombReleased < 1.5f) { targetPosition = vessel.transform.position + vessel.srf_velocity; } targetPosition = FlightPosition(targetPosition, minAltitude); targetPosition = vesselTransform.position + ((targetPosition - vesselTransform.position).normalized * 100); } 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; //ang vel Vector3 localAngVel = vessel.angularVelocity; //test Vector3 currTargetDir = (targetPosition-vesselTransform.position).normalized; if(steerMode == SteerModes.NormalFlight) { float gRotVel = ((10f * maxAllowedGForce) / ((float)vessel.srfSpeed)); //currTargetDir = Vector3.RotateTowards(prevTargetDir, currTargetDir, gRotVel*Mathf.Deg2Rad, 0); } Vector3 targetAngVel = Vector3.Cross(prevTargetDir, currTargetDir)/Time.fixedDeltaTime; Vector3 localTargetAngVel = vesselTransform.InverseTransformVector(targetAngVel); prevTargetDir = currTargetDir; targetPosition = vessel.transform.position + (currTargetDir * 100); if(BDArmorySettings.DRAW_DEBUG_LINES) { flyingToPosition = targetPosition; } //test poststall float AoA = Vector3.Angle(vessel.ReferenceTransform.up, vessel.srf_velocity); if(AoA > 30f) { steerMode = SteerModes.Aiming; } //slow down for tighter turns float velAngleToTarget = Vector3.Angle(targetPosition-vesselTransform.position, vessel.srf_velocity); float normVelAngleToTarget = Mathf.Clamp(velAngleToTarget, 0, 90)/90; float speedReductionFactor = 1.25f; float finalSpeed = Mathf.Min(speedController.targetSpeed, Mathf.Clamp(maxSpeed - (speedReductionFactor * normVelAngleToTarget), idleSpeed, maxSpeed)); debugString += "\nFinal Target Speed: " + finalSpeed.ToString("0.0"); AdjustThrottle(finalSpeed, useBrakes, useAB); if(steerMode == SteerModes.Aiming) { localAngVel -= localTargetAngVel; } 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 = 0.25f; postPitchFactor = 0.8f; } else//(steerMode == SteerModes.Aiming) { targetDirection = vesselTransform.InverseTransformDirection(targetPosition-vesselTransform.position).normalized; targetDirection = Vector3.RotateTowards(Vector3.up, targetDirection, 25 * Mathf.Deg2Rad, 0); targetDirectionYaw = targetDirection; if(command == PilotCommands.Follow) { postYawFactor = 0.45f; postPitchFactor = 1f; } else { postYawFactor = 1.75f; postPitchFactor = 2f; } } pitchError = VectorUtils.SignedAngle(Vector3.up, Vector3.ProjectOnPlane(targetDirection, Vector3.right), Vector3.back); yawError = VectorUtils.SignedAngle(Vector3.up, Vector3.ProjectOnPlane(targetDirectionYaw, Vector3.forward), Vector3.right); //test debugString += "\n finalMaxSteer: " + finalMaxSteer; float steerPitch = (postPitchFactor * 0.015f * steerMult * pitchError) - (postPitchFactor * steerDamping * -localAngVel.x); float steerYaw = (postYawFactor * 0.020f * steerMult * yawError) - (postYawFactor * steerDamping * 0.64f * -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; float rollUp = (steerMode == SteerModes.Aiming ? 5f : 10f); if(steerMode == SteerModes.NormalFlight) { rollUp += (1 - finalMaxSteer) * 10f; } rollTarget = (targetPosition + (rollUp * upDirection)) - vesselTransform.position; //test if(steerMode == SteerModes.Aiming && !belowMinAltitude) { angVelRollTarget = -140 * vesselTransform.TransformVector(Quaternion.AngleAxis(90f, Vector3.up) * localTargetAngVel); rollTarget += angVelRollTarget; } if(command == PilotCommands.Follow && useRollHint) { rollTarget = -commandLeader.vessel.ReferenceTransform.forward; } // if(belowMinAltitude) { rollTarget = vessel.upAxis * 100; } if(useVelRollTarget && !belowMinAltitude) { rollTarget = Vector3.ProjectOnPlane(rollTarget, vessel.srf_velocity); currentRoll = Vector3.ProjectOnPlane(currentRoll, vessel.srf_velocity); } else { rollTarget = Vector3.ProjectOnPlane(rollTarget, vesselTransform.up); } float rollError = Misc.SignedAngle(currentRoll, rollTarget, vesselTransform.right); float steerRoll = (steerMult * 0.0015f * rollError); float rollDamping = (.10f * steerDamping * -localAngVel.y); steerRoll -= rollDamping; float roll = Mathf.Clamp(steerRoll, -maxSteer, maxSteer); s.roll = roll; }
void UpdateFollowCommand(FlightCtrlState s) { if (!commandLeader) { ReleaseCommand(); return; } threatLevel = 1; steerMode = SteerModes.NormalFlight; s.mainThrottle = 1; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, false); commandSpeed = commandLeader.vessel.srfSpeed; commandHeading = commandLeader.vessel.srf_velocity.normalized; //formation position commandPosition = GetFormationPosition(); float distanceToPos = Vector3.Distance(vesselTransform.position, commandPosition); //if(distanceToPos > 100) //{ float dotToPos = Vector3.Dot(vesselTransform.up, commandPosition - vesselTransform.position); Vector3 flyPos = commandPosition + (15 * commandHeading); useRollHint = false; if (distanceToPos < 300) { steerMode = SteerModes.Aiming; if (dotToPos < 0) { flyPos = commandPosition + (315 * commandHeading); s.mainThrottle = 0; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); steerMode = SteerModes.NormalFlight; } if (distanceToPos < 15) { useRollHint = true; } } double finalMaxSpeed = commandSpeed; if (dotToPos > 0) { finalMaxSpeed += (distanceToPos / 8); } if (vessel.srfSpeed > finalMaxSpeed) { s.mainThrottle = 0; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); } FlyToPosition(s, flyPos); }