private Waypoint GenerateSubTaskWaypoint(MissionTemplateSubTask objectiveTemplate, Coordinates objectiveCoordinates, string objectiveName, MissionTemplateRecord template, bool scriptIgnore = false) { var AirOnGroundBehaviorLocations = new List <DBEntryObjectiveTargetBehaviorLocation> { DBEntryObjectiveTargetBehaviorLocation.SpawnOnAirbaseParking, DBEntryObjectiveTargetBehaviorLocation.SpawnOnAirbaseParkingNoHardenedShelter }; DBEntryObjectiveTarget targetDB = Database.Instance.GetEntry <DBEntryObjectiveTarget>(objectiveTemplate.Target); DBEntryObjectiveTargetBehaviorLocation targetBehaviorLocation = Database.Instance.GetEntry <DBEntryObjectiveTargetBehavior>(objectiveTemplate.TargetBehavior).Location; if (targetDB == null) { throw new BriefingRoomException($"Target \"{targetDB.UIDisplayName}\" not found for objective."); } Coordinates waypointCoordinates = objectiveCoordinates; bool onGround = !targetDB.UnitCategory.IsAircraft() || AirOnGroundBehaviorLocations.Contains(targetBehaviorLocation); // Ground targets = waypoint on the ground var taskDB = Database.Instance.GetEntry <DBEntryObjectiveTask>(objectiveTemplate.Task); if (objectiveTemplate.Options.Contains(ObjectiveOption.InaccurateWaypoint) && !TRANSPORT_TASKS.Contains(taskDB.ID)) { waypointCoordinates += Coordinates.CreateRandom(3.0, 6.0) * Toolbox.NM_TO_METERS; if (template.OptionsMission.Contains("MarkWaypoints")) { DrawingMaker.AddDrawing($"Target Zone {objectiveName}", DrawingType.Circle, waypointCoordinates, "Radius".ToKeyValuePair(6.0 * Toolbox.NM_TO_METERS)); } } else if (TRANSPORT_TASKS.Contains(taskDB.ID)) { DrawingMaker.AddDrawing($"Target Zone {objectiveName}", DrawingType.Circle, waypointCoordinates, "Radius".ToKeyValuePair(500)); } return(new Waypoint(objectiveName, waypointCoordinates, onGround, scriptIgnore)); }
//----------------SUB TASK SUPPORT FUNCTIONS------------------------------- private static void GetSubTaskData(MissionTemplateSubTask objectiveTemplate, out DBEntryObjectiveTarget targetDB, out DBEntryObjectiveTargetBehavior targetBehaviorDB, out DBEntryObjectiveTask taskDB, out ObjectiveOption[] objectiveOptions) { targetDB = Database.Instance.GetEntry <DBEntryObjectiveTarget>(objectiveTemplate.Target); targetBehaviorDB = Database.Instance.GetEntry <DBEntryObjectiveTargetBehavior>(objectiveTemplate.TargetBehavior); taskDB = Database.Instance.GetEntry <DBEntryObjectiveTask>(objectiveTemplate.Task); objectiveOptions = objectiveTemplate.Options.ToArray(); if (targetDB == null) { throw new BriefingRoomException($"Target \"{targetDB.UIDisplayName}\" not found for objective."); } if (targetBehaviorDB == null) { throw new BriefingRoomException($"Target behavior \"{targetBehaviorDB.UIDisplayName}\" not found for objective."); } if (taskDB == null) { throw new BriefingRoomException($"Task \"{taskDB.UIDisplayName}\" not found for objective."); } if (!taskDB.ValidUnitCategories.Contains(targetDB.UnitCategory)) { throw new BriefingRoomException($"Task \"{taskDB.UIDisplayName}\" not valid for objective targets, which belong to category \"{targetDB.UnitCategory}\"."); } }
private void GenerateSubTask( DCSMission mission, MissionTemplateRecord template, DBEntrySituation situationDB, MissionTemplateSubTask subTask, Coordinates coreCoordinates, DBEntryAirbase playerAirbase, List <SpawnPointType> preValidSpawns, DBEntryObjectiveTargetBehaviorLocation mainObjLocation, string[] featuresID, ref int objectiveIndex, ref List <Coordinates> objectiveCoordinatesList, ref List <Waypoint> waypoints, ref List <Waypoint> waypointList, ref List <UnitFamily> objectiveTargetUnitFamilies ) { var extraSettings = new List <KeyValuePair <string, object> >(); DBEntryObjectiveTarget targetDB; DBEntryObjectiveTargetBehavior targetBehaviorDB; DBEntryObjectiveTask taskDB; ObjectiveOption[] objectiveOptions; GetSubTaskData(subTask, out targetDB, out targetBehaviorDB, out taskDB, out objectiveOptions); preValidSpawns.AddRange(targetDB.ValidSpawnPoints); if (preValidSpawns.Contains(SpawnPointType.Sea) && preValidSpawns.Any(x => LAND_SPAWNS.Contains(x))) { throw new BriefingRoomException("Cannot Mix Land and Sea Objectives. Check Sub Objective targets"); } var luaUnit = targetBehaviorDB.UnitLua[(int)targetDB.UnitCategory]; Coordinates objectiveCoordinates = GetNearestSpawnCoordinates(template, coreCoordinates, targetDB); // Spawn target on airbase var unitCount = targetDB.UnitCount[(int)subTask.TargetCount].GetValue(); var objectiveTargetUnitFamily = Toolbox.RandomFrom(targetDB.UnitFamilies); if (AIRBASE_LOCATIONS.Contains(targetBehaviorDB.Location) && !AIRBASE_LOCATIONS.Contains(mainObjLocation)) { throw new BriefingRoomException("Spawning on airbase is not a valid Sub Objective unless main objective is also spawning on airbase."); } 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; } extraSettings.Add("GroupX2".ToKeyValuePair(destinationPoint.X)); extraSettings.Add("GroupY2".ToKeyValuePair(destinationPoint.Y)); 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 = GenerateSubTaskWaypoint(subTask, unitCoordinates, $"{objectiveName} Pickup", template, true); waypoints.Add(cargoWaypoint); waypointList.Add(cargoWaypoint); if (taskDB.isEscort()) { extraSettings.Remove("GroupX2".ToKeyValuePair(destinationPoint.X)); extraSettings.Remove("GroupY2".ToKeyValuePair(destinationPoint.Y)); extraSettings.Remove("GroupX2".ToKeyValuePair(objectiveCoordinates.X)); extraSettings.Add("GroupY2".ToKeyValuePair(objectiveCoordinates.Y)); groupFlags |= UnitMakerGroupFlags.RadioAircraftSpawn; } } 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 = GenerateSubTaskWaypoint(subTask, objectiveCoordinates, objectiveName, template); waypoints.Add(waypoint); waypointList.Add(waypoint); objectiveTargetUnitFamilies.Add(objectiveTargetUnitFamily); }