/// <summary> /// Gets a random spawn point around a given point. /// </summary> /// <param name="validTypes">Valid spawn point types</param> /// <param name="distanceOrigin1">Origin point distance must be computed from</param> /// <param name="distanceFrom1">Min/max distance from origin point, in nautical miles</param> /// <param name="distanceOrigin2">Second origin point distance must be computed from</param> /// <param name="distanceFrom2">Min/max distance from second origin point, in nautical miles</param> /// <param name="coalition">Which coalition should the spawn point belong to?</param> /// <returns>A spawn point, or null if none found matching the provided criteria</returns> public DBEntryTheaterSpawnPoint?GetRandomSpawnPoint( TheaterLocationSpawnPointType[] validTypes = null, Coordinates?distanceOrigin1 = null, MinMaxD?distanceFrom1 = null, Coordinates?distanceOrigin2 = null, MinMaxD?distanceFrom2 = null, Coalition?coalition = null) { // Select all spoint points IEnumerable <DBEntryTheaterSpawnPoint> validSP = from DBEntryTheaterSpawnPoint pt in SpawnPoints select pt; if (validTypes != null) // Remove spawn points of invalid types { validSP = (from DBEntryTheaterSpawnPoint pt in validSP where validTypes.Contains(pt.PointType) select pt); } if (coalition.HasValue) // Select spawn points belonging to the proper coalition { IEnumerable <DBEntryTheaterSpawnPoint> coalitionValidSP = coalitionValidSP = (from DBEntryTheaterSpawnPoint sp in validSP where sp.Coalition == coalition.Value select sp); // At least one spawn point found, only use SP for the preferred coalition if (coalitionValidSP.Count() > 0) { validSP = coalitionValidSP; } } Coordinates?[] distanceOrigin = new Coordinates?[] { distanceOrigin1, distanceOrigin2 }; MinMaxD?[] distanceFrom = new MinMaxD?[] { distanceFrom1, distanceFrom2 }; for (int i = 0; i < 2; i++) // Remove spawn points too far or too close from distanceOrigin1 and distanceOrigin2 { if (validSP.Count() == 0) { return(null); } if (!distanceFrom[i].HasValue || !distanceOrigin[i].HasValue) { continue; } MinMaxD searchRange = distanceFrom[i].Value * Toolbox.NM_TO_METERS; // convert distance to meters IEnumerable <DBEntryTheaterSpawnPoint> validSPInRange = (from DBEntryTheaterSpawnPoint s in validSP select s); int iterationsLeft = MAX_RADIUS_SEARCH_ITERATIONS; do { Coordinates origin = distanceOrigin[i].Value; validSPInRange = (from DBEntryTheaterSpawnPoint s in validSP where searchRange.Contains(origin.GetDistanceFrom(s.Coordinates)) select s); searchRange = new MinMaxD(searchRange.Min * 0.9, Math.Max(100, searchRange.Max * 1.1)); iterationsLeft--; } while ((validSPInRange.Count() == 0) && (iterationsLeft > 0)); validSP = (from DBEntryTheaterSpawnPoint s in validSPInRange select s); } if (validSP.Count() == 0) { return(null); } DBEntryTheaterSpawnPoint selectedSpawnPoint = Toolbox.RandomFrom(validSP.ToArray()); SpawnPoints.Remove(selectedSpawnPoint); // Remove spawn point so it won't be used again return(selectedSpawnPoint); }
/// <summary> /// Picks a starting airbase for the player(s) /// </summary> /// <param name="mission">Mission for which the starting airbase must be set</param> /// <param name="template">Mission template to use</param> /// <param name="theaterDB">Theater database entry</param> /// <param name="lastCoordinates">Last location for referance</param> /// <param name="distance">Base Distance Range</param> /// <param name="first">is first objective</param> /// <returns>Information about the starting airbase</returns> public DBEntryTheaterAirbase SelectObjectiveAirbase(DCSMission mission, MissionTemplate template, DBEntryTheater theaterDB, Coordinates lastCoordinates, MinMaxD distance, bool first = false) { List <DBEntryTheaterAirbase> airbasesList = new List <DBEntryTheaterAirbase>(); // Select all airbases with enough parking spots, trying to match the preferred coalition for enemy unit location, if any if ((template.OptionsTheaterCountriesCoalitions == CountryCoalition.AllBlue) || (template.OptionsTheaterCountriesCoalitions == CountryCoalition.AllRed) || (template.OptionsEnemyUnitsLocation == SpawnPointPreferredCoalition.Any)) { airbasesList.AddRange((from DBEntryTheaterAirbase ab in theaterDB.Airbases where ab.ParkingSpots.Length >= Toolbox.MAXIMUM_FLIGHT_GROUP_SIZE select ab).ToArray()); } else { Coalition preferredCoalition; if (template.OptionsEnemyUnitsLocation == SpawnPointPreferredCoalition.Blue) { preferredCoalition = (template.OptionsTheaterCountriesCoalitions == CountryCoalition.Inverted) ? Coalition.Red : Coalition.Blue; } else { preferredCoalition = (template.OptionsTheaterCountriesCoalitions == CountryCoalition.Inverted) ? Coalition.Blue : Coalition.Red; } airbasesList.AddRange( (from DBEntryTheaterAirbase ab in theaterDB.Airbases where ab.ParkingSpots.Length >= Toolbox.MAXIMUM_FLIGHT_GROUP_SIZE && ab.Coalition == preferredCoalition select ab).ToArray()); if (airbasesList.Count == 0) { airbasesList.AddRange((from DBEntryTheaterAirbase ab in theaterDB.Airbases where ab.ParkingSpots.Length >= Toolbox.MAXIMUM_FLIGHT_GROUP_SIZE select ab).ToArray()); } } // Remove players' home airbase and airbases already used by other objectives from the list of available airbases List <int> airbasesInUse = (from DCSMissionObjective objective in mission.Objectives select objective.AirbaseID).ToList(); airbasesInUse.Add(mission.InitialAirbaseID); airbasesList = (from DBEntryTheaterAirbase ab in airbasesList where !airbasesInUse.Contains(ab.DCSID) select ab).ToList(); if (airbasesList.Count == 0) { throw new Exception($"No airbase found with at least {Toolbox.MAXIMUM_FLIGHT_GROUP_SIZE} parking spots to use as an objective."); } int distanceMultiplier = 1; do { MinMaxD searchDistance = new MinMaxD(first ? distance.Min : 0, distance.Max * distanceMultiplier); List <DBEntryTheaterAirbase> airbasesInRange = airbasesList.FindAll(x => searchDistance.Contains(x.Coordinates.GetDistanceFrom(lastCoordinates) * Toolbox.METERS_TO_NM)); if (airbasesInRange.Count > 0) { DBEntryTheaterAirbase selectedAirbase = Toolbox.RandomFrom(airbasesInRange); mission.AirbasesCoalition[selectedAirbase.DCSID] = mission.CoalitionEnemy; return(selectedAirbase); } distanceMultiplier++; if (distanceMultiplier > 128) { throw new Exception($"No target airbase found within range, try a larger objective range."); } } while (true); }
public DefinitionTheaterSpawnPoint?GetRandomSpawnPoint( TheaterLocationSpawnPointType[] validTypes = null, DCSCountry[] validCountries = null, MinMaxD?distanceFrom = null, Coordinates?distanceOrigin = null, MinMaxD?distanceFrom2 = null, Coordinates?distanceOrigin2 = null) { IEnumerable <DefinitionTheaterSpawnPoint> validSP = (from DefinitionTheaterSpawnPoint s in SpawnPoints where !UsedSpawnPointsID.Contains(s.UniqueID) select s); if (validTypes != null) { validSP = (from DefinitionTheaterSpawnPoint s in validSP where validTypes.Contains(s.PointType) select s); } if (validCountries != null) { validSP = (from DefinitionTheaterSpawnPoint s in validSP where validCountries.Contains(s.Country) select s); } if (distanceFrom.HasValue && distanceOrigin.HasValue) { if (validSP.Count() == 0) { return(null); } MinMaxD searchRange = distanceFrom.Value; IEnumerable <DefinitionTheaterSpawnPoint> validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP select s); do { validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP where searchRange.Contains(distanceOrigin.Value.GetDistanceFrom(s.Coordinates)) select s); searchRange = new MinMaxD(searchRange.Min * 0.9, Math.Max(100, searchRange.Max * 1.1)); } while (validSPInRange.Count() == 0); validSP = (from DefinitionTheaterSpawnPoint s in validSPInRange select s); } if (distanceFrom2.HasValue && distanceOrigin2.HasValue) { if (validSP.Count() == 0) { return(null); } MinMaxD searchRange = distanceFrom2.Value; IEnumerable <DefinitionTheaterSpawnPoint> validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP select s); do { validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP where searchRange.Contains(distanceOrigin2.Value.GetDistanceFrom(s.Coordinates)) select s); searchRange = new MinMaxD(searchRange.Min * 0.9, Math.Max(100, searchRange.Max * 1.1)); } while (validSPInRange.Count() == 0); validSP = (from DefinitionTheaterSpawnPoint s in validSPInRange select s); } if (validSP.Count() == 0) { return(null); } DefinitionTheaterSpawnPoint selectedSpawnPoint = HQTools.RandomFrom(validSP.ToArray()); UsedSpawnPointsID.Add(selectedSpawnPoint.UniqueID); return(selectedSpawnPoint); }