internal UnitMakerGroupInfo?AddUnitGroup( UnitFamily family, int unitCount, Side side, string groupLua, string unitLua, Coordinates coordinates, UnitMakerGroupFlags unitMakerGroupFlags = 0, params KeyValuePair <string, object>[] extraSettings) => AddUnitGroup( new List <UnitFamily> { family }, unitCount, side, groupLua, unitLua, coordinates, unitMakerGroupFlags, extraSettings);
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); }
internal UnitMakerGroupInfo?AddUnitGroup( List <UnitFamily> families, int unitCount, Side side, string groupLua, string unitLua, Coordinates coordinates, UnitMakerGroupFlags unitMakerGroupFlags = 0, params KeyValuePair <string, object>[] extraSettings) { if (unitCount <= 0) { throw new BriefingRoomException("Asking for a zero units"); } if (families.Count <= 0) { throw new BriefingRoomException("No Unit Families Provided"); } DBEntryCoalition unitsCoalitionDB = CoalitionsDB[(int)((side == Side.Ally) ? PlayerCoalition : PlayerCoalition.GetEnemy())]; var(country, units) = unitsCoalitionDB.GetRandomUnits(families, Template.ContextDecade, unitCount, Template.Mods); if (units.Count == 0) { throw new BriefingRoomException($"Found no units for {string.Join(", ", families)} {country}"); } if (country != Country.ALL) { extraSettings = extraSettings.Append("Country".ToKeyValuePair(country)).ToArray(); } if (unitMakerGroupFlags.HasFlag(UnitMakerGroupFlags.EmbeddedAirDefense) && (families.First().GetUnitCategory() == UnitCategory.Vehicle)) { string[] airDefenseUnits = GeneratorTools.GetEmbeddedAirDefenseUnits(Template, side, country != Country.ALL ? country : null); units.AddRange(airDefenseUnits); } return(AddUnitGroup(Toolbox.ShuffleArray(units.ToArray()), side, families.First(), groupLua, unitLua, coordinates, unitMakerGroupFlags, extraSettings)); }
protected UnitMakerGroupInfo?AddMissionFeature(T featureDB, DCSMission mission, Coordinates coordinates, Coordinates?coordinates2, ref Dictionary <string, object> extraSettings, Side?objectiveTargetSide = null, bool hideEnemy = false) { // Add secondary coordinates (destination point) to the extra settings if (!coordinates2.HasValue) { coordinates2 = coordinates; // No destination point? Use initial point } extraSettings.AddIfKeyUnused("GroupX2", coordinates2.Value.X); extraSettings.AddIfKeyUnused("GroupY2", coordinates2.Value.Y); var TACANStr = GetExtraSettingsFromFeature(featureDB, ref extraSettings); // Add specific settings for this feature (TACAN frequencies, etc) // Feature unit group UnitMakerGroupInfo?groupInfo = null; if (FeatureHasUnitGroup(featureDB)) { UnitMakerGroupFlags groupFlags = 0; if (featureDB.UnitGroupFlags.HasFlag(FeatureUnitGroupFlags.ImmediateAircraftActivation)) { groupFlags |= UnitMakerGroupFlags.ImmediateAircraftSpawn; } if (featureDB.UnitGroupFlags.HasFlag(FeatureUnitGroupFlags.RadioAircraftActivation)) { groupFlags |= UnitMakerGroupFlags.RadioAircraftSpawn; } Side groupSide = Side.Enemy; if (featureDB.UnitGroupFlags.HasFlag(FeatureUnitGroupFlags.Friendly)) { groupSide = Side.Ally; } else if (featureDB.UnitGroupFlags.HasFlag(FeatureUnitGroupFlags.SameSideAsTarget) && objectiveTargetSide.HasValue) { groupSide = objectiveTargetSide.Value; } if (hideEnemy && groupSide == Side.Enemy) { groupFlags |= UnitMakerGroupFlags.AlwaysHidden; } extraSettings.AddIfKeyUnused("Payload", featureDB.UnitGroupPayload); var groupLua = featureDB.UnitGroupLuaGroup; var unitCount = featureDB.UnitGroupSize.GetValue(); var unitFamily = Toolbox.RandomFrom(featureDB.UnitGroupFamilies); var luaUnit = featureDB.UnitGroupLuaUnit; SetAirbase(featureDB, unitFamily, ref groupLua, ref luaUnit, groupSide, ref coordinates, coordinates2.Value, unitCount, ref extraSettings); groupInfo = _unitMaker.AddUnitGroup( unitFamily, unitCount, groupSide, groupLua, luaUnit, coordinates, groupFlags, extraSettings.ToArray()); if ( groupSide == Side.Ally && groupInfo.HasValue && groupInfo.Value.UnitDB != null && groupInfo.Value.UnitDB.IsAircraft) { mission.Briefing.AddItem(DCSMissionBriefingItemType.FlightGroup, $"{groupInfo.Value.Name}\t" + $"{unitCount}× {groupInfo.Value.UnitDB.UIDisplayName}\t" + $"{GeneratorTools.FormatRadioFrequency(groupInfo.Value.Frequency)}{TACANStr}\t" + $"{Toolbox.FormatPayload(featureDB.UnitGroupPayload)}"); // TODO: human-readable payload name } if (featureDB.ExtraGroups.Max > 1) { SpawnExtraGroups(featureDB, mission, groupSide, groupFlags, coordinates, coordinates2.Value, extraSettings); } } // Feature Lua script string featureLua = ""; // Adds the features' group ID to the briefingRoom.mission.missionFeatures.groupsID table if (this is MissionGeneratorFeaturesMission) { featureLua += $"briefingRoom.mission.missionFeatures.groupsID.{GeneratorTools.LowercaseFirstCharacter(featureDB.ID)} = {(groupInfo.HasValue ? groupInfo.Value.GroupID : 0)}\n"; featureLua += $"briefingRoom.mission.missionFeatures.unitsID.{GeneratorTools.LowercaseFirstCharacter(featureDB.ID)} = {{{(groupInfo.HasValue ? string.Join(",", groupInfo.Value.UnitsID) : "")}}}\n"; } if (!string.IsNullOrEmpty(featureDB.IncludeLuaSettings)) { featureLua = featureDB.IncludeLuaSettings + "\n"; } foreach (string luaFile in featureDB.IncludeLua) { featureLua += Toolbox.ReadAllTextIfFileExists($"{featureDB.SourceLuaDirectory}{luaFile}") + "\n"; } foreach (KeyValuePair <string, object> extraSetting in extraSettings) { GeneratorTools.ReplaceKey(ref featureLua, extraSetting.Key, extraSetting.Value); } if (groupInfo.HasValue) { GeneratorTools.ReplaceKey(ref featureLua, "FeatureGroupID", groupInfo.Value.GroupID); } if (featureDB is DBEntryFeatureObjective) { mission.AppendValue("ScriptObjectivesFeatures", featureLua); } else { mission.AppendValue("ScriptMissionFeatures", featureLua); } // Add feature ogg files foreach (string oggFile in featureDB.IncludeOgg) { mission.AddMediaFile($"l10n/DEFAULT/{oggFile}", $"{BRPaths.INCLUDE_OGG}{oggFile}"); } return(groupInfo); }
private void SpawnExtraGroups(T featureDB, DCSMission mission, Side groupSide, UnitMakerGroupFlags groupFlags, Coordinates coordinates, Coordinates coordinates2, Dictionary <string, object> extraSettings) { foreach (var i in Enumerable.Range(1, featureDB.ExtraGroups.GetValue())) { var groupLua = featureDB.UnitGroupLuaGroup; var unitCount = featureDB.UnitGroupSize.GetValue(); var unitFamily = Toolbox.RandomFrom(featureDB.UnitGroupFamilies); var luaUnit = featureDB.UnitGroupLuaUnit; var spawnCoords = _unitMaker.SpawnPointSelector.GetRandomSpawnPoint( featureDB.UnitGroupValidSpawnPoints, coordinates, new MinMaxD(0, 5), coalition: GeneratorTools.GetSpawnPointCoalition(_template, groupSide) ); if (!spawnCoords.HasValue) { continue; } SetAirbase(featureDB, unitFamily, ref groupLua, ref luaUnit, groupSide, ref coordinates, coordinates2, unitCount, ref extraSettings); var groupInfo = _unitMaker.AddUnitGroup( unitFamily, unitCount, groupSide, groupLua, luaUnit, spawnCoords.Value, groupFlags, extraSettings.ToArray()); if ( groupSide == Side.Ally && groupInfo.HasValue && groupInfo.Value.UnitDB != null && groupInfo.Value.UnitDB.IsAircraft) { mission.Briefing.AddItem(DCSMissionBriefingItemType.FlightGroup, $"{groupInfo.Value.Name}\t" + $"{unitCount}× {groupInfo.Value.UnitDB.UIDisplayName}\t" + $"{GeneratorTools.FormatRadioFrequency(groupInfo.Value.Frequency)}\t" + $"{Toolbox.FormatPayload(featureDB.UnitGroupPayload)}"); } } }
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 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)); }
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 void AddEmbeddedAirDefenseUnits(MissionTemplateRecord template, DBEntryObjectiveTarget targetDB, DBEntryObjectiveTargetBehavior targetBehaviorDB, DBEntryObjectiveTask taskDB, ObjectiveOption[] objectiveOptions, Coordinates objectiveCoordinates, UnitMakerGroupFlags groupFlags, List <KeyValuePair <string, object> > extraSettings) { // Static targets (aka buildings) need to have their "embedded" air defenses spawned in another group string[] airDefenseUnits = GeneratorTools.GetEmbeddedAirDefenseUnits(template, taskDB.TargetSide); if (airDefenseUnits.Length > 0) { UnitMaker.AddUnitGroup( airDefenseUnits, taskDB.TargetSide, UnitFamily.VehicleAAA, targetBehaviorDB.GroupLua[(int)targetDB.UnitCategory], targetBehaviorDB.UnitLua[(int)targetDB.UnitCategory], objectiveCoordinates + Coordinates.CreateRandom(100, 500), groupFlags, extraSettings.ToArray()); } }
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); }