public void CheckTemplate(MissionTemplate template) { #if !DEBUG if (template.GetPlayerCount() < 1) { throw new HQ4DCSException($"No player flight groups. A mission must have at least one player flight group."); } #endif CheckMissingDefinitions(template); CheckCoalitions(template); CheckTheaterNodes(template); //mission.Countries[(int)Coalition.Red].Except(mission.Countries[(int)Coalition.Blue]) //// Copy blue and red coalitions' countries list //mission.Countries[(int)Coalition.Blue] = coalitions[(int)Coalition.Blue].Countries.ToArray(); //if (mission.Countries[(int)Coalition.Blue].Length == 0) // throw new Exception("Blue coalition has no countries."); //mission.Countries[(int)Coalition.Red] = coalitions[(int)Coalition.Red].Countries.ToArray(); //if (mission.Countries[(int)Coalition.Red].Length == 0) // throw new Exception("Red coalition has no countries."); //// Remove blue countries from red coalition to make sure no country belongs to both. //mission.Countries[(int)Coalition.Red] = mission.Countries[(int)Coalition.Red].Except(mission.Countries[(int)Coalition.Blue]).ToArray(); //if (mission.Countries[(int)Coalition.Red].Length == 0) // throw new Exception("Blue and red coalitions share the same countries."); //// TODO: check template nodes //foreach (HQTemplateNode n in template.Nodes.Values) //{ //} }
/// <summary> /// Generates the list of tasks for the mission. /// </summary> /// <param name="mission"></param> /// <param name="template"></param> /// <param name="missionTask"></param> //public void GenerateMissionTasks(HQMission mission, MissionTemplate template, DefinitionMissionObjective missionTask) //{ // HQDebugLog.Instance.Log("Generating mission briefing objectives..."); // mission.BriefingTasks.Clear(); // mission.BriefingTasks.Add(Language.GetStringRandom("BriefingCommon", $"Task.TakeOff").Replace("$AIRBASE$", mission.Airbases[0].Name)); // foreach (HQMissionObjectiveLocation o in mission.Objectives) // mission.BriefingTasks.Add(Language.GetStringRandom("BriefingMission", $"Task.{missionTask.BriefingTask}").Replace("$NAME$", o.Name)); // mission.BriefingTasks.Add(Language.GetStringRandom("BriefingCommon", $"Task.Land").Replace("$AIRBASE$", mission.Airbases[1].Name)); // HQDebugLog.Instance.Log(""); //} //public void GenerateMissionRemarks(HQMission mission, MissionTemplate template, DefinitionMissionObjective missionTask) //{ // HQDebugLog.Instance.Log("Generating mission briefing remarks..."); // mission.BriefingRemarks.Clear(); // foreach (string s in missionTask.BriefingRemarks) // mission.BriefingRemarks.Add(Language.GetStringRandom("BriefingMission", $"Remark.{s}")); // HQDebugLog.Instance.Log(""); //} public void GenerateRawTextBriefing(DCSMission mission, MissionTemplate template) { DebugLog.Instance.Log("Generating raw text MIZ briefing..."); string text = ""; if (template.GetPlayerCount() == 1) { text += $"{Language.GetString("Briefing", "Subtitle.SinglePlayer")}\n\n"; } else { text += $"{Language.GetString("Briefing", "Subtitle.PvE").Replace("$PLAYERS$", HQTools.ValToString(template.GetPlayerCount()))}\n\n"; } text += mission.BriefingDescription + "\n\n"; // Tasks text += $"{Language.GetString("Briefing", "Section.Tasks").ToUpperInvariant()}{Language.Semicolon}\n"; foreach (string t in mission.BriefingTasks) { text += $"- {t}\n"; } if (mission.BriefingTasks.Count == 0) { text += $"- {Language.GetString("Briefing", "Misc.None")}\n"; } text += "\n"; // Remarks text += $"{Language.GetString("Briefing", "Section.Remarks").ToUpperInvariant()}{Language.Semicolon}\n"; if (mission.BriefingImperialUnits) { text += $"- {Language.GetString("Briefing", "Remark.TotalFlightPlanNM", "Distance", (mission.TotalFlightPlanDistance * HQTools.METERS_TO_NM).ToString("F0"))}\n"; } else { text += $"- {Language.GetString("Briefing", "Remark.TotalFlightPlanKM", "Distance", (mission.TotalFlightPlanDistance / 1000.0).ToString("F0"))}\n"; } foreach (string t in mission.BriefingRemarks) { text += $"- {t}\n"; } text += "\n"; // Flight package //text += $"{GetString("Section.Package").ToUpperInvariant()}{Language.Semicolon}\n"; //foreach (HQMissionBriefingFlightGroup fg in (from HQMissionBriefingFlightGroup f in mission.BriefingFlightPackage where !f.IsSupport select f).OrderBy(x => x.Task)) // text += $"- {fg.Callsign} ({fg.UnitCount}x {GetUnitName(fg.UnitType)}), {HQTools.ValToString(fg.Frequency, "F1")} Mhz\n"; // Make sure endlines are in the proper format (escaped LF) or it can cause bugs. text = text.Replace("\r\n", "\n").Trim(' ', '\n', '\t').Replace("\n", "\\\n"); mission.BriefingRawText = text; DebugLog.Instance.Log(""); }
private string CreateHTMLBriefing( DCSMission mission, MissionTemplate template, string description, List <string> tasks, List <string> remarks, List <UnitFlightGroupBriefingDescription> flightGroups, DBEntryTheaterAirbase airbaseDB, DBEntryCoalition[] coalitionsDB, DBEntryObjective objectiveDB) { 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(objectiveDB.ID) + " 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 = ""; foreach (var carrier in mission.Carriers) { carrierHTML += "<tr>" + $"<td>{carrier.Units[0].Name}</td>" + $"<td>{carrier.RadioFrequency.ToString("n3")}{carrier.RadioModulation}</td>" + $"<td>{carrier.ILS}</td>" + $"<td>{carrier.TACAN.ToString()}</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); }
public void GenerateHTMLBriefing(DCSMission mission, MissionTemplate template /*, DefinitionMissionObjective missionTask*/) { DebugLog.Instance.Log("Generating HTML briefing..."); string htmlTemplateFile = HQTools.PATH_INCLUDE + "Briefing.html"; string htmlTemplate = File.Exists(htmlTemplateFile) ? File.ReadAllText(htmlTemplateFile) : "$BRIEFING$"; string html = ""; string semiColon = Language.GetString("Misc", "Semicolon"); html += $"<h1>{mission.BriefingName}</h1>"; if (template.GetPlayerCount() == 1) { html += $"<h3>{Language.GetString("Briefing", "Subtitle.SinglePlayer")}</h3>"; } else { html += $"<h3>{Language.GetString("Briefing", "Subtitle.PvE").Replace("$PLAYERS$", HQTools.ValToString(template.GetPlayerCount()))}</h3>"; } // Header (objective/task, date, time...) html += "<p>"; html += $"<strong>{Language.GetString("Briefing", "Section.Date")}{semiColon}</strong> {FormatDate(mission, true)}<br />"; html += $"<strong>{Language.GetString("Briefing", "Section.Time")}{semiColon}</strong> {FormatTime(mission, true)}<br />"; html += $"<strong>{Language.GetString("Briefing", "Section.Weather")}{semiColon}</strong> {Language.GetEnum(mission.WeatherLevel)}<br />"; html += $"<strong>{Language.GetString("Briefing", "Section.Wind")}{semiColon}</strong> {Language.GetEnum(mission.WindLevel)}"; html += $" ({mission.WeatherWindSpeedAverage.ToString("F0")} m/s)"; html += "</p>"; // Description html += $"<h2>{Language.GetString("Briefing", "Section.Description")}</h2>"; html += $"<p>{mission.BriefingDescription}</p>"; // Tasks html += $"<h2>{Language.GetString("Briefing", "Section.Tasks")}</h2>"; html += "<ul>"; foreach (string task in mission.BriefingTasks) { html += $"<li>{task}</li>"; } if (mission.BriefingTasks.Count == 0) { html += $"<li>{Language.GetString("Briefing", "Misc.None")}</li>"; } html += "</ul>"; // Remarks html += $"<h2>{Language.GetString("Briefing", "Section.Remarks")}</h2>"; html += "<ul>"; if (mission.BriefingImperialUnits) { html += $"<li>{Language.GetString("Briefing", "Remark.TotalFlightPlanNM", "Distance", (mission.TotalFlightPlanDistance * HQTools.METERS_TO_NM).ToString("F0"))}</li>"; } else { html += $"<li>{Language.GetString("Briefing", "Remark.TotalFlightPlanKM", "Distance", (mission.TotalFlightPlanDistance / 1000.0).ToString("F0"))}</li>"; } foreach (string remark in mission.BriefingRemarks) { html += $"<li>{remark}</li>"; } html += "</ul>"; // mission.FlightPlanLength // Airbases //html += $"<h2>{Language.GetString("BriefingCommon", "Airbases")}</h2>"; //html += "<table>"; //html += "<tr><th></th><th>Airbase</th><th>TCN</th><th>ATC</th><th>RWY</th><th>ILS</th></tr>"; // FIXME: Localize //{ // string header; // FIXME: Localize // if (i == 0) header = "DEP"; // else if (i == 1) header = "ARR"; // else header = "NAV"; // DefinitionTheaterAirbase airbase = mission.Airbases[i]; // html += $"<tr><th>{header}</th><td>{airbase.Name}</td><td>{airbase.TACAN}</td><td>{HQTools.ValToString(airbase.ATC, "F1")}</td><td>{airbase.Runways[0]}</td><td>{airbase.ILS}</td></tr>"; //} //html += "</table>"; // Flight package html += $"<h2>{Language.GetString("Briefing", "Section.FlightPackage")}</h2>"; html += "<table>"; html += $"<tr><th>{Language.GetString("Briefing", "Table.Header.Callsign")}</th><th>{Language.GetString("Briefing", "Table.Header.Aircraft")}</th><th>{Language.GetString("Briefing", "Table.Header.Task")}</th><th>{Language.GetString("Briefing", "Table.Header.Airbase")}</th><th>{Language.GetString("Briefing", "Table.Header.Radio")}</th></tr>"; foreach (DCSMissionBriefingFlightGroup fg in (from DCSMissionBriefingFlightGroup f in mission.BriefingFlightPackage where !f.IsSupport select f).OrderBy(x => x.Task)) { html += // TODO: localize fg.Task $"<tr><td>{fg.Callsign}</td><td>{fg.UnitCount}x {GetUnitName(fg.UnitType)}</td>" + $"<td>{fg.Task}</td><td>{fg.AirbaseName}</td>" + $"<td>{HQTools.ValToString(fg.Frequency, "F1")}</td></tr>"; } html += "</table>"; // Support flight groups //html += $"<h2>{Language.GetString("BriefingCommon", "Support")}</h2>"; //html += "<table>"; //html += "<tr><th></th><th>Aircraft</th><th>Callsign</th><th>UHF</th><th>TACAN</th></tr>"; // FIXME: Localize //foreach (HQMissionBriefingFlightGroup fg in (from HQMissionBriefingFlightGroup f in mission.BriefingFlightPackage where f.IsSupport select f).OrderBy(x => x.Task)) // html += $"<tr><th>{fg.Task}</th><td>{GetUnitName(fg.UnitType)}</td><td>{fg.Callsign}</td><td>{HQTools.ValToString(fg.Frequency, "F1")}</td><td>{fg.TACAN}</td></tr>"; //html += "</table>"; // Flight plan //html += $"<h2>{Language.GetString("BriefingCommon", "FlightPlan")}</h2>"; //html += "<table>"; //html += "<tr><th></th><th>ID</th><th>Action</th><th>Dist</th><th>Alt</th></tr>"; // FIXME: Localize //double totalWpDist = 0.0; //for (int i = 0; i < mission.Waypoints.Count; i++) //{ // HQMissionWaypoint wp = mission.Waypoints[i]; // if (i > 0) totalWpDist += wp.Coordinates.GetDistanceFrom(mission.Waypoints[i - 1].Coordinates); // if (template.BriefingUnits == SpeedAndDistanceUnit.Metric) // html += $"<tr><th>{i + 1}</th><td>{wp.Name}</td><td>NO ACTION FIXME</td><td>{((i == 0) ? "0" : Math.Round(totalWpDist / 1000.0).ToString("F0"))} Km</td><td>{wp.AltitudeMultiplier * 2000}</td></tr>"; // else // html += $"<tr><th>{i + 1}</th><td>{wp.Name}</td><td>NO ACTION FIXME</td><td>{((i == 0) ? "0" : Math.Round(totalWpDist * HQTools.METERS_TO_NM).ToString("F0"))} nm</td><td>{wp.AltitudeMultiplier * 2000}</td></tr>"; //} //html += "</table>"; mission.BriefingHTML = htmlTemplate.Replace("$BRIEFING$", html); DebugLog.Instance.Log(""); }
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); }