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