diff --git a/BDArmory/Ammo/PooledBullet.cs b/BDArmory/Ammo/PooledBullet.cs
index 72eb74ae9..f222804f1 100644
--- a/BDArmory/Ammo/PooledBullet.cs
+++ b/BDArmory/Ammo/PooledBullet.cs
@@ -539,15 +539,22 @@ public void PostCollisions()
{
if (fuzeType == BulletFuzeTypes.Delay || fuzeType == BulletFuzeTypes.Penetrating)
{
- fuzeTriggered = true;
- delayedDetonationRoutine = StartCoroutine(DelayedDetonationRoutine());
+ if (!fuzeTriggered)
+ {
+ fuzeTriggered = true;
+ delayedDetonationRoutine = StartCoroutine(DelayedDetonationRoutine());
+ }
}
else //if (fuzeType != BulletFuzeTypes.None)
{
if (HEType != PooledBulletTypes.Slug)
+ {
ExplosionFx.CreateExplosion(currentPosition, tntMass, explModelPath, explSoundPath, ExplosionSourceType.Bullet, caliber, null, sourceVesselName, null, null, default, -1, false, bulletMass, -1, dmgMult);
+ }
if (nuclear)
+ {
NukeFX.CreateExplosion(currentPosition, ExplosionSourceType.Bullet, sourceVesselName, bullet.DisplayName, 0, tntMass * 200, tntMass, tntMass, EMP, blastSoundPath, flashModelPath, shockModelPath, blastModelPath, plumeModelPath, debrisModelPath, "", "");
+ }
hasDetonated = true;
if (BDArmorySettings.waterHitEffect && FlightGlobals.currentMainBody.ocean) FXMonger.Splash(currentPosition, caliber / 2);
KillBullet();
@@ -1510,7 +1517,11 @@ bool BulletHitAnalysis(BulletHit bulletHit, float period)
// Should penetrating fuzes also get triggered here? I guess they should...
if (fuzeType == BulletFuzeTypes.Delay || fuzeType == BulletFuzeTypes.Penetrating)
{
- fuzeTriggered = true;
+ if (!fuzeTriggered)
+ {
+ fuzeTriggered = true;
+ delayedDetonationRoutine = StartCoroutine(DelayedDetonationRoutine());
+ }
}
}
}
diff --git a/BDArmory/BDArmory.csproj b/BDArmory/BDArmory.csproj
index e8cb0f468..e1eb3e12b 100644
--- a/BDArmory/BDArmory.csproj
+++ b/BDArmory/BDArmory.csproj
@@ -345,6 +345,7 @@
+
diff --git a/BDArmory/Control/MissileFire.cs b/BDArmory/Control/MissileFire.cs
index 977d433ad..464cb517f 100644
--- a/BDArmory/Control/MissileFire.cs
+++ b/BDArmory/Control/MissileFire.cs
@@ -1919,7 +1919,7 @@ public override void OnUpdate()
{
MissileLauncher msl = CurrentMissile as MissileLauncher;
Vector3 missileForward = ml.GetForwardTransform();
- Vector3 missilePos = ml.transform.position;
+ Vector3 missilePos = ml.MissileReferenceTransform.position;
for (int i = 0; i < rwr.pingsData.Length; i++)
{
Vector3 position;
@@ -2062,17 +2062,26 @@ void UpdateWeaponIndex()
void UpdateGuidanceTargets()
{
UpdateHMDRay();
+ CalculateMissilesAway();
+ ClearQueuedLaunches();
+
+ if (guardFiringMissile)
+ {
+ SearchForLaserPoint(currFiringMissile);
+ SearchForHeatTarget(currFiringMissile, currFiringTarget);
+ SearchForRadarSource(currFiringMissile);
+ return;
+ }
+
if (weaponIndex > 0 &&
(selectedWeapon.GetWeaponClass() == WeaponClasses.Missile ||
selectedWeapon.GetWeaponClass() == WeaponClasses.SLW ||
selectedWeapon.GetWeaponClass() == WeaponClasses.Bomb))
{
- SearchForLaserPoint();
+ SearchForLaserPoint(CurrentMissile);
SearchForHeatTarget(CurrentMissile);
- SearchForRadarSource();
+ SearchForRadarSource(CurrentMissile);
}
- CalculateMissilesAway();
- ClearQueuedLaunches();
}
public void ToggleHMD()
@@ -2418,7 +2427,7 @@ void OnGUI()
if (incomingMissileVessel)
{
GUIUtils.DrawLineBetweenWorldPositions(part.transform.position,
- incomingMissileVessel.transform.position, 5, Color.cyan);
+ incomingMissileVessel.CoM, 5, Color.cyan);
}
if (guardTarget != null)
GUIUtils.DrawLineBetweenWorldPositions(guardTarget.LandedOrSplashed ? guardTarget.CoM + ((guardTarget.vesselSize.y / 2) * vessel.up) : guardTarget.CoM,
@@ -2775,14 +2784,20 @@ float GetMissileTurretFireAngle(MissileLauncher mlauncher)
return (mTurret.turretLoft, mTurret.turretLoftFac);
}
- IEnumerator GuardMissileRoutine(Vessel targetVessel, MissileBase ml)
+ MissileBase currFiringMissile = null;
+ TargetInfo currFiringTarget = null;
+
+ IEnumerator GuardMissileRoutine(TargetInfo tgtInfo, MissileBase ml)
{
if (ml && !guardFiringMissile)
{
bool dumbfiring = false;
guardFiringMissile = true;
+ currFiringMissile = ml;
+ currFiringTarget = tgtInfo;
var wait = new WaitForFixedUpdate();
- float tryLockTime = targetVessel.IsMissile() ? 0.05f : 0.25f; // More urgency for incoming missiles
+ Vessel targetVessel = tgtInfo.Vessel;
+ float tryLockTime = tgtInfo.isMissile ? 0.05f : 0.25f; // More urgency for incoming missiles
targetParts.Clear();
if (!targetCoM)
{
@@ -3593,6 +3608,8 @@ IEnumerator GuardMissileRoutine(Vessel targetVessel, MissileBase ml)
dumbfiring = false;
}
guardFiringMissile = false;
+ currFiringTarget = null;
+ currFiringMissile = null;
}
}
IEnumerator GuardBombRoutine()
@@ -6332,7 +6349,7 @@ bool SmartPickWeapon_EngagementEnvelope(TargetInfo target)
candidateAccel = 1;
candidatePriority = Mathf.RoundToInt(mm.priority);
- if (vessel.Splashed && FlightGlobals.getAltitudeAtPos(mlauncher.transform.position) < -5) continue;
+ if (vessel.Splashed && FlightGlobals.getAltitudeAtPos(mlauncher.MissileReferenceTransform.position) < -5) continue;
if (targetWeapon != null && targetWeaponPriority > candidatePriority)
continue; //keep higher priority weapon
if (candidateDetDist + candidateAccel > targetWeaponTDPS)
@@ -6724,7 +6741,7 @@ bool SmartPickWeapon_EngagementEnvelope(TargetInfo target)
bool antiRad = mlauncher.TargetingMode == MissileBase.TargetingModes.AntiRad;
float heatThresh = mlauncher.heatThreshold;
if (EMP && target.isDebilitated) continue;
- if (vessel.Splashed && (!surfaceAI || surfaceAI.SurfaceType != AIUtils.VehicleMovementType.Submarine) && (BDArmorySettings.BULLET_WATER_DRAG && FlightGlobals.getAltitudeAtPos(mlauncher.transform.position) < -10)) continue; //allow submarine-mounted missiles; new launch depth check in launchAuth
+ if (vessel.Splashed && (!surfaceAI || surfaceAI.SurfaceType != AIUtils.VehicleMovementType.Submarine) && (BDArmorySettings.BULLET_WATER_DRAG && FlightGlobals.getAltitudeAtPos(mlauncher.MissileReferenceTransform.position) < -10)) continue; //allow submarine-mounted missiles; new launch depth check in launchAuth
if (targetWeapon != null && targetWeaponPriority > candidatePriority)
continue; //keep higher priority weapon
@@ -6803,7 +6820,7 @@ bool SmartPickWeapon_EngagementEnvelope(TargetInfo target)
{
candidateTDPS *= 0.001f; //no laserdot, skip to something else unless nothing else available
}
- float fovAngle = VectorUtils.Angle(mlauncher.GetForwardTransform(), targetVessel.CoM - mlauncher.transform.position);
+ float fovAngle = VectorUtils.Angle(mlauncher.GetForwardTransform(), targetVessel.CoM - mlauncher.MissileReferenceTransform.position);
if (fovAngle > mlauncher.missileFireAngle && mlauncher.missileFireAngle < mlauncher.maxOffBoresight * 0.75f)
{
candidateTDPS *= mlauncher.missileFireAngle / fovAngle; //missile is clamped to a narrow boresight - do we have anything with a wider FoV we should start with?
@@ -6817,7 +6834,7 @@ bool SmartPickWeapon_EngagementEnvelope(TargetInfo target)
//candidateTurning = ((MissileLauncher)item.Current).maxTurnRateDPS; //for anti-aircraft, prioritize detonation dist and turn capability
candidatePriority = Mathf.RoundToInt(mm.priority);
- if ((!surfaceAI || surfaceAI.SurfaceType != AIUtils.VehicleMovementType.Submarine) && vessel.Splashed && (BDArmorySettings.BULLET_WATER_DRAG && FlightGlobals.getAltitudeAtPos(mlauncher.transform.position) < 0)) continue;
+ if ((!surfaceAI || surfaceAI.SurfaceType != AIUtils.VehicleMovementType.Submarine) && vessel.Splashed && (BDArmorySettings.BULLET_WATER_DRAG && FlightGlobals.getAltitudeAtPos(mlauncher.MissileReferenceTransform.position) < 0)) continue;
if (targetWeapon != null && targetWeaponPriority > candidatePriority)
continue; //keep higher priority weapon
@@ -7510,7 +7527,7 @@ bool SmartPickWeapon_EngagementEnvelope(TargetInfo target)
//targetWeaponPriority = candidatePriority;
}
}
- float fovAngle = VectorUtils.Angle(Missile.GetForwardTransform(), targetVessel.CoM - Missile.transform.position);
+ float fovAngle = VectorUtils.Angle(Missile.GetForwardTransform(), targetVessel.CoM - Missile.MissileReferenceTransform.position);
if (fovAngle > Missile.missileFireAngle && Missile.missileFireAngle < Missile.maxOffBoresight * 0.75f)
{
candidateYield *= Missile.missileFireAngle / fovAngle; //missile is clamped to a narrow boresight - do we have anything with a wider FoV we should start with?
@@ -8292,24 +8309,22 @@ public bool CanSeeTarget(MissileBase target)
return false;
}
- void SearchForRadarSource()
+ void SearchForRadarSource(MissileBase currMissile)
{
antiRadTargetAcquired = false;
antiRadiationTarget = Vector3.zero;
if (rwr && rwr.rwrEnabled)
{
float closestAngle = 360;
- MissileBase missile = CurrentMissile;
-
- if (!missile) return;
+
+ if (!currMissile) return;
+ if (currMissile.TargetingMode != MissileBase.TargetingModes.AntiRad) return;
- float maxOffBoresight = missile.maxOffBoresight;
+ float maxOffBoresight = currMissile.maxOffBoresight;
- if (missile.TargetingMode != MissileBase.TargetingModes.AntiRad) return;
-
- MissileLauncher ml = CurrentMissile as MissileLauncher;
- Vector3 missilePos = missile.transform.position;
- Vector3 missileForward = missile.GetForwardTransform();
+ //MissileLauncher ml = currMissile as MissileLauncher;
+ Vector3 missilePos = currMissile.MissileReferenceTransform.position;
+ Vector3 missileForward = currMissile.GetForwardTransform();
//Debug.Log($"antiradTgt count: {(ml.antiradTargets != null ? ml.antiradTargets.Length : "null")}");
//if (ml.antiradTargets == null) ml.ParseAntiRadTargetTypes();
for (int i = 0; i < rwr.pingsData.Length; i++)
@@ -8317,7 +8332,7 @@ void SearchForRadarSource()
RWRSignatureData currPing = rwr.pingsData[i];
// These CanDetectRWRThreat function calls can probably be replaced with the actual code,
// but I think this is more readable and maintainable for anyone not familiar with bitmasks
- if (currPing.exists && RadarWarningReceiver.CanDetectRWRThreat(ml.antiradTargets, currPing.signalType))
+ if (currPing.exists && RadarWarningReceiver.CanDetectRWRThreat(currMissile.antiradTargets, currPing.signalType))
{
Vector3 position = currPing.position;
float angle = VectorUtils.Angle(position - missilePos, missileForward);
@@ -8334,15 +8349,14 @@ void SearchForRadarSource()
}
}
- void SearchForLaserPoint()
+ void SearchForLaserPoint(MissileBase currMissile)
{
- MissileBase ml = CurrentMissile;
- if (!ml || !(ml.TargetingMode == MissileBase.TargetingModes.Laser || ml.TargetingMode == MissileBase.TargetingModes.Gps))
+ if (!currMissile || !(currMissile.TargetingMode == MissileBase.TargetingModes.Laser || currMissile.TargetingMode == MissileBase.TargetingModes.Gps))
{
return;
}
- MissileLauncher launcher = ml as MissileLauncher;
+ MissileLauncher launcher = currMissile as MissileLauncher;
if (launcher != null)
{
bool parentOnly = launcher.GuidanceMode == GuidanceModes.BeamRiding || launcher.GuidanceMode == GuidanceModes.CLOS || launcher.GuidanceMode == GuidanceModes.CLOSThreePoint || launcher.GuidanceMode == GuidanceModes.CLOSLead;
@@ -8350,7 +8364,7 @@ void SearchForLaserPoint()
}
else
{
- foundCam = BDATargetManager.GetLaserTarget((BDModularGuidance)ml, false, Team);
+ foundCam = BDATargetManager.GetLaserTarget((BDModularGuidance)currMissile, false, Team);
}
if (foundCam)
@@ -8363,7 +8377,7 @@ void SearchForLaserPoint()
}
}
- void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = null)
+ void SearchForHeatTarget(MissileBase currMissile, TargetInfo missileTgt = null)
{
if (currMissile == null)
{
@@ -8393,7 +8407,7 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
// If not missile with uncaged lock or torpedo
if (!currMissile.uncagedLock && currMissile.GuidanceMode != MissileBase.GuidanceModes.SLW)
{
- heatTarget = BDATargetManager.GetHeatTarget(vessel, vessel, new Ray(adjustedPos, forward), TargetSignatureData.noTarget, scanRadius, currMissile.heatThreshold, currMissile.frontAspectHeatModifier, currMissile.uncagedLock, currMissile.targetCoM, currMissile.lockedSensorFOVBias, currMissile.lockedSensorVelocityBias, currMissile.lockedSensorVelocityMagnitudeBias, currMissile.lockedSensorMinAngularVelocity, this, targetMissile != null ? targetMissile : guardMode ? currentTarget : null, IFF: currMissile.hasIFF);
+ heatTarget = BDATargetManager.GetHeatTarget(vessel, vessel, new Ray(adjustedPos, forward), TargetSignatureData.noTarget, scanRadius, currMissile.heatThreshold, currMissile.frontAspectHeatModifier, currMissile.uncagedLock, currMissile.targetCoM, currMissile.lockedSensorFOVBias, currMissile.lockedSensorVelocityBias, currMissile.lockedSensorVelocityMagnitudeBias, currMissile.lockedSensorMinAngularVelocity, this, missileTgt != null ? missileTgt : guardMode ? currentTarget : null, IFF: currMissile.hasIFF);
return;
}
@@ -8405,7 +8419,7 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
// Prioritize radar target
if (vesselRadarData.locked)
{
- if (targetMissile == null) //uncaged radar lock
+ if (missileTgt == null) //uncaged radar lock
{
currTarget = vesselRadarData.lockedTargetData.targetData;
radarTarget = true;
@@ -8415,7 +8429,7 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
List possibleTargets = vesselRadarData.GetLockedTargets();
for (int i = 0; i < possibleTargets.Count; i++)
{
- if (possibleTargets[i].vessel == targetMissile.Vessel)
+ if (possibleTargets[i].vessel == missileTgt.Vessel)
{
currTarget = possibleTargets[i];
radarTarget = true;
@@ -8426,10 +8440,10 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
}
else if (_irstsEnabled && !(HMDcond && _isHMDEnabled)) // Try IRST if we don't have an HMD
{
- if (targetMissile == null)
+ if (missileTgt == null)
currTarget = vesselRadarData.activeIRTarget(guardTarget, this); //point seeker at active target's IR return
else
- currTarget = vesselRadarData.activeIRTarget(targetMissile.Vessel, this);
+ currTarget = vesselRadarData.activeIRTarget(missileTgt.Vessel, this);
}
}
@@ -8440,7 +8454,7 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
if (currTarget.exists)
{
// Override target if angle is > 2 * lockedSensorFOV
- if (VectorUtils.Angle(currTarget.position - vessel.CoM, targetMissile ? (targetMissile.position - vessel.CoM) : _HMDray.direction) > 2f * currMissile.lockedSensorFOV)
+ if (VectorUtils.Angle(currTarget.position - vessel.CoM, missileTgt ? (missileTgt.position - vessel.CoM) : _HMDray.direction) > 2f * currMissile.lockedSensorFOV)
{
currTarget = TargetSignatureData.noTarget;
}
@@ -8448,9 +8462,9 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
if (!currTarget.exists)
{
- if (targetMissile)
+ if (missileTgt)
{
- HMDTarget = CanSeeTarget(targetMissile.MissileBaseModule);
+ HMDTarget = CanSeeTarget(missileTgt.MissileBaseModule);
}
else
{
@@ -8477,9 +8491,9 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
{
if (HMDTarget)
{
- if (targetMissile)
+ if (missileTgt)
{
- direction = VectorUtils.Angle(targetMissile.position - currMissile.MissileReferenceTransform.position, forward) < maxOffBoresight ? (targetMissile.position - adjustedPos)
+ direction = VectorUtils.Angle(missileTgt.position - currMissile.MissileReferenceTransform.position, forward) < maxOffBoresight ? (missileTgt.position - adjustedPos)
: forward;
}
else
@@ -8494,8 +8508,8 @@ void SearchForHeatTarget(MissileBase currMissile, TargetInfo targetMissile = nul
// TECHNICALLY uncagedLock = false missiles should NOT be allowed to point in any direction other than forward prior to launch, but that may be too restrictive...
// remove AI target check/move to a missile .cfg option to allow older gen heaters?
if (currMissile.GuidanceMode != MissileBase.GuidanceModes.SLW || (currMissile.GuidanceMode == MissileBase.GuidanceModes.SLW && currMissile.activeRadarRange > 0))
- heatTarget = BDATargetManager.GetHeatTarget(vessel, vessel, new Ray(adjustedPos, direction), TargetSignatureData.noTarget, scanRadius, currMissile.heatThreshold, currMissile.frontAspectHeatModifier, currMissile.uncagedLock, currMissile.targetCoM, currMissile.lockedSensorFOVBias, currMissile.lockedSensorVelocityBias, currMissile.lockedSensorVelocityMagnitudeBias, currMissile.lockedSensorMinAngularVelocity, this, targetMissile != null ? targetMissile : guardMode ? currentTarget : null, IFF: currMissile.hasIFF);
- else heatTarget = BDATargetManager.GetAcousticTarget(vessel, vessel, new Ray(adjustedPos, direction), TargetSignatureData.noTarget, scanRadius, currMissile.heatThreshold, currMissile.targetCoM, currMissile.lockedSensorFOVBias, currMissile.lockedSensorVelocityBias, currMissile.lockedSensorVelocityMagnitudeBias, currMissile.lockedSensorMinAngularVelocity, this, targetMissile != null ? targetMissile : guardMode ? currentTarget : null, IFF: currMissile.hasIFF);
+ heatTarget = BDATargetManager.GetHeatTarget(vessel, vessel, new Ray(adjustedPos, direction), TargetSignatureData.noTarget, scanRadius, currMissile.heatThreshold, currMissile.frontAspectHeatModifier, currMissile.uncagedLock, currMissile.targetCoM, currMissile.lockedSensorFOVBias, currMissile.lockedSensorVelocityBias, currMissile.lockedSensorVelocityMagnitudeBias, currMissile.lockedSensorMinAngularVelocity, this, missileTgt != null ? missileTgt : guardMode ? currentTarget : null, IFF: currMissile.hasIFF);
+ else heatTarget = BDATargetManager.GetAcousticTarget(vessel, vessel, new Ray(adjustedPos, direction), TargetSignatureData.noTarget, scanRadius, currMissile.heatThreshold, currMissile.targetCoM, currMissile.lockedSensorFOVBias, currMissile.lockedSensorVelocityBias, currMissile.lockedSensorVelocityMagnitudeBias, currMissile.lockedSensorMinAngularVelocity, this, missileTgt != null ? missileTgt : guardMode ? currentTarget : null, IFF: currMissile.hasIFF);
}
bool CrossCheckWithRWR(TargetInfo v)
@@ -8551,9 +8565,8 @@ public void SendTargetDataToMissile(MissileBase ml, Vessel targetVessel, bool cl
{
ml.lockedCamera = foundCam;
ml.TargetAcquired = true;
-
if (!targetCoM && targetNum >= targetParts.Count) targetNum -= targetParts.Count * Mathf.FloorToInt((targetNum / targetParts.Count));
- if (guardMode && guardTarget != null && (foundCam.groundTargetPosition - (targetCoM ? targetVessel.CoM : targetParts[targetNum].transform.position)).sqrMagnitude < 10 * 10) validTarget = true; //*highly* unlikely laser-guided missiles used for missile interception, so leaving these guardTarget
+ if (guardMode && (targetVessel ? targetVessel : (targetVessel = guardTarget)) && (foundCam.groundTargetPosition - (targetCoM ? targetVessel.CoM : targetParts[targetNum].transform.position)).sqrMagnitude < 10 * 10) validTarget = true; //*highly* unlikely laser-guided missiles used for missile interception, so leaving these guardTarget
}
else
{
@@ -8656,7 +8669,10 @@ public void SendTargetDataToMissile(MissileBase ml, Vessel targetVessel, bool cl
}
}
else
+ {
ml.radarTarget = vesselRadarData.lockedTargetData.targetData;
+ }
+
ml.vrd = vesselRadarData;
vesselRadarData.LastMissile = ml;
@@ -8687,6 +8703,10 @@ public void SendTargetDataToMissile(MissileBase ml, Vessel targetVessel, bool cl
case MissileBase.TargetingModes.None:
{
ml.TargetAcquired = true;
+ if (guardMode && null == targetVessel)
+ {
+ targetVessel = guardTarget;
+ }
validTarget = true;
break;
}
@@ -8795,6 +8815,10 @@ public void SendTargetDataToMissile(MissileBase ml, Vessel targetVessel, bool cl
{
if (ml.GetWeaponClass() == WeaponClasses.Bomb)
{
+ if (guardMode && null == targetVessel)
+ {
+ targetVessel = guardTarget;
+ }
validTarget = true;
}
break;
@@ -8984,7 +9008,7 @@ void GuardMode()
//&& (CurrentMissile.TargetingMode != MissileBase.TargetingModes.Radar || (vesselRadarData != null && (!vesselRadarData.locked || vesselRadarData.lockedTargetData.vessel == guardTarget)))) // Allow firing multiple missiles at the same target. FIXME This is a stop-gap until proper multi-locking support is available.
{
if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileFire]: {vessel.vesselName} firing {(unguidedWeapon ? "unguided" : "")} missile");
- StartCoroutine(GuardMissileRoutine(guardTarget, CurrentMissile));
+ StartCoroutine(GuardMissileRoutine(currentTarget, CurrentMissile));
}
}
else if (BDArmorySettings.DEBUG_MISSILES)
@@ -9648,7 +9672,7 @@ public void PointDefenseTurretFiring()
if (TurretID >= PDMslTgts.Count) TurretID = 0;
if (PDMslTgts.Count > 0)
{
- if (PDMslTgts[TurretID].Vessel != null && PDMslTgts[TurretID].transform.position.FurtherFromThan(weapon.fireTransforms[0].position, weapon.engageRangeMax * 1.25f)) TurretID = 0; //reset cycle so out of range guns engage closer targets
+ if (PDMslTgts[TurretID].Vessel != null && PDMslTgts[TurretID].position.FurtherFromThan(weapon.fireTransforms[0].position, weapon.engageRangeMax * 1.25f)) TurretID = 0; //reset cycle so out of range guns engage closer targets
if (PDMslTgts[TurretID].Vessel != null)
{
bool viableTarget = true;
@@ -9918,16 +9942,18 @@ public void PointDefenseTurretFiring()
}
// Look for a better way to do this...
- SearchForHeatTarget(currMissile, PDMslTgts[MissileID]);
+ //SearchForHeatTarget(currMissile, PDMslTgts[MissileID]);
+ Vector3 missilePos = currMissile.MissileReferenceTransform.position + 5f * currMissile.GetForwardTransform();
+ TargetSignatureData currHeatTarget = BDATargetManager.GetHeatTarget(vessel, vessel, new Ray(missilePos, targetVessel.CoM - missilePos), TargetSignatureData.noTarget, 0.5f * currMissile.lockedSensorFOV, currMissile.heatThreshold, currMissile.frontAspectHeatModifier, currMissile.uncagedLock, currMissile.targetCoM, currMissile.lockedSensorFOVBias, currMissile.lockedSensorVelocityBias, currMissile.lockedSensorVelocityMagnitudeBias, currMissile.lockedSensorMinAngularVelocity, this, PDMslTgts[MissileID], IFF: currMissile.hasIFF);
// If no heat target -> we're probably out of view
- if (!heatTarget.exists)
+ if (!currHeatTarget.exists)
{
continue;
}
// If we get decoyed -> we're gonna need a better missile, so skip this one
- if (heatTarget.isDecoy)
+ if (currHeatTarget.isDecoy)
{
// Write down the missile type that failed to lock
//if (logging)
@@ -9938,7 +9964,7 @@ public void PointDefenseTurretFiring()
}
// If we haven't gotten a heat target, continue
- if (heatTarget.vessel != targetVessel)
+ if (currHeatTarget.vessel != targetVessel)
{
continue;
}
@@ -9963,9 +9989,8 @@ public void PointDefenseTurretFiring()
//need to see if missile is turreted (and is a unique turret we haven't seen yet); if so, check if target is within traverse, else see if target is within boresight
bool turreted = false;
MissileTurret mT = null;
- if (launcher && (launcher.missileTurret || launcher.multiLauncher && launcher.multiLauncher.turret))
+ if (launcher && (mT = launcher.missileTurret ? launcher.missileTurret : launcher.multiLauncher.turret))
{
- mT = launcher.missileTurret ? launcher.missileTurret : launcher.multiLauncher.turret;
if (!MslTurrets.Contains(mT))
{
turreted = true;
@@ -9976,7 +10001,7 @@ public void PointDefenseTurretFiring()
mT.SlavedAim();
}
}
- if (currMissile.customTurret.Count> 0)
+ if (currMissile.customTurret.Count > 0)
{
for (int i = 0; i < currMissile.customTurret.Count; i++)
{
@@ -9994,7 +10019,7 @@ public void PointDefenseTurretFiring()
//missileTarget = targetVessel;
//if (logging)
// Debug.Log($"[BDArmory.MissileFire] firing interceptor missile: {currMissile.shortName} at {targetVessel.name}");
- StartCoroutine(GuardMissileRoutine(targetVessel, currMissile));
+ StartCoroutine(GuardMissileRoutine(PDMslTgts[MissileID], currMissile));
break;
}
else
@@ -10129,7 +10154,7 @@ public bool GetLaunchAuthorization(Vessel targetV, MissileFire mf, MissileBase m
target = MissileGuidance.GetAirToAirFireSolution(missile, targetV);
}
- Vector3 missilePos = missile.transform.position;
+ Vector3 missilePos = missile.MissileReferenceTransform.position;
float boresightAngle = missile.maxOffBoresight * ((mf.vessel.LandedOrSplashed || targetV.LandedOrSplashed || missile.uncagedLock) ? 0.75f : 0.35f); // Allow launch at close to maxOffBoresight for ground targets or missiles with allAspect = true
if (unguidedWeapon || missile.TargetingMode == MissileBase.TargetingModes.None) // Override boresightAngle based on blast radius for unguidedWeapons or weapons with no targeting mode
diff --git a/BDArmory/Radar/RadarWarningReceiver.cs b/BDArmory/Radar/RadarWarningReceiver.cs
index 6bc9de2ea..19d38858c 100644
--- a/BDArmory/Radar/RadarWarningReceiver.cs
+++ b/BDArmory/Radar/RadarWarningReceiver.cs
@@ -160,11 +160,11 @@ public override void OnStart(StartState state)
if (HighLogic.LoadedSceneIsFlight)
{
pingsData = new RWRSignatureData[dataCount];
- MWSData = new RWRSignatureData[dataCount];
+ MWSData = new RWRSignatureData[2 *dataCount];
//pingWorldPositions = new Vector3[dataCount];
RWRSignatureData.ResetRWRSDArray(ref pingsData);
- launchWarnings = new RWRSignatureData[dataCount]; //new List();
- missileLockData = new RWRSignatureData[dataCount];
+ launchWarnings = new RWRSignatureData[2 * dataCount]; //new List();
+ missileLockData = new RWRSignatureData[2 * dataCount];
rwrIconLabelStyle = new GUIStyle();
rwrIconLabelStyle.alignment = TextAnchor.MiddleCenter;
@@ -431,7 +431,7 @@ private void CleanPings()
private void CleanMissileLocks()
{
- float currentTime = Time.time;
+ float currentTime = Time.time + Time.fixedDeltaTime;
while (_missileLockSize > 0)
{
int idx = _missileLockHead;
diff --git a/BDArmory/WeaponMounts/MissileTurret.cs b/BDArmory/WeaponMounts/MissileTurret.cs
index 73976609b..7c73bf397 100644
--- a/BDArmory/WeaponMounts/MissileTurret.cs
+++ b/BDArmory/WeaponMounts/MissileTurret.cs
@@ -94,6 +94,7 @@ public bool slavedGuard
[KSPField] public bool deployBlocksYaw = false; // Turret must deploy before yawing, turret must return to yaw standby position to stow/"undeploy".
[KSPField] public bool deployBlocksPitch = false; // Turret must deploy before pitching, turret must return to pitch standby position to stow/"undeploy".
public bool isReloading = false;
+ float _reloadUntil = 0;
[KSPField] public bool startsDeployed = false; //Turret starts in deployed position and only uses deploy anim for relaoding. TODO: proper reload anim support for turrets independent of deployAnim
//animation
@@ -112,7 +113,7 @@ public bool isDeployed()
//special
[KSPField] public bool activeMissileOnly = false;
- MissileFire WeaponManager
+ public MissileFire WeaponManager
{
get
{
@@ -123,6 +124,54 @@ MissileFire WeaponManager
}
MissileFire _weaponManager;
+ public float DeployIfBlocking(bool yaw)
+ {
+ if (!hasDeployAnimation)
+ {
+ turret.SetDeployFlag(true, true);
+ return 0;
+ }
+
+ // If not blocking, return 0 without doing anything
+ if (!(yaw ? deployBlocksYaw : deployBlocksPitch))
+ {
+ if (yaw)
+ {
+ turret.SetYawDeployFlag(true);
+ }
+ else
+ {
+ turret.SetPitchDeployFlag(true);
+ }
+ return 0;
+ }
+
+ bool reloadBlock = deployBlocksReload && isReloading;
+
+ // If no deploy animation or deployed and not reloading
+ if (!(deployAnimState.normalizedTime < 1 || reloadBlock)) return 0;
+
+ // If not blocked by reload
+ if (!reloadBlock)
+ {
+ if (deployAnimRoutine != null)
+ {
+ StopCoroutine(deployAnimRoutine);
+ }
+
+ deployAnimRoutine = StartCoroutine(DeployAnimation(true));
+
+ hasReturned = false;
+
+ return deployAnimState.length - deployAnimState.time;
+ }
+ else
+ {
+ // If blocked by reload, return time that reload completes at
+ return _reloadUntil - Time.fixedDeltaTime;
+ }
+ }
+
IEnumerator DeployAnimation(bool forward)
{
var wait = new WaitForFixedUpdate();
@@ -137,6 +186,9 @@ IEnumerator DeployAnimation(bool forward)
}
deployAnimState.normalizedTime = 1;
+
+ // Unblock turret
+ turret.SetDeployFlag(true, true);
}
else
{
@@ -144,6 +196,9 @@ IEnumerator DeployAnimation(bool forward)
yield return new WaitWhileFixed(() => pausingAfterShot);
+ // Block turret prior to undeploy
+ turret.SetDeployFlag(!deployBlocksYaw, !deployBlocksPitch);
+
while (deployAnimState.normalizedTime > 0)
{
deployAnimState.speed = -deployAnimationSpeed;
@@ -279,7 +334,7 @@ IEnumerator ReturnRoutine()
bool pitch = !turretEnabled || (deployBlocksPitch && deployBlocksReload);
bool yaw = !turretEnabled || (deployBlocksYaw && deployBlocksReload);
- while (turret != null && !turret.ReturnTurret(pitch, yaw))
+ while (turret != null && !turret.ReturnTurret(pitch, yaw, isReloading))
{
UpdateMissilePositions();
yield return new WaitForFixedUpdate();
@@ -325,6 +380,7 @@ public override void OnStart(StartState state)
if (tur.Current == null) continue;
if (tur.Current.turretID != turretID) continue;
turret = tur.Current;
+ turret.turretMissile = this;
break;
}
tur.Dispose();
@@ -473,12 +529,34 @@ public void SetSlavedGuard(bool slavedGuard, MissileBase ml)
}
}
+ public bool IsCurrentWMMissile()
+ {
+ MissileFire wm;
+ if (!(wm = WeaponManager)) return false;
+
+ if (!wm.CurrentMissile) return false;
+
+ return slavedGuard || wm.CurrentMissile.GetPartName() == activeMissile.GetPartName();
+ }
+
public void SlavedAim()
{
if (pausingAfterShot) return;
- bool deployCond = hasDeployAnimation && (deployAnimState.normalizedTime < 1 || isReloading);
+ bool deployCond = hasDeployAnimation && (deployAnimState.normalizedTime < 1 || (deployBlocksReload && isReloading));
+
+ turret.AimToTarget(slavedTargetPosition, !(deployCond && deployBlocksPitch), !(deployCond && deployBlocksYaw), IsCurrentWMMissile());
+ }
+
+ public void SetReloadBlock(float duration)
+ {
+ // Deploy must block reload and a deploy animation must exist before we block the turret
+ if (!(deployBlocksReload && hasDeployAnimation)) return;
+
+ _reloadUntil = Time.fixedDeltaTime + duration;
- turret.AimToTarget(slavedTargetPosition, !(deployCond && deployBlocksPitch), !(deployCond && deployBlocksYaw));
+ // We only block if the respective toggle is also enabled
+ if (deployBlocksPitch && turret.pitchAxisManager) turret.pitchAxisManager.SetTurretBlock(_reloadUntil);
+ if (deployBlocksYaw && turret.yawAxisManager) turret.yawAxisManager.SetTurretBlock(_reloadUntil);
}
const int mouseAimLayerMask = (int)(LayerMasks.Parts | LayerMasks.Scenery | LayerMasks.EVA | LayerMasks.Unknown19 | LayerMasks.Unknown23 | LayerMasks.Wheels);
@@ -523,8 +601,8 @@ void MouseAim()
FlightCamera.fetch.mainCamera.transform.position;
}
- bool deployCond = hasDeployAnimation && (deployAnimState.normalizedTime < 1 || isReloading);
- turret.AimToTarget(targetPosition, !(deployCond && deployBlocksPitch), !(deployCond && deployBlocksYaw));
+ bool deployCond = hasDeployAnimation && (deployAnimState.normalizedTime < 1 || (deployBlocksReload && isReloading));
+ turret.AimToTarget(targetPosition, !(deployCond && deployBlocksPitch), !(deployCond && deployBlocksYaw), IsCurrentWMMissile());
}
public void UpdateMissileChildren()
diff --git a/BDArmory/WeaponMounts/ModuleTurret.cs b/BDArmory/WeaponMounts/ModuleTurret.cs
index ee475812c..4d33d0622 100644
--- a/BDArmory/WeaponMounts/ModuleTurret.cs
+++ b/BDArmory/WeaponMounts/ModuleTurret.cs
@@ -5,6 +5,8 @@
using BDArmory.Settings;
using BDArmory.UI;
using BDArmory.Utils;
+using BDArmory.Weapons;
+using System.Collections.Generic;
namespace BDArmory.WeaponMounts
{
@@ -24,6 +26,16 @@ public class ModuleTurret : PartModule
public Transform referenceTransform { get; }
Transform _referenceTransform; //set this to gun's fireTransform
+ public ModuleWeapon turretWeapon = null;
+ public MissileTurret turretMissile = null;
+
+ public TurretAxisManager yawAxisManager = null;
+ public int yawAxisIndex = 0;
+ public TurretAxisManager pitchAxisManager = null;
+ public int pitchAxisIndex = 0;
+
+ [KSPField] public int turretPriority = 0;
+
[KSPField] public float pitchSpeedDPS;
[KSPField] public float yawSpeedDPS;
@@ -43,6 +55,7 @@ public class ModuleTurret : PartModule
UI_FloatRange(minValue = -90f, maxValue = 90f, stepIncrement = 0.5f, scene = UI_Scene.All, affectSymCounterparts = UI_Scene.None)]
public float yawStandbyAngle = 0;
Quaternion standbyLocalRotation;// = Quaternion.identity;
+ bool _yawStandbyAngleEnabled = true;
[KSPField(isPersistant = true)] public float minPitchLimit = 400;
[KSPField(isPersistant = true)] public float maxPitchLimit = 400;
@@ -70,6 +83,75 @@ public override void OnStart(StartState state)
{
base.OnStart(state);
+ SetupTransforms();
+
+ SetupTweakables();
+
+ if (yawTransform && !yawAxisManager)
+ {
+ yawAxisManager = part.gameObject.AddComponent();
+ if (!yawAxisManager.AddTurrets(part, true, yawTransform))
+ {
+ yawAxisManager = null;
+ }
+ }
+
+ if (pitchTransform && !pitchAxisManager)
+ {
+ pitchAxisManager = part.gameObject.AddComponent();
+ if (!pitchAxisManager.AddTurrets(part, false, pitchTransform))
+ {
+ pitchAxisManager = null;
+ }
+ }
+
+ if (!string.IsNullOrEmpty(audioPath) && (yawSpeedDPS != 0 || pitchSpeedDPS != 0))
+ {
+ soundClip = SoundUtils.GetAudioClip(audioPath);
+
+ audioSource = gameObject.AddComponent();
+ audioSource.clip = soundClip;
+ audioSource.loop = true;
+ audioSource.dopplerLevel = 0;
+ audioSource.minDistance = .5f;
+ audioSource.maxDistance = 150;
+ audioSource.Play();
+ audioSource.volume = 0;
+ audioSource.pitch = 0;
+ audioSource.priority = 9999;
+ audioSource.spatialBlend = 1;
+
+ if (pitchTransform || yawTransform)
+ {
+ lastTurretDirection = baseTransform.InverseTransformDirection(pitchTransform ? pitchTransform.forward : yawTransform.forward);
+ }
+
+ audioRotationRate = 0;
+ //maxAudioRotRate = Mathf.Min(yawSpeedDPS, pitchSpeedDPS);
+ maxAudioRotRate = Mathf.Min(yawTransform ? yawSpeedDPS : float.MaxValue, pitchTransform ? pitchSpeedDPS : float.MaxValue);
+
+ // If one of the two values is zero, try to salvage things
+ if (maxAudioRotRate <= 0)
+ {
+ maxAudioRotRate = Mathf.Max(yawTransform ? yawSpeedDPS : -1, pitchTransform ? pitchSpeedDPS : -1);
+ }
+
+ // If all else fails, default to 90 DPS
+ if (maxAudioRotRate == float.MaxValue || maxAudioRotRate <= 0)
+ {
+ maxAudioRotRate = 90;
+ }
+
+ hasAudio = true;
+ }
+ }
+
+ bool transformsSetup = false;
+
+ public void SetupTransforms()
+ {
+ if (transformsSetup) return;
+
pitchTransform = part.FindModelTransform(pitchTransformName);
yawTransform = part.FindModelTransform(yawTransformName);
if (!string.IsNullOrEmpty(baseTransformName))
@@ -123,33 +205,7 @@ public override void OnStart(StartState state)
}
}
- SetupTweakables();
-
- if (!string.IsNullOrEmpty(audioPath) && (yawSpeedDPS != 0 || pitchSpeedDPS != 0))
- {
- soundClip = SoundUtils.GetAudioClip(audioPath);
-
- audioSource = gameObject.AddComponent();
- audioSource.clip = soundClip;
- audioSource.loop = true;
- audioSource.dopplerLevel = 0;
- audioSource.minDistance = .5f;
- audioSource.maxDistance = 150;
- audioSource.Play();
- audioSource.volume = 0;
- audioSource.pitch = 0;
- audioSource.priority = 9999;
- audioSource.spatialBlend = 1;
-
- if (pitchTransform || yawTransform)
- {
- lastTurretDirection = baseTransform.InverseTransformDirection(pitchTransform ? pitchTransform.forward : yawTransform.forward);
- }
-
- maxAudioRotRate = Mathf.Min(yawSpeedDPS, pitchSpeedDPS);
-
- hasAudio = true;
- }
+ transformsSetup = true;
}
void FixedUpdate()
@@ -210,14 +266,24 @@ void Update()
void OnDestroy()
{
GameEvents.onEditorPartPlaced.Remove(OnEditorPartPlaced);
+
+ if (yawAxisManager)
+ {
+ Destroy(yawAxisManager);
+ }
+
+ if (pitchAxisManager)
+ {
+ Destroy(pitchAxisManager);
+ }
}
- public void AimToTarget(Vector3 targetPosition, bool pitch = true, bool yaw = true)
+ public void AimToTarget(Vector3 targetPosition, bool pitch = true, bool yaw = true, bool activeWeap = false)
{
- AimInDirection(targetPosition - _referenceTransform.position, pitch, yaw);
+ AimInDirection(targetPosition - _referenceTransform.position, pitch, yaw, activeWeap);
}
- public void AimInDirection(Vector3 targetDirection, bool pitch = true, bool yaw = true)
+ public void AimInDirection(Vector3 targetDirection, bool pitch = true, bool yaw = true, bool activeWeap = false)
{
if (!(pitch || yaw)) return;
@@ -229,7 +295,8 @@ public void AimInDirection(Vector3 targetDirection, bool pitch = true, bool yaw
Vector3 yawComponent;
Vector3 pitchComponent;
- if (yawTransform)
+ // Perform the yaw axis manager check here, as we can skip all the calculations if false
+ if (yawTransform && (!yawAxisManager || yawAxisManager.CheckTurret(this, false, activeWeap)))
{
yawNormal = yawTransform.up;
yawComponent = targetDirection.ProjectOnPlanePreNormalized(yawNormal);
@@ -270,7 +337,9 @@ public void AimInDirection(Vector3 targetDirection, bool pitch = true, bool yaw
float pitchOffset;
float targetPitchAngle;
- if (pitchTransform)
+
+ // Perform the pitch axis manager check here, as we can skip all the calculations if false
+ if (pitchTransform && (!pitchAxisManager || pitchAxisManager.CheckTurret(this, false, activeWeap)))
{
float pitchError = (float)Vector3d.Angle(pitchComponent, yawNormal) - (float)Vector3d.Angle(_referenceTransform.forward, yawNormal);
float currentPitch = -pitchTransform.localEulerAngles.x.ToAngle(); // from current rotation transform
@@ -300,7 +369,6 @@ public void AimInDirection(Vector3 targetDirection, bool pitch = true, bool yaw
pitchSpeed = pitchSpeedDPS * deltaTime;
}
-
if (yaw)
{
float linYawMult = pitch && pitchOffset > 0 ? Mathf.Clamp01((yawOffset / pitchOffset) * (pitchSpeedDPS / yawSpeedDPS)) : 1;
@@ -316,15 +384,19 @@ public void AimInDirection(Vector3 targetDirection, bool pitch = true, bool yaw
public float Pitch => -pitchTransform.localEulerAngles.x.ToAngle();
public float Yaw => yawTransform.localEulerAngles.y.ToAngle();
- public bool ReturnTurret(bool pitch = true, bool yaw = true)
+ public bool ReturnTurret(bool pitch = true, bool yaw = true, bool reloading = false)
{
if (!(pitch || yaw)) return true;
float deltaTime = Time.fixedDeltaTime;
float yawOffset;
+ // Are we yawing? Is there a yawTransform? Are we actually yawed?
+ // The last check is important as it allows us to skip the CheckTurret check, which causes turrets that were stowed to redeploy
+ bool checkYaw = yaw && yawTransform && !(yawTransform.localRotation == standbyLocalRotation);
- if (yawTransform)
+ // If we're yawing, there's a yawTransform, we're yawed, and there's no axis manager or the axis manager allows the movement...
+ if (checkYaw && (!yawAxisManager || yawAxisManager.CheckTurret(this, !reloading)))
{
yawOffset = Quaternion.Angle(yawTransform.localRotation, standbyLocalRotation);
}
@@ -335,8 +407,12 @@ public bool ReturnTurret(bool pitch = true, bool yaw = true)
}
float pitchOffset;
-
- if (pitchTransform)
+ // Are we pitching? Is there a pitchTransform? Are we actually pitched?
+ // The last check is important as it allows us to skip the CheckTurret check, which causes turrets that were stowed to redeploy
+ bool checkPitch = pitch && pitchTransform && !(pitchTransform.localRotation == Quaternion.identity);
+
+ // If we're pitching, there's a pitchTransform, we're pitched, and there's no axis manager or the axis manager allows the movement...
+ if (checkPitch && (!pitchAxisManager || pitchAxisManager.CheckTurret(this, !reloading)))
{
pitchOffset = VectorUtils.Angle(pitchTransform.forward, yawTransform ? yawTransform.forward : baseTransform.forward);
}
@@ -346,7 +422,7 @@ public bool ReturnTurret(bool pitch = true, bool yaw = true)
pitch = false;
}
- if (!(pitch || yaw)) return true;
+ if (!(checkPitch || checkYaw)) return true;
float yawSpeed;
float pitchSpeed;
@@ -373,7 +449,7 @@ public bool ReturnTurret(bool pitch = true, bool yaw = true)
pitchTransform.localRotation = Quaternion.RotateTowards(pitchTransform.localRotation, Quaternion.identity, pitchSpeed * linPitchMult);
}
- return (!yaw || yawTransform.localRotation == standbyLocalRotation) && (!pitch || pitchTransform.localRotation == Quaternion.identity);
+ return (!checkYaw || yawTransform.localRotation == standbyLocalRotation) && (!checkPitch || pitchTransform.localRotation == Quaternion.identity);
}
public bool TargetInRange(Vector3 targetPosition, float maxDistance, float thresholdDegrees = 0)
@@ -467,9 +543,20 @@ void SetupStandbyLocalRotation(BaseField field = null, object obj = null)
void OnStandbyAngleChanged(BaseField field = null, object obj = null)
{
SetStandbyAngle();
+ PropagateStandbyAngle();
foreach (Part symmetryPart in part.symmetryCounterparts)
{
- ModuleTurret symmetryTurret = symmetryPart.FindModuleImplementing();
+ ModuleTurret symmetryTurret = null;
+
+ List turrets = symmetryPart.FindModulesImplementing();
+ for (int i = 0; i < turrets.Count; i++)
+ {
+ if (turrets[i] == null) continue;
+ if (turrets[i].turretID == turretID) symmetryTurret = turrets[i];
+ }
+
+ if (!symmetryTurret) continue;
+
if (part.symMethod == SymmetryMethod.Mirror)
{
symmetryTurret.yawStandbyAngle = -yawStandbyAngle;
@@ -480,13 +567,98 @@ void OnStandbyAngleChanged(BaseField field = null, object obj = null)
}
symmetryTurret.SetStandbyAngle();
+ symmetryTurret.PropagateStandbyAngle();
+ }
+ }
+
+ void PropagateStandbyAngle()
+ {
+ if (yawAxisManager)
+ {
+ yawAxisManager.SetYawStandbyAngle(this, yawStandbyAngle);
}
}
- void SetStandbyAngle()
+ public void SetStandbyAngle()
{
standbyLocalRotation = Quaternion.AngleAxis(yawStandbyAngle, Vector3.up);
- if (yawTransform != null) yawTransform.localRotation = standbyLocalRotation;
+ if (yawTransform != null && _yawStandbyAngleEnabled) yawTransform.localRotation = standbyLocalRotation;
+ }
+
+ public void DisableYawStandbyAngle()
+ {
+ Fields["yawStandbyAngle"].guiActiveEditor = false;
+ _yawStandbyAngleEnabled = false;
+ }
+
+ public float DeployIfBlocking(bool yaw)
+ {
+ if (turretWeapon)
+ {
+ return turretWeapon.DeployIfBlocking();
+ }
+ if (turretMissile)
+ {
+ return turretMissile.DeployIfBlocking(yaw);
+ }
+
+ return 0;
+ }
+
+ public void StowTurret()
+ {
+ if (turretWeapon)
+ {
+ turretWeapon.ReturnWeapon();
+ }
+ if (turretMissile)
+ {
+ turretMissile.ReturnTurret();
+ }
+ }
+
+ public void SetDeployFlag(bool yawEnabled, bool pitchEnabled)
+ {
+ if (yawAxisManager) yawAxisManager.SetTurretFlag(!yawEnabled, yawAxisIndex);
+ if (pitchAxisManager) pitchAxisManager.SetTurretFlag(!pitchEnabled, pitchAxisIndex);
+ }
+
+ public void SetYawDeployFlag(bool yawEnabled)
+ {
+ if (yawAxisManager) yawAxisManager.SetTurretFlag(!yawEnabled, yawAxisIndex);
+ }
+
+ public void SetPitchDeployFlag(bool pitchEnabled)
+ {
+ if (pitchAxisManager) pitchAxisManager.SetTurretFlag(!pitchEnabled, pitchAxisIndex);
+ }
+
+ public bool turretEnabled()
+ {
+ if (turretWeapon)
+ {
+ switch (turretWeapon.weaponState)
+ {
+ case ModuleWeapon.WeaponStates.Enabled:
+ case ModuleWeapon.WeaponStates.PoweringUp:
+ case ModuleWeapon.WeaponStates.Locked:
+ case ModuleWeapon.WeaponStates.EnabledForSecondaryFiring:
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ if (turretMissile)
+ {
+ return turretMissile.turretEnabled;
+ }
+
+ return false;
}
}
public class BDAScaleByDistance : PartModule
diff --git a/BDArmory/WeaponMounts/TurretAxisManager.cs b/BDArmory/WeaponMounts/TurretAxisManager.cs
new file mode 100644
index 000000000..04b2b58b8
--- /dev/null
+++ b/BDArmory/WeaponMounts/TurretAxisManager.cs
@@ -0,0 +1,385 @@
+using BDArmory.Control;
+using BDArmory.Weapons;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using UnityEngine;
+
+namespace BDArmory.WeaponMounts
+{
+ public class TurretAxisManager : MonoBehaviour
+ {
+ // Set when any command issued (Aim / Return), no command may be issued until Time.time > timeOfLastMoveCommand
+ // this is used both for regular movements, to prevent two turrets from making commands in the same frame as
+ // well as to lock the turret during some action, E.G. deployment of something, or missile turret reloading etc.
+ public float timeOfLastMoveCommand = 0;
+
+ // Current index of the turret in command
+ public int currTurretIndex = -1;
+
+ // Sorted list of turrets, based on priority
+ public List turrets;
+
+ bool _sortingTurretList = false;
+
+ bool _yaw = false;
+
+ int _blockedTurrets = 0; // Bitmask used for determining which turrets are blocked
+
+ IEnumerator SortTurretListRoutine()
+ {
+ _sortingTurretList = true;
+
+ yield return new WaitForFixedUpdate();
+
+ turrets.Sort(delegate (ModuleTurret t1, ModuleTurret t2)
+ {
+ // We want them sorted from greatest to least
+ int temp = t2.turretPriority.CompareTo(t1.turretPriority);
+
+ if (temp != 0)
+ {
+ return temp;
+ }
+
+ // If equal, sort from lowest turretID to highest
+ return t1.turretID.CompareTo(t2.turretID);
+ });
+
+ for (int i = 0; i < turrets.Count; i++)
+ {
+ if (_yaw)
+ {
+ turrets[i].yawAxisIndex = i;
+ if (i != 0)
+ {
+ turrets[i].DisableYawStandbyAngle();
+ }
+ }
+ else
+ {
+ turrets[i].pitchAxisIndex = i;
+ }
+ }
+
+ _sortingTurretList = false;
+ }
+
+ void SortTurretList()
+ {
+ if (!_sortingTurretList)
+ {
+ StartCoroutine(SortTurretListRoutine());
+ }
+ }
+
+ // Checks for other turrets on this axis, returns true if successful
+ public bool AddTurrets(Part part, bool yaw, Transform axisTransform)
+ {
+ // Need to null this in the calling turret
+ if (axisTransform == null)
+ {
+ Destroy(this);
+ return false;
+ }
+
+ _yaw = yaw;
+
+ List turr = part.FindModulesImplementing();
+ ModuleTurret currTurret;
+
+ // Pre-allocate list
+ turrets = new List(turr.Count);
+ _blockedTurrets = 0;
+
+ for (int i = 0; i < turr.Count; i++)
+ {
+ if ((currTurret = turr[i]) == null) continue;
+ if (turrets.Contains(currTurret)) continue;
+
+ currTurret.SetupTransforms();
+
+ if ((_yaw ? currTurret.yawTransform : currTurret.pitchTransform) == axisTransform)
+ {
+ turrets.Add(currTurret);
+
+ if (_yaw)
+ {
+ currTurret.yawAxisManager = this;
+ }
+ else
+ {
+ currTurret.pitchAxisManager = this;
+ }
+
+ // Default the turret to blocked, resolve it later when checking
+ _blockedTurrets |= 1 << i;
+ }
+ }
+
+ // If there's no turrets somehow, or there's only one turret and there's no need to manage this axis, delete this
+ if (turrets.Count <= 1)
+ {
+ Destroy(this);
+ return false;
+ }
+
+ SortTurretList();
+
+ return true;
+ }
+
+ public void SetYawStandbyAngle(ModuleTurret caller, float standbyAngle)
+ {
+ for (int i = 0; i < turrets.Count; i++)
+ {
+ if (turrets[i] == null) continue;
+ if (turrets[i] == caller) continue;
+
+ turrets[i].yawStandbyAngle = standbyAngle;
+ turrets[i].SetStandbyAngle();
+ }
+ }
+
+ // While the commanding weapon can get replaced when timeOfLastMoveCommand > Time.fixedTime
+ // the turret can only move when timeOfLastMoveCommand < Time.fixedTime
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ bool CanMove()
+ {
+ if (timeOfLastMoveCommand >= Time.fixedTime)
+ {
+ return false;
+ }
+
+ if (_blockedTurrets != 0)
+ {
+ DeployTurrets();
+ return false;
+ }
+
+ timeOfLastMoveCommand = Time.fixedTime;
+
+ return true;
+ }
+
+ void DeployTurrets()
+ {
+ float currBlockedTime = 0;
+ for (int i = 0; i < turrets.Count; i++)
+ {
+ if ((_blockedTurrets & (1 << i)) != 0)
+ {
+ float tempTime = turrets[i].DeployIfBlocking(_yaw);
+ if (tempTime > currBlockedTime) currBlockedTime = tempTime;
+ }
+ }
+
+ if (currBlockedTime > timeOfLastMoveCommand) timeOfLastMoveCommand = currBlockedTime;
+ }
+
+ public void StowTurrets()
+ {
+ if (currTurretIndex >= 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < turrets.Count; i++)
+ {
+ if (turrets[i] == null) continue;
+
+ turrets[i].StowTurret();
+ }
+ }
+
+ public bool CheckTurret(ModuleTurret t, bool returning, bool activeWeap = false)
+ {
+ // Special case, where we've previously confirmed all turrets were disabled
+ if (currTurretIndex < 0)
+ {
+ // If not returning, set currTurretIndex
+ // NOTE: returning does NOT include missile reload Return()!
+ if (!returning)
+ {
+ currTurretIndex = GetTurretIndex(t);
+ }
+
+ // And return CanMove()
+ return CanMove();
+ }
+
+ ModuleTurret currTurret = turrets[currTurretIndex];
+
+ // If we want to return the turret...
+ if (returning)
+ {
+ // If the current turret is enabled return false
+ if (currTurret && currTurret.turretEnabled())
+ {
+ return false;
+ }
+
+ // Check all turrets to see if any are enabled...
+ for (int i = 0; i < turrets.Count; i++)
+ {
+ if (turrets[i] == null) continue;
+ if (turrets[i].turretEnabled())
+ {
+ currTurretIndex = i;
+ return false;
+ }
+ }
+
+ // If none are, set currTurretIndex to -1 and return CanMove()
+ currTurretIndex = -1;
+ return CanMove();
+ }
+
+ // If the current turret is the turret trying to move, and it's not returning, allow it to do so
+ if (currTurret && currTurret == t)
+ {
+ return CanMove();
+ }
+
+ // If we're forcing the movement, E.G. we're the current weapon or we're in slavedGuard
+ if (activeWeap)
+ {
+ // If there's a turret, check if it has higher priority, and if it is also part of the
+ // current weapon set, if so, then prioritize that
+ if (currTurret && currTurret.turretPriority >= t.turretPriority &&
+ ((currTurret.turretWeapon && currTurret.turretWeapon.IsCurrentWMWeapon()) ||
+ (currTurret.turretMissile && currTurret.turretMissile.IsCurrentWMMissile())))
+ {
+ return false;
+ }
+
+ currTurretIndex = GetTurretIndex(t);
+ return CanMove();
+ }
+
+ int startIndex;
+
+ // If currTurret exists...
+ if (currTurret)
+ {
+ // If the current turret's priority is > t's
+ if (currTurret.turretPriority >= t.turretPriority)
+ {
+ // If it's enabled, return false
+ if (currTurret.turretEnabled())
+ {
+ return false;
+ }
+
+ // Otherwise, we have to check if there's any higher priority turrets enabled,
+ // starting from currTurretIndex as currTurret comes before t in the list
+ startIndex = currTurretIndex;
+ }
+ else
+ {
+ // If the priority of the current turret is lower than t's, then we must check
+ // the list starting from the highest priority turret. While this is technically
+ // less efficient in the case where t is the highest priority turret active, and
+ // there are higher priority turrets than t that are not active, this does prevent
+ // repeated replacements of currTurretIndex and incorrectly prioritized turret
+ // movements
+ startIndex = 0;
+ }
+
+ // Note that we do the above checks first, instead of after these override checks,
+ // as the priority -> enabled return path is faster than checking what's below
+
+ // No overriding current weapon / missile or slavedGuard
+ if (IsCurrentWMTurr(currTurret))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ startIndex = 0;
+ }
+
+ for (int i = startIndex; i < turrets.Count; i++)
+ {
+ if (turrets[i] == null) continue;
+
+ // If the highest priority turret currently enabled is
+ // our own turret, set currTurretIndex to it, and return CanMove()
+ if (turrets[i] == t)
+ {
+ currTurretIndex = i;
+ return CanMove();
+ }
+
+ // Otherwise, if there's a higher priority turret currently
+ // enabled, set currTurretIndex to it, and return false
+ if (turrets[i].turretEnabled())
+ {
+ currTurretIndex = i;
+ return false;
+ }
+ }
+
+ // This *shouldn't* happen but if somehow everything breaks,
+ // set currTurretIndex to t's index and return CanMove()
+ currTurretIndex = GetTurretIndex(t);
+ return CanMove();
+ }
+
+ void OnDestroy()
+ {
+ if (turrets == null) return;
+
+ for (int i = 0; i < turrets.Count; i++)
+ {
+ if (turrets[i] == null) continue;
+
+ if (_yaw)
+ {
+ turrets[i].yawAxisManager = null;
+ }
+ else
+ {
+ turrets[i].pitchAxisManager = null;
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int GetTurretIndex(ModuleTurret t)
+ {
+ return _yaw ? t.yawAxisIndex : t.pitchAxisIndex;
+ }
+
+ // Block axis from moving, E.G. for missile turret reloading
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void SetTurretBlock(float time)
+ {
+ if (timeOfLastMoveCommand < time)
+ {
+ timeOfLastMoveCommand = time;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool IsCurrentWMTurr(ModuleTurret t)
+ {
+ return (t.turretWeapon && t.turretWeapon.IsCurrentWMWeapon()) || (t.turretMissile && t.turretMissile.IsCurrentWMMissile());
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void SetTurretFlag(bool blocked, int index)
+ {
+ if (blocked)
+ {
+ _blockedTurrets |= 1 << index;
+ }
+ else
+ {
+ _blockedTurrets &= ~(1 << index);
+ }
+ }
+ }
+}
diff --git a/BDArmory/Weapons/Missiles/MissileBase.cs b/BDArmory/Weapons/Missiles/MissileBase.cs
index cd8d66a72..258823804 100644
--- a/BDArmory/Weapons/Missiles/MissileBase.cs
+++ b/BDArmory/Weapons/Missiles/MissileBase.cs
@@ -1112,8 +1112,8 @@ protected void UpdateRadarTarget()
if (scannedTargets == null) scannedTargets = new TargetSignatureData[BDATargetManager.LoadedVessels.Count];
TargetSignatureData.ResetTSDArray(ref scannedTargets);
Ray ray = new Ray(transform.position, vectorToTarget);
- bool pingRWR = Time.time - lastRWRPing > (0.5f * RadarUtils.ACTIVE_MISSILE_PING_PERSIST_TIME);
- if (pingRWR) lastRWRPing = Time.time;
+ bool pingRWR = Time.fixedTime - lastRWRPing > (RadarUtils.ACTIVE_MISSILE_PING_PERISTS_TIME);
+ if (pingRWR) lastRWRPing = Time.fixedTime;
bool radarSnapshot = (snapshotTicker > 10);
if (radarSnapshot)
{
@@ -1141,44 +1141,49 @@ protected void UpdateRadarTarget()
if (scannedTargets[i].exists && (scannedTargets[i].predictedPosition - radarTarget.predictedPosition).sqrMagnitude < sqrThresh)
{
//re-check engagement envelope, only lock appropriate targets
- if (CheckTargetEngagementEnvelope(scannedTargets[i].targetInfo) && (!hasIFF || !Team.IsFriendly(scannedTargets[i].Team)))
+ if (!CheckTargetEngagementEnvelope(scannedTargets[i].targetInfo)) continue;
+
+ if (hasIFF && Team.IsFriendly(scannedTargets[i].Team)) continue;
+
+ radarTarget = scannedTargets[i];
+ TargetAcquired = true;
+ radarLOALSearching = false;
+ //if (weaponClass == WeaponClasses.SLW)
+ // TargetPosition = radarTarget.predictedPosition + (radarTarget.velocity * Time.fixedDeltaTime);
+ //else
+ TargetPosition = radarTarget.predictedPositionWithChaffFactor(chaffEffectivity, chaffNotchVFac, chaffNotchRFac);
+
+ TargetVelocity = radarTarget.velocity;
+ TargetAcceleration = radarTarget.acceleration;
+ _lockFailTimer = 0;
+ if (!ActiveRadar && Time.time - TimeFired > 1)
{
- radarTarget = scannedTargets[i];
- TargetAcquired = true;
- radarLOALSearching = false;
- //if (weaponClass == WeaponClasses.SLW)
- // TargetPosition = radarTarget.predictedPosition + (radarTarget.velocity * Time.fixedDeltaTime);
- //else
- TargetPosition = radarTarget.predictedPositionWithChaffFactor(chaffEffectivity, chaffNotchVFac, chaffNotchRFac);
- startDirection = TargetPosition - transform.position;
- TargetVelocity = radarTarget.velocity;
- TargetAcceleration = radarTarget.acceleration;
- _lockFailTimer = 0;
- if (!ActiveRadar && Time.time - TimeFired > 1)
+ if (locksCount == 0)
{
- if (locksCount == 0)
+ if (weaponClass == WeaponClasses.SLW)
{
- if (weaponClass == WeaponClasses.SLW)
- RadarWarningReceiver.PingRWR(ray, lockedSensorFOV, RadarWarningReceiver.RWRThreatTypes.Torpedo, RadarUtils.LAUNCH_PING_PERSIST_TIME, vessel);
- else
- RadarWarningReceiver.PingRWR(ray, lockedSensorFOV, RadarWarningReceiver.RWRThreatTypes.MissileLaunch, RadarUtils.LAUNCH_PING_PERSIST_TIME, vessel);
- if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase]: Pitbull! Radar missilebase has gone active. Radar sig strength: {radarTarget.signalStrength:0.0}");
+ RadarWarningReceiver.PingRWR(ray, lockedSensorFOV, RadarWarningReceiver.RWRThreatTypes.Torpedo, RadarUtils.LAUNCH_PING_PERSIST_TIME, vessel);
}
- else if (locksCount > 2)
+ else
{
- guidanceActive = false;
- checkMiss = true;
- if (BDArmorySettings.DEBUG_MISSILES)
- {
- Debug.Log("[BDArmory.MissileBase]: Active Radar guidance failed. Radar missileBase reached max re-lock attempts.");
- }
+ RadarWarningReceiver.PingRWR(ray, lockedSensorFOV, RadarWarningReceiver.RWRThreatTypes.MissileLaunch, RadarUtils.LAUNCH_PING_PERSIST_TIME, vessel);
}
- locksCount++;
+ if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase]: Pitbull! Radar missilebase has gone active. Radar sig strength: {radarTarget.signalStrength:0.0}");
}
- ActiveRadar = true;
- updateRadarCS = true;
- return;
+ else if (locksCount > 2)
+ {
+ guidanceActive = false;
+ checkMiss = true;
+ if (BDArmorySettings.DEBUG_MISSILES)
+ {
+ Debug.Log("[BDArmory.MissileBase]: Active Radar guidance failed. Radar missileBase reached max re-lock attempts.");
+ }
+ }
+ locksCount++;
}
+ ActiveRadar = true;
+ updateRadarCS = true;
+ return;
}
//if (!scannedTargets[i].exists)
// if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar Active]: Target: {i} doesn't exist!.");
@@ -1229,7 +1234,7 @@ protected void UpdateRadarTarget()
TargetSignatureData.ResetTSDArray(ref scannedTargets);
Vector3 forward = GetForwardTransform();
Ray ray = new Ray(transform.position, forward);
- bool pingRWR = Time.time - lastRWRPing > (0.5f * RadarUtils.ACTIVE_MISSILE_PING_PERSIST_TIME);
+ bool pingRWR = Time.time - lastRWRPing > (RadarUtils.ACTIVE_MISSILE_PING_PERISTS_TIME);
if (pingRWR) lastRWRPing = Time.time;
bool radarSnapshot = (snapshotTicker > 5);
if (radarSnapshot)
@@ -1269,40 +1274,52 @@ protected void UpdateRadarTarget()
if (scannedTargets[i].exists && !useSoughtTarget || (tempDist = (scannedTargets[i].predictedPosition - soughtTarget).sqrMagnitude) < 1000000f)
{
//re-check engagement envelope, only lock appropriate targets
- if (CheckTargetEngagementEnvelope(scannedTargets[i].targetInfo))
+ if (!CheckTargetEngagementEnvelope(scannedTargets[i].targetInfo))
{
- if (hasIFF && Team.IsFriendly(scannedTargets[i].targetInfo.Team)) continue;//Don't lock friendlies
+ if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {scannedTargets[i].vessel.name} rejected due to target envelope!");
+ continue;
+ }
- if (!useSoughtTarget)
- {
- (tempDist, Vector3 currDir) = (scannedTargets[i].predictedPosition - soughtTarget).MagNorm();
- currAngle = Mathf.Rad2Deg * Mathf.Acos(Vector3.Dot(currDir, forward));
- if (currAngle > (smallestAngle + 5f)) continue; // Look for the smallest angle, give 5 degrees of wiggle room.
- // Look for closest target to the missile
- currDist = tempDist;
- }
- else
+ //Don't lock friendlies
+ if (hasIFF && Team.IsFriendly(scannedTargets[i].targetInfo.Team))
+ {
+ if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {scannedTargets[i].vessel.name} rejected due to IFF!");
+ continue;
+ }
+
+ if (!useSoughtTarget)
+ {
+ (tempDist, Vector3 currDir) = (scannedTargets[i].predictedPosition - soughtTarget).MagNorm();
+ currAngle = Mathf.Rad2Deg * Mathf.Acos(Vector3.Dot(currDir, forward));
+ if (currAngle > (smallestAngle + 5f))
{
- // Look for closest target to the previous target location
- currDist = tempDist;
+ if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {scannedTargets[i].vessel.name} rejected due to angle!");
+ continue; // Look for the smallest angle, give 5 degrees of wiggle room.
}
+ // Look for closest target to the missile
+ currDist = tempDist;
+ }
+ else
+ {
+ // Look for closest target to the previous target location
+ currDist = tempDist;
+ }
- if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {scannedTargets[i].vessel.name} has {(targetVessel == null ? "currDist" : "currSqrDist")}: {currDist}.");
+ if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {scannedTargets[i].vessel.name} has {(targetVessel == null ? "currDist" : "currSqrDist")}: {currDist}.");
- if (currDist < smallestDist)
+ if (currDist < smallestDist)
+ {
+ if (!useSoughtTarget && currAngle < smallestAngle)
{
- if (!useSoughtTarget && currAngle < smallestAngle)
- {
- smallestAngle = currAngle;
- }
- smallestDist = currDist;
- lockedTarget = scannedTargets[i];
- ActiveRadar = true;
- updateRadarCS = true;
- //if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {scannedTargets[i].vessel.name} selected.");
+ smallestAngle = currAngle;
}
- //return;
+ smallestDist = currDist;
+ lockedTarget = scannedTargets[i];
+ ActiveRadar = true;
+ updateRadarCS = true;
+ //if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {scannedTargets[i].vessel.name} selected.");
}
+ //return;
}
//if (!scannedTargets[i].exists)
//if (BDArmorySettings.DEBUG_MISSILES) Debug.Log($"[BDArmory.MissileBase][Radar LOAL]: Target: {i} doesn't exist!.");
diff --git a/BDArmory/Weapons/Missiles/MissileLauncher.cs b/BDArmory/Weapons/Missiles/MissileLauncher.cs
index 57bc8e1b0..909b68c05 100644
--- a/BDArmory/Weapons/Missiles/MissileLauncher.cs
+++ b/BDArmory/Weapons/Missiles/MissileLauncher.cs
@@ -1994,6 +1994,10 @@ public IEnumerator MissileReload()
{
if (vessel.isActiveVessel) gauge.UpdateReloadMeter(reloadTimer);
reloadInProgress = true;
+ if (turret)
+ {
+ turret.SetReloadBlock(reloadableRail.reloadTime);
+ }
yield return new WaitForSecondsFixed(reloadableRail.reloadTime);
reloadInProgress = false;
launched = false;
@@ -2672,7 +2676,7 @@ private void UpdateTerminalGuidance()
ActiveRadar = true;
updateRadarCS = true;
- bool pingRWR = Time.time - lastRWRPing > (0.5f * RadarUtils.ACTIVE_MISSILE_PING_PERSIST_TIME);
+ bool pingRWR = Time.time - lastRWRPing > (RadarUtils.ACTIVE_MISSILE_PING_PERISTS_TIME);
if (pingRWR) lastRWRPing = Time.time;
//RadarUtils.UpdateRadarLock(ray, maxOffBoresight, activeRadarMinThresh, ref scannedTargets, 0.4f, true, RadarWarningReceiver.RWRThreatTypes.MissileLock, true);
diff --git a/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs b/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs
index 13d6916e0..b97661069 100644
--- a/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs
+++ b/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs
@@ -192,11 +192,6 @@ IEnumerator DelayedStart()
missileLauncher.reloadableRail = missileSpawner;
missileLauncher.hasAmmo = true;
missileLauncher.multiLauncher = this;
- missileLauncher.MissileReferenceTransform = part.FindModelTransform("missileTransform");
- if (!missileLauncher.MissileReferenceTransform)
- {
- missileLauncher.MissileReferenceTransform = launchTransforms[0];
- }
if (isClusterMissile)
{
@@ -228,6 +223,7 @@ IEnumerator DelayedStart()
{
Fields["clusterMissileTriggerDist"].guiActive = false;
Fields["clusterMissileTriggerDist"].guiActiveEditor = false;
+ missileLauncher.MissileReferenceTransform = launchTransforms[0];
}
Fields["salvoSize"].guiActive = setSalvoSize;
Fields["salvoSize"].guiActiveEditor = setSalvoSize;
diff --git a/BDArmory/Weapons/ModuleWeapon.cs b/BDArmory/Weapons/ModuleWeapon.cs
index d65441b9b..c8adcca95 100644
--- a/BDArmory/Weapons/ModuleWeapon.cs
+++ b/BDArmory/Weapons/ModuleWeapon.cs
@@ -1673,6 +1673,7 @@ public void Start()
if (turr.Current.turretID != turretID) continue;
turret = turr.Current;
turret.SetReferenceTransform(fireTransforms[0]);
+ turret.turretWeapon = this;
break;
}
if (yawRange == 0 && maxPitch == minPitch)
@@ -2066,6 +2067,16 @@ public void ToggleDeploy()
}
}
+ public bool IsCurrentWMWeapon()
+ {
+ MissileFire wm;
+ if (!(wm = WeaponManager)) return false;
+
+ if (wm.selectedWeapon == null) return false;
+
+ return GetShortName() == wm.selectedWeapon.GetShortName();
+ }
+
void FAOCos(BaseField field, object obj)
{
maxAutoFireCosAngle = Mathf.Cos((FiringTolerance * Mathf.Deg2Rad));
@@ -3988,6 +3999,16 @@ public void DisableWeapon()
if (part.isActiveAndEnabled) shutdownRoutine = StartCoroutine(ShutdownRoutine());
}
+ public void ReturnWeapon()
+ {
+ if (!disabledStates.Contains(weaponState))
+ return;
+
+ StopShutdownStartupRoutines();
+
+ if (part.isActiveAndEnabled) shutdownRoutine = StartCoroutine(ShutdownRoutine());
+ }
+
HashSet standbyStates = new HashSet { WeaponStates.Standby, WeaponStates.PoweringUp, WeaponStates.Locked };
public void StandbyWeapon()
{
@@ -4496,7 +4517,7 @@ void Aim()
{
turret.smoothRotation = false;
}
- turret.AimToTarget(finalAimTarget); //no aimbot turrets when target out of sight
+ turret.AimToTarget(finalAimTarget, activeWeap: IsCurrentWMWeapon()); //no aimbot turrets when target out of sight
turret.smoothRotation = origSmooth;
}
for (int i = 0; i < customTurret.Count; i++)
@@ -6254,6 +6275,30 @@ void UpdateGUIWeaponState()
guiStatusString = weaponState.ToString();
}
+ public float DeployIfBlocking()
+ {
+ // If no deploy anim or deploy state, the turret is ready regardless
+ if (!(hasDeployAnim && deployState))
+ {
+ turret.SetDeployFlag(true, true);
+ return 0;
+ }
+
+ if (hasReloadAnim && isReloading) // If reloading, return how long it'll take for the reload to complete
+ {
+ return reloadState.length - reloadState.time;
+ }
+
+ // If currently deploying
+ if (deployState.enabled && deployState.speed > 0) return deployState.length - deployState.time;
+
+ // Otherwise, weapon is either shutting down or inactive, thus requiring startup routine
+ StopShutdownStartupRoutines();
+ startupRoutine = StartCoroutine(StartupRoutine(true));
+
+ return deployState.length;
+ }
+
IEnumerator StartupRoutine(bool calledByReload = false, bool secondaryFiring = false)
{
if (hasReloadAnim && isReloading) //wait for reload to finish before shutting down
@@ -6281,6 +6326,12 @@ IEnumerator StartupRoutine(bool calledByReload = false, bool secondaryFiring = f
else
weaponState = WeaponStates.EnabledForSecondaryFiring;
}
+
+ if (turret)
+ {
+ turret.SetDeployFlag(true, true);
+ }
+
UpdateGUIWeaponState();
UpdateOffsetWeapon(); // Re-calculate offset/non-centerline weapon corrections on weapon selection
BDArmorySetup.Instance.UpdateCursorState();
@@ -6333,6 +6384,12 @@ IEnumerator ShutdownRoutine(bool calledByReload = false)
}
if (hasDeployAnim && deployState != null)
{
+ // Block turret prior to undeploy
+ if (turret)
+ {
+ turret.SetDeployFlag(false, false);
+ }
+
deployState.enabled = true;
deployState.speed = -1;
yield return new WaitWhileFixed(() => deployState.normalizedTime > 0);