示例#1
0
        /// <summary>
        /// Generates the <see cref="DCSMissionObjective"/>.
        /// </summary>
        /// <param name="mission">The mission for which to generate objectives</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Objective database entry</param>
        public void CreateObjectives(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryTheater theaterDB)
        {
            // Set the array for the proper number of objective
            mission.Objectives = new DCSMissionObjective[template.ObjectiveCount];

            GenerateObjectivesData(mission, template, objectiveDB, theaterDB);
            GenerateObjectivesScript(mission);
        }
示例#2
0
        /// <summary>
        /// Decide what should be spawned.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <param name="coalitionsDB">Coalitions database entries</param>
        public void CreateUnitGroups(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryCoalition[] coalitionsDB)
        {
            Coalition coalition =
                objectiveDB.UnitGroup.Flags.HasFlag(DBUnitGroupFlags.Friendly) ?
                mission.CoalitionPlayer : mission.CoalitionEnemy;
            Side side = objectiveDB.UnitGroup.Flags.HasFlag(DBUnitGroupFlags.Friendly) ? Side.Ally : Side.Enemy;

            SpawnUnitGroups(mission, template, objectiveDB.UnitGroup, coalitionsDB, side, coalition);
            if (objectiveDB.AllyUnitGroup.Category != null)
            {
                DebugLog.Instance.WriteLine($"Generating Friendly units for objective");
                SpawnUnitGroups(mission, template, objectiveDB.AllyUnitGroup, coalitionsDB, Side.Ally, mission.CoalitionPlayer);
            }
        }
示例#3
0
        /// <summary>
        /// Adds waypoints for the mission objectives.
        /// </summary>
        /// <param name="mission">Mission</param>
        /// <param name="objectiveDB">Objective database entry</param>
        public void AddObjectiveWaypoints(DCSMission mission, DBEntryObjective objectiveDB)
        {
            DebugLog.Instance.WriteLine("Generating objective waypoints...", 1);

            for (int i = 0; i < mission.Objectives.Length; i++)
            {
                Coordinates waypointCoordinates = mission.Objectives[i].WaypointCoordinates;
                DebugLog.Instance.WriteLine($"Created objective waypoint at {waypointCoordinates}", 2);

                mission.Waypoints.Add(
                    new DCSMissionWaypoint(
                        waypointCoordinates, mission.Objectives[i].Name,
                        objectiveDB.WaypointOnGround ? 0.0 : 1.0,
                        1.0));
            }
        }
示例#4
0
        /// <summary>
        /// Main unit generation method.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <param name="coalitionDB">Enemy coalition database entry</param>
        /// <param name="coalition">Coalition of the spawn points air defense must be spawned at, or null to spawn them anywhere</param>
        /// <param name="unitMods">Unit mods the units can belong to</param>
        public void CreateUnitGroups(DCSMission mission, DBEntryObjective objectiveDB, DBEntryCoalition coalitionDB, Coalition?coalition, string[] unitMods)
        {
            foreach (AirDefenseRange airDefenseRange in (AirDefenseRange[])Enum.GetValues(typeof(AirDefenseRange)))
            {
                DebugLog.Instance.WriteLine($"Adding {airDefenseRange} air defense", 1);
                if (
                    ((airDefenseRange == AirDefenseRange.ShortRange) && objectiveDB.Flags.HasFlag(DBEntryObjectiveFlags.NoEnemyAirDefenseShort)) ||
                    ((airDefenseRange == AirDefenseRange.MediumRange) && objectiveDB.Flags.HasFlag(DBEntryObjectiveFlags.NoEnemyAirDefenseMedium)) ||
                    ((airDefenseRange == AirDefenseRange.LongRange) && objectiveDB.Flags.HasFlag(DBEntryObjectiveFlags.NoEnemyAirDefenseLong)))
                {
                    DebugLog.Instance.WriteLine($"{airDefenseRange} air defense disabled for this mission objective type, not spawning any units", 1);
                    continue;
                }

                AddAirDefenseUnits(mission, airDefenseRange, coalitionDB, coalition, unitMods);
            }
        }
        /// <summary>
        /// Return a string describing the task of a player flight group, to display in the flight group table part of the briefing.
        /// </summary>
        /// <param name="task">Task assigned to this flight group in the mission package</param>
        /// <param name="objectiveDB">(optional) Mission objective database entry</param>
        /// <returns>Name of task as it will appear in the flight group table</returns>
        private string GetTaskingDescription(MissionTemplateFlightGroupTask task, DBEntryObjective objectiveDB)
        {
            switch (task)
            {
            default:     // case MissionTemplateMPFlightGroupTask.Objectives
                if (objectiveDB == null)
                {
                    return("Mission objectives");
                }
                return(objectiveDB.BriefingTaskFlightGroup);

            case MissionTemplateFlightGroupTask.SupportCAP:
                return("CAP escort");

            case MissionTemplateFlightGroupTask.SupportSEAD:
                return("SEAD escort");
            }
        }
        /// <summary>
        /// Main unit generation method.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <param name="playerCoalitionDB">Player coalition database entry</param>
        /// <param name="aiEscortTypeCAP">Type of aircraft selected for AI CAP escort</param>
        /// <param name="aiEscortTypeSEAD">Type of aircraft selected for AI SEAD escort</param>
        /// <returns>An array of <see cref="UnitFlightGroupBriefingDescription"/> describing the flight groups, to be used in the briefing</returns>
        public UnitFlightGroupBriefingDescription[] CreateUnitGroups(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryCoalition playerCoalitionDB, out string aiEscortTypeCAP, out string aiEscortTypeSEAD)
        {
            List <UnitFlightGroupBriefingDescription> briefingFGList = new List <UnitFlightGroupBriefingDescription>();

            if (template.MissionType == MissionType.SinglePlayer)
            {
                briefingFGList.Add(GenerateSinglePlayerFlightGroup(mission, template, objectiveDB));
            }
            else
            {
                briefingFGList.AddRange(GenerateMultiplayerFlightGroups(mission, template, objectiveDB));
            }

            aiEscortTypeCAP  = "";
            aiEscortTypeSEAD = "";
            UnitFlightGroupBriefingDescription?escortDescription;

            escortDescription = GenerateAIEscort(mission, template, template.SituationFriendlyEscortCAP, MissionTemplateFlightGroupTask.SupportCAP, playerCoalitionDB);
            if (escortDescription.HasValue)
            {
                briefingFGList.Add(escortDescription.Value);
                aiEscortTypeCAP = escortDescription.Value.Type;
            }

            escortDescription = GenerateAIEscort(mission, template, template.SituationFriendlyEscortSEAD, MissionTemplateFlightGroupTask.SupportSEAD, playerCoalitionDB);
            if (escortDescription.HasValue)
            {
                briefingFGList.Add(escortDescription.Value);
                aiEscortTypeSEAD = escortDescription.Value.Type;
            }

            return(briefingFGList.ToArray());
        }
        /// <summary>
        /// Returns the proper payload type for a given task.
        /// </summary>
        /// <param name="task">Task assigned to this flight group in the mission package</param>
        /// <param name="objectiveDB">(optional) Mission objective database entry</param>
        /// <returns>A payload</returns>
        private UnitTaskPayload GetPayloadByTask(MissionTemplateFlightGroupTask task, DBEntryObjective objectiveDB = null)
        {
            switch (task)
            {
            default:     // case MissionTemplateMPFlightGroupTask.Objectives
                if (objectiveDB == null)
                {
                    return(UnitTaskPayload.Default);
                }
                return(objectiveDB.Payload);

            case MissionTemplateFlightGroupTask.SupportCAP:
                return(UnitTaskPayload.AirToAir);

            case MissionTemplateFlightGroupTask.SupportSEAD:
                return(UnitTaskPayload.SEAD);
            }
        }
        /// <summary>
        /// Creates the flight group player will lead in a single-player mission.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <returns>A <see cref="UnitFlightGroupBriefingDescription"/> describing the flight group, to be used in the briefing</returns>
        private UnitFlightGroupBriefingDescription GenerateSinglePlayerFlightGroup(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB)
        {
            var  playerFlightGroup = template.PlayerFlightGroups[0];
            bool isCarrier         = !string.IsNullOrEmpty(playerFlightGroup.Carrier);

            DebugLog.Instance.WriteLine($"{playerFlightGroup.Carrier} -> {string.Join(",",mission.Carriers.Select(x => x.Name).ToArray())}");
            DCSMissionUnitGroup group = UnitMaker.AddUnitGroup(
                mission,
                Enumerable.Repeat(playerFlightGroup.Aircraft, playerFlightGroup.Count).ToArray(),
                Side.Ally, isCarrier? mission.Carriers.First(x => x.Units[0].Name == playerFlightGroup.Carrier).Coordinates : mission.InitialPosition,
                isCarrier? "GroupAircraftPlayerCarrier" : "GroupAircraftPlayer", "UnitAircraft",
                Toolbox.BRSkillLevelToDCSSkillLevel(template.SituationFriendlyAISkillLevel), DCSMissionUnitGroupFlags.FirstUnitIsPlayer,
                objectiveDB.Payload,
                null, isCarrier? -99 : mission.InitialAirbaseID, true, country: playerFlightGroup.Country,
                startLocation: playerFlightGroup.StartLocation
                );

            if (group == null)
            {
                throw new Exception($"Failed to create group of player aircraft of type \"{playerFlightGroup.Aircraft}\".");
            }

            if (isCarrier)
            {
                group.CarrierId = mission.Carriers.First(x => x.Units[0].Name == playerFlightGroup.Carrier).Units[0].ID;
            }

            return(new UnitFlightGroupBriefingDescription(
                       group.Name, group.Units.Length, playerFlightGroup.Aircraft,
                       objectiveDB.BriefingTaskFlightGroup,
                       Database.Instance.GetEntry <DBEntryUnit>(playerFlightGroup.Aircraft).AircraftData.GetRadioAsString()));
        }
        /// <summary>
        /// Creates multiplayer client flight groups.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <returns>An array of <see cref="UnitFlightGroupBriefingDescription"/> describing the flight groups, to be used in the briefing</returns>
        private UnitFlightGroupBriefingDescription[] GenerateMultiplayerFlightGroups(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB)
        {
            int totalGroupsCreated = 0;

            List <UnitFlightGroupBriefingDescription> briefingFGList = new List <UnitFlightGroupBriefingDescription>();

            foreach (MissionTemplateFlightGroup fg in template.PlayerFlightGroups)
            {
                // Select proper payload for the flight group according to its tasking
                UnitTaskPayload     payload    = GetPayloadByTask(fg.Tasking, objectiveDB);
                bool                hasCarrier = !string.IsNullOrEmpty(fg.Carrier);
                DCSMissionUnitGroup group      = UnitMaker.AddUnitGroup(
                    mission,
                    Enumerable.Repeat(fg.Aircraft, fg.Count).ToArray(),
                    Side.Ally, hasCarrier ? mission.Carriers.First(x => x.Units[0].Name == fg.Carrier).Coordinates : mission.InitialPosition,
                    hasCarrier ? "GroupAircraftPlayerCarrier" : "GroupAircraftPlayer", "UnitAircraft",
                    DCSSkillLevel.Client, 0,
                    payload,
                    null, hasCarrier ? -99 : mission.InitialAirbaseID, true, country: fg.Country,
                    startLocation: fg.StartLocation == PlayerStartLocation.Runway ? PlayerStartLocation.ParkingHot : fg.StartLocation);
                if (group == null)
                {
                    DebugLog.Instance.WriteLine($"Failed to create group of player aircraft of type \"{fg.Aircraft}\".", 1, DebugLogMessageErrorLevel.Warning);
                    continue;
                }
                if (hasCarrier)
                {
                    group.CarrierId = mission.Carriers.First(x => x.Units[0].Name == fg.Carrier).Units[0].ID;
                }

                briefingFGList.Add(
                    new UnitFlightGroupBriefingDescription(
                        group.Name, group.Units.Length, fg.Aircraft,
                        GetTaskingDescription(fg.Tasking, objectiveDB),
                        Database.Instance.GetEntry <DBEntryUnit>(fg.Aircraft).AircraftData.GetRadioAsString()));

                totalGroupsCreated++;
            }

            // Not a single player flight group was created succesfully, abort mission generation
            if (totalGroupsCreated == 0)
            {
                throw new Exception("No player flight groups could be created, mission generation failed.");
            }

            return(briefingFGList.ToArray());
        }
示例#10
0
        /// <summary>
        /// Generates the data for the objectives.
        /// </summary>
        /// <param name="mission">The mission for which to generate objectives</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Objective database entry</param>
        private void GenerateObjectivesData(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryTheater theaterDB)
        {
            // Keep in mind the position of the last objective/player location.
            // Start with initial player location.
            Coordinates lastCoordinates = mission.InitialPosition;

            // Common family to use for all objectives if DBEntryObjectiveFlags.SingleTargetUnitFamily is set
            UnitFamily singleObjectiveUnitFamily = objectiveDB.GetRandomUnitFamily();

            for (int i = 0; i < template.ObjectiveCount; i++)
            {
                // Pick a random unique name, or a waypoint number if objectives shouldn't be named
                string objectiveName = PickUniqueObjectiveName();

                DebugLog.Instance.WriteLine($"Adding objective #{i + 1}, designated {objectiveName}", 1);

                // Compute a random distance from last position, in nautical miles
                double objectiveDistanceNM =
                    (template.ObjectiveDistanceNM == 0) ?
                    Toolbox.RandomInt(TemplateTools.MIN_OBJECTIVE_DISTANCE, TemplateTools.MAX_OBJECTIVE_DISTANCE) :
                    template.ObjectiveDistanceNM;

                if (i > 0) // Objective is not the first one, spawn it close to the previous objective
                {
                    objectiveDistanceNM /= 5.0;
                }

                MinMaxD distanceFromLast =
                    new MinMaxD(OBJECTIVE_DISTANCE_VARIATION_MIN, OBJECTIVE_DISTANCE_VARIATION_MAX) * objectiveDistanceNM;
                Coordinates           objectiveCoordinates;
                DBEntryTheaterAirbase?airbase = null;

                if (objectiveDB.UnitGroup.SpawnPoints[0] != TheaterLocationSpawnPointType.Airbase)
                {
                    // Look for a valid spawn point
                    DBEntryTheaterSpawnPoint?spawnPoint =
                        SpawnPointSelector.GetRandomSpawnPoint(
                            // If spawn point types are specified, use them. Else look for spawn points of any type
                            (objectiveDB.UnitGroup.SpawnPoints.Length > 0) ? objectiveDB.UnitGroup.SpawnPoints : null,
                            // Select spawn points at a proper distance from last location (previous objective or home airbase)
                            lastCoordinates, distanceFromLast,
                            // Make sure no objective is too close to the initial location
                            mission.InitialPosition, new MinMaxD(objectiveDistanceNM * OBJECTIVE_DISTANCE_VARIATION_MIN, 999999999),
                            GeneratorTools.GetEnemySpawnPointCoalition(template));
                    // No spawn point found for the objective, abort mission creation.
                    if (!spawnPoint.HasValue)
                    {
                        throw new Exception($"Failed to find a spawn point for objective {i + 1}");
                    }
                    objectiveCoordinates = spawnPoint.Value.Coordinates;
                }
                else
                {
                    airbase = new MissionGeneratorAirbases().SelectObjectiveAirbase(mission, template, theaterDB, lastCoordinates, distanceFromLast, i == 0);
                    if (!airbase.HasValue)
                    {
                        throw new Exception($"Failed to find a airbase point for objective {i + 1}");
                    }
                    objectiveCoordinates = airbase.Value.Coordinates;
                }


                // Set the waypoint coordinates according the the inaccuracy defined in the objective database entry
                Coordinates waypointCoordinates =
                    objectiveCoordinates +
                    Coordinates.CreateRandom(objectiveDB.WaypointInaccuracy * Toolbox.NM_TO_METERS);

                // Select an objective family for the target if any or default to VehicleTransport.
                UnitFamily objectiveUnitFamily = singleObjectiveUnitFamily;

                if (!objectiveDB.Flags.HasFlag(DBEntryObjectiveFlags.SingleTargetUnitFamily))
                {
                    objectiveUnitFamily = objectiveDB.GetRandomUnitFamily();
                }

                // Set the mission objective
                mission.Objectives[i] = new DCSMissionObjective(
                    objectiveName, objectiveCoordinates, objectiveUnitFamily, waypointCoordinates, airbase.HasValue? airbase.Value.DCSID: 0);

                // Last position is now the position of this objective
                lastCoordinates = objectiveCoordinates;
            }

            // If the target is a static object, make sure the correct flag is enabled as it has an influence of some scripts
            mission.ObjectiveIsStatic = objectiveDB.UnitGroup.Category.HasValue && (objectiveDB.UnitGroup.Category.Value == UnitCategory.Static);

            // Make sure objectives are ordered by distance from the players' starting location
            mission.Objectives = mission.Objectives.OrderBy(x => mission.InitialPosition.GetDistanceFrom(x.WaypointCoordinates)).ToArray();
        }
示例#11
0
        /// <summary>
        /// Picks a starting airbase for the player(s)
        /// </summary>
        /// <param name="mission">Mission for which the starting airbase must be set</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="theaterDB">Theater database entry</param>
        /// <param name="objectiveDB">Objective database entry</param>
        /// <returns>Information about the starting airbase</returns>
        public DBEntryTheaterAirbase SelectStartingAirbase(DCSMission mission, MissionTemplate template, DBEntryTheater theaterDB, DBEntryObjective objectiveDB)
        {
            List <DBEntryTheaterAirbase[]> airbasesList = new List <DBEntryTheaterAirbase[]>();

            // Select all airbases with enough parking spots
            int requiredParkingSpots = template.GetMissionPackageRequiredParkingSpots();

            airbasesList.Add((from DBEntryTheaterAirbase ab in theaterDB.Airbases where ab.ParkingSpots.Length >= requiredParkingSpots select ab).ToArray());

            // Select all airbases belonging to the proper coalition (unless all airbase belong to the same coalition)
            if ((template.OptionsTheaterCountriesCoalitions == CountryCoalition.Default) || (template.OptionsTheaterCountriesCoalitions == CountryCoalition.Inverted))
            {
                Coalition requiredCoalition = template.OptionsTheaterCountriesCoalitions == CountryCoalition.Inverted ? mission.CoalitionEnemy : mission.CoalitionPlayer;
                airbasesList.Add((from DBEntryTheaterAirbase ab in airbasesList.Last() where ab.Coalition == requiredCoalition select ab).ToArray());
            }

            // If mission must start near water, or some player start on a carrier, select all airbases near water
            if (objectiveDB.Flags.HasFlag(DBEntryObjectiveFlags.MustStartNearWater) || !string.IsNullOrEmpty(template.PlayerFlightGroups[0].Carrier))
            {
                airbasesList.Add((from DBEntryTheaterAirbase ab in airbasesList.Last() where ab.Flags.HasFlag(DBEntryTheaterAirbaseFlag.NearWater) select ab).ToArray());
            }

            // If a particular airbase name has been specified and an airbase with this name exists, pick it
            if (!string.IsNullOrEmpty(template.FlightPlanTheaterStartingAirbase))
            {
                airbasesList.Add((from DBEntryTheaterAirbase airbase in theaterDB.Airbases
                                  where airbase.Name.ToLowerInvariant() == template.FlightPlanTheaterStartingAirbase.ToLowerInvariant()
                                  select airbase).ToArray());

                if (airbasesList.Last().Length == 0)
                {
                    DebugLog.Instance.WriteLine($"Airbase \"{template.FlightPlanTheaterStartingAirbase}\" not found or airbase doesn't have enough parking spots. Selecting a random airbase instead.", 1, DebugLogMessageErrorLevel.Warning);
                }
            }

            // Check for valid airbases in all list, starting from the last one (with the most criteria filtered, and go back to the previous ones
            // as long as no airbase is found.
            for (int i = airbasesList.Count - 1; i >= 0; i--)
            {
                if (airbasesList[i].Length > 0)
                {
                    return(Toolbox.RandomFrom(airbasesList[i]));
                }
            }

            throw new Exception($"No airbase found with {requiredParkingSpots} parking spots, cannot spawn all player aircraft.");
        }
        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);
        }
示例#13
0
        /// <summary>
        /// Generates a <see cref="DCSMission"/> from a <see cref="MissionTemplate"/>
        /// </summary>
        /// <param name="template">The <see cref="MissionTemplate"/> to use</param>
        /// <returns>A <see cref="DCSMission"/>, or nuLL if something when wrong</returns>
        private DCSMission DoMissionGeneration(MissionTemplate template)
        {
            DateTime generationStartTime = DateTime.Now;

            DebugLog.Instance.Clear();
            DebugLog.Instance.WriteLine($"Starting mission generation...");

            // Check for missing entries in the database
            GeneratorTools.CheckDBForMissingEntry <DBEntryCoalition>(template.ContextCoalitionBlue);
            GeneratorTools.CheckDBForMissingEntry <DBEntryCoalition>(template.ContextCoalitionRed);
            GeneratorTools.CheckDBForMissingEntry <DBEntryObjective>(template.ObjectiveType);
            GeneratorTools.CheckDBForMissingEntry <DBEntryTheater>(template.TheaterID);

            // Create the mission and copy some values (theater database entry ID, etc.) from the template
            DCSMission mission = new DCSMission();

            CopyTemplateValues(mission, template);

            // Get some DB entries from the database for easier reference
            DBEntryCoalition[] coalitionsDB = new DBEntryCoalition[2];
            coalitionsDB[(int)Coalition.Blue] = Database.Instance.GetEntry <DBEntryCoalition>(template.ContextCoalitionBlue);
            coalitionsDB[(int)Coalition.Red]  = Database.Instance.GetEntry <DBEntryCoalition>(template.ContextCoalitionRed);
            DBEntryObjective objectiveDB = Database.Instance.GetEntry <DBEntryObjective>(template.ObjectiveType);
            DBEntryTheater   theaterDB   = Database.Instance.GetEntry <DBEntryTheater>(template.TheaterID);

            // Create the unit maker, which will be used to generate unit groups and their properties
            UnitMaker unitMaker = new UnitMaker(coalitionsDB, theaterDB);

            // Create a list of flight group descriptions which will be used in the briefing
            List <UnitFlightGroupBriefingDescription> briefingFGList = new List <UnitFlightGroupBriefingDescription>();

            // Setup airbases
            DBEntryTheaterAirbase airbaseDB;

            using (MissionGeneratorAirbases airbaseGen = new MissionGeneratorAirbases())
            {
                airbaseDB = airbaseGen.SelectStartingAirbase(mission, template, theaterDB, objectiveDB);

                mission.InitialAirbaseID = airbaseDB.DCSID;
                mission.InitialPosition  = airbaseDB.Coordinates;

                airbaseGen.SetupAirbasesCoalitions(mission, template.TheaterRegionsCoalitions, theaterDB);
            }

            // Generate mission objectives
            DebugLog.Instance.WriteLine("Generating mission objectives...");
            using (MissionGeneratorObjectives objectives = new MissionGeneratorObjectives(unitMaker.SpawnPointSelector))
                objectives.CreateObjectives(mission, template, objectiveDB);

            // Generate mission date and time
            DebugLog.Instance.WriteLine("Generating mission date and time...");
            using (MissionGeneratorDateTime dateTime = new MissionGeneratorDateTime())
            {
                dateTime.GenerateMissionDate(mission, template, coalitionsDB);
                dateTime.GenerateMissionTime(mission, template, theaterDB);
            }

            int windDirection0; // Wind direction at altitude 0, in degrees. Used by carrier groups to make sure carriers sail into the wind.

            // Generate mission weather
            DebugLog.Instance.WriteLine("Generating mission weather...");
            using (MissionGeneratorWeather weather = new MissionGeneratorWeather())
            {
                weather.GenerateWeather(mission, template.EnvironmentWeather, theaterDB);
                weather.GenerateWind(mission, template.EnvironmentWind, theaterDB, out windDirection0);
            }

            // Generate Carrier
            DBEntryUnit carrierDB;

            using (MissionGeneratorCarrier unitGroupGen = new MissionGeneratorCarrier(unitMaker))
                carrierDB = unitGroupGen.GenerateCarrier(mission, template, coalitionsDB[(int)mission.CoalitionPlayer], windDirection0);

            // Generate player unit groups
            DebugLog.Instance.WriteLine("Generating player unit groups and mission package...");
            string aiEscortTypeCAP, aiEscortTypeSEAD;

            using (MissionGeneratorPlayerFlightGroups unitGroupGen = new MissionGeneratorPlayerFlightGroups(unitMaker))
                briefingFGList.AddRange(
                    unitGroupGen.CreateUnitGroups(
                        mission, template, objectiveDB, coalitionsDB[(int)mission.CoalitionPlayer],
                        out aiEscortTypeCAP, out aiEscortTypeSEAD));

            // Generate objective unit groups
            DebugLog.Instance.WriteLine("Generating objectives unit groups...");
            using (MissionGeneratorObjectivesUnitGroups unitGroupGen = new MissionGeneratorObjectivesUnitGroups(unitMaker))
                unitGroupGen.CreateUnitGroups(mission, template, objectiveDB, coalitionsDB);

            // Generate friendly support units
            DebugLog.Instance.WriteLine("Generating friendly support units...");
            using (MissionGeneratorSupportUnits unitGroupGen = new MissionGeneratorSupportUnits(unitMaker))
                briefingFGList.AddRange(unitGroupGen.CreateUnitGroups(mission, coalitionsDB[(int)mission.CoalitionPlayer], template.OptionsUnitMods));

            // Generate enemy air defense unit groups
            DebugLog.Instance.WriteLine("Generating enemy air defense unit groups...");
            using (MissionGeneratorAirDefense unitGroupGen = new MissionGeneratorAirDefense(unitMaker, false, template, mission))
                unitGroupGen.CreateUnitGroups(mission, objectiveDB, coalitionsDB[(int)mission.CoalitionEnemy], GeneratorTools.GetEnemySpawnPointCoalition(template), template.OptionsUnitMods);

            // Generate ally air defense unit groups
            DebugLog.Instance.WriteLine("Generating friendly air defense unit groups...");
            using (MissionGeneratorAirDefense unitGroupGen = new MissionGeneratorAirDefense(unitMaker, true, template, mission))
                unitGroupGen.CreateUnitGroups(mission, objectiveDB, coalitionsDB[(int)mission.CoalitionPlayer], GeneratorTools.GetAllySpawnPointCoalition(template), template.OptionsUnitMods);

            //// Generate enemy fighter patrols
            DebugLog.Instance.WriteLine("Generating enemy fighter patrol unit groups...");
            using (MissionGeneratorEnemyFighterPatrols unitGroupGen = new MissionGeneratorEnemyFighterPatrols(unitMaker))
                unitGroupGen.CreateUnitGroups(mission, template, objectiveDB, coalitionsDB[(int)mission.CoalitionEnemy], aiEscortTypeCAP, aiEscortTypeSEAD);

            //// Generate mission features
            DebugLog.Instance.WriteLine("Generating mission features unit groups...");
            using (MissionGeneratorExtensionsAndFeatures featuresGen = new MissionGeneratorExtensionsAndFeatures(unitMaker))
                featuresGen.GenerateExtensionsAndFeatures(mission, template, objectiveDB, coalitionsDB);

            // Generates the mission flight plan
            DebugLog.Instance.WriteLine("Generating mission flight plan...");
            using (MissionGeneratorFlightPlan flightPlan = new MissionGeneratorFlightPlan())
            {
                flightPlan.SetBullseye(mission);
                flightPlan.AddObjectiveWaypoints(mission, objectiveDB);
                flightPlan.AddExtraWaypoints(mission, template);
            }

            // Generate briefing. Must be last because it uses information from other generators
            DebugLog.Instance.WriteLine("Generating mission briefing...");
            using (MissionGeneratorBriefing briefing = new MissionGeneratorBriefing())
            {
                briefing.GenerateMissionName(mission, template);
                briefing.GenerateMissionBriefing(mission, template, objectiveDB, airbaseDB, carrierDB, briefingFGList, coalitionsDB);
            }

            // Set if radio sounds are enabled
            mission.RadioSounds = !template.OptionsPreferences.Contains(MissionTemplatePreferences.DisableRadioSounds);

            // Add common .ogg vorbis files and make sure each only appears only once.
            mission.OggFiles.AddRange(Database.Instance.Common.CommonOGG);
            mission.OggFiles.AddRange(Database.Instance.Common.CommonOGGForGameMode[(int)template.GetMissionType()]);
            mission.OggFiles =
                (from string f in mission.OggFiles
                 where !string.IsNullOrEmpty(f.Trim()) select f.Trim())
                .Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();

            // If radio sounds are disabled, do not include radio .ogg files to save on file size
            if (!mission.RadioSounds)
            {
                mission.OggFiles =
                    (from string f in mission.OggFiles
                     where (f.ToLowerInvariant() == "radio0") || (!f.ToLowerInvariant().StartsWith("radio")) select f).ToList();
            }

            // Make sure included Lua scripts appear only once
            mission.IncludedLuaScripts = mission.IncludedLuaScripts.Distinct().OrderBy(x => x).ToList();

            // Create aircraft queues and finalize the core script
            CreateAircraftActivationQueues(mission);
            switch (template.GetMissionType())
            {
            case MissionType.SinglePlayer:
                mission.CoreLuaScript += "briefingRoom.mission.missionType = brMissionType.SINGLE_PLAYER\r\n"; break;

            case MissionType.Cooperative:
                mission.CoreLuaScript += "briefingRoom.mission.missionType = brMissionType.COOPERATIVE\r\n"; break;

            case MissionType.Versus:
                mission.CoreLuaScript += "briefingRoom.mission.missionType = brMissionType.VERSUS\r\n"; break;
            }

            DebugLog.Instance.WriteLine($"Mission generation completed successfully in {(DateTime.Now - generationStartTime).TotalSeconds.ToString("F3", NumberFormatInfo.InvariantInfo)} second(s).");

            unitMaker.Dispose();

            return(mission);
        }
示例#14
0
        /// <summary>
        /// Adds media files, scripts and units associated with mission features.
        /// </summary>
        /// <param name="mission">Mission to which features and extensions should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <param name="coalitionsDB">Coalitions database entries</param>
        public void GenerateExtensionsAndFeatures(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryCoalition[] coalitionsDB)
        {
            int i, j;

            DBEntryExtension[] extensions = Database.Instance.GetEntries <DBEntryExtension>(template.ScriptExtensions);
            foreach (DBEntryExtension extension in extensions)
            {
                AddIncludedFiles(mission, extension);
            }

            DBEntryMissionFeature[] features = Database.Instance.GetEntries <DBEntryMissionFeature>(objectiveDB.MissionFeatures);
            foreach (DBEntryMissionFeature feature in features)
            {
                AddIncludedFiles(mission, feature);

                // No unit family in the unit group, so not unit group to add
                if (feature.UnitGroup.Families.Length == 0)
                {
                    continue;
                }

                Side side = feature.UnitGroup.Flags.HasFlag(DBUnitGroupFlags.Friendly) ? Side.Ally : Side.Enemy;

                UnitFamily unitFamily = Toolbox.RandomFrom(feature.UnitGroup.Families);

                // Pick units
                string[] units =
                    coalitionsDB[(int)((side == Side.Ally) ? mission.CoalitionPlayer : mission.CoalitionEnemy)].GetRandomUnits(
                        unitFamily, mission.DateTime.Decade,
                        feature.UnitGroup.Count.GetValue(), template.UnitMods);

                DCSSkillLevel skillLevel;
                if (side == Side.Ally)
                {
                    skillLevel = Toolbox.BRSkillLevelToDCSSkillLevel(template.SituationFriendlyAISkillLevel);
                }
                else
                {
                    skillLevel = Toolbox.IsUnitFamilyAircraft(unitFamily) ?
                                 Toolbox.BRSkillLevelToDCSSkillLevel(template.SituationEnemySkillLevelAir) : Toolbox.BRSkillLevelToDCSSkillLevel(template.SituationEnemySkillLevelGround);
                }

                DCSMissionUnitGroupFlags flags = 0;

                List <int> unitGroupsID = new List <int>();
                for (i = 0; i < mission.Objectives.Length; i++)
                {
                    Coordinates[] coordinates = new Coordinates[2];
                    for (j = 0; j < 2; j++)
                    {
                        switch (feature.UnitGroupCoordinates[j])
                        {
                        case DBEntryMissionFeatureUnitGroupLocation.Homebase:
                            coordinates[j] = mission.InitialPosition + Coordinates.CreateRandom(2, 6) * Toolbox.NM_TO_METERS;
                            break;

                        case DBEntryMissionFeatureUnitGroupLocation.Objective:
                            coordinates[j] = mission.Objectives[i].Coordinates;
                            break;

                        case DBEntryMissionFeatureUnitGroupLocation.ObjectiveNear:
                            coordinates[j] = mission.Objectives[i].Coordinates + Coordinates.CreateRandom(1.5, 4) * Toolbox.NM_TO_METERS;
                            break;

                        case DBEntryMissionFeatureUnitGroupLocation.Waypoint:
                            coordinates[j] = mission.Objectives[i].WaypointCoordinates;
                            break;

                        case DBEntryMissionFeatureUnitGroupLocation.WaypointNear:
                            coordinates[j] = mission.Objectives[i].WaypointCoordinates + Coordinates.CreateRandom(1.5, 4) * Toolbox.NM_TO_METERS;
                            break;
                        }
                    }

                    DCSMissionUnitGroup group = UnitMaker.AddUnitGroup(
                        mission, units, side,
                        coordinates[0],
                        Toolbox.RandomFrom(feature.UnitGroup.LuaGroup), feature.UnitGroup.LuaUnit,
                        skillLevel, flags, UnitTaskPayload.Default, coordinates[1]);

                    if (group == null)
                    {
                        DebugLog.Instance.WriteLine($"Failed to create mission feature unit group for objective #{i + 1} made of the following units: {string.Join(", ", units)}", 1, DebugLogMessageErrorLevel.Warning);
                    }

                    unitGroupsID.Add(group.GroupID);

                    // Add aircraft group to the queue of aircraft groups to be spawned
                    if (!feature.UnitGroup.Flags.HasFlag(DBUnitGroupFlags.ManualActivation) &&
                        ((group.Category == UnitCategory.Helicopter) || (group.Category == UnitCategory.Plane) || feature.UnitGroup.Flags.HasFlag(DBUnitGroupFlags.DelaySpawn)))
                    {
                        mission.AircraftSpawnQueue.Add(new DCSMissionAircraftSpawnQueueItem(group.GroupID, true));
                    }
                }

                if (unitGroupsID.Count > 0)
                {
                    mission.LuaSettings += $"briefingRoom.mission.featuresUnitGroups.{feature.ID} = {{ {string.Join(", ", unitGroupsID)} }}";
                }
            }
        }
示例#15
0
        /// <summary>
        /// Creates the flight group player will lead in a single-player mission.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <returns>A <see cref="UnitFlightGroupBriefingDescription"/> describing the flight group, to be used in the briefing</returns>
        private UnitFlightGroupBriefingDescription GenerateSinglePlayerFlightGroup(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB)
        {
            DCSMissionUnitGroup group = UnitMaker.AddUnitGroup(
                mission,
                Enumerable.Repeat(template.PlayerSPAircraft, template.PlayerSPWingmen + 1).ToArray(),
                Side.Ally, mission.Carrier != null ? mission.Carrier.Coordinates : mission.InitialPosition,
                mission.Carrier != null ? "GroupAircraftPlayerCarrier" : "GroupAircraftPlayer", "UnitAircraft",
                Toolbox.BRSkillLevelToDCSSkillLevel(template.PlayerAISkillLevel), DCSMissionUnitGroupFlags.FirstUnitIsPlayer,
                objectiveDB.Payload,
                null, mission.Carrier != null ? -99 : mission.InitialAirbaseID, true);

            if (group == null)
            {
                throw new Exception($"Failed to create group of player aircraft of type \"{template.PlayerSPAircraft}\".");
            }

            return(new UnitFlightGroupBriefingDescription(
                       group.Name, group.Units.Length, template.PlayerSPAircraft,
                       objectiveDB.BriefingTaskFlightGroup,
                       Database.Instance.GetEntry <DBEntryUnit>(template.PlayerSPAircraft).AircraftData.GetRadioAsString()));
        }
        /// <summary>
        /// Main unit generation method.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <param name="enemyCoalitionDB">Enemy coalition database entry</param>
        /// <param name="aiEscortTypeCAP">Type of aircraft selected for player AI CAP escort (single-player only)</param>
        /// <param name="aiEscortTypeSEAD">Type of aircraft selected for player AI SEAD escort (single-player only)</param>
        public void CreateUnitGroups(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryCoalition enemyCoalitionDB, string aiEscortTypeCAP, string aiEscortTypeSEAD)
        {
            if (objectiveDB.Flags.HasFlag(DBEntryObjectiveFlags.NoEnemyCAP))
            {
                DebugLog.Instance.WriteLine("Enemy CAP disabled for this mission objective type, not spawning any units", 1);
                return;
            }
            int totalAirForcePower =
                (int)(GetMissionPackageAirPower(template, objectiveDB, aiEscortTypeCAP, aiEscortTypeSEAD) *
                      Database.Instance.Common.EnemyCAPRelativePower[(int)template.SituationEnemyAirForce.Get()]);

            DebugLog.Instance.WriteLine($"Enemy air power set to {totalAirForcePower}...", 1);

            DCSMissionUnitGroupFlags flags = template.Realism.Contains(RealismOption.HideEnemyUnits) ? DCSMissionUnitGroupFlags.Hidden : 0;

            int aircraftCount = 0;
            int groupCount    = 0;

            while (totalAirForcePower > 0)
            {
                string[] unitTypes = enemyCoalitionDB.GetRandomUnits(UnitFamily.PlaneFighter, mission.DateTime.Decade, 1, template.UnitMods);
                if (unitTypes.Length == 0)
                {
                    DebugLog.Instance.WriteLine("No valid units found for enemy fighter patrols.", 1, DebugLogMessageErrorLevel.Warning);
                    break;
                }

                // Find spawn point at the proper distance from the objective(s), but not to close from starting airbase
                DBEntryTheaterSpawnPoint?spawnPoint =
                    UnitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                        null,
                        mission.ObjectivesCenter, Database.Instance.Common.EnemyCAPDistanceFromObjectives,
                        mission.InitialPosition, new MinMaxD(Database.Instance.Common.EnemyCAPMinDistanceFromTakeOffLocation, 99999),
                        GeneratorTools.GetEnemySpawnPointCoalition(template));

                if (!spawnPoint.HasValue) // No spawn point found, stop here.
                {
                    DebugLog.Instance.WriteLine("No spawn point found for enemy fighter patrol group.", 1, DebugLogMessageErrorLevel.Warning);
                    break;
                }

                int unitPower = Database.Instance.GetEntry <DBEntryUnit>(unitTypes[0]).AircraftData.AirToAirRating[1];
                int groupSize = 1;
                if (totalAirForcePower >= unitPower * 2)
                {
                    groupSize = 2;
                }
                if (Toolbox.RandomDouble() < .3)
                {
                    if (totalAirForcePower >= unitPower * 4)
                    {
                        groupSize = 4;
                    }
                    else if (totalAirForcePower >= unitPower * 3)
                    {
                        groupSize = 3;
                    }
                }
                totalAirForcePower -= unitPower * groupSize;

                DCSMissionUnitGroup group = UnitMaker.AddUnitGroup(
                    mission, Enumerable.Repeat(unitTypes[0], groupSize).ToArray(),
                    Side.Enemy, spawnPoint.Value.Coordinates,
                    "GroupAircraftCAP", "UnitAircraft",
                    Toolbox.BRSkillLevelToDCSSkillLevel(template.SituationEnemySkillLevelAir),
                    flags, UnitTaskPayload.AirToAir,
                    mission.ObjectivesCenter + Coordinates.CreateRandom(20, 40) * Toolbox.NM_TO_METERS);

                if (group == null)
                {
                    DebugLog.Instance.WriteLine($"Failed to add a group of {groupSize}× {unitTypes[0]} at {spawnPoint.Value.Coordinates}", 1, DebugLogMessageErrorLevel.Warning);
                }
                else
                {
                    DebugLog.Instance.WriteLine($"Added a group of {groupSize}× {unitTypes[0]} at {spawnPoint.Value.Coordinates}");
                    mission.AircraftSpawnQueue.Add(new DCSMissionAircraftSpawnQueueItem(group.GroupID, template.SituationEnemyCAPOnStationChance.RollChance()));
                }

                aircraftCount += groupSize;
                groupCount++;
            }
        }
        /// <summary>
        /// Returns the total air-to-air power rating of the player's (and AI escort) flight package
        /// </summary>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <param name="aiEscortTypeCAP">Type of aircraft selected for player AI CAP escort (single-player only)</param>
        /// <param name="aiEscortTypeSEAD">Type of aircraft selected for player AI SEAD escort (single-player only)</param>
        /// <returns>Total air-to-air power rating of the flight package</returns>
        private int GetMissionPackageAirPower(MissionTemplate template, DBEntryObjective objectiveDB, string aiEscortTypeCAP, string aiEscortTypeSEAD)
        {
            int         airPowerRating = 0;
            DBEntryUnit aircraft;

            if (template.MissionType == MissionType.SinglePlayer)
            {
                // Player flight group
                aircraft        = Database.Instance.GetEntry <DBEntryUnit>(template.PlayerFlightGroups[0].Aircraft);
                airPowerRating += ((aircraft != null) ? aircraft.AircraftData.AirToAirRating[1] : 1) * (template.PlayerFlightGroups[0].Count);
            }
            else // Mission is multi-player
            {
                foreach (MissionTemplateFlightGroup fg in template.PlayerFlightGroups)
                {
                    aircraft = Database.Instance.GetEntry <DBEntryUnit>(fg.Aircraft);

                    if (aircraft == null) // Aircraft doesn't exist
                    {
                        airPowerRating += fg.Count;
                        continue;
                    }

                    bool hasAirToAirLoadout;
                    switch (fg.Tasking)
                    {
                    default:     // case MissionTemplateMPFlightGroupTask.Objectives
                        if (objectiveDB.Payload == UnitTaskPayload.Default)
                        {
                            hasAirToAirLoadout = aircraft.Families.Contains(UnitFamily.PlaneFighter) || aircraft.Families.Contains(UnitFamily.PlaneInterceptor);
                        }
                        else if (objectiveDB.Payload == UnitTaskPayload.AirToAir)
                        {
                            hasAirToAirLoadout = true;
                        }
                        else
                        {
                            hasAirToAirLoadout = false;
                        }
                        break;

                    case MissionTemplateFlightGroupTask.SupportCAP:
                        hasAirToAirLoadout = true;
                        break;

                    case MissionTemplateFlightGroupTask.SupportSEAD:
                        hasAirToAirLoadout = false;
                        break;
                    }

                    airPowerRating += aircraft.AircraftData.AirToAirRating[hasAirToAirLoadout ? 1 : 0] * fg.Count;
                }
            }

            // AI CAP escort
            aircraft        = Database.Instance.GetEntry <DBEntryUnit>(aiEscortTypeCAP);
            airPowerRating += ((aircraft != null) ? aircraft.AircraftData.AirToAirRating[1] : 1) * template.SituationFriendlyEscortCAP;

            // AI SEAD escort
            aircraft        = Database.Instance.GetEntry <DBEntryUnit>(aiEscortTypeSEAD);
            airPowerRating += ((aircraft != null) ? aircraft.AircraftData.AirToAirRating[0] : 1) * template.SituationFriendlyEscortSEAD;

            return(airPowerRating);
        }
        /// <summary>
        /// Adds media files, scripts and units associated with mission features.
        /// </summary>
        /// <param name="mission">Mission to which features and extensions should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="objectiveDB">Mission objective database entry</param>
        /// <param name="coalitionsDB">Coalitions database entries</param>
        public void GenerateExtensionsAndFeatures(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryCoalition[] coalitionsDB)
        {
            DBEntryExtension[] extensions = Database.Instance.GetEntries <DBEntryExtension>(template.OptionsScriptExtensions);
            foreach (DBEntryExtension extension in extensions)
            {
                AddIncludedFiles(mission, extension);
            }

            DBEntryMissionFeature[] features = Database.Instance.GetEntries <DBEntryMissionFeature>(objectiveDB.MissionFeatures);
            foreach (DBEntryMissionFeature feature in features)
            {
                AddIncludedFiles(mission, feature);

                // No unit family in the unit group, so not unit group to add
                if (feature.UnitGroup.Families.Length == 0)
                {
                    continue;
                }

                // TODO: add feature unit group
            }
        }
        /// <summary>
        /// Generates the mission briefing.
        /// </summary>
        /// <param name="mission">Mission</param>
        /// <param name="template">Template from which the mission should be built</param>
        /// <param name="airbaseDB">Airbase player will take off from and land back on</param>
        /// <param name="coalitionsDB">Database entries for the mission coalitions</param>
        public void GenerateMissionBriefing(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryTheaterAirbase airbaseDB, List <UnitFlightGroupBriefingDescription> flightGroups, DBEntryCoalition[] coalitionsDB)
        {
            DebugLog.Instance.WriteLine("Generating mission briefing...", 1);

            // Get mission features
            DBEntryMissionFeature[] features = Database.Instance.GetEntries <DBEntryMissionFeature>(objectiveDB.MissionFeatures);

            string description = GeneratorTools.SanitizeString(template.BriefingDescription);

            if (string.IsNullOrEmpty(description)) // No custom mission description has been provided, generate one
            {
                description = objectiveDB.BriefingDescriptionByUnitFamily[(int)mission.Objectives[0].TargetFamily];
                if (string.IsNullOrEmpty(description)) // No custom briefing for this target family, use the default
                {
                    description = objectiveDB.BriefingDescription;
                }

                description =
                    GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(description), mission, coalitionsDB);
            }
            description = GeneratorTools.SanitizeString(description);

            // Generate tasks
            string        baseName = airbaseDB.Name; // TODO: this doesn't work for lots of carriers so simplifying for now
            List <string> tasks    = new List <string> {
                $"Take off from {baseName}"
            };
            string objectiveTask = GeneratorTools.ParseRandomString(objectiveDB.BriefingTask);

            for (int i = 0; i < mission.Objectives.Length; i++)
            {
                string taskString = GeneratorTools.MakeBriefingStringReplacements(objectiveTask, mission, coalitionsDB, i);
                tasks.Add(taskString);
                mission.CoreLuaScript += $"briefingRoom.mission.objectives[{i + 1}].task = \"{taskString}\"\r\n";
            }
            tasks.Add($"Return to {baseName}");
            DebugLog.Instance.WriteLine($"{tasks.Count} task(s)", 2);

            // Generate mission remarks...
            List <string> remarks = new List <string>();

            remarks.AddRange( // ...from objective
                from string remark in objectiveDB.BriefingRemarks
                select GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(remark), mission, coalitionsDB));
            foreach (DBEntryMissionFeature feature in features)
            {
                remarks.AddRange( // ...from features
                    from string remark in feature.BriefingRemarks
                    select GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(remark), mission, coalitionsDB));
            }

            /*
             * // Opposition Remarks
             * string airDefenseNumbers = template.OppositionAirDefense == AmountN.Random? "Unknown":template.OppositionAirDefense.ToString();
             * string airDefenseSkill = template.OppositionSkillLevelGround == BRSkillLevel.Random? "Varied":template.OppositionSkillLevelGround.ToString();
             * string airForceNumbers = template.OppositionAirForce == AmountN.Random? "Unknown":template.OppositionAirForce.ToString();
             * string airForceSkill = template.OppositionSkillLevelAir == BRSkillLevel.Random? "Varied":template.OppositionSkillLevelAir.ToString();
             * string allyAirDefenseNumbers = template.PlayerFriendlyAirDefense == AmountN.Random? "Unknown":template.PlayerFriendlyAirDefense.ToString();
             * string allyAirDefenseSkill = template.PlayerAISkillLevel == BRSkillLevel.Random? "Varied":template.PlayerAISkillLevel.ToString();
             * remarks.AddRange(new List<string>{
             *  $"Enemy Air Defenses are {airDefenseNumbers} and they are {airDefenseSkill} troops",
             *  $"Expected Enemy Air Force response is {airForceNumbers} and they are {airForceSkill} pilots",
             *  $"Our Air Defenses are {allyAirDefenseNumbers} and they are {allyAirDefenseSkill} troops",});
             * remarks.Add("Use the \"F10/Other\" item in the comms for additional options");
             * DebugLog.Instance.WriteLine($"{remarks.Count} remark(s)", 2);
             */

            mission.BriefingHTML = CreateHTMLBriefing(mission, template, description, tasks, remarks, flightGroups, airbaseDB, coalitionsDB, objectiveDB);
            mission.BriefingTXT  = CreateTXTBriefing(mission, description, tasks, remarks, flightGroups, airbaseDB);
        }
示例#20
0
        /// <summary>
        /// Generates the mission briefing.
        /// </summary>
        /// <param name="mission">Mission</param>
        /// <param name="template">Template from which the mission should be built</param>
        /// <param name="airbaseDB">Airbase player will take off from and land back on</param>
        /// <param name="coalitionsDB">Database entries for the mission coalitions</param>
        public void GenerateMissionBriefing(DCSMission mission, MissionTemplate template, DBEntryObjective objectiveDB, DBEntryTheaterAirbase airbaseDB, List <UnitFlightGroupBriefingDescription> flightGroups, DBEntryCoalition[] coalitionsDB)
        {
            DebugLog.Instance.WriteLine("Generating mission briefing...", 1);

            // Get mission features
            DBEntryMissionFeature[] features = Database.Instance.GetEntries <DBEntryMissionFeature>(objectiveDB.MissionFeatures);

            string description = objectiveDB.BriefingDescriptionByUnitFamily[(int)mission.Objectives[0].TargetFamily];

            if (string.IsNullOrEmpty(description)) // No custom briefing for this target family, use the default
            {
                description = objectiveDB.BriefingDescription;
            }

            description =
                GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(description), mission, coalitionsDB);
            description = GeneratorTools.SanitizeString(description);

            // Generate tasks
            string        baseName = airbaseDB.Name; // TODO: this doesn't work for lots of carriers so simplifying for now
            List <string> tasks    = new List <string> {
                $"Take off from {baseName}"
            };
            string objectiveTask = GeneratorTools.ParseRandomString(objectiveDB.BriefingTask);

            for (int i = 0; i < mission.Objectives.Length; i++)
            {
                string taskString = GeneratorTools.MakeBriefingStringReplacements(objectiveTask, mission, coalitionsDB, i);
                tasks.Add(taskString);
                mission.CoreLuaScript += $"briefingRoom.mission.objectives[{i + 1}].task = \"{taskString}\"\r\n";
            }
            tasks.Add($"Return to {baseName}");
            DebugLog.Instance.WriteLine($"{tasks.Count} task(s)", 2);

            // Generate mission remarks...
            List <string> remarks = new List <string>();

            remarks.AddRange( // ...from objective
                from string remark in objectiveDB.BriefingRemarks
                select GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(remark), mission, coalitionsDB));
            foreach (DBEntryMissionFeature feature in features)
            {
                remarks.AddRange( // ...from features
                    from string remark in feature.BriefingRemarks
                    select GeneratorTools.MakeBriefingStringReplacements(GeneratorTools.ParseRandomString(remark), mission, coalitionsDB));
            }

            mission.BriefingHTML = CreateHTMLBriefing(mission, template, description, tasks, remarks, flightGroups, airbaseDB, coalitionsDB, objectiveDB);
            mission.BriefingTXT  = CreateTXTBriefing(mission, description, tasks, remarks, flightGroups, airbaseDB);
        }