private static void GenerateFOB( UnitMaker unitMaker, ZoneMaker zoneMaker, MissionTemplateFlightGroupRecord flightGroup, Dictionary <string, UnitMakerGroupInfo> carrierDictionary, DCSMission mission, MissionTemplateRecord template, Coordinates landbaseCoordinates, Coordinates objectivesCenter) { DBEntryTheater theaterDB = Database.Instance.GetEntry <DBEntryTheater>(template.ContextTheater); if (theaterDB == null) { return; // Theater doesn't exist. Should never happen. } Coordinates?spawnPoint = unitMaker.SpawnPointSelector.GetRandomSpawnPoint( new SpawnPointType[] { SpawnPointType.LandLarge }, landbaseCoordinates, new MinMaxD(5, template.FlightPlanObjectiveDistance), objectivesCenter, new MinMaxD(10, template.FlightPlanObjectiveDistance / 2), template.ContextPlayerCoalition); if (!spawnPoint.HasValue) { BriefingRoom.PrintToLog($"No spawn point found for FOB air defense unit groups", LogMessageErrorLevel.Warning); return; } DBEntryUnit unitDB = Database.Instance.GetEntry <DBEntryUnit>(flightGroup.Carrier); if (unitDB == null) { return; // Unit doesn't exist or is not a carrier } double radioFrequency = 127.5 + carrierDictionary.Count; var FOBNames = new List <string> { "FOB_London", "FOB_Dallas", "FOB_Paris", "FOB_Moscow", "FOB_Berlin" }; UnitMakerGroupInfo?groupInfo = unitMaker.AddUnitGroup( unitDB.Families[0], 1, Side.Ally, "GroupStatic", "UnitStaticFOB", spawnPoint.Value, 0, "FOBCallSignIndex".ToKeyValuePair(FOBNames.IndexOf(flightGroup.Carrier) + 1), "RadioBand".ToKeyValuePair((int)RadioModulation.AM), "RadioFrequency".ToKeyValuePair(GeneratorTools.GetRadioFrenquency(radioFrequency))); if (!groupInfo.HasValue || (groupInfo.Value.UnitsID.Length == 0)) { return; // Couldn't generate group } zoneMaker.AddCTLDPickupZone(spawnPoint.Value, true); mission.Briefing.AddItem( DCSMissionBriefingItemType.Airbase, $"{unitDB.UIDisplayName}\t-\t{GeneratorTools.FormatRadioFrequency(radioFrequency)}\t\t"); carrierDictionary.Add(flightGroup.Carrier, groupInfo.Value); // This bit limits FOBS to one per game think about how we can fix this }
internal UnitMakerGroupInfo(int groupID, Coordinates coordinates, List <int> unitsID, string name, double frequency = 0.0, DBEntryUnit unitDB = null) { GroupID = groupID; Coordinates = coordinates; Name = name; UnitsID = unitsID.ToArray(); Frequency = frequency; UnitDB = unitDB; }
private string ApplyAircraftFields(string groupLua, DBEntryUnit firstUnitDB, params KeyValuePair <string, object>[] extraSettings) { GeneratorTools.ReplaceKey(ref groupLua, "Altitude", firstUnitDB.AircraftData.CruiseAltitude); GeneratorTools.ReplaceKey(ref groupLua, "AltitudeHalf", firstUnitDB.AircraftData.CruiseAltitude / 2); GeneratorTools.ReplaceKey(ref groupLua, "EPLRS", firstUnitDB.Flags.HasFlag(DBEntryUnitFlags.EPLRS)); GeneratorTools.ReplaceKey(ref groupLua, "RadioBand", (int)firstUnitDB.AircraftData.RadioModulation); GeneratorTools.ReplaceKey(ref groupLua, "RadioFrequency", firstUnitDB.AircraftData.RadioFrequency); GeneratorTools.ReplaceKey(ref groupLua, "Speed", firstUnitDB.AircraftData.CruiseSpeed); return(groupLua); }
private void SetUnitCoordinatesAndHeading( DBEntryUnit unitDB, int unitIndex, Coordinates groupCoordinates, double groupHeading, out Coordinates unitCoordinates, out double unitHeading) { unitCoordinates = groupCoordinates; unitHeading = groupHeading; if (unitDB.IsAircraft) { unitCoordinates = groupCoordinates + new Coordinates(AIRCRAFT_UNIT_SPACING, AIRCRAFT_UNIT_SPACING) * unitIndex; } else { if (unitDB.OffsetCoordinates.Length > unitIndex) // Unit has a fixed set of coordinates (for SAM sites, etc.) { Coordinates offsetCoordinates = unitDB.OffsetCoordinates[unitIndex]; unitCoordinates = TransformFromOffset(unitHeading, groupCoordinates, offsetCoordinates); } else // No fixed coordinates, generate random coordinates { switch (unitDB.Category) { case UnitCategory.Ship: if (unitIndex > 0) { unitCoordinates = groupCoordinates.CreateNearRandom(SHIP_UNIT_SPACING, SHIP_UNIT_SPACING * 10); } break; case UnitCategory.Cargo: case UnitCategory.Static: // Static units are spawned exactly on the group location (and there's only a single unit per group) break; default: unitCoordinates = groupCoordinates.CreateNearRandom(VEHICLE_UNIT_SPACING, VEHICLE_UNIT_SPACING * 10); break; } } if (unitDB.OffsetHeading.Length > unitIndex) // Unit has a fixed heading (for SAM sites, etc.) { unitHeading = Toolbox.ClampAngle(unitHeading + unitDB.OffsetHeading[unitIndex]); } else if (unitDB.Category != UnitCategory.Ship) { unitHeading = Toolbox.RandomDouble(Toolbox.TWO_PI); } } }
private (string unitsLua, List <int> unitsIDList) AddUnits( string[] unitSets, string groupName, UnitCallsign?callsign, string unitTypeLua, Coordinates coordinates, UnitMakerGroupFlags unitMakerGroupFlags, params KeyValuePair <string, object>[] extraSettings ) { string unitsLuaTable = ""; int unitLuaIndex = 1; List <int> unitsIDList = new List <int>(); foreach (var unitSet in unitSets) { DBEntryUnit unitDB = Database.Instance.GetEntry <DBEntryUnit>(unitSet); if (unitDB == null) { BriefingRoom.PrintToLog($"Unit \"{unitSet}\" not found.", LogMessageErrorLevel.Warning); continue; } int unitSetIndex = 0; foreach (string DCSID in unitDB.DCSIDs) { unitsLuaTable += AddUnit( DCSID, groupName, callsign, unitLuaIndex, unitSetIndex, unitDB, unitTypeLua, coordinates, unitMakerGroupFlags, extraSettings ); unitsIDList.Add(UnitID); unitSetIndex++; unitLuaIndex++; UnitID++; } } return(unitsLuaTable, unitsIDList); }
private void CreatePlayerWaypoints(ref string groupLua, DCSMission mission, DBEntryUnit unitBP) { string waypointLua = LuaTools.ReadIncludeLuaFile("Mission\\WaypointPlayer.lua"); string allWaypointsLua = ""; for (int i = 0; i < mission.Waypoints.Count; i++) { string waypoint = waypointLua; LuaTools.ReplaceKey(ref waypoint, "Index", i + 2); LuaTools.ReplaceKey(ref waypoint, "Name", mission.Waypoints[i].Name); LuaTools.ReplaceKey(ref waypoint, "X", mission.Waypoints[i].Coordinates.X); LuaTools.ReplaceKey(ref waypoint, "Y", mission.Waypoints[i].Coordinates.Y); double waypointAltitude, waypointSpeed; if (unitBP == null) // Unit not found in the database, use default values for the unit category { waypointAltitude = GetAircraftCruiseAltitude(unitBP.Category, Amount.Average); waypointSpeed = GetAircraftCruiseSpeed(unitBP.Category, Amount.Average); } else { waypointAltitude = GetAircraftCruiseAltitude(unitBP.Category, unitBP.AircraftData.CruiseAltitude); waypointSpeed = GetAircraftCruiseSpeed(unitBP.Category, unitBP.AircraftData.CruiseAltitude); } waypointAltitude *= mission.Waypoints[i].AltitudeMultiplier; waypointSpeed *= mission.Waypoints[i].SpeedMultiplier; LuaTools.ReplaceKey(ref waypoint, "Altitude", waypointAltitude); LuaTools.ReplaceKey(ref waypoint, "Speed", waypointSpeed); allWaypointsLua += waypoint + "\n"; } LuaTools.ReplaceKey(ref groupLua, "PlayerWaypoints", allWaypointsLua); LuaTools.ReplaceKey(ref groupLua, "LastPlayerWaypointIndex", mission.Waypoints.Count + 2); }
private void CreatePlayerWaypoints(ref string groupLua, DCSMission mission, DBEntryUnit unitBP) { string waypointLua = LuaTools.ReadIncludeLuaFile("Mission\\WaypointPlayer.lua"); string allWaypointsLua = ""; for (int i = 0; i < mission.Waypoints.Count; i++) { string waypoint = waypointLua; LuaTools.ReplaceKey(ref waypoint, "Index", i + 2); LuaTools.ReplaceKey(ref waypoint, "Name", mission.Waypoints[i].Name); LuaTools.ReplaceKey(ref waypoint, "X", mission.Waypoints[i].Coordinates.X); LuaTools.ReplaceKey(ref waypoint, "Y", mission.Waypoints[i].Coordinates.Y); double waypointAltitude, waypointSpeed; if (unitBP == null) // Unit not found in the database, use default values for the unit category { waypointAltitude = ((unitBP.Category == UnitCategory.Helicopter) ? 1500 : 20000) * Toolbox.FEET_TO_METERS; waypointSpeed = ((unitBP.Category == UnitCategory.Helicopter) ? 90 : 300) * Toolbox.KNOTS_TO_METERS_PER_SECOND; } else { waypointAltitude = unitBP.AircraftData.CruiseAltitude; waypointSpeed = unitBP.AircraftData.CruiseAltitude; } waypointAltitude *= mission.Waypoints[i].AltitudeMultiplier; waypointSpeed *= mission.Waypoints[i].SpeedMultiplier; LuaTools.ReplaceKey(ref waypoint, "Altitude", waypointAltitude); LuaTools.ReplaceKey(ref waypoint, "Speed", waypointSpeed); allWaypointsLua += waypoint + "\n"; } LuaTools.ReplaceKey(ref groupLua, "PlayerWaypoints", allWaypointsLua); LuaTools.ReplaceKey(ref groupLua, "LastPlayerWaypointIndex", mission.Waypoints.Count + 2); }
internal static Dictionary <string, UnitMakerGroupInfo> GenerateCarrierGroup( UnitMaker unitMaker, ZoneMaker zoneMaker, DCSMission mission, MissionTemplateRecord template, Coordinates landbaseCoordinates, Coordinates objectivesCenter, double windSpeedAtSeaLevel, double windDirectionAtSeaLevel) { Dictionary <string, UnitMakerGroupInfo> carrierDictionary = new Dictionary <string, UnitMakerGroupInfo>(StringComparer.InvariantCultureIgnoreCase); DBEntryTheater theaterDB = Database.Instance.GetEntry <DBEntryTheater>(template.ContextTheater); double carrierSpeed = Math.Max( Database.Instance.Common.CarrierGroup.MinimumCarrierSpeed, Database.Instance.Common.CarrierGroup.IdealWindOfDeck - windSpeedAtSeaLevel); if (windSpeedAtSeaLevel == 0) // No wind? Pick a random direction so carriers don't always go to a 0 course when wind is calm. { windDirectionAtSeaLevel = Toolbox.RandomDouble(Toolbox.TWO_PI); } var carrierPathDeg = ((windDirectionAtSeaLevel + Math.PI) % Toolbox.TWO_PI) * Toolbox.RADIANS_TO_DEGREES; var usedCoordinates = new List <Coordinates>(); foreach (MissionTemplateFlightGroupRecord flightGroup in template.PlayerFlightGroups) { if (string.IsNullOrEmpty(flightGroup.Carrier)) { continue; // No carrier for } if (carrierDictionary.ContainsKey(flightGroup.Carrier)) { continue; // Carrier type already added } if (flightGroup.Carrier.StartsWith("FOB")) { //It Carries therefore carrier not because I can't think of a name to rename this lot GenerateFOB(unitMaker, zoneMaker, flightGroup, carrierDictionary, mission, template, landbaseCoordinates, objectivesCenter); continue; } DBEntryUnit unitDB = Database.Instance.GetEntry <DBEntryUnit>(flightGroup.Carrier); if ((unitDB == null) || !unitDB.Families.Any(x => x.IsCarrier())) { continue; // Unit doesn't exist or is not a carrier } var(shipCoordinates, shipDestination) = GetSpawnAndDestination(unitMaker, template, theaterDB, usedCoordinates, landbaseCoordinates, objectivesCenter, carrierPathDeg); usedCoordinates.Add(shipCoordinates); string cvnID = carrierDictionary.Count > 0 ? (carrierDictionary.Count + 1).ToString() : ""; int ilsChannel = 11 + carrierDictionary.Count; double radioFrequency = 127.5 + carrierDictionary.Count; string tacanCallsign = $"CVN{cvnID}"; int tacanChannel = 74 + carrierDictionary.Count; UnitMakerGroupInfo?groupInfo = unitMaker.AddUnitGroup( new string[] { unitDB.ID }, Side.Ally, unitDB.Families[0], "GroupShipCarrier", "UnitShip", shipCoordinates, 0, "GroupX2".ToKeyValuePair(shipDestination.X), "GroupY2".ToKeyValuePair(shipDestination.Y), "ILS".ToKeyValuePair(ilsChannel), "RadioBand".ToKeyValuePair((int)RadioModulation.AM), "RadioFrequency".ToKeyValuePair(GeneratorTools.GetRadioFrenquency(radioFrequency)), "Speed".ToKeyValuePair(carrierSpeed), "TACANCallsign".ToKeyValuePair(tacanCallsign), "TACANChannel".ToKeyValuePair(tacanChannel), "TACANFrequency".ToKeyValuePair(GeneratorTools.GetTACANFrequency(tacanChannel, 'X', false)), "TACANMode".ToKeyValuePair("X")); if (!groupInfo.HasValue || (groupInfo.Value.UnitsID.Length == 0)) { continue; // Couldn't generate group } mission.Briefing.AddItem( DCSMissionBriefingItemType.Airbase, $"{unitDB.UIDisplayName}\t-\t{GeneratorTools.FormatRadioFrequency(radioFrequency)}\t{ilsChannel}\t{tacanCallsign}, {tacanChannel}X"); carrierDictionary.Add(flightGroup.Carrier, groupInfo.Value); } return(carrierDictionary); }
private string AddUnit( string DCSID, string groupName, UnitCallsign?callsign, int unitLuaIndex, int unitSetIndex, DBEntryUnit unitDB, string unitTypeLua, Coordinates coordinates, UnitMakerGroupFlags unitMakerGroupFlags, params KeyValuePair <string, object>[] extraSettings) { string unitLuaTemplate = File.ReadAllText($"{BRPaths.INCLUDE_LUA_UNITS}{Toolbox.AddMissingFileExtension(unitTypeLua, ".lua")}"); var groupHeading = GetGroupHeading(coordinates, extraSettings); SetUnitCoordinatesAndHeading(unitDB, unitSetIndex, coordinates, groupHeading, out Coordinates unitCoordinates, out double unitHeading); string singleUnitLuaTable = new string(unitLuaTemplate); if (Toolbox.IsAircraft(unitDB.Category) && (unitLuaIndex == 1) && unitMakerGroupFlags.HasFlag(UnitMakerGroupFlags.FirstUnitIsClient)) { GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Skill", SinglePlayerMission ? "Player" : "Client"); } foreach (KeyValuePair <string, object> extraSetting in extraSettings) // Replace custom values first so they override other replacements { if (extraSetting.Value is Array) { GeneratorTools.ReplaceKey(ref singleUnitLuaTable, extraSetting.Key, extraSetting.Value, unitLuaIndex - 1); } else { GeneratorTools.ReplaceKey(ref singleUnitLuaTable, extraSetting.Key, extraSetting.Value); } } GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "ExtraLua", unitDB.ExtraLua); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Heading", unitHeading); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "DCSID", DCSID); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "UnitID", UnitID); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "UnitX", unitCoordinates.X); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "UnitY", unitCoordinates.Y); if (Toolbox.IsAircraft(unitDB.Category)) { GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Callsign", callsign.Value.GetLua(unitLuaIndex)); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Name", callsign.Value.GetUnitName(unitLuaIndex)); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "OnBoardNumber", Toolbox.RandomInt(1, 1000).ToString("000")); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "PropsLua", unitDB.AircraftData.PropsLua); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "RadioPresetsLua", string.Join("", unitDB.AircraftData.RadioPresets.Select((x, index) => $"[{index + 1}] = {x.ToLuaString()}"))); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Speed", unitDB.AircraftData.CruiseSpeed); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "PayloadCommon", unitDB.AircraftData.PayloadCommon); var payload = unitDB.AircraftData.GetPayloadLua(extraSettings.Any(x => x.Key == "Payload") ? extraSettings.First(x => x.Key == "Payload").Value.ToString() : "default"); if (extraSettings.Any(x => x.Key == "Payload" && x.Value.ToString() == "EMPTY")) { payload = ""; } GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "PayloadPylons", payload); GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Livery", extraSettings.Any(x => x.Key == "Livery") ? extraSettings.First(x => x.Key == "Livery").Value : "default"); } else if (unitDB.Category == UnitCategory.Static || unitDB.Category == UnitCategory.Cargo) { if (unitDB.Shape.Length - 1 > unitSetIndex) { GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Shape", unitDB.Shape[unitSetIndex]); } GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Name", $"{groupName} {unitLuaIndex}"); } else { GeneratorTools.ReplaceKey(ref singleUnitLuaTable, "Name", $"{groupName} {unitLuaIndex}"); } var unitString = $"[{unitLuaIndex}] =\n"; unitString += "{\n"; unitString += $"{singleUnitLuaTable}\n"; unitString += $"}}, -- end of [{unitLuaIndex}]\n"; return(unitString); }
private UnitMakerGroupInfo?AddStaticGroup( Country country, Coalition coalition, DCSSkillLevel?skill, UnitFamily unitFamily, Side side, string[] unitSets, string groupName, UnitCallsign?callsign, string groupTypeLua, Coordinates coordinates, UnitMakerGroupFlags unitMakerGroupFlags, params KeyValuePair <string, object>[] extraSettings ) { List <int> unitsIDList = new List <int>(); var initalGroupId = GroupID; foreach (var unitSet in unitSets) { DBEntryUnit unitDB = Database.Instance.GetEntry <DBEntryUnit>(unitSet); if (unitDB == null) { BriefingRoom.PrintToLog($"Unit \"{unitSet}\" not found.", LogMessageErrorLevel.Warning); continue; } int unitSetIndex = 0; foreach (var DCSID in unitDB.DCSIDs) { var groupHeading = GetGroupHeading(coordinates, extraSettings); SetUnitCoordinatesAndHeading(unitDB, unitSetIndex, coordinates, groupHeading, out Coordinates unitCoordinates, out double unitHeading); var firstUnitID = UnitID; var groupLua = CreateGroup( groupTypeLua, unitCoordinates, groupName, extraSettings ); var unitLua = DCSID == "FARP" ? "UnitStaticFOB" : (unitDB.Category == UnitCategory.Cargo ? "UnitCargo" : "UnitStatic"); var unitsLuaTable = AddUnit( DCSID, groupName, callsign, 1, unitSetIndex, unitDB, unitLua, coordinates, unitMakerGroupFlags, extraSettings ); unitsIDList.Add(UnitID); unitSetIndex++; UnitID++; GeneratorTools.ReplaceKey(ref groupLua, "Units", unitsLuaTable); GeneratorTools.ReplaceKey(ref groupLua, "UnitID", firstUnitID); // Must be after units are added GeneratorTools.ReplaceKey(ref groupLua, "Skill", skill); // Must be after units are added, because skill is set as a unit level GeneratorTools.ReplaceKey(ref groupLua, "Hidden", GeneratorTools.GetHiddenStatus(Template.OptionsFogOfWar, side, unitMakerGroupFlags)); // If "hidden" was not set through custom values AddUnitGroupToTable(country, UnitCategory.Static, groupLua); BriefingRoom.PrintToLog($"Added group of {DCSID} {coalition} {unitFamily} at {coordinates}"); GroupID++; } } if (unitMakerGroupFlags.HasFlag(UnitMakerGroupFlags.EmbeddedAirDefense) && unitFamily != UnitFamily.StaticStructureOffshore) { var firstUnitID = UnitID; string[] airDefenseUnits = GeneratorTools.GetEmbeddedAirDefenseUnits(Template, side); var groupLua = CreateGroup( "GroupVehicle", coordinates, groupName, extraSettings ); var(unitsLuaTable, embeddedunitsIDList) = AddUnits( airDefenseUnits, groupName, callsign, "UnitVehicle", coordinates, unitMakerGroupFlags, extraSettings ); GeneratorTools.ReplaceKey(ref groupLua, "Units", unitsLuaTable); GeneratorTools.ReplaceKey(ref groupLua, "UnitID", firstUnitID); // Must be after units are added GeneratorTools.ReplaceKey(ref groupLua, "Skill", skill); // Must be after units are added, because skill is set as a unit level GeneratorTools.ReplaceKey(ref groupLua, "Hidden", GeneratorTools.GetHiddenStatus(Template.OptionsFogOfWar, side, unitMakerGroupFlags)); // If "hidden" was not set through custom values GroupID++; unitsIDList.AddRange(embeddedunitsIDList); AddUnitGroupToTable(country, UnitCategory.Vehicle, groupLua); BriefingRoom.PrintToLog($"Added group of Embedded Air Defense for Static {coalition} {unitFamily} at {coordinates}"); } DBEntryUnit firstUnitDB = Database.Instance.GetEntry <DBEntryUnit>(unitSets.First()); if (firstUnitDB == null) { return(new UnitMakerGroupInfo(initalGroupId, coordinates, unitsIDList, groupName)); } return(new UnitMakerGroupInfo(initalGroupId, coordinates, unitsIDList, groupName, firstUnitDB.AircraftData.RadioFrequency, firstUnitDB)); }
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); }
internal UnitMakerGroupInfo?AddUnitGroup( string[] units, Side side, UnitFamily unitFamily, string groupTypeLua, string unitTypeLua, Coordinates coordinates, UnitMakerGroupFlags unitMakerGroupFlags = 0, params KeyValuePair <string, object>[] extraSettings) { if (units.Length == 0) { return(null); } Coalition coalition = (side == Side.Ally) ? PlayerCoalition : PlayerCoalition.GetEnemy(); Country country = (coalition == Coalition.Blue) ? Country.CJTFBlue : Country.CJTFRed; if (extraSettings.Any(x => x.Key == "Country")) { country = (Country)extraSettings.First(x => x.Key == "Country").Value; } var skill = GeneratorTools.GetDefaultSkillLevel(Template, side); if (extraSettings.Any(x => x.Key == "Skill")) { skill = (DCSSkillLevel)extraSettings.First(x => x.Key == "Skill").Value; } var isUsingSkynet = Template.MissionFeatures.Contains("SkynetIADS"); string groupName; UnitCallsign?callsign = null; if (unitFamily.GetUnitCategory().IsAircraft()) { callsign = CallsignGenerator.GetCallsign(unitFamily, coalition, side, isUsingSkynet); groupName = callsign.Value.GroupName; if (extraSettings.Any(x => x.Key == "PlayerStartingType") && extraSettings.First(x => x.Key == "PlayerStartingType").Value.ToString() == "TakeOffParking") { groupName += "(C)"; } } else { groupName = GeneratorTools.GetGroupName(GroupID, unitFamily, side, isUsingSkynet); } if (unitFamily.GetUnitCategory() == UnitCategory.Static || unitFamily.GetUnitCategory() == UnitCategory.Cargo && unitFamily != UnitFamily.FOB) { return(AddStaticGroup( country, coalition, skill, unitFamily, side, units, groupName, callsign, groupTypeLua, coordinates, unitMakerGroupFlags, extraSettings )); } var groupLua = CreateGroup( groupTypeLua, coordinates, groupName, extraSettings ); int firstUnitID = UnitID; var(unitsLuaTable, unitsIDList) = AddUnits( units, groupName, callsign, unitTypeLua, coordinates, unitMakerGroupFlags, extraSettings ); if (unitsIDList.Count == 0) { return(null); // No valid units added to this group } GeneratorTools.ReplaceKey(ref groupLua, "Units", unitsLuaTable); DBEntryUnit firstUnitDB = units.Select(x => Database.Instance.GetEntry <DBEntryUnit>(x)).First(x => x != null); var aircraftCategories = new UnitCategory[] { UnitCategory.Helicopter, UnitCategory.Plane }; var isAircraft = firstUnitDB != null && aircraftCategories.Contains(firstUnitDB.Category); if (isAircraft) { groupLua = ApplyAircraftFields(groupLua, firstUnitDB, extraSettings); if (unitMakerGroupFlags.HasFlag(UnitMakerGroupFlags.ImmediateAircraftSpawn)) { Mission.AppendValue("AircraftActivatorCurrentQueue", $"{GroupID},"); } else if (unitMakerGroupFlags.HasFlag(UnitMakerGroupFlags.RadioAircraftSpawn)) { Mission.AppendValue("AircraftRadioActivator", $"{{{GroupID}, \"{groupName}\"}},"); } else if (groupTypeLua != "GroupAircraftParkedUncontrolled") { Mission.AppendValue("AircraftActivatorReserveQueue", $"{GroupID},"); } } GeneratorTools.ReplaceKey(ref groupLua, "UnitID", firstUnitID); // Must be after units are added GeneratorTools.ReplaceKey(ref groupLua, "Skill", skill); // Must be after units are added, because skill is set as a unit level GeneratorTools.ReplaceKey(ref groupLua, "Hidden", GeneratorTools.GetHiddenStatus(Template.OptionsFogOfWar, side, unitMakerGroupFlags)); // If "hidden" was not set through custom values AddUnitGroupToTable(country, unitFamily.GetUnitCategory(), groupLua); BriefingRoom.PrintToLog($"Added group of {units.Length} {coalition} {unitFamily} at {coordinates}"); GroupID++; if (firstUnitDB == null) { return(new UnitMakerGroupInfo(GroupID - 1, coordinates, unitsIDList, groupName)); } return(new UnitMakerGroupInfo(GroupID - 1, coordinates, unitsIDList, groupName, firstUnitDB.AircraftData.RadioFrequency, firstUnitDB)); }
private void SetUnitCoordinatesAndHeading(ref Coordinates unitCoordinates, ref double unitHeading, DBEntryUnit unitBP, int unitIndex) { if (unitBP.IsAircraft) { unitCoordinates += new Coordinates(AIRCRAFT_UNIT_SPACING, AIRCRAFT_UNIT_SPACING) * unitIndex; } else { if (unitBP.OffsetCoordinates.Length > unitIndex) // Unit has a fixed set of coordinates (for SAM sites, etc.) { double s = Math.Sin(unitHeading); double c = Math.Cos(unitHeading); Coordinates offsetCoordinates = unitBP.OffsetCoordinates[unitIndex]; unitCoordinates += new Coordinates(offsetCoordinates.X * c - offsetCoordinates.Y * s, offsetCoordinates.X * s + offsetCoordinates.Y * c); } else // No fixed coordinates, generate random coordinates { switch (unitBP.Category) { case UnitCategory.Ship: unitCoordinates = unitCoordinates.CreateNearRandom(SHIP_UNIT_SPACING, SHIP_UNIT_SPACING * 10); break; case UnitCategory.Static: // Static units are spawned exactly on the group location (and there's only a single unit per group) break; default: unitCoordinates = unitCoordinates.CreateNearRandom(VEHICLE_UNIT_SPACING, VEHICLE_UNIT_SPACING * 10); break; } } if (unitBP.OffsetHeading.Length > unitIndex) // Unit has a fixed heading (for SAM sites, etc.) { unitHeading = Toolbox.ClampAngle(unitHeading + unitBP.OffsetHeading[unitIndex]); // editor looks odd but works fine if negative or over 2Pi } else if (unitBP.Category != UnitCategory.Ship) { unitHeading = Toolbox.RandomDouble(Toolbox.TWO_PI); } } }
/// <summary> /// Generates the mission briefing. /// </summary> /// <param name="mission">Mission</param> /// <param name="template">Template from which the mission should be built</param> /// <param name="airbaseDB">Airbase player will take off from and land back on</param> /// <param name="coalitionsDB">Database entries for the mission coalitions</param> public void GenerateMissionBriefing(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryTheaterAirbase airbaseDB, DBEntryUnit carrierDB, List <UnitFlightGroupBriefingDescription> flightGroups, DBEntryCoalition[] coalitionsDB) { DebugLog.Instance.WriteLine("Generating mission briefing...", 1); // Get mission features DBEntryMissionFeature[] features = Database.Instance.GetEntries <DBEntryMissionFeature>(objectiveDB.MissionFeatures); string description = GeneratorTools.SanitizeString(template.BriefingDescription); if (string.IsNullOrEmpty(description)) // No custom mission description has been provided, generate one { description = objectiveDB.BriefingDescriptionByUnitFamily[(int)mission.Objectives[0].TargetFamily]; if (string.IsNullOrEmpty(description)) // No custom briefing for this target family, use the default { description = objectiveDB.BriefingDescription; } description = GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(description), mission, coalitionsDB); } description = GeneratorTools.SanitizeString(description); // Generate tasks string baseName = carrierDB != null? carrierDB.ID : airbaseDB.Name; List <string> tasks = new List <string> { $"Take off from {baseName}" }; string objectiveTask = GeneratorTools.ParseRandomString(objectiveDB.BriefingTask); for (int i = 0; i < mission.Objectives.Length; i++) { string taskString = GeneratorTools.MakeBriefingStringReplacements(objectiveTask, mission, coalitionsDB, i); tasks.Add(taskString); mission.CoreLuaScript += $"briefingRoom.mission.objectives[{i + 1}].task = \"{taskString}\"\r\n"; } tasks.Add($"Return to {baseName}"); DebugLog.Instance.WriteLine($"{tasks.Count} task(s)", 2); // Generate mission remarks... List <string> remarks = new List <string>(); remarks.AddRange( // ...from objective from string remark in objectiveDB.BriefingRemarks select GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(remark), mission, coalitionsDB)); foreach (DBEntryMissionFeature feature in features) { remarks.AddRange( // ...from features from string remark in feature.BriefingRemarks select GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(remark), mission, coalitionsDB)); } /* * // Opposition Remarks * string airDefenseNumbers = template.OppositionAirDefense == AmountN.Random? "Unknown":template.OppositionAirDefense.ToString(); * string airDefenseSkill = template.OppositionSkillLevelGround == BRSkillLevel.Random? "Varied":template.OppositionSkillLevelGround.ToString(); * string airForceNumbers = template.OppositionAirForce == AmountN.Random? "Unknown":template.OppositionAirForce.ToString(); * string airForceSkill = template.OppositionSkillLevelAir == BRSkillLevel.Random? "Varied":template.OppositionSkillLevelAir.ToString(); * string allyAirDefenseNumbers = template.PlayerFriendlyAirDefense == AmountN.Random? "Unknown":template.PlayerFriendlyAirDefense.ToString(); * string allyAirDefenseSkill = template.PlayerAISkillLevel == BRSkillLevel.Random? "Varied":template.PlayerAISkillLevel.ToString(); * remarks.AddRange(new List<string>{ * $"Enemy Air Defenses are {airDefenseNumbers} and they are {airDefenseSkill} troops", * $"Expected Enemy Air Force response is {airForceNumbers} and they are {airForceSkill} pilots", * $"Our Air Defenses are {allyAirDefenseNumbers} and they are {allyAirDefenseSkill} troops",}); * remarks.Add("Use the \"F10/Other\" item in the comms for additional options"); * DebugLog.Instance.WriteLine($"{remarks.Count} remark(s)", 2); */ mission.BriefingHTML = CreateHTMLBriefing(mission, template, description, tasks, remarks, flightGroups, airbaseDB, carrierDB, coalitionsDB); mission.BriefingTXT = CreateTXTBriefing(description, tasks, remarks, flightGroups, airbaseDB, carrierDB); }
/// <summary> /// Creates the raw text briefing, to be used for the mission description inside DCS World. /// </summary> /// <param name="description"></param> /// <param name="tasks"></param> /// <param name="remarks"></param> /// <param name="flightGroups"></param> /// <param name="airbaseDB">Airbase player will take off from and land back on</param> /// <returns></returns> private string CreateTXTBriefing( string description, List <string> tasks, List <string> remarks, List <UnitFlightGroupBriefingDescription> flightGroups, DBEntryTheaterAirbase airbaseDB, DBEntryUnit carrier) { DebugLog.Instance.WriteLine("Generating raw text mission briefing...", 2); string briefing = description + "\n\n"; briefing += "TASKS:\n"; foreach (string t in tasks) { briefing += $"- {t}\n"; } briefing += "\n"; briefing += "REMARKS:\n"; foreach (string r in remarks) { briefing += $"- {r}\n"; } briefing += "\n"; briefing += "MISSION PACKAGE:\n"; foreach (UnitFlightGroupBriefingDescription fg in flightGroups) { briefing += $"- {fg.Callsign} ({fg.Count}×{fg.Type}, {fg.Task}) - {fg.Radio}{(string.IsNullOrEmpty(fg.Remarks) ? "" : $", {fg.Remarks}")}\n"; }
private string CreateHTMLBriefing( DCSMission mission, MissionTemplate template, string description, List <string> tasks, List <string> remarks, List <UnitFlightGroupBriefingDescription> flightGroups, DBEntryTheaterAirbase airbaseDB, DBEntryUnit carrierDB, DBEntryCoalition[] coalitionsDB) { DebugLog.Instance.WriteLine("Generating HTML mission briefing...", 2); if (!File.Exists(HTML_TEMPLATE_FILE)) // Briefing template not found { DebugLog.Instance.WriteLine("HTML template file not found.", 1, DebugLogMessageErrorLevel.Warning); return("HTML template file not found."); } string briefing = File.ReadAllText(HTML_TEMPLATE_FILE); // Title briefing = briefing.Replace("$MISSIONNAME$", mission.MissionName); briefing = briefing.Replace("$MISSIONTYPE$", GeneratorTools.RemoveAfterComma(template.ObjectiveType) + " mission " + ((template.GetMissionType() == MissionType.SinglePlayer) ? "(single-player)" : $"({template.GetPlayerCount()}-players multiplayer)")); // Situation summary briefing = briefing.Replace("$LONGDATE$", mission.DateTime.ToDateString(true)); briefing = briefing.Replace("$LONGTIME$", mission.DateTime.ToTimeString()); briefing = briefing.Replace("$SHORTDATE$", mission.DateTime.ToDateString(false)); briefing = briefing.Replace("$SHORTTIME$", mission.DateTime.ToTimeString()); briefing = briefing.Replace("$WEATHER$", GeneratorTools.GetEnumString(mission.Weather.WeatherLevel)); briefing = briefing.Replace("$WIND$", GeneratorTools.GetEnumString(mission.Weather.WindLevel)); briefing = briefing.Replace("$WINDSPEED$", mission.Weather.WindSpeedAverage.ToString("F0")); // Friends and enemies briefing = briefing.Replace("$PLAYERCOALITION$", GeneratorTools.RemoveAfterComma(template.GetCoalition(mission.CoalitionPlayer))); briefing = briefing.Replace("$ENEMYCOALITION$", GeneratorTools.RemoveAfterComma(template.GetCoalition(mission.CoalitionEnemy))); // Description briefing = briefing.Replace("$DESCRIPTION$", description.Replace("\n", "<br />")); // Tasks string tasksHTML = ""; foreach (string task in tasks) { tasksHTML += $"<li>{task}</li>"; } briefing = briefing.Replace("$TASKS$", tasksHTML); // Remarks string remarksHTML = ""; foreach (string remark in remarks) { remarksHTML += $"<li>{remark}</li>"; } briefing = briefing.Replace("$REMARKS$", remarksHTML); // Flight groups string flightGroupsHTML = ""; foreach (UnitFlightGroupBriefingDescription fg in flightGroups) { flightGroupsHTML += "<tr>" + $"<td>{fg.Callsign}</td>" + $"<td>{fg.Count}×{fg.Type}</td>" + $"<td>{fg.Task}</td><td>{fg.Radio}</td>" + $"<td>{fg.Remarks}</td>" + "</tr>"; } briefing = briefing.Replace("$FLIGHTGROUPS$", flightGroupsHTML); // Airbases string airbasesHTML = "<tr>" + $"<td>{airbaseDB.Name}</td>" + $"<td>{airbaseDB.Runways}</td>" + $"<td>{airbaseDB.ATC}</td>" + $"<td>{airbaseDB.ILS}</td>" + $"<td>{airbaseDB.TACAN}</td>" + "</tr>"; briefing = briefing.Replace("$AIRBASES$", airbasesHTML); string carrierHTML = ""; if (carrierDB != null) { carrierHTML = "<tr>" + $"<td>{carrierDB.ID}</td>" + $"<td>127.500AM</td>" + $"<td>11</td>" + $"<td>74X</td>" + "</tr>"; } briefing = briefing.Replace("$CARRIERS$", carrierHTML); // Waypoints string waypointsHTML = ""; double distance; double totalDistance = 0.0; Coordinates currentPosition = mission.InitialPosition; waypointsHTML += $"<tr><td><strong>TAKEOFF</strong></td><td>-</td><td>-</td></tr>"; foreach (DCSMissionWaypoint wp in mission.Waypoints) { distance = currentPosition.GetDistanceFrom(wp.Coordinates); totalDistance += distance; currentPosition = wp.Coordinates; waypointsHTML += $"<tr><td>{wp.Name}</td>" + $"<td>{GeneratorTools.ConvertDistance(distance, template.BriefingUnitSystem)}</td>" + $"<td>{GeneratorTools.ConvertDistance(totalDistance, template.BriefingUnitSystem)}</td></tr>"; } distance = currentPosition.GetDistanceFrom(mission.InitialPosition); totalDistance += distance; waypointsHTML += $"<tr><td><strong>LANDING</strong></td>" + $"<td>{GeneratorTools.ConvertDistance(distance, template.BriefingUnitSystem)}</td>" + $"<td>{GeneratorTools.ConvertDistance(totalDistance, template.BriefingUnitSystem)}</td></tr>"; briefing = briefing.Replace("$WAYPOINTS$", waypointsHTML); return(briefing); }
private void CreateUnitGroups(ref string lua, DCSMission mission, Coalition coalition, UnitCategory unitCategory) { int i, j; int groupIndex = 1; string allGroupsLua = ""; foreach (DCSMissionUnitGroup group in mission.UnitGroups) { if ((group.Coalition != coalition) || // Group does not belong to this coalition (group.Category != unitCategory) || // Group does not belong to this unit category (group.Units.Length == 0)) // Group doesn't contain any units { continue; // Ignore it } string groupLua = LuaTools.ReadIncludeLuaFile($"Units\\{group.LuaGroup}"); LuaTools.ReplaceKey(ref groupLua, "Index", groupIndex); LuaTools.ReplaceKey(ref groupLua, "X", group.Coordinates.X); LuaTools.ReplaceKey(ref groupLua, "Y", group.Coordinates.Y); LuaTools.ReplaceKey(ref groupLua, "X2", group.Coordinates2.X); LuaTools.ReplaceKey(ref groupLua, "Y2", group.Coordinates2.Y); LuaTools.ReplaceKey(ref groupLua, "Hidden", group.Flags.HasFlag(DCSMissionUnitGroupFlags.Hidden)); LuaTools.ReplaceKey(ref groupLua, "ID", group.GroupID); LuaTools.ReplaceKey(ref groupLua, "FirstUnitID", group.Units[0].ID); LuaTools.ReplaceKey(ref groupLua, "Name", group.Name); LuaTools.ReplaceKey(ref groupLua, "ObjectiveAirbaseID", group.AirbaseID); if (group.CarrierId > 0) { LuaTools.ReplaceKey(ref groupLua, "LinkUnit", group.CarrierId); } if (group.TACAN != null) { LuaTools.ReplaceKey(ref groupLua, "TacanFrequency", group.TACAN.freqency); LuaTools.ReplaceKey(ref groupLua, "TacanCallSign", group.TACAN.callsign); LuaTools.ReplaceKey(ref groupLua, "TacanChannel", group.TACAN.channel); LuaTools.ReplaceKey(ref groupLua, "UnitID", group.Units[0].ID); } if (group.ILS > 0) { LuaTools.ReplaceKey(ref groupLua, "ILS", group.ILS); } DBEntryUnit unitBP = Database.Instance.GetEntry <DBEntryUnit>(group.UnitID); if (unitBP == null) { continue; // TODO: error message? } // Group is a client group, requires player waypoints if (group.IsAPlayerGroup()) { CreatePlayerWaypoints(ref groupLua, mission, unitBP); } string allUnitsLua = ""; for (i = 0; i < group.Units.Length; i++) { string unitLua = LuaTools.ReadIncludeLuaFile($"Units\\{group.LuaUnit}"); Coordinates unitCoordinates = new Coordinates(group.Coordinates); double unitHeading = 0; if ((group.Category == UnitCategory.Static) || (group.Category == UnitCategory.Vehicle)) { double randomSpreadAngle = Toolbox.RandomDouble(Math.PI * 2); unitCoordinates += new Coordinates(Math.Cos(randomSpreadAngle) * 35, Math.Sin(randomSpreadAngle) * 35); unitHeading = Toolbox.RandomDouble(Math.PI * 2); } else { unitCoordinates += new Coordinates(50 * i, 50 * i); } if ((group.Category == UnitCategory.Helicopter) || (group.Category == UnitCategory.Plane)) // Unit is an aircraft { if (unitBP == null) { LuaTools.ReplaceKey(ref groupLua, "Altitude", ((group.Category == UnitCategory.Helicopter) ? 1500 : 4572) * Toolbox.RandomDouble(.8, 1.2)); LuaTools.ReplaceKey(ref unitLua, "Altitude", ((group.Category == UnitCategory.Helicopter) ? 1500 : 4572) * Toolbox.RandomDouble(.8, 1.2)); LuaTools.ReplaceKey(ref groupLua, "EPLRS", false); LuaTools.ReplaceKey(ref unitLua, "PayloadCommon", ""); LuaTools.ReplaceKey(ref unitLua, "PayloadPylons", ""); LuaTools.ReplaceKey(ref unitLua, "RadioPresetsLua", ""); LuaTools.ReplaceKey(ref unitLua, "PropsLua", ""); LuaTools.ReplaceKey(ref groupLua, "RadioBand", 0); LuaTools.ReplaceKey(ref groupLua, "RadioFrequency", 124.0f); LuaTools.ReplaceKey(ref groupLua, "Speed", ((group.Category == UnitCategory.Helicopter) ? 51 : 125) * Toolbox.RandomDouble(.9, 1.1)); } else { LuaTools.ReplaceKey(ref groupLua, "Altitude", unitBP.AircraftData.CruiseAltitude); LuaTools.ReplaceKey(ref unitLua, "Altitude", unitBP.AircraftData.CruiseAltitude); LuaTools.ReplaceKey(ref groupLua, "EPLRS", unitBP.Flags.HasFlag(DBEntryUnitFlags.EPLRS)); LuaTools.ReplaceKey(ref unitLua, "PayloadCommon", unitBP.AircraftData.PayloadCommon); if (group.IsAPlayerGroup()) { LuaTools.ReplaceKey(ref unitLua, "RadioPresetsLua", string.Join("", unitBP.AircraftData.RadioPresets.Select((x, index) => $"[{index + 1}] = {x.ToLuaString()}"))); LuaTools.ReplaceKey(ref unitLua, "PropsLua", unitBP.AircraftData.PropsLua); } else { LuaTools.ReplaceKey(ref unitLua, "RadioPresetsLua", ""); LuaTools.ReplaceKey(ref unitLua, "PropsLua", ""); } LuaTools.ReplaceKey(ref groupLua, "RadioBand", (int)unitBP.AircraftData.RadioModulation); LuaTools.ReplaceKey(ref groupLua, "RadioFrequency", unitBP.AircraftData.RadioFrequency); LuaTools.ReplaceKey(ref groupLua, "Speed", unitBP.AircraftData.CruiseSpeed); string pylonLua = ""; string[] payload = unitBP.AircraftData.GetPayload(group.Payload, mission.DateTime.Decade); for (j = 0; j < DBEntryUnitAircraftData.MAX_PYLONS; j++) { string pylonCode = payload[j]; if (!string.IsNullOrEmpty(pylonCode)) { pylonLua += $"[{j + 1}] = {{[\"CLSID\"] = \"{pylonCode}\" }},\r\n"; } } LuaTools.ReplaceKey(ref unitLua, "PayloadPylons", pylonLua); } } else if ((group.Category == UnitCategory.Ship)) { if (group.RadioFrequency > 0) { LuaTools.ReplaceKey(ref unitLua, "RadioBand", (int)group.RadioModulation); LuaTools.ReplaceKey(ref unitLua, "RadioFrequency", group.RadioFrequency * 1000000); } else { LuaTools.ReplaceKey(ref unitLua, "RadioBand", 0); LuaTools.ReplaceKey(ref unitLua, "RadioFrequency", 127.0f * 1000000); } LuaTools.ReplaceKey(ref groupLua, "Speed", group.Speed); } if (unitBP == null) { LuaTools.ReplaceKey(ref unitLua, "ExtraLua", ""); } else { LuaTools.ReplaceKey(ref unitLua, "ExtraLua", unitBP.ExtraLua); } LuaTools.ReplaceKey(ref unitLua, "Callsign", group.CallsignLua); // Must be before "index" replacement, as is it is integrated in the callsign LuaTools.ReplaceKey(ref unitLua, "Index", i + 1); LuaTools.ReplaceKey(ref unitLua, "ID", group.Units[i].ID); LuaTools.ReplaceKey(ref unitLua, "Type", group.Units[i].Type); LuaTools.ReplaceKey(ref unitLua, "Name", $"{group.Name} {i + 1}"); if (group.Flags.HasFlag(DCSMissionUnitGroupFlags.FirstUnitIsPlayer)) { LuaTools.ReplaceKey(ref unitLua, "Skill", (i == 0) ? DCSSkillLevel.Player : group.Skill, false); } else { LuaTools.ReplaceKey(ref unitLua, "Skill", group.Skill, false); } LuaTools.ReplaceKey(ref unitLua, "X", group.Units[i].Coordinates.X); LuaTools.ReplaceKey(ref unitLua, "Y", group.Units[i].Coordinates.Y); LuaTools.ReplaceKey(ref unitLua, "Heading", group.Units[i].Heading); LuaTools.ReplaceKey(ref unitLua, "OnboardNumber", Toolbox.RandomInt(1, 1000).ToString("000")); LuaTools.ReplaceKey(ref unitLua, "ParkingID", group.Units[i].ParkingSpot); allUnitsLua += unitLua + "\n"; } LuaTools.ReplaceKey(ref groupLua, "units", allUnitsLua); allGroupsLua += groupLua + "\n"; groupIndex++; } LuaTools.ReplaceKey(ref lua, $"Groups{unitCategory}{coalition}", allGroupsLua); }
private static void SaveFlightGroup(DCSMission mission, UnitMakerGroupInfo?groupInfo, MissionTemplateFlightGroupRecord flightGroup, DBEntryUnit unitDB, string homeBase) { mission.Briefing.AddItem(DCSMissionBriefingItemType.FlightGroup, $"{groupInfo.Value.Name}(P)\t" + $"{flightGroup.Count}× {unitDB.UIDisplayName}\t" + $"{GeneratorTools.FormatRadioFrequency(unitDB.AircraftData.RadioFrequency)}\t" + $"{Toolbox.FormatPayload(flightGroup.Payload)}\t" + $"{homeBase}"); for (int i = 0; i < flightGroup.Count; i++) { mission.AppendValue("SCRIPTCLIENTPILOTNAMES", $"\"{groupInfo.Value.Name} {i + 2}\","); } }