/// <summary>
        /// Converts
        /// </summary>
        /// <returns>A string to display in the PropertyGrid.</returns>
        public override string ToString()
        {
            string acName = Library.Instance.DefinitionExists <DefinitionUnit>(AircraftType) ? Library.Instance.GetDefinition <DefinitionUnit>(AircraftType).DisplayName : AircraftType;

            return($"{HQTools.ValToString(Count)}x {acName}, {GUITools.SplitEnumCamelCase(Task)} " +
                   $"({GUITools.SplitEnumCamelCase(StartLocation).ToLowerInvariant()}{(WingmenAI ? ", AI wingmen" : "")})");
        }
        /// <summary>
        /// Returns an unique callsign in the NATO format (Callsign Number Number)
        /// </summary>
        /// <param name="csFamily">The type of aircraft (AWACS, tanker, fighter...)</param>
        /// <returns>The callsign</returns>
        private MGCallsign GetNATOCallsign(CallsignFamily csFamily)
        {
            int callsignIndex;

            do
            {
                callsignIndex = HQTools.RandomInt(NATO_CALLSIGN_NAMES[(int)csFamily].Length);
            } while (NATOCallsigns[(int)csFamily][callsignIndex] >= 9);

            NATOCallsigns[(int)csFamily][callsignIndex]++;

            string groupName =
                NATO_CALLSIGN_NAMES[(int)csFamily][callsignIndex] + " " +
                HQTools.ValToString(NATOCallsigns[(int)csFamily][callsignIndex]);

            string unitName = groupName + " $INDEX$";
            //string onboardNum = HQTools.ValToString((callsignIndex % 9) + 1) +
            //    NATOCallsigns[(int)csFamily][callsignIndex] + "$INDEX$";
            string lua =
                $"{{ [1]= {HQTools.ValToString(callsignIndex + 1)}, " +
                $"[2]={HQTools.ValToString(NATOCallsigns[(int)csFamily][callsignIndex])}, " +
                "[3]=$INDEX$, " +
                $"[\"name\"] = \"{unitName.Replace(" ", "")}\", }}";

            return(new MGCallsign(groupName, unitName /*, onboardNum*/, lua));
        }
Ejemplo n.º 3
0
        public DCSMissionUnitGroup(
            string luaGroup, string luaUnit, UnitCategory category,
            int groupID, Coalition coalition, Coordinates coordinates,
            params string[] units)
        {
            LuaGroup    = luaGroup;
            LuaUnit     = luaUnit;
            Category    = category;
            Coalition   = coalition;
            GroupID     = groupID;
            Units       = units.ToList();
            Name        = $"Group #{HQTools.ValToString(GroupID)}";
            Coordinates = coordinates;

            if (units.Length == 0)
            {
                DebugLog.Instance.Log($"    WARNING: Tried to create an empty unit group at {Coordinates.ToString("F0")}.");
            }
            else
            {
                DebugLog.Instance.Log($"    Added a group of {units.Length} unit(s) ({string.Join(", ", Units)}) with ID #{GroupID} at {Coordinates.ToString("F0")}.");
            }

            CheckAbsolueMaxUnitCount();
        }
        private string FormatTime(DCSMission mission, bool longFormat)
        {
            string formattedString = Language.GetString("Briefing", longFormat ? "Format.Time.Long" : "Format.Time.Short");

            formattedString = formattedString
                              .Replace("$H$", HQTools.ValToString(mission.TimeHour, "0"))
                              .Replace("$HH$", HQTools.ValToString(mission.TimeHour, "00"))
                              .Replace("$M$", HQTools.ValToString(mission.TimeMinute, "0"))
                              .Replace("$MM$", HQTools.ValToString(mission.TimeMinute, "00"));

            return(formattedString);
        }
Ejemplo n.º 5
0
        public static string GetDCSTaskAdditionalTasksString(DCSFlightGroupTask dcsTask, int firstTaskIndex = 1)
        {
            string taskInfo = "";

            switch (dcsTask)
            {
            case DCSFlightGroupTask.CAS:
                taskInfo =
                    "[$1$] = { [\"enabled\"] = true, [\"key\"] = \"CAS\", [\"id\"] = \"EngageTargets\", [\"number\"] = $1$, " +
                    "[\"auto\"] = true, [\"params\"] = { [\"targetTypes\"] = { [1] = \"Helicopters\", [2] = \"Ground Units\", [3] = \"Light armed ships\", }, [\"priority\"] = 0, }, },";
                break;
            }

            taskInfo = taskInfo.Replace("$1$", HQTools.ValToString(firstTaskIndex));
            return(taskInfo);
        }
        private string FormatDate(DCSMission mission, bool longFormat)
        {
            string formattedString = Language.GetString("Briefing", longFormat ? "Format.Date.Long" : "Format.Date.Short");

            DateTime dt = new DateTime(2003, 5, 1);

            formattedString = formattedString
                              .Replace("$W$", Language.GetEnum(new DateTime(mission.DateYear, (int)mission.DateMonth + 1, mission.DateDay).DayOfWeek))
                              .Replace("$D$", HQTools.ValToString(mission.DateDay, "0"))
                              .Replace("$DD$", HQTools.ValToString(mission.DateDay, "00"))
                              .Replace("$DDD$", Language.GetOrdinalAdjective(mission.DateDay))
                              .Replace("$M$", HQTools.ValToString((int)mission.DateMonth + 1, "0"))
                              .Replace("$MM$", HQTools.ValToString((int)mission.DateMonth + 1, "00"))
                              .Replace("$MMM$", Language.GetEnum(mission.DateMonth))
                              .Replace("$YY$", HQTools.ValToString(mission.DateYear).Substring(2))
                              .Replace("$YYYY$", HQTools.ValToString(mission.DateYear));

            return(formattedString);
        }
        /// <summary>
        /// Returns an unique callsign in the russian format (3-digits)
        /// </summary>
        /// <returns>The callsign</returns>
        private MGCallsign GetRussianCallsign()
        {
            int[]  fgNumber = new int[2];
            string fgName   = "";

            do
            {
                fgNumber[0] = HQTools.RandomMinMax(1, 9);
                fgNumber[1] = HQTools.RandomMinMax(0, 9);

                fgName = HQTools.ValToString(fgNumber[0]) + HQTools.ValToString(fgNumber[1]);
            } while (RussianCallsigns.Contains(fgName));

            RussianCallsigns.Add(fgName);

            string unitName = fgName + "$INDEX$";

            return(new MGCallsign(fgName + "0", unitName /*, unitName*/, unitName));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Returns a string representing the ordinal adjective (1st, 2nd, 3rd, 4th...) for a given integer.
        /// </summary>
        /// <param name="number">The integer.</param>
        /// <returns>A string with the ordinal adjective.</returns>
        public string GetOrdinalAdjective(int number)
        {
            string template  = "";
            string numberStr = HQTools.ValToString(number);

            for (int i = 0; i < numberStr.Length; i++)
            {
                template = FindString("OrdinalAdjectives", $"EndsWith{numberStr.Substring(i)}");
                if (!string.IsNullOrEmpty(template))
                {
                    break;
                }
            }

            if (string.IsNullOrEmpty(template))
            {
                template = GetString("OrdinalAdjectives", "Default");
            }

            return(template.Replace("$N$", numberStr));
        }
        /// <summary>
        /// Returns a proper loadout for this aircraft.
        /// </summary>
        /// <param name="payloadType"></param>
        /// <returns></returns>
        public string GetPayloadLua(PlayerFlightGroupPayloadType payloadType)
        {
            if ((Category != UnitCategory.Helicopter) && (Category != UnitCategory.Plane))
            {
                return("{ }");
            }
            if (AircraftAvailablePayloads.Length == 0)
            {
                return("{ }");                                       // No payloads
            }
            string payloadLua = "[\"pylons\"] = {\n";

            // No payload for this configuration, use the default payload instead
            if (!AircraftAvailablePayloads.Contains(payloadType))
            {
                payloadType = PlayerFlightGroupPayloadType.Default;
            }

            for (int i = 0; i < MAX_PYLONS; i++)
            {
                string p = AircraftPayloadPylons[(int)payloadType, i].Trim();
                if (string.IsNullOrEmpty(p))
                {
                    continue;                          // No payload on this pylon
                }
                payloadLua +=
                    $"[{HQTools.ValToString(i + 1)}] = {{ [\"CLSID\"] = \"{p}\" }},\n";
            }

            payloadLua += "},\n";

            payloadLua += AircraftPayloadCommon.Replace(",", ",\n");

            // NEXTVERSION: payload upgrades by decade

            return("{\n" + payloadLua + "\n}");
        }
        // NEXTVERSION
        // public Country[][] LiveriesPriority { get; private set; } = new Country[2][];
        // public string[][] Liveries { get; private set; } = new string[HQTools.EnumCount<Country>()][];

        /// <summary>
        /// Loads data required by this definition.
        /// </summary>
        /// <param name="ini">The ini file to load from.</param>
        /// <returns>True is successful, false if an error happened.</returns>
        protected override bool OnLoad(INIFile ini)
        {
            // --------------
            // [Unit] section
            // --------------
            ID = ini.GetValue <string>("Unit", "ID");
            if (string.IsNullOrEmpty(ID))
            {
                return(false);
            }

            DCSID = ini.GetValue <string>("Unit", "DCSID");
            if (string.IsNullOrEmpty(DCSID))
            {
                DCSID = ID;
            }

            DisplayName = ini.GetValue <string>("Unit", "DisplayName");

            Families = ini.GetValueArray <UnitFamily>("Unit", "Families"); if (Families.Length == 0)
            {
                return(false);
            }

            Category = HQTools.GetUnitCategoryFromUnitFamily(Families[0]);
            // All families must belong to the same category. If that's not the case, remove all "wrong" families.
            Families = (from UnitFamily f in Families where f.ToString().StartsWith(Category.ToString()) select f).ToArray();
            if (Families.Length == 0)
            {
                return(false);
            }

            InService = HQTools.ParseEnumString <TimePeriod>(ini.GetValue <string>("Unit", "InService"), '-', "Decade");
            if (InService.Length < 2)
            {
                return(false);
            }
            InService = InService.Take(2).OrderBy(x => x).ToArray();

            ExtraLua = ini.GetValue <string>("Unit", "ExtraLua");

            // ---------------
            // [Comms] section
            // ---------------
            CommsRadioFrequency = ini.GetValue <float>("Comms", "RadioFrequency");
            CommsRadioFrequency = (CommsRadioFrequency <= 0) ? DEFAULT_RADIO_FREQUENCY : CommsRadioFrequency;

            CommsTACANChannel     = HQTools.Clamp(ini.GetValue <int>("Comms", "TACAN.Channel"), 0, 99);
            CommsTACANChannelMode = ini.GetValue <string>("Comms", "TACAN.ChannelMode").ToUpperInvariant();
            CommsTACANChannelMode = (CommsTACANChannelMode == "Y") ? "Y" : "X";
            CommsTACANCallsign    = ini.GetValue <string>("Comms", "TACAN.Callsign").ToUpperInvariant();

            CommsILSChannel = HQTools.Clamp(ini.GetValue <int>("Comms", "ILS.Channel"), 0, 99);

            // ----------------------------------------------------
            // [Aircraft] section (only for planes and helicopters)
            // ----------------------------------------------------
            if ((Category == UnitCategory.Helicopter) || (Category == UnitCategory.Plane))
            {
                AircraftDefaultTask       = ini.GetValue <DCSFlightGroupTask>("Aircraft", "DefaultTask");
                AircraftAirToAirRating[0] = ini.GetValue <int>("Aircraft", "AirToAirRating.A2APayload");
                AircraftAirToAirRating[1] = ini.GetValue <int>("Aircraft", "AirToAirRating.A2GPayload");
                AircraftCruiseAltitude    = ini.GetValue <int>("Aircraft", "CruiseAltitude") * HQTools.FEET_TO_METERS;
                if (AircraftCruiseAltitude <= 0)
                {
                    AircraftCruiseAltitude = Category == UnitCategory.Helicopter ? 350 : 6000;
                }
                AircraftCruiseSpeed = ini.GetValue <int>("Aircraft", "CruiseSpeed") * HQTools.KNOTS_TO_METERSPERSECOND;
                if (AircraftCruiseSpeed <= 0)
                {
                    AircraftCruiseSpeed = Category == UnitCategory.Helicopter ? 50 : 130;
                }
                AircraftPlayerControllable = ini.GetValue <bool>("Aircraft", "PlayerControllable");
                AircraftCarrierShipType    = ini.GetValueArray <CarrierGroupShipType>("Aircraft", "CarrierShipType");

                // -----------------------------------------------------------
                // [AircraftPayload] section (only for planes and helicopters)
                // -----------------------------------------------------------
                int i, j;

                AircraftPayloadCommon = ini.GetValue <string>("AircraftPayload", "Common");

                List <PlayerFlightGroupPayloadType> payloadsList = new List <PlayerFlightGroupPayloadType>();

                for (i = 0; i < AircraftPayloadPylons.GetLength(0); i++)
                {
                    for (j = 0; j < AircraftPayloadPylons.GetLength(1); j++)
                    {
                        AircraftPayloadPylons[i, j] = ini.GetValue <string>("AircraftPayload",
                                                                            $"Pylons.{((PlayerFlightGroupPayloadType)i).ToString()}.Pylon{HQTools.ValToString(j + 1, "00")}");

                        // Each payload with at least one pylon not empty is a valid payload
                        if (!payloadsList.Contains((PlayerFlightGroupPayloadType)i) && !string.IsNullOrEmpty(AircraftPayloadPylons[i, j]))
                        {
                            payloadsList.Add((PlayerFlightGroupPayloadType)i);
                        }
                    }
                }

                AircraftAvailablePayloads = payloadsList.ToArray();
            }

            // ------------------
            // [Liveries] section
            // ------------------
            // NEXT VERSION
            //LiveriesPriority[0] = ini.GetValueArray<Country>("Liveries", "Priority.Real");
            //LiveriesPriority[1] = ini.GetValueArray<Country>("Liveries", "Priority.Fictional");

            //Liveries = new string[HQTools.EnumCount<Country>()][];
            //for (int i = 0; i < Liveries.Length; i++)
            //    Liveries[i] = ini.GetValueArray<string>("Liveries", $"Country.{(Country)i}", '|');

            return(true);
        }
        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("");
        }
        /// <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("");
        }