Ejemplo n.º 1
0
        //public virtual void Sweep()
        //{
        //    if (!IsReady)
        //    {
        //        return;
        //    }
        //    if (OwnerUnit.CarriedByUnit != null)
        //    {
        //        return;
        //    }
        //    System.Diagnostics.Debug.Assert(OwnerPlayer != null, "BaseSensor.Sweep: Sensor OwnerPlayer should never be null.");
        //    System.Diagnostics.Debug.Assert(OwnerUnit != null, "BaseSensor.Sweep: Sensor OwnerUnit should never be null.");
        //    System.Diagnostics.Debug.Assert(SensorClass != null, "BaseSensor.Sweep: Sensor SensorClass should never be null.");


        //}

        public virtual bool AttemptDetectUnit(BaseUnit unit, double distanceM)
        {
            //TODO: Hit test on detection
            if (!IsAbleToDetectUnit(unit, distanceM))
            {
                return(false);
            }
            if (SensorClass.MaxHeightDeployedM > 0 && OwnerUnit.ActualHeightOverSeaLevelM > SensorClass.MaxHeightDeployedM)
            {
                ReadyInSec = 120;
                return(false);
            }
            if (SensorClass.MaxSpeedDeployedKph > 0 && OwnerUnit.ActualSpeedKph > SensorClass.MaxSpeedDeployedKph)
            {
                ReadyInSec = 120;
                return(false);
            }
            //if (!OwnerPlayer.IsComputerPlayer)
            //{
            //    GameManager.Instance.Log.LogDebug(string.Format(
            //        "PLAYER {0}, UNIT {1}, SENSOR {2} attemtping to detect unit {3}.",
            //        OwnerPlayer.ToString(), OwnerUnit.ToString(), this.ToString(), unit.ToString()));
            //}
            GameConstants.DirectionCardinalPoints DirectionToTarget =
                MapHelper.CalculateBearingDegrees(OwnerUnit.Position.Coordinate,
                                                  unit.Position.Coordinate).ToCardinalMark();

            TerrainLineSummary terrainLineSummary = GetTerrainHeightSummaryToTarget(unit);

            //No sensor can see through terrain
            if (terrainLineSummary.MaxHeightM > OwnerUnit.Position.HeightOverSeaLevelM && terrainLineSummary.MaxHeightM > unit.Position.HeightOverSeaLevelM)
            {
                return(false);
            }
            double targetApparentSizeArcSec =
                unit.CalculateRadarCorrectedSizeArcSec(DirectionToTarget, distanceM);

            if (SensorClass.SensorType == GameConstants.SensorType.Visual)
            {
                if ((double)OwnerUnit.Position.HeightOverSeaLevelM < GameConstants.DEPTH_PERISCOPE_MIN_M ||
                    (double)unit.Position.HeightOverSeaLevelM < GameConstants.DEPTH_SHALLOW_MIN_M)    //under sea level
                {
                    return(false);
                }
                double lineOfSightM = MapHelper.CalculateMaxLineOfSightM(
                    (double)OwnerUnit.Position.HeightOverSeaLevelM
                    + OwnerUnit.UnitClass.HeightM,
                    (double)unit.Position.HeightOverSeaLevelM
                    + unit.UnitClass.HeightM);

                double minimumTargetSizeArcSec = SensorClass.MinimumTargetSurfaceSizeArcSec;
                if (unit.Position.HeightOverSeaLevelM > 10)
                {
                    minimumTargetSizeArcSec = SensorClass.MinimumTargetAirSizeArcSec;
                }
                if (distanceM <= lineOfSightM && targetApparentSizeArcSec >= minimumTargetSizeArcSec)
                {
                    double        degradationPercent = 0;
                    WeatherSystem wsystem            = OwnerUnit.GetWeatherSystem();
                    if (wsystem != null && SensorClass.SensorType == GameConstants.SensorType.Visual)
                    {
                        degradationPercent = 100 - wsystem.TotalLightPercent;
                    }

                    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(wsystem);
                    }
                    //double MinDetectableSizeArcSec = SensorClass.MinimumTargetSurfaceSizeArcSec;
                    minimumTargetSizeArcSec = minimumTargetSizeArcSec * (1.0 + (degradationPercent / 100));
                    double DetectionStrength = targetApparentSizeArcSec
                                               / minimumTargetSizeArcSec; //(LineOfSightM - DistanceM) / LineOfSightM;
                    DetectedUnit detect = CreateOrUpdateDetectionReport(unit, DetectionStrength, distanceM,
                                                                        targetApparentSizeArcSec, minimumTargetSizeArcSec);
                    return(detect != null);
                }
                else
                {
                    return(false); //does not detect it
                }
            }
            else if (SensorClass.SensorType == GameConstants.SensorType.Infrared)
            {
                if ((double)OwnerUnit.Position.HeightOverSeaLevelM < GameConstants.DEPTH_PERISCOPE_MIN_M ||
                    (double)unit.Position.HeightOverSeaLevelM < GameConstants.DEPTH_SHALLOW_MIN_M)    //under sea level
                {
                    return(false);
                }

                double        irDegradationPercent = 0;
                WeatherSystem weatherSystem        = OwnerUnit.GetWeatherSystem();
                if (OwnerUnit.Position.HeightOverSeaLevelM < GameConstants.HEIGHT_MEDIUM_MIN_M ||
                    unit.Position.HeightOverSeaLevelM < GameConstants.HEIGHT_MEDIUM_MIN_M)    //only if any below cloud cover
                {
                    irDegradationPercent += GameManager.Instance.GetIRDegradationFromWeatherPercent(weatherSystem);
                }

                double maxTargetDetectionDistanceM = unit.GetMaxIrDetectionDistanceM();
                double LineOfSightM = MapHelper.CalculateMaxLineOfSightM(
                    (double)OwnerUnit.Position.HeightOverSeaLevelM
                    + OwnerUnit.UnitClass.HeightM,
                    (double)unit.Position.HeightOverSeaLevelM)
                                      + unit.UnitClass.HeightM;
                if (maxTargetDetectionDistanceM > LineOfSightM)
                {
                    maxTargetDetectionDistanceM = LineOfSightM;
                }
                double detectionStrength = distanceM / maxTargetDetectionDistanceM;
                if (detectionStrength > 1.0)
                {
                    DetectedUnit detect = CreateOrUpdateDetectionReport(unit, detectionStrength, distanceM,
                                                                        0, 0);
                    return(detect != null);
                }
                else
                {
                    return(false);
                }
            }
            else if (SensorClass.SensorType == GameConstants.SensorType.MAD)
            {
                if (unit.Position == null ||
                    !unit.Position.HasHeightOverSeaLevel ||
                    unit.Position.HeightOverSeaLevelM >= GameConstants.DEPTH_SHALLOW_MIN_M)
                {
                    return(false);
                }
                var unitDepthM = (double)unit.Position.HeightOverSeaLevelM;
                if (OwnerUnit.Position == null || !OwnerUnit.Position.HasHeightOverSeaLevel ||
                    OwnerUnit.Position.HeightOverSeaLevelM >= GameConstants.HEIGHT_MEDIUM_MIN_M)
                {
                    return(false);
                }
                if (unitDepthM <= GameConstants.DEPTH_DEEP_MIN_M)
                {
                    return(false);
                }
                double maxDetectionDistanceM = 1000.0;
                if (unitDepthM <= GameConstants.DEPTH_MEDIUM_MIN_M)
                {
                    maxDetectionDistanceM = 500;
                }
                double detectionStrength = distanceM / maxDetectionDistanceM;
                if (detectionStrength > 1.0)
                {
                    DetectedUnit detect = CreateOrUpdateDetectionReport(unit, detectionStrength, distanceM,
                                                                        0, 0);
                    return(detect != null);
                }
                else
                {
                    return(false);
                }
            }
            return(false);
        }