Пример #1
0
 public override bool IsAbleToDetectUnit(BaseUnit unit)
 {
     if (unit.Position.HasHeightOverSeaLevel && unit.Position.HeightOverSeaLevelM < GameConstants.DEPTH_PERISCOPE_MIN_M)
     {
         return(false);
     }
     if (base.IsAbleToDetectUnit(unit))
     {
         return(true);
     }
     if (IsActive)
     {
         return(true);
     }
     if (SensorClass.IsEsmDetector)
     {
         GameConstants.EsmRadiationLevel esmRad = unit.GetCurrentEsmRadiation();
         if (esmRad == GameConstants.EsmRadiationLevel.EsmNone)
         {
             return(false);
         }
         return(true);
     }
     return(false);
 }
Пример #2
0
        //ESM detection calculator: http://www.y1pwe.co.uk/AppletCD/Prop2.htm

        public override bool AttemptDetectUnit(BaseUnit unit, double distanceM)
        {
            if (!IsAbleToDetectUnit(unit, distanceM))
            {
                return(false);
            }
            if ((double)OwnerUnit.Position.HeightOverSeaLevelM < GameConstants.DEPTH_PERISCOPE_MIN_M ||
                (double)unit.Position.HeightOverSeaLevelM < GameConstants.DEPTH_PERISCOPE_MIN_M)    //under sea level
            {
                return(false);
            }
            //TODO: Take into account over-the horizon capabilities of some radars
            double sensorHeightOverSeaLevelM = (double)OwnerUnit.Position.HeightOverSeaLevelM
                                               + OwnerUnit.UnitClass.HeightM;
            double targetMaxHeightOverSeaLevelM = (double)unit.Position.HeightOverSeaLevelM + unit.UnitClass.HeightM;
            double LineOfSightM = MapHelper.CalculateMaxRadarLineOfSightM(sensorHeightOverSeaLevelM, targetMaxHeightOverSeaLevelM);

            TerrainLineSummary terrainLineSummary = null;

            if (IsActive)
            {
                if (distanceM <= LineOfSightM)
                {
                    GameConstants.DirectionCardinalPoints direction =
                        MapHelper.CalculateBearingDegrees(OwnerUnit.Position.Coordinate,
                                                          unit.Position.Coordinate).ToCardinalMark();
                    double targetApparentSizeArcSec = unit.CalculateRadarCorrectedSizeArcSec(direction, distanceM);
                    double minDetectableSizeArcSec  = SensorClass.MinimumTargetSurfaceSizeArcSec;
                    double degradationPercent       = 0;
                    if (targetMaxHeightOverSeaLevelM > 90)
                    {
                        minDetectableSizeArcSec = SensorClass.MinimumTargetAirSizeArcSec;
                    }
                    else
                    {
                        degradationPercent = GameManager.Instance.GetRadarDegradationFromSeaStatePercent(
                            OwnerUnit.GetEffectiveSeaState());
                    }

                    terrainLineSummary = GetTerrainHeightSummaryToTarget(unit);

                    if (sensorHeightOverSeaLevelM < GameConstants.MAX_HEIGHT_TERRAIN_M)
                    {
                        if (sensorHeightOverSeaLevelM < terrainLineSummary.MaxHeightM && targetMaxHeightOverSeaLevelM < terrainLineSummary.MaxHeightM)
                        {
                            return(false); //no radar detection through terrain
                        }
                        if (targetMaxHeightOverSeaLevelM < terrainLineSummary.MaxHeightM * 1.2 && terrainLineSummary.HeightVarianceM > 0)
                        {
                            degradationPercent += 10;
                        }
                    }
                    if (targetMaxHeightOverSeaLevelM < terrainLineSummary.MaxHeightBehindM)
                    {
                        degradationPercent += 75;
                    }
                    if (OwnerUnit.Position.HeightOverSeaLevelM < GameConstants.HEIGHT_MEDIUM_MIN_M ||
                        unit.Position.HeightOverSeaLevelM < GameConstants.HEIGHT_MEDIUM_MIN_M)    //only if any below cloud cover
                    {
                        degradationPercent += GameManager.Instance.GetRadarDegradationFromWeatherPercent(
                            unit.GetWeatherSystem());
                    }
                    degradationPercent += OwnerUnit.GetDegradationFromJammingPercent(this.SensorClass.SensorType);
                    if (unit.UnitClass.UnitType == GameConstants.UnitType.Missile && unit.Position.HeightOverSeaLevelM < 20)
                    {
                        degradationPercent += 40; //make sea skimming missiles much harder to detect
                    }
                    if (degradationPercent > 100)
                    {
                        degradationPercent = 100;
                    }
                    var degradationFactor = (1.0 - (degradationPercent / 100.0));
                    if (degradationFactor < 0.001)
                    {
                        degradationFactor = 0.001;
                    }
                    minDetectableSizeArcSec = minDetectableSizeArcSec * degradationFactor;
                    if (targetApparentSizeArcSec >= minDetectableSizeArcSec)
                    {
                        double       detectionStrength = targetApparentSizeArcSec / minDetectableSizeArcSec; //(SensorClass.MaxRangeM - DistanceM) / SensorClass.MaxRangeM;
                        DetectedUnit detect            = CreateOrUpdateDetectionReport(unit, detectionStrength,
                                                                                       distanceM, targetApparentSizeArcSec, minDetectableSizeArcSec);
                        if (detect != null)
                        {
                            return(true);
                        }
                    }
                }
            } //Even if active detection attempt has been made and failed, test for esm (passive)
            if (SensorClass.IsEsmDetector)
            {
                GameConstants.EsmRadiationLevel esmRad = unit.GetCurrentEsmRadiation();
                if (esmRad == GameConstants.EsmRadiationLevel.EsmNone)
                {
                    return(false);
                }
                else
                {
                    LineOfSightM = (LineOfSightM * SensorClass.EsmDetectionOverHorizonPercent) / 100.0;
                    if (esmRad == GameConstants.EsmRadiationLevel.EsmLow)
                    {
                        LineOfSightM *= 0.1;
                    }
                    else if (esmRad == GameConstants.EsmRadiationLevel.EsmMedium)
                    {
                        LineOfSightM *= 0.25;
                    }
                    if (sensorHeightOverSeaLevelM < GameConstants.MAX_HEIGHT_TERRAIN_M)
                    {
                        // Get terrain summary if not already gotten
                        if (terrainLineSummary == null)
                        {
                            terrainLineSummary = GetTerrainHeightSummaryToTarget(unit);
                        }

                        if (sensorHeightOverSeaLevelM < terrainLineSummary.MaxHeightM && targetMaxHeightOverSeaLevelM < terrainLineSummary.MaxHeightM)
                        {
                            return(false); //no radar detection through terrain
                        }
                        if (targetMaxHeightOverSeaLevelM < terrainLineSummary.MaxHeightM * 1.2 && terrainLineSummary.HeightVarianceM > 0)
                        {
                            LineOfSightM *= 0.75;
                        }
                    }
                    if (unit.UnitClass.UnitType == GameConstants.UnitType.Missile && unit.Position.HeightOverSeaLevelM < 20) //sea skimmers
                    {
                        LineOfSightM *= 0.25;
                    }
                    var degrJammingPercent = OwnerUnit.GetDegradationFromJammingPercent(this.SensorClass.SensorType);
                    LineOfSightM *= (100.0 - degrJammingPercent);

                    if (distanceM <= LineOfSightM)
                    {
                        DetectedUnit detect = CreateOrUpdateDetectionReport(unit, (LineOfSightM / distanceM),
                                                                            distanceM, 3600, 60);
                        return(detect != null);
                    }
                }
            }
            return(false);
        }