//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); }