internal void SelectStartingAirbaseForPackages(DCSMission mission, DBEntryAirbase homeBase) { var missionPackages = new List <DCSMissionPackage>(); foreach (var package in _template.AircraftPackages) { if (package.StartingAirbase == "home") { missionPackages.Add(new DCSMissionPackage(_template.AircraftPackages.IndexOf(package), homeBase)); continue; } var flights = _template.PlayerFlightGroups.Where((v, i) => package.FlightGroupIndexes.Contains(i)); var requiredSpots = flights.Sum(x => x.Count); var requiredRunway = flights.Select(x => Database.Instance.GetEntry <DBEntryUnit>(x.Aircraft).AircraftData.MinimumRunwayLengthFt).Max(); var airbase = SelectStartingAirbase(mission, package.StartingAirbase, requiredSpots, requiredRunway); if (missionPackages.Any(x => x.Airbase == airbase)) { mission.Briefing.AddItem(DCSMissionBriefingItemType.Airbase, $"{airbase.Name}\t{airbase.Runways}\t{airbase.ATC}\t{airbase.ILS}\t{airbase.TACAN}"); } missionPackages.Add(new DCSMissionPackage(_template.AircraftPackages.IndexOf(package), airbase)); } mission.MissionPackages.AddRange(missionPackages); }
private Coordinates PlaceInAirbase(MissionTemplateRecord template, DBEntrySituation situationDB, DBEntryAirbase playerAirbase, List <KeyValuePair <string, object> > extraSettings, DBEntryObjectiveTarget targetDB, DBEntryObjectiveTargetBehavior targetBehaviorDB, ref string luaUnit, Coordinates objectiveCoordinates, int unitCount, UnitFamily objectiveTargetUnitFamily) { int airbaseID = 0; var parkingSpotIDsList = new List <int>(); var parkingSpotCoordinatesList = new List <Coordinates>(); var targetAirbaseOptions = (from DBEntryAirbase airbaseDB in situationDB.GetAirbases(template.OptionsMission.Contains("InvertCountriesCoalitions")) where airbaseDB.DCSID != playerAirbase.DCSID select airbaseDB).OrderBy(x => x.Coordinates.GetDistanceFrom(objectiveCoordinates)); DBEntryAirbase targetAirbase = targetAirbaseOptions.FirstOrDefault(x => template.OptionsMission.Contains("SpawnAnywhere") ? true : x.Coalition == template.ContextPlayerCoalition.GetEnemy()); airbaseID = targetAirbase.DCSID; var parkingSpots = UnitMaker.SpawnPointSelector.GetFreeParkingSpots( targetAirbase.DCSID, unitCount, objectiveTargetUnitFamily, targetBehaviorDB.Location == DBEntryObjectiveTargetBehaviorLocation.SpawnOnAirbaseParkingNoHardenedShelter); parkingSpotIDsList = parkingSpots.Select(x => x.DCSID).ToList(); parkingSpotCoordinatesList = parkingSpots.Select(x => x.Coordinates).ToList(); luaUnit += "Parked"; extraSettings.Add("GroupAirbaseID".ToKeyValuePair(airbaseID)); extraSettings.Add("ParkingID".ToKeyValuePair(parkingSpotIDsList.ToArray())); extraSettings.Add("UnitX".ToKeyValuePair((from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.X).ToArray())); extraSettings.Add("UnitY".ToKeyValuePair((from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.Y).ToArray())); return(targetAirbase.Coordinates); }
private bool ValidateAirfieldRunway(DBEntryAirbase airbaseDB, UnitFamily unitFamily) { if (airbaseDB.RunwayLengthFt == -1 || !LARGE_AIRCRAFT.Contains(unitFamily)) //TODO implement runway distances on all relavant airbases { return(true); } return(airbaseDB.RunwayLengthFt > 7000); //TODO This is a guess based on most runways I know work so far. Place holder for per aircraft data }
internal void SetupAirbasesCoalitions(DCSMission mission, DBEntryAirbase playerAirbase) { // Select all airbases for this theater DBEntryAirbase[] situationAirbases = _situationDB.GetAirbases(_template.OptionsMission.Contains("InvertCountriesCoalitions")); foreach (DBEntryAirbase airbase in situationAirbases) { var coalition = airbase.DCSID == playerAirbase.DCSID || mission.MissionPackages.Any(x => x.Airbase.DCSID == airbase.DCSID) ? _template.ContextPlayerCoalition : airbase.Coalition; mission.SetAirbase(airbase.DCSID, coalition); } }
internal static int GenerateWeather(DCSMission mission, MissionTemplateRecord template, DBEntryTheater theaterDB, Month month, DBEntryAirbase playerAirbase) { var baseAlt = template.OptionsMission.Contains("SeaLevelRefCloud") ? 0.0 : playerAirbase.Elevation; if (template.OptionsMission.Contains("HighCloud")) { baseAlt += 2000; } DBEntryWeatherPreset weatherDB; if (string.IsNullOrEmpty(template.EnvironmentWeatherPreset)) // Random weather { weatherDB = Toolbox.RandomFrom(Database.Instance.GetAllEntries <DBEntryWeatherPreset>()); } else { weatherDB = Database.Instance.GetEntry <DBEntryWeatherPreset>(template.EnvironmentWeatherPreset); } mission.SetValue("WeatherName", weatherDB.BriefingDescription); mission.SetValue("WeatherCloudsBase", weatherDB.CloudsBase.GetValue() + baseAlt); mission.SetValue("WeatherCloudsPreset", Toolbox.RandomFrom(weatherDB.CloudsPresets)); mission.SetValue("WeatherCloudsThickness", weatherDB.CloudsThickness.GetValue()); mission.SetValue("WeatherDust", weatherDB.Dust); mission.SetValue("WeatherDustDensity", weatherDB.DustDensity.GetValue()); mission.SetValue("WeatherFog", weatherDB.Fog); mission.SetValue("WeatherFogThickness", weatherDB.FogThickness.GetValue()); mission.SetValue("WeatherFogVisibility", weatherDB.FogVisibility.GetValue()); mission.SetValue("WeatherQNH", weatherDB.QNH.GetValue()); mission.SetValue("WeatherTemperature", theaterDB.Temperature[(int)month].GetValue()); mission.SetValue("WeatherVisibility", weatherDB.Visibility.GetValue()); return(weatherDB.Turbulence.GetValue()); }
internal Tuple <Coordinates, List <Waypoint> > GenerateObjective( DCSMission mission, MissionTemplateRecord template, DBEntrySituation situationDB, MissionTemplateObjectiveRecord objectiveTemplate, Coordinates lastCoordinates, DBEntryAirbase playerAirbase, bool useObjectivePreset, ref int objectiveIndex, ref List <Coordinates> objectiveCoordinatesList, ref List <Waypoint> waypoints, ref List <UnitFamily> objectiveTargetUnitFamilies) { var extraSettings = new List <KeyValuePair <string, object> >(); var waypointList = new List <Waypoint>(); string[] featuresID; DBEntryObjectiveTarget targetDB; DBEntryObjectiveTargetBehavior targetBehaviorDB; DBEntryObjectiveTask taskDB; ObjectiveOption[] objectiveOptions; GetObjectiveData(objectiveTemplate, useObjectivePreset, out featuresID, out targetDB, out targetBehaviorDB, out taskDB, out objectiveOptions); var luaUnit = targetBehaviorDB.UnitLua[(int)targetDB.UnitCategory]; Coordinates objectiveCoordinates = GetSpawnCoordinates(template, lastCoordinates, playerAirbase, targetDB); // Spawn target on airbase var unitCount = targetDB.UnitCount[(int)objectiveTemplate.TargetCount].GetValue(); var objectiveTargetUnitFamily = Toolbox.RandomFrom(targetDB.UnitFamilies); if (AIRBASE_LOCATIONS.Contains(targetBehaviorDB.Location) && targetDB.UnitCategory.IsAircraft()) { objectiveCoordinates = PlaceInAirbase(template, situationDB, playerAirbase, extraSettings, targetDB, targetBehaviorDB, ref luaUnit, objectiveCoordinates, unitCount, objectiveTargetUnitFamily); } UnitMakerGroupFlags groupFlags = 0; if (objectiveOptions.Contains(ObjectiveOption.ShowTarget)) { groupFlags = UnitMakerGroupFlags.NeverHidden; } else if (objectiveOptions.Contains(ObjectiveOption.HideTarget)) { groupFlags = UnitMakerGroupFlags.AlwaysHidden; } if (objectiveOptions.Contains(ObjectiveOption.EmbeddedAirDefense)) { groupFlags |= UnitMakerGroupFlags.EmbeddedAirDefense; } // Set destination point for moving unit groups Coordinates destinationPoint = objectiveCoordinates + ( (targetDB.UnitCategory == UnitCategory.Plane ? Coordinates.CreateRandom(30, 60) : Coordinates.CreateRandom(10, 20)) * Toolbox.NM_TO_METERS ); if (targetBehaviorDB.Location == DBEntryObjectiveTargetBehaviorLocation.GoToPlayerAirbase) { destinationPoint = playerAirbase.Coordinates; } var unitCoordinates = objectiveCoordinates; var objectiveName = Toolbox.RandomFrom(ObjectiveNames); if (TRANSPORT_TASKS.Contains(taskDB.ID)) { Coordinates?spawnPoint = UnitMaker.SpawnPointSelector.GetRandomSpawnPoint( targetDB.ValidSpawnPoints, playerAirbase.Coordinates, new MinMaxD(1, 5), coalition: GeneratorTools.GetSpawnPointCoalition(template, Side.Ally)); if (!spawnPoint.HasValue) // Failed to generate target group { throw new BriefingRoomException($"Failed to find Cargo SpawnPoint"); } unitCoordinates = spawnPoint.Value; var cargoWaypoint = GenerateObjectiveWaypoint(objectiveTemplate, unitCoordinates, $"{objectiveName} Pickup", template, true); waypoints.Add(cargoWaypoint); waypointList.Add(cargoWaypoint); if (taskDB.isEscort()) { extraSettings.Add("GroupX2".ToKeyValuePair(objectiveCoordinates.X)); extraSettings.Add("GroupY2".ToKeyValuePair(objectiveCoordinates.Y)); groupFlags |= UnitMakerGroupFlags.RadioAircraftSpawn; } } extraSettings.Add("GroupX2".ToKeyValuePair(destinationPoint.X)); extraSettings.Add("GroupY2".ToKeyValuePair(destinationPoint.Y)); UnitMakerGroupInfo?targetGroupInfo = UnitMaker.AddUnitGroup( objectiveTargetUnitFamily, unitCount, taskDB.TargetSide, targetBehaviorDB.GroupLua[(int)targetDB.UnitCategory], luaUnit, unitCoordinates, groupFlags, extraSettings.ToArray()); if (!targetGroupInfo.HasValue) // Failed to generate target group { throw new BriefingRoomException($"Failed to generate group for objective."); } if (objectiveOptions.Contains(ObjectiveOption.EmbeddedAirDefense) && (targetDB.UnitCategory == UnitCategory.Static)) { AddEmbeddedAirDefenseUnits(template, targetDB, targetBehaviorDB, taskDB, objectiveOptions, objectiveCoordinates, groupFlags, extraSettings); } var pluralIndex = targetGroupInfo.Value.UnitsID.Length == 1 ? 0 : 1; var taskString = GeneratorTools.ParseRandomString(taskDB.BriefingTask[pluralIndex], mission).Replace("\"", "''"); // Pick a name, then remove it from the list ObjectiveNames.Remove(objectiveName); CreateTaskString(mission, pluralIndex, ref taskString, objectiveName, objectiveTargetUnitFamily); CreateLua(mission, template, targetDB, taskDB, objectiveIndex, objectiveName, targetGroupInfo, taskString); // Add briefing remarks for this objective task if (taskDB.BriefingRemarks.Length > 0) { string remark = Toolbox.RandomFrom(taskDB.BriefingRemarks); GeneratorTools.ReplaceKey(ref remark, "ObjectiveName", objectiveName); GeneratorTools.ReplaceKey(ref remark, "UnitFamily", Database.Instance.Common.Names.UnitFamilies[(int)objectiveTargetUnitFamily][pluralIndex]); mission.Briefing.AddItem(DCSMissionBriefingItemType.Remark, remark); } // Add feature ogg files foreach (string oggFile in taskDB.IncludeOgg) { mission.AddMediaFile($"l10n/DEFAULT/{oggFile}", $"{BRPaths.INCLUDE_OGG}{oggFile}"); } // Add objective features Lua for this objective mission.AppendValue("ScriptObjectivesFeatures", ""); // Just in case there's no features foreach (string featureID in featuresID) { FeaturesGenerator.GenerateMissionFeature(mission, featureID, objectiveName, objectiveIndex, targetGroupInfo.Value.GroupID, objectiveCoordinates, taskDB.TargetSide, objectiveOptions.Contains(ObjectiveOption.HideTarget)); } objectiveCoordinatesList.Add(objectiveCoordinates); var waypoint = GenerateObjectiveWaypoint(objectiveTemplate, objectiveCoordinates, objectiveName, template); waypoints.Add(waypoint); waypointList.Add(waypoint); objectiveTargetUnitFamilies.Add(objectiveTargetUnitFamily); var preValidSpawns = targetDB.ValidSpawnPoints.ToList(); foreach (var subTasks in objectiveTemplate.SubTasks) { objectiveIndex++; GenerateSubTask(mission, template, situationDB, subTasks, objectiveCoordinates, playerAirbase, preValidSpawns, targetBehaviorDB.Location, featuresID, ref objectiveIndex, ref objectiveCoordinatesList, ref waypoints, ref waypointList, ref objectiveTargetUnitFamilies); } return(new (objectiveCoordinates, waypointList)); }
private Coordinates GetSpawnCoordinates(MissionTemplateRecord template, Coordinates lastCoordinates, DBEntryAirbase playerAirbase, DBEntryObjectiveTarget targetDB) { int objectiveDistance = template.FlightPlanObjectiveDistance; if (objectiveDistance < 1) { objectiveDistance = Toolbox.RandomInt(40, 160); } int objectiveSeperation = template.FlightPlanObjectiveSeperation; if (objectiveSeperation < 1) { objectiveSeperation = Toolbox.RandomInt(10, 100); } Coordinates?spawnPoint = UnitMaker.SpawnPointSelector.GetRandomSpawnPoint( targetDB.ValidSpawnPoints, playerAirbase.Coordinates, new MinMaxD( objectiveDistance * OBJECTIVE_DISTANCE_VARIATION_MIN, objectiveDistance * OBJECTIVE_DISTANCE_VARIATION_MAX), lastCoordinates, new MinMaxD( objectiveSeperation * OBJECTIVE_DISTANCE_VARIATION_MIN, objectiveSeperation * OBJECTIVE_DISTANCE_VARIATION_MAX), GeneratorTools.GetSpawnPointCoalition(template, Side.Enemy)); if (!spawnPoint.HasValue) { throw new BriefingRoomException($"Failed to spawn objective unit group. {String.Join(",", targetDB.ValidSpawnPoints.Select(x => x.ToString()).ToList())} Please try again (Consider Adusting Flight Plan)"); } Coordinates objectiveCoordinates = spawnPoint.Value; return(objectiveCoordinates); }
internal DCSMissionPackage(int recordIndex, DBEntryAirbase airbase) { RecordIndex = recordIndex; Airbase = airbase; }
internal void AddAirbaseZones(DBEntryAirbase homeBase, List <DCSMissionPackage> missionPackages) { AddCTLDPickupZone(homeBase.Coordinates); missionPackages.ForEach(x => AddCTLDPickupZone(x.Airbase.Coordinates)); }
internal static void GeneratePlayerFlightGroup( UnitMaker unitMaker, DCSMission mission, MissionTemplateRecord template, MissionTemplateFlightGroupRecord flightGroup, DBEntryAirbase playerAirbase, List <Waypoint> waypoints, Dictionary <string, UnitMakerGroupInfo> carrierDictionary, Coordinates averageInitialLocation, Coordinates objectivesCenter) { DBEntryAirbase airbase = playerAirbase; List <Waypoint> flightWaypoints = new List <Waypoint>(waypoints); Coordinates groupStartingCoords = playerAirbase.Coordinates; var package = template.AircraftPackages.FirstOrDefault(x => x.FlightGroupIndexes.Contains(template.PlayerFlightGroups.IndexOf(flightGroup))); if (package is not null) { var missionPackage = mission.MissionPackages.First(x => x.RecordIndex == template.AircraftPackages.IndexOf(package)); flightWaypoints = missionPackage.Waypoints; airbase = missionPackage.Airbase; groupStartingCoords = missionPackage.Airbase.Coordinates; } DBEntryUnit unitDB = Database.Instance.GetEntry <DBEntryUnit>(flightGroup.Aircraft); // Not an unit, or not a player-controllable unit, abort. if ((unitDB == null) || !unitDB.AircraftData.PlayerControllable) { throw new BriefingRoomException($"Player flight group unit {flightGroup.Aircraft} does not exist or is not player-controllable."); } if (unitDB.AircraftData.MinimumRunwayLengthFt > 0 && airbase.RunwayLengthFt < unitDB.AircraftData.MinimumRunwayLengthFt) { BriefingRoom.PrintToLog($"Runway at {airbase.Name}({airbase.RunwayLengthFt}ft) is shorter than {unitDB.UIDisplayName}({unitDB.AircraftData.MinimumRunwayLengthFt}ft) required runway length.", LogMessageErrorLevel.Warning); } List <int> parkingSpotIDsList = new List <int>(); List <Coordinates> parkingSpotCoordinatesList = new List <Coordinates>(); var groupLuaFile = "GroupAircraftPlayer"; var carrierUnitID = 0; string carrierName = null; var side = flightGroup.Hostile ? Side.Enemy : Side.Ally; var country = flightGroup.Country; var payload = flightGroup.Payload; var extraSettings = new Dictionary <string, object>(); UnitMakerGroupFlags unitMakerGroupFlags = flightGroup.AIWingmen ? UnitMakerGroupFlags.FirstUnitIsClient : 0; DCSSkillLevel skillLevel = flightGroup.AIWingmen ? Toolbox.RandomFrom(DCSSkillLevel.High, DCSSkillLevel.Excellent) : DCSSkillLevel.Client; if (!string.IsNullOrEmpty(flightGroup.Carrier) && carrierDictionary.ContainsKey(flightGroup.Carrier) && !flightGroup.Hostile) // Carrier take off { var carrier = carrierDictionary[flightGroup.Carrier]; if (carrier.UnitDB.Families.Contains(UnitFamily.ShipCarrierSTOVL) && flightGroup.Carrier != "LHA_Tarawa") { extraSettings.AddIfKeyUnused("Speed", 0); unitMakerGroupFlags = 0; skillLevel = DCSSkillLevel.Client; if (flightGroup.Aircraft == "AV8BNA") { payload = "EMPTY"; } } groupLuaFile = "GroupAircraftPlayerCarrier"; carrierUnitID = carrier.UnitsID[0]; carrierName = carrier.UnitDB.UIDisplayName; for (int i = 0; i < flightGroup.Count; i++) { parkingSpotIDsList.Add(i + 1); parkingSpotCoordinatesList.Add(carrier.Coordinates); } groupStartingCoords = carrier.Coordinates; } else if (flightGroup.Hostile) { var coalition = GeneratorTools.GetSpawnPointCoalition(template, side, true); var(hostileAirbase, hostileParkingSpotIDsList, hostileParkingSpotCoordinatesList) = unitMaker.SpawnPointSelector.GetAirbaseAndParking(template, objectivesCenter, flightGroup.Count, coalition.Value, unitDB.Families.First()); parkingSpotIDsList = hostileParkingSpotIDsList; parkingSpotCoordinatesList = hostileParkingSpotCoordinatesList; groupStartingCoords = hostileParkingSpotCoordinatesList.First(); airbase = hostileAirbase; if (country == Country.CJTFBlue || country == Country.CJTFRed) { country = coalition == Coalition.Blue ? Country.CJTFBlue : Country.CJTFRed; } } else // Land airbase take off { var parkingSpots = unitMaker.SpawnPointSelector.GetFreeParkingSpots(airbase.DCSID, flightGroup.Count, unitDB.Families[0]); parkingSpotIDsList = parkingSpots.Select(x => x.DCSID).ToList(); parkingSpotCoordinatesList = parkingSpots.Select(x => x.Coordinates).ToList(); groupStartingCoords = parkingSpotCoordinatesList.First(); } extraSettings.AddIfKeyUnused("Payload", payload); extraSettings.AddIfKeyUnused("Skill", skillLevel); extraSettings.AddIfKeyUnused("PlayerStartingAction", GeneratorTools.GetPlayerStartingAction(flightGroup.StartLocation)); extraSettings.AddIfKeyUnused("PlayerStartingType", GeneratorTools.GetPlayerStartingType(flightGroup.StartLocation)); extraSettings.AddIfKeyUnused("Country", country); extraSettings.AddIfKeyUnused("InitialWPName", Database.Instance.Common.Names.WPInitialName); extraSettings.AddIfKeyUnused("FinalWPName", Database.Instance.Common.Names.WPFinalName); extraSettings.AddIfKeyUnused("ParkingID", parkingSpotIDsList.ToArray()); extraSettings.AddIfKeyUnused("PlayerWaypoints", GenerateFlightPlanLua(flightWaypoints)); extraSettings.AddIfKeyUnused("LastPlayerWaypointIndex", flightWaypoints.Count + 2); extraSettings.AddIfKeyUnused("LinkUnit", carrierUnitID); extraSettings.AddIfKeyUnused("UnitX", (from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.X).ToArray()); extraSettings.AddIfKeyUnused("UnitY", (from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.Y).ToArray()); extraSettings.AddIfKeyUnused("MissionAirbaseX", groupStartingCoords.X); extraSettings.AddIfKeyUnused("MissionAirbaseY", groupStartingCoords.Y); extraSettings.AddIfKeyUnused("MissionAirbaseID", airbase.DCSID); extraSettings.AddIfKeyUnused("Livery", flightGroup.Livery); UnitMakerGroupInfo?groupInfo = unitMaker.AddUnitGroup( Enumerable.Repeat(flightGroup.Aircraft, flightGroup.Count).ToArray(), side, unitDB.Families[0], groupLuaFile, "UnitAircraftParked", groupStartingCoords, unitMakerGroupFlags, extraSettings.ToArray() ); if (!groupInfo.HasValue) { BriefingRoom.PrintToLog("Failed to generate player flight group.", LogMessageErrorLevel.Warning); return; } SaveFlightGroup(mission, groupInfo, flightGroup, unitDB, carrierName ?? airbase.Name); SaveWaypointsToBriefing( mission, groupStartingCoords, flightWaypoints, template.OptionsMission.Contains("ImperialUnitsForBriefing"), groupInfo); }