/// <summary> /// Generate a random mission name if none is provided in the template, or returns the provided name if there is one. /// </summary> /// <param name="mission">The mission.</param> /// <param name="template">The provided mission name in the template.</param> public void GenerateMissionName(DCSMission mission, string templateMissionName) { DebugLog.Instance.Log("Generating mission name..."); if (templateMissionName == null) { templateMissionName = ""; } // If a custom mission name was provided, use it... if (!string.IsNullOrEmpty(templateMissionName.Trim())) { mission.BriefingName = templateMissionName.Trim(); return; } // ...else generate a random name. // First get a random template then replace parts 1 to MAX_MISSION_NAME_PARTS ($PART1$, $PART2$, $PART3$...) by random parts. string name = HQTools.RandomFrom(Language.GetStringArray("Mission", "Name.Template")); for (int i = 1; i <= MAX_MISSION_NAME_PARTS; i++) { name = name.Replace( $"$P{i.ToString()}$", HQTools.RandomFrom(Language.GetStringArray("Mission", $"Name.Part{i.ToString()}"))); } mission.BriefingName = name; DebugLog.Instance.Log(""); }
// Adds "embedded" air defense to ground vehicle groups public void AddAirDefenseUnits(DefinitionCoalition army, TimePeriod timePeriod, LibraryCommonSettingsEnemyAirDefense airDefenseSettings) { if (Category != UnitCategory.Vehicle) { return; } List <string> unitList = new List <string>(Units); if (HQTools.RandomDouble() < airDefenseSettings.EmbeddedChance) { int airDefCount = airDefenseSettings.EmbeddedCount.GetValue(); for (int i = 0; i < airDefCount; i++) { string airDefUnit = HQTools.RandomFrom( army.GetUnits(timePeriod, HQTools.RandomFrom(airDefenseSettings.EmbeddedFamilies), true, false)); if (airDefUnit == null) { continue; } unitList.Add(airDefUnit); } } // Randomize list order so air defense units are not always at the end Units = unitList.OrderBy(x => HQTools.RandomInt()).ToList(); CheckAbsolueMaxUnitCount(); }
/// <summary> /// Generates weather settings (precipitation, cloud coverage, temperature...) for the mission. /// Must be called after mission date has been set because min/max temperature changes every month. /// </summary> /// <param name="mission">The mission.</param> /// <param name="weather">The preferred type of weather (clear, cloudy, storm...).</param> /// <param name="theater">Theater definition from which to get weather info for this part of the world.</param> public void GenerateWeather(DCSMission mission, Weather weather, DefinitionTheater theater) { DebugLog.Instance.Log("Generating weather conditions..."); mission.WeatherTemperature = theater.Temperature[(int)mission.DateMonth].GetValue(); DebugLog.Instance.Log($" Weather should be {weather.ToString().ToUpperInvariant()}"); mission.WeatherLevel = (weather == Weather.Random) ? HQTools.RandomFrom(RANDOM_WEATHER) : weather; DebugLog.Instance.Log($" Weather quality set to {mission.WeatherLevel}"); // Clouds and precipitations mission.WeatherCloudBase = theater.Weather[(int)mission.WeatherLevel].CloudsBase.GetValue(); mission.WeatherCloudsDensity = theater.Weather[(int)mission.WeatherLevel].CloudsDensity.GetValue(); mission.WeatherCloudsPrecipitation = HQTools.RandomFrom(theater.Weather[(int)mission.WeatherLevel].CloudsPrecipitation); mission.WeatherCloudsThickness = theater.Weather[(int)mission.WeatherLevel].CloudsThickness.GetValue(); // Dust mission.WeatherDustEnabled = HQTools.RandomFrom(theater.Weather[(int)mission.WeatherLevel].DustEnabled); mission.WeatherDustDensity = mission.WeatherDustEnabled ? theater.Weather[(int)mission.WeatherLevel].DustDensity.GetValue() : 0; // Fog mission.WeatherFogEnabled = HQTools.RandomFrom(theater.Weather[(int)mission.WeatherLevel].FogEnabled); mission.WeatherFogThickness = mission.WeatherFogEnabled ? theater.Weather[(int)mission.WeatherLevel].FogThickness.GetValue() : 0; mission.WeatherFogVisibility = mission.WeatherFogEnabled ? theater.Weather[(int)mission.WeatherLevel].FogVisibility.GetValue() : 0; // Pressure, turbulence and visiblity mission.WeatherQNH = theater.Weather[(int)mission.WeatherLevel].QNH.GetValue(); mission.WeatherTurbulence = theater.Weather[(int)mission.WeatherLevel].Turbulence.GetValue(); mission.WeatherVisibility = theater.Weather[(int)mission.WeatherLevel].Visibility.GetValue(); DebugLog.Instance.Log($" Cloud base altitude set to {mission.WeatherCloudBase} m"); DebugLog.Instance.Log($" Cloud density set to {mission.WeatherCloudBase}"); DebugLog.Instance.Log($" Precipitation set to {mission.WeatherCloudsPrecipitation}"); DebugLog.Instance.Log($" Cloud thickness set to {mission.WeatherCloudsThickness} m"); DebugLog.Instance.Log($" Dust set to {mission.WeatherDustEnabled}"); DebugLog.Instance.Log($" Dust density set to {mission.WeatherDustDensity}"); DebugLog.Instance.Log($" Fog set to {mission.WeatherFogEnabled}"); DebugLog.Instance.Log($" Fog thickness set to {mission.WeatherFogThickness}"); DebugLog.Instance.Log($" Fog visibility set to {mission.WeatherFogVisibility} m"); DebugLog.Instance.Log($" QNH set to {mission.WeatherQNH}"); DebugLog.Instance.Log($" Turbulence set to {mission.WeatherTurbulence} m/s"); DebugLog.Instance.Log($" Visibility set to {mission.WeatherVisibility} m"); DebugLog.Instance.Log(); }
public static DCSMissionUnitGroup FromCoalitionArmyAndUnitFamily( string luaGroup, string luaUnit, DefinitionCoalition army, TimePeriod timePeriod, UnitFamily family, int unitCount, int groupID, Coalition coalition, Coordinates coordinates) { List <string> unitList = new List <string>(); UnitCategory category = HQTools.GetUnitCategoryFromUnitFamily(family); // FIXME: extendSearchToUnitsOfOtherFamilies and returnDefaultIfNoneFound should be parameters string[] availableUnits = army.GetUnits(timePeriod, family, false, false); if (availableUnits.Length == 0) { DebugLog.Instance.Log($" WARNING: Cannot spawn unit group, no units of type {family.ToString().ToUpperInvariant()} for coalition {army.DisplayName.ToUpperInvariant()} in {timePeriod.ToString().ToUpperInvariant()}."); return(null); } do { unitList.AddRange((from u in HQTools.RandomFrom(availableUnits).Split('|') select u.Trim())); } while (unitList.Count < unitCount); // Some unit categories (helicopters and planes) require all units to be the same type if ((category == UnitCategory.Helicopter) || (category == UnitCategory.Plane)) { for (int i = 1; i < unitList.Count; i++) { unitList[i] = unitList[0]; } } DCSMissionUnitGroup uGroup = new DCSMissionUnitGroup( luaGroup, luaUnit, category, groupID, coalition, coordinates, unitList.ToArray()); return(uGroup); }
/// <summary> /// Randomizes parts of a string. /// </summary> /// <param name="rndStr">The string to randomize</param> /// <returns>A randomized string.</returns> private string ParseRandomString(string rndStr) { Regex regex = new Regex("{.*?}"); if (!regex.IsMatch(rndStr)) { return(rndStr.Replace("{", "").Replace("}", "").Replace("|", "")); } int lastOpen = -1; for (int i = 0; i < rndStr.Length; i++) { char c = rndStr[i]; if (c == '{') { lastOpen = i; } else if (c == '}') { if (lastOpen == -1) { continue; } string subStr = rndStr.Substring(lastOpen + 1, i - lastOpen - 1); subStr = HQTools.RandomFrom(subStr.Split('|')); string outStr = rndStr.Substring(0, lastOpen) + subStr + rndStr.Substring(i + 1); return(ParseRandomString(outStr)); } } return(rndStr.Replace("{", "").Replace("}", "").Replace("|", "")); }
public DefinitionTheaterSpawnPoint?GetRandomSpawnPoint( TheaterLocationSpawnPointType[] validTypes = null, DCSCountry[] validCountries = null, MinMaxD?distanceFrom = null, Coordinates?distanceOrigin = null, MinMaxD?distanceFrom2 = null, Coordinates?distanceOrigin2 = null) { IEnumerable <DefinitionTheaterSpawnPoint> validSP = (from DefinitionTheaterSpawnPoint s in SpawnPoints where !UsedSpawnPointsID.Contains(s.UniqueID) select s); if (validTypes != null) { validSP = (from DefinitionTheaterSpawnPoint s in validSP where validTypes.Contains(s.PointType) select s); } if (validCountries != null) { validSP = (from DefinitionTheaterSpawnPoint s in validSP where validCountries.Contains(s.Country) select s); } if (distanceFrom.HasValue && distanceOrigin.HasValue) { if (validSP.Count() == 0) { return(null); } MinMaxD searchRange = distanceFrom.Value; IEnumerable <DefinitionTheaterSpawnPoint> validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP select s); do { validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP where searchRange.Contains(distanceOrigin.Value.GetDistanceFrom(s.Coordinates)) select s); searchRange = new MinMaxD(searchRange.Min * 0.9, Math.Max(100, searchRange.Max * 1.1)); } while (validSPInRange.Count() == 0); validSP = (from DefinitionTheaterSpawnPoint s in validSPInRange select s); } if (distanceFrom2.HasValue && distanceOrigin2.HasValue) { if (validSP.Count() == 0) { return(null); } MinMaxD searchRange = distanceFrom2.Value; IEnumerable <DefinitionTheaterSpawnPoint> validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP select s); do { validSPInRange = (from DefinitionTheaterSpawnPoint s in validSP where searchRange.Contains(distanceOrigin2.Value.GetDistanceFrom(s.Coordinates)) select s); searchRange = new MinMaxD(searchRange.Min * 0.9, Math.Max(100, searchRange.Max * 1.1)); } while (validSPInRange.Count() == 0); validSP = (from DefinitionTheaterSpawnPoint s in validSPInRange select s); } if (validSP.Count() == 0) { return(null); } DefinitionTheaterSpawnPoint selectedSpawnPoint = HQTools.RandomFrom(validSP.ToArray()); UsedSpawnPointsID.Add(selectedSpawnPoint.UniqueID); return(selectedSpawnPoint); }
public DCSMission Generate(MissionTemplate template, out string errorMessage) { int i; errorMessage = ""; // Clear log, begin timing then create an instance of the HQ mission class Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); DCSMission mission = new DCSMission(); DebugLog.Instance.Clear(); DebugLog.Instance.Log($"STARTING MISSION GENERATION AT {DateTime.Now.ToLongTimeString()}..."); DebugLog.Instance.Log(new string('=', DebugLog.Instance.GetLastMessage().Length)); DebugLog.Instance.Log(); try { using (MissionGeneratorTemplateChecker templateChecker = new MissionGeneratorTemplateChecker()) { templateChecker.CheckTemplate(template); } if (template.GetPlayerCount() < 1) { throw new HQ4DCSException("Mission must include at least one player-controlled aircraft."); } // Pick definitions DefinitionCoalition[] coalitions = new DefinitionCoalition[2]; coalitions[(int)Coalition.Blue] = Library.Instance.GetDefinition <DefinitionCoalition>(template.ContextCoalitionBlue); coalitions[(int)Coalition.Red] = Library.Instance.GetDefinition <DefinitionCoalition>(template.ContextCoalitionRed); DefinitionLanguage languageDef = Library.Instance.GetDefinition <DefinitionLanguage>(template.PreferencesLanguage.ToLowerInvariant()); DefinitionObjective objectiveDef = Library.Instance.GetDefinition <DefinitionObjective>(template.ObjectiveType.ToLowerInvariant()); DefinitionTheater theaterDef = Library.Instance.GetDefinition <DefinitionTheater>(template.ContextTheater); theaterDef.ResetUsedSpawnPoints(); // Create a list of all available objective names List <string> objectiveNames = languageDef.GetStringArray("Mission", "Waypoint.ObjectiveNames").ToList(); // Create unit generators MissionGeneratorCallsign callsignGenerator = new MissionGeneratorCallsign(coalitions[(int)Coalition.Blue].NATOCallsigns, coalitions[(int)Coalition.Red].NATOCallsigns); MissionGeneratorUnitGroups unitGroupsGenerator = new MissionGeneratorUnitGroups(languageDef, callsignGenerator); // Copy values from the template to the mission mission.TheaterDefinition = template.ContextTheater; mission.ObjectiveDefinition = template.ObjectiveType; mission.Language = template.PreferencesLanguage; mission.CoalitionPlayer = template.ContextPlayerCoalition; mission.SinglePlayer = (template.GetPlayerCount() < 2); mission.UseNATOCallsigns = coalitions[(int)template.ContextPlayerCoalition].NATOCallsigns; // Make sure no countries are shared between both coalitions mission.Countries[(int)Coalition.Blue] = coalitions[(int)Coalition.Blue].Countries.ToArray(); mission.Countries[(int)Coalition.Red] = coalitions[(int)Coalition.Red].Countries.Except(coalitions[(int)Coalition.Blue].Countries).ToArray(); if (mission.Countries[(int)Coalition.Red].Length == 0) { throw new HQ4DCSException("Red and blue coalitions cannot share the same countries."); } switch (template.BriefingUnits) { case UnitSystem.ByCoalition: mission.BriefingImperialUnits = (coalitions[(int)mission.CoalitionPlayer].UnitSystem == UnitSystem.Imperial); break; case UnitSystem.Imperial: mission.BriefingImperialUnits = true; break; case UnitSystem.Metric: mission.BriefingImperialUnits = false; break; } // Generate mission environment parameters (weather, time of day, date...) using (MissionGeneratorEnvironment environment = new MissionGeneratorEnvironment()) { environment.GenerateMissionDate(mission, template.ContextTimePeriod, template.EnvironmentSeason); environment.GenerateMissionTime(mission, template.EnvironmentTimeOfDay, theaterDef); environment.GenerateWeather(mission, template.EnvironmentWeather, theaterDef); environment.GenerateWind(mission, template.EnvironmentWind, theaterDef); } // Randomly select players' airbase DefinitionTheaterAirbase missionAirbase = HQTools.RandomFrom((from DefinitionTheaterAirbase ab in theaterDef.Airbases where ab.Coalition == template.ContextPlayerCoalition select ab).ToArray()); // Randomly select objective spawn points int objectiveCount = (int)template.ObjectiveCount; if (objectiveCount == 0) { objectiveCount = HQTools.RandomFrom(1, 1, 1, 2, 2, 3, 3, 4, 5); // Random objective count } //AmountR objectiveDistance = template.ObjectiveDistance; //if (objectiveDistance == AmountR.Random) objectiveDistance = // HQTools.RandomFrom(AmountR.VeryLow, AmountR.VeryLow, AmountR.Low, AmountR.Low, AmountR.Low, AmountR.Average, AmountR.Average, AmountR.Average, AmountR.High, AmountR.High, AmountR.VeryHigh); List <DCSMissionObjectiveLocation> objectivesList = new List <DCSMissionObjectiveLocation>(); List <DCSMissionWaypoint> waypointsList = new List <DCSMissionWaypoint>(); for (i = 0; i < objectiveCount; i++) { // If this is the first objective, measure distance from the airbase. Else measure distance from the previous objective. Coordinates previousPoint = (i == 0) ? missionAirbase.Coordinates : objectivesList[i - 1].Coordinates; MinMaxD distanceFromLastPoint = new MinMaxD(template.ObjectiveDistance * 0.75, template.ObjectiveDistance * 1.25) * HQTools.NM_TO_METERS; if (i > 0) { distanceFromLastPoint /= 4.0; } DefinitionTheaterSpawnPoint?spawnPoint = theaterDef.GetRandomSpawnPoint(objectiveDef.SpawnPointType, null, distanceFromLastPoint, previousPoint); if (!spawnPoint.HasValue) // No valid spawn point, throw an error { throw new HQ4DCSException($"Cannot find a valid spawn point for objective #{i + 1}"); } // Select a random name for the objective string objName; if (objectiveNames.Count == 0) { objName = $"OBJECTIVE{(i + 1).ToString("00")}"; } else { objName = HQTools.RandomFrom(objectiveNames); objectiveNames.Remove(objName); } objectivesList.Add(new DCSMissionObjectiveLocation(spawnPoint.Value.Coordinates, objName, objectiveDef.WaypointOnGround ? 0.0 : 1.0, 0)); // Add a waypoint for each objective waypointsList.Add(new DCSMissionWaypoint(spawnPoint.Value.Coordinates + Coordinates.CreateRandomInaccuracy(objectiveDef.WaypointInaccuracy), objName)); } // If required, add additional waypoints on the way to & from the objectives if (template.PreferencesExtraWaypoints && (waypointsList.Count > 0)) { Coordinates firstWPCoos = waypointsList.First().Coordinates; Coordinates lastWPCoos = waypointsList.Last().Coordinates; int wpBeforeCount = HQTools.RandomMinMax(1, 3); for (i = 0; i < wpBeforeCount; i++) { waypointsList.Insert(i, new DCSMissionWaypoint( Coordinates.Lerp(missionAirbase.Coordinates, firstWPCoos, (double)(i + 1) / (wpBeforeCount + 1)) + Coordinates.CreateRandomInaccuracy(firstWPCoos.GetDistanceFrom(missionAirbase.Coordinates) * 0.05, firstWPCoos.GetDistanceFrom(missionAirbase.Coordinates) * 0.15), $"WP{(i + 1).ToString()}")); } int wpAfterCount = HQTools.RandomMinMax(1, 2); for (i = 0; i < wpAfterCount; i++) { waypointsList.Add( new DCSMissionWaypoint( Coordinates.Lerp(lastWPCoos, missionAirbase.Coordinates, (double)(i + 1) / (wpAfterCount + 1)) + Coordinates.CreateRandomInaccuracy(lastWPCoos.GetDistanceFrom(missionAirbase.Coordinates) * 0.05, lastWPCoos.GetDistanceFrom(missionAirbase.Coordinates) * 0.15), $"WP{(waypointsList.Count + 1).ToString()}")); } } mission.Objectives = objectivesList.ToArray(); mission.Waypoints = waypointsList.ToArray(); mission.TotalFlightPlanDistance = 0.0; for (i = 0; i <= mission.Waypoints.Length; i++) { if (i == 0) // first point, add distance between the takeoff airbase and the first waypoint { mission.TotalFlightPlanDistance += missionAirbase.Coordinates.GetDistanceFrom(mission.Waypoints.First().Coordinates); } else if (i == mission.Waypoints.Length) // last point, add distance between last waypoint and landing airbase { mission.TotalFlightPlanDistance += missionAirbase.Coordinates.GetDistanceFrom(mission.Waypoints.Last().Coordinates); } else // any other point, add distance between this waypoint and the last one { mission.TotalFlightPlanDistance += mission.Waypoints[i].Coordinates.GetDistanceFrom(mission.Waypoints[i - 1].Coordinates); } } // Create a list of used player aircraft types, so the proper kneeboard subdirectories can be created in the .miz file mission.UsedPlayerAircraftTypes = (from MissionTemplatePlayerFlightGroup pfg in template.FlightPackagePlayers select pfg.AircraftType).Distinct().OrderBy(x => x).ToArray(); // Generate bullseyes and map center mission.MapCenter = Coordinates.GetCenter( (from DCSMissionObjectiveLocation o in mission.Objectives select o.Coordinates).Union(new Coordinates[] { missionAirbase.Coordinates }).ToArray()); mission.Bullseye = new Coordinates[2]; for (i = 0; i < 2; i++) { mission.Bullseye[i] = mission.MapCenter + Coordinates.CreateRandomInaccuracy(10000, 20000); } // Copy scripts //mission.ScriptsMission = missionObjective.ScriptMission.ToList(); //mission.ScriptsObjective = missionObjective.ScriptObjective.ToList(); mission.RealismAllowExternalViews = template.RealismAllowExternalViews; mission.RealismBirdStrikes = template.RealismBirdStrikes; mission.RealismRandomFailures = template.RealismRandomFailures; // Create list of airbase alignment from the theater definition mission.AirbasesCoalition.Clear(); foreach (DefinitionTheaterAirbase ab in theaterDef.Airbases) { if (mission.AirbasesCoalition.ContainsKey(ab.DCSID)) { continue; } Coalition airbaseCoalition = ab.Coalition; switch (template.ContextCountriesCoalitions) { case CountriesCoalition.AllBlue: airbaseCoalition = Coalition.Blue; break; case CountriesCoalition.AllRed: airbaseCoalition = Coalition.Red; break; case CountriesCoalition.Inverted: airbaseCoalition = (Coalition)(1 - (int)ab.Coalition); break; } mission.AirbasesCoalition.Add(ab.DCSID, airbaseCoalition); } // Make sure the starting airbase belongs to the players' coalition no matter which coalition other airbases belong to if (mission.AirbasesCoalition.ContainsKey(missionAirbase.DCSID)) { mission.AirbasesCoalition[missionAirbase.DCSID] = template.ContextPlayerCoalition; } List <string> oggFilesList = new List <string>(); oggFilesList.AddRange(Library.Instance.Common.SharedOggFiles); // Default wave files oggFilesList.AddRange(objectiveDef.IncludeOgg); // Objective wave files mission.OggFiles = oggFilesList.Distinct().ToArray(); //mission.Scripts /* * // Generate mission flight plan * using (GeneratorFlightPlan flightPlan = new GeneratorFlightPlan(Library, language, csGenerator)) * { * flightPlan.SelectTakeoffAndLandingAirbases(mission, theater); * mission.MapCenter = mission.Airbases[0].Coordinates; // Center the map on the starting airdrome * flightPlan.GenerateObjectiveLocations(mission, template, theater, missionObjective); * flightPlan.GenerateWaypoints(mission, template, theater, missionObjective); * flightPlan.GenerateBullseye(mission); * } */ // Generate units AmountNR selectedEnemyAirDefense, selectedEnemyCAP; // We have to store these values here because they're used in the briefing remarks using (MissionGeneratorUnitGroups unitGenerator = new MissionGeneratorUnitGroups(languageDef, callsignGenerator)) { foreach (MissionTemplatePlayerFlightGroup pfg in template.FlightPackagePlayers) { unitGenerator.AddPlayerFlightGroup(mission, template, pfg, objectiveDef, missionAirbase); } //unitGroups.GeneratePlayerFlightGroups(mission, template, missionObjective); //unitGroups.GenerateAIEscortFlightGroups(mission, template, coalitions, template.FlightGroupsAICAP, UnitFamily.PlaneFighter, "GroupPlaneEscortCAP", AircraftPayloadType.A2A, DCSAircraftTask.CAP); //unitGroups.GenerateAIEscortFlightGroups(mission, template, coalitions, template.FlightGroupsAISEAD, UnitFamily.PlaneSEAD, "GroupPlaneEscortSEAD", AircraftPayloadType.SEAD, DCSAircraftTask.SEAD); unitGenerator.AddObjectiveUnitGroupsAtEachObjective(mission, template, objectiveDef, coalitions); //unitGroups.GenerateObjectiveUnitGroupsAtCenter(mission, template, missionObjective, coalitions); unitGenerator.AddFriendlySupportAircraft(mission, template, coalitions[(int)mission.CoalitionPlayer], theaterDef, missionAirbase); unitGenerator.AddEnemyAirDefenseUnits(mission, template, theaterDef, objectiveDef, coalitions, missionAirbase, out selectedEnemyAirDefense); unitGenerator.AddFriendlyAirDefenseUnits(mission, template, theaterDef, objectiveDef, coalitions, missionAirbase, out AmountNR selectedFriendlyAirDefense); unitGenerator.AddCombatAirPatrolUnits(mission, template, theaterDef, coalitions, missionAirbase, out AmountNR selectedFriendlyCAP, out selectedEnemyCAP); } using (MissionGeneratorBriefing briefingGenerator = new MissionGeneratorBriefing(languageDef)) { // Add briefing remarks for (i = 0; i < objectiveDef.BriefingRemarks.Length; i++) { mission.BriefingRemarks.Add(languageDef.GetStringRandom("Briefing", $"Remark.{objectiveDef.BriefingRemarks}")); } mission.BriefingRemarks.Add(languageDef.GetStringRandom("Briefing", $"Remark.EnemyAirDefense.{selectedEnemyAirDefense}")); mission.BriefingRemarks.Add(languageDef.GetStringRandom("Briefing", $"Remark.EnemyCAP.{selectedEnemyCAP}")); mission.BriefingTasks.Add(languageDef.GetString("Briefing", "Task.TakeOffFrom", "Airbase", missionAirbase.Name)); for (i = 0; i < mission.Objectives.Length; i++) { mission.BriefingTasks.Add(languageDef.GetString("Briefing", $"Task.{objectiveDef.BriefingTask}", "Objective", mission.Objectives[i].Name.ToUpperInvariant())); } mission.BriefingTasks.Add(languageDef.GetString("Briefing", "Task.LandAt", "Airbase", missionAirbase.Name)); briefingGenerator.GenerateMissionName(mission, template.BriefingName); briefingGenerator.GenerateMissionDescription(mission, template.BriefingDescription, objectiveDef); /* * briefing.GenerateMissionTasks(mission, template, missionObjective); * briefing.GenerateMissionRemarks(mission, template, missionObjective); */ briefingGenerator.GenerateRawTextBriefing(mission, template /*, missionObjective*/); briefingGenerator.GenerateHTMLBriefing(mission, template /*, missionObjective*/); } stopwatch.Stop(); DebugLog.Instance.Log(); DebugLog.Instance.Log($"COMPLETED MISSION GENERATION AT {DateTime.Now.ToLongTimeString()} (TOOK {stopwatch.Elapsed.TotalMilliseconds.ToString("F0")} MILLISECONDS)."); DebugLog.Instance.Log(); mission.GenerationLog = DebugLog.Instance.GetFullLog(); } #if DEBUG catch (HQ4DCSException e) #else catch (Exception e) #endif { stopwatch.Stop(); DebugLog.Instance.Log($"ERROR: {e.Message}"); DebugLog.Instance.Log(); DebugLog.Instance.Log($"MISSION GENERATION FAILED."); DebugLog.Instance.Log(); errorMessage = e.Message; mission.Dispose(); mission = null; } DebugLog.Instance.SaveToFileAndClear("MissionGeneration"); return(mission); }