Exemple #1
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="unitMaker">Unit maker class to use to generate units</param>
        public MissionGeneratorAirDefense(UnitMaker unitMaker, bool _ally, MissionTemplate template, DCSMission mission)
        {
            UnitMaker = unitMaker;
            ally      = _ally;
            if (ally)
            {
                airDefense               = template.SituationFriendlyAirDefense.Get();
                centerPoint              = mission.InitialPosition;
                opposingPoint            = mission.ObjectivesCenter;
                distsFromCenter          = Database.Instance.Common.AllyAirDefenseDistanceFromTakeOffLocation;
                minDistFromOpposingPoint = Database.Instance.Common.AllyAirDefenseDistanceFromObjectives;
                skillLevel               = template.SituationFriendlyAISkillLevel;
                optionsShowEnemyUnits    = 0;
                return;
            }

            airDefense               = template.SituationEnemyAirDefense.Get();
            centerPoint              = mission.ObjectivesCenter;
            opposingPoint            = mission.InitialPosition;
            distsFromCenter          = Database.Instance.Common.EnemyAirDefenseDistanceFromObjectives;
            minDistFromOpposingPoint = Database.Instance.Common.EnemyAirDefenseDistanceFromTakeOffLocation;
            skillLevel               = template.SituationEnemySkillLevelGround;
            optionsShowEnemyUnits    = template.Realism.Contains(RealismOption.HideEnemyUnits) ? DCSMissionUnitGroupFlags.Hidden : 0;
        }
Exemple #2
0
        /// <summary>
        /// Add surface-to-air defense groups.
        /// </summary>
        /// <param name="mission">Mission to which generated units should be added</param>
        /// <param name="template">Mission template to use</param>
        /// <param name="airDefenseRange">Air-defense range category</param>
        /// <param name="enemyCoalitionDB">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>
        private void AddAirDefenseUnits(DCSMission mission, AirDefenseRange airDefenseRange, DBEntryCoalition enemyCoalitionDB, Coalition?coalition, string[] unitMods)
        {
            // Get the proper number of groups
            int groupCount = Database.Instance.Common.
                             EnemyAirDefense[(int)airDefense].GroupsInArea[(int)airDefenseRange].GetValue();

            if (groupCount < 1)
            {
                return;                  // No groups to add, no need to go any further
            }
            DCSMissionUnitGroupFlags flags = optionsShowEnemyUnits;

            UnitFamily[] unitFamilies;
            TheaterLocationSpawnPointType[] validSpawnPoints;
            switch (airDefenseRange)
            {
            default:     // case AirDefenseRange.ShortRange:
                unitFamilies     = new UnitFamily[] { UnitFamily.VehicleAAA, UnitFamily.VehicleAAAStatic, UnitFamily.VehicleInfantryMANPADS, UnitFamily.VehicleSAMShort, UnitFamily.VehicleSAMShort, UnitFamily.VehicleSAMShortIR, UnitFamily.VehicleSAMShortIR };
                validSpawnPoints = new TheaterLocationSpawnPointType[] { TheaterLocationSpawnPointType.LandSmall, TheaterLocationSpawnPointType.LandMedium, TheaterLocationSpawnPointType.LandLarge };
                break;

            case AirDefenseRange.MediumRange:
                unitFamilies     = new UnitFamily[] { UnitFamily.VehicleSAMMedium };
                validSpawnPoints = new TheaterLocationSpawnPointType[] { TheaterLocationSpawnPointType.LandMedium, TheaterLocationSpawnPointType.LandLarge };
                break;

            case AirDefenseRange.LongRange:
                unitFamilies     = new UnitFamily[] { UnitFamily.VehicleSAMLong };
                validSpawnPoints = new TheaterLocationSpawnPointType[] { TheaterLocationSpawnPointType.LandLarge };
                break;
            }

            for (int i = 0; i < groupCount; i++)
            {
                // Find spawn point at the proper distance from the objective(s), but not to close from starting airbase
                DBEntryTheaterSpawnPoint?spawnPoint =
                    UnitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                        validSpawnPoints,
                        centerPoint,
                        distsFromCenter[(int)airDefenseRange],
                        opposingPoint,
                        new MinMaxD(minDistFromOpposingPoint[(int)airDefenseRange], 99999),
                        coalition);

                // No spawn point found, stop here.
                if (!spawnPoint.HasValue)
                {
                    DebugLog.Instance.WriteLine($"No spawn point found for {airDefenseRange} air defense unit groups", 1, DebugLogMessageErrorLevel.Warning);
                    return;
                }

                string[] units = enemyCoalitionDB.GetRandomUnits(Toolbox.RandomFrom(unitFamilies), mission.DateTime.Decade, 1, unitMods);

                DCSMissionUnitGroup group = UnitMaker.AddUnitGroup(
                    mission, units, ally? Side.Ally : Side.Enemy,
                    spawnPoint.Value.Coordinates,
                    "GroupVehicle", "UnitVehicle",
                    Toolbox.BRSkillLevelToDCSSkillLevel(skillLevel),
                    flags);

                if (group == null)
                {
                    DebugLog.Instance.WriteLine($"Failed to add {airDefenseRange} air defense unit group of type {units[0]}", 1, DebugLogMessageErrorLevel.Warning);
                }
            }
        }
Exemple #3
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)} }}";
                }
            }
        }
Exemple #4
0
        public DCSMissionUnitGroup AddUnitGroup(
            DCSMission mission, string[] units, Side side,
            Coordinates coordinates, string groupLua, string unitLua,
            DCSSkillLevel skill, DCSMissionUnitGroupFlags flags = 0, UnitTaskPayload payload = UnitTaskPayload.Default,
            Coordinates?coordinates2 = null, int airbaseID = 0, bool requiresParkingSpots = false, bool requiresOpenAirParking = false, Country?country = null, PlayerStartLocation startLocation = PlayerStartLocation.Runway)
        {
            if (units.Length == 0)
            {
                return(null);                   // No units database entries ID provided, cancel group creation
            }
            // TODO: check for missing units
            DBEntryUnit[] unitsBP = (from string u in units where Database.Instance.EntryExists <DBEntryUnit>(u) select Database.Instance.GetEntry <DBEntryUnit>(u)).ToArray();
            unitsBP = (from DBEntryUnit u in unitsBP where u != null select u).ToArray();
            if (unitsBP.Length == 0)
            {
                return(null);                                                                             // All database entries were null, cancel group creation
            }
            Coalition coalition = (side == Side.Ally) ? mission.CoalitionPlayer : mission.CoalitionEnemy; // Pick group coalition

            if (!country.HasValue)
            {
                country = coalition == Coalition.Blue? Country.CJTFBlue : Country.CJTFRed;
            }

            double groupHeading = unitsBP[0].IsAircraft ? 0 : Toolbox.RandomDouble(Toolbox.TWO_PI); // Generate global group heading

            // Generate units in the group
            int         unitIndex = 0;
            Coordinates?lastSpot  = null;
            List <DCSMissionUnitGroupUnit> groupUnits = new List <DCSMissionUnitGroupUnit>();

            foreach (DBEntryUnit unitBP in unitsBP)
            {
                if (unitBP == null)
                {
                    continue;
                }

                for (int i = 0; i < unitBP.DCSIDs.Length; i++)
                {
                    // Set unit coordinates and heading
                    Coordinates unitCoordinates = coordinates;
                    double      unitHeading     = groupHeading;

                    SetUnitCoordinatesAndHeading(ref unitCoordinates, ref unitHeading, unitBP, unitIndex);

                    // Get parking spot for the unit, if unit is parked at an airdrome
                    int parkingSpot = 0;
                    if (airbaseID > 0)
                    {
                        if (requiresParkingSpots)
                        {
                            parkingSpot = SpawnPointSelector.GetFreeParkingSpot(airbaseID, lastSpot, out Coordinates parkingCoordinates, requiresOpenAirParking);
                            if (parkingSpot >= 0)
                            {
                                unitCoordinates = parkingCoordinates;
                            }
                            else
                            {
                                parkingSpot = 0;
                            }
                            lastSpot = unitCoordinates;
                        }
                    }
                    else if (airbaseID == -99)  //carrier code always parks 1 maybe will need more
                    {
                        parkingSpot = 1;
                    }
                    // Add unit to the list of units
                    DCSMissionUnitGroupUnit unit = new DCSMissionUnitGroupUnit
                    {
                        Coordinates = unitCoordinates,
                        Heading     = unitHeading,
                        ID          = NextUnitID,
                        Type        = unitBP.DCSIDs[i],
                        ParkingSpot = parkingSpot,
                        Name        = unitBP.ID
                    };
                    groupUnits.Add(unit);
                    unitIndex++; NextUnitID++;
                }
            }

            // Generate group name
            string       groupName;
            UnitCallsign callsign = new UnitCallsign();

            if (unitsBP[0].IsAircraft) // Aircraft group, name is a callsign
            {
                callsign  = CallsignGenerator.GetCallsign(unitsBP[0].Families[0], coalition);
                groupName = callsign.GroupName;
            }
            else // Vehicle/ship/static group, name is a random group name
            {
                groupName = GetGroupName(unitsBP[0].Families[0]);
            }

            // Add group to the mission
            DCSMissionUnitGroup group = new DCSMissionUnitGroup
            {
                AirbaseID     = airbaseID,
                CallsignLua   = callsign.Lua,
                Category      = unitsBP[0].Category,
                Coalition     = coalition,
                Country       = country.Value,
                Coordinates   = airbaseID != 0?  groupUnits[0].Coordinates : coordinates,
                Coordinates2  = coordinates2 ?? coordinates + Coordinates.CreateRandom(1, 2) * Toolbox.NM_TO_METERS,
                Flags         = flags,
                GroupID       = NextGroupID,
                LuaGroup      = groupLua,
                Name          = groupName,
                Skill         = skill,
                Payload       = payload,
                UnitID        = units[0],
                LuaUnit       = unitLua,
                Units         = groupUnits.ToArray(),
                StartLocation = startLocation
            };

            mission.UnitGroups.Add(group);

            NextGroupID++;

            DebugLog.Instance.WriteLine($"Added \"{group.Units[0].Type}\" unit group \"{group.Name}\" for coalition {group.Coalition.ToString().ToUpperInvariant()}", 2);

            return(group);
        }
        /// <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++;
            }
        }
Exemple #6
0
        /// <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="coalitionsDB">Coalitions database entries</param>
        /// <param name="moving">Will the group be moving</param>
        /// <param name="objectiveGroup">If the group should be tracked as an objective</param>
        public void SpawnUnitGroups(DCSMission mission, MissionTemplate template, DBUnitGroup unitGroup, DBEntryCoalition[] coalitionsDB, Side side, Coalition coalition)
        {
            DCSMissionUnitGroupFlags flags =
                GeneratorTools.ShouldUnitBeHidden(unitGroup, !template.OptionsPreferences.Contains(MissionTemplatePreferences.HideEnemyUnits)) ?
                DCSMissionUnitGroupFlags.Hidden : 0;

            for (int i = 0; i < mission.Objectives.Length; i++)
            {
                // This objective requires no unit group generation
                if (!mission.Objectives[i].TargetFamily.HasValue)
                {
                    continue;
                }

                string[] units =
                    coalitionsDB[(int)coalition].GetRandomUnits(
                        mission.Objectives[i].TargetFamily.Value, mission.DateTime.Decade,
                        unitGroup.Count.GetValue(), template.OptionsUnitMods);

                // Pick the skill level once for each objective so not all target groups have the same skill level when a "random" skill level is chosen.
                DCSSkillLevel skillLevel;
                if (side == Side.Ally)
                {
                    skillLevel = Toolbox.BRSkillLevelToDCSSkillLevel(template.PlayerAISkillLevel);
                }
                else
                {
                    skillLevel =
                        Toolbox.IsUnitFamilyAircraft(mission.Objectives[i].TargetFamily.Value) ?
                        Toolbox.BRSkillLevelToDCSSkillLevel(template.OppositionSkillLevelAir) : Toolbox.BRSkillLevelToDCSSkillLevel(template.OppositionSkillLevelGround);
                }

                DCSMissionUnitGroup      group;
                DBEntryTheaterSpawnPoint?spawnPoint = null;
                if (unitGroup.SpawnPoints[0] != TheaterLocationSpawnPointType.Airbase)
                {
                    if (unitGroup.Flags.HasFlag(DBUnitGroupFlags.DestinationObjective))
                    {
                        spawnPoint = UnitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                            unitGroup.SpawnPoints,
                            mission.Objectives[i].Coordinates,
                            unitGroup.DistanceFromPoint);
                        if (!spawnPoint.HasValue)
                        {
                            throw new Exception($"Failed to find spawn point for moving objective unit");
                        }
                    }
                }

                if (unitGroup.Flags.HasFlag(DBUnitGroupFlags.EmbeddedAirDefense))                                                // Add "embedded" close range surface-to-air defense
                {
                    if (Toolbox.GetUnitCategoryFromUnitFamily(mission.Objectives[i].TargetFamily.Value) == UnitCategory.Vehicle) // Objectives are ground vehicles, insert air defense units in the group itself
                    {
                        units = GeneratorTools.AddEmbeddedAirDefense(units, template.OppositionAirDefense, coalitionsDB[(int)coalition], mission.DateTime.Decade, template.OptionsUnitMods);
                    }
                    else // Objectives are not ground vehicles, create another group nearby
                    {
                        // TODO: make sure the group is not spawn in water
                        string[] airDefenseGroupUnits = new string[0];
                        for (int j = 0; j < 2; j++)
                        {
                            airDefenseGroupUnits = GeneratorTools.AddEmbeddedAirDefense(airDefenseGroupUnits, template.OppositionAirDefense, coalitionsDB[(int)coalition], mission.DateTime.Decade, template.OptionsUnitMods);
                        }

                        UnitMaker.AddUnitGroup(
                            mission, airDefenseGroupUnits,
                            side,
                            (spawnPoint != null ? spawnPoint.Value.Coordinates : mission.Objectives[i].Coordinates) + Coordinates.CreateRandom(0.5, 1.5) * Toolbox.NM_TO_METERS,
                            "GroupVehicle", "UnitVehicle",
                            skillLevel, flags);
                    }
                }

                group = UnitMaker.AddUnitGroup(
                    mission, units,
                    side,
                    spawnPoint != null? spawnPoint.Value.Coordinates : mission.Objectives[i].Coordinates,
                    Toolbox.RandomFrom(unitGroup.LuaGroup), unitGroup.LuaUnit,
                    skillLevel, flags, coordinates2: getDestination(unitGroup, mission, i),
                    airbaseID: mission.Objectives[i].AirbaseID,
                    requiresParkingSpots: mission.Objectives[i].AirbaseID > 0,
                    requiresOpenAirParking: unitGroup.Flags.HasFlag(DBUnitGroupFlags.AvoidHardenedBunkers)
                    );

                // Something went wrong, abort mission generation, objective unit groups are required for the mission to work properly.
                if (group == null)
                {
                    throw new Exception($"Failed to create objective unit group for objective #{i + 1} made of the following units: {string.Join(", ", units)}");
                }

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

                if (!unitGroup.Flags.HasFlag(DBUnitGroupFlags.NotObjectiveTarget))
                {
                    if (mission.ObjectiveIsStatic)
                    {
                        mission.CoreLuaScript += $"briefingRoom.mission.objectives[{i + 1}].groupID = {group.Units[0].ID}\r\n";
                    }
                    else
                    {
                        // Add the ID of the unit group associated with this objective to the Lua script
                        mission.CoreLuaScript += $"briefingRoom.mission.objectives[{i + 1}].groupID = {group.GroupID}\r\n";
                    }
                }
            }
        }
Exemple #7
0
        /// <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="coalitionsDB">Coalitions database entries</param>
        /// <param name="moving">Will the group be moving</param>
        /// <param name="objectiveGroup">If the group should be tracked as an objective</param>
        public void SpawnUnitGroups(DCSMission mission, MissionTemplate template, DBUnitGroup unitGroup, DBEntryCoalition[] coalitionsDB, Side side, Coalition coalition)
        {
            DCSMissionUnitGroupFlags flags =
                GeneratorTools.ShouldUnitBeHidden(unitGroup, !template.OptionsPreferences.Contains(MissionTemplatePreferences.HideEnemyUnits)) ?
                DCSMissionUnitGroupFlags.Hidden : 0;

            for (int i = 0; i < mission.Objectives.Length; i++)
            {
                // This objective requires no unit group generation
                if (!mission.Objectives[i].TargetFamily.HasValue)
                {
                    continue;
                }

                string[] units =
                    coalitionsDB[(int)coalition].GetRandomUnits(
                        mission.Objectives[i].TargetFamily.Value, mission.DateTime.Decade,
                        unitGroup.Count.GetValue(), template.OptionsUnitMods);

                if (unitGroup.Flags.HasFlag(DBUnitGroupFlags.EmbeddedAirDefense) &&
                    coalition != mission.CoalitionPlayer &&
                    (Toolbox.GetUnitCategoryFromUnitFamily(mission.Objectives[i].TargetFamily.Value) == UnitCategory.Vehicle))
                {
                    units = GeneratorTools.AddEmbeddedAirDefense(units, template.OppositionAirDefense, coalitionsDB[(int)coalition], mission.DateTime.Decade, template.OptionsUnitMods);
                }

                // Pick the skill level once for each objective so not all target groups have the same skill level when a
                // "random" skill level is chosen.
                DCSSkillLevel skillLevel =
                    Toolbox.IsUnitFamilyAircraft(mission.Objectives[i].TargetFamily.Value) ?
                    Toolbox.BRSkillLevelToDCSSkillLevel(template.OppositionSkillLevelAir) :
                    Toolbox.BRSkillLevelToDCSSkillLevel(template.OppositionSkillLevelGround);
                DCSMissionUnitGroup      group;
                DBEntryTheaterSpawnPoint?spawnPoint = null;
                if (unitGroup.Flags.HasFlag(DBUnitGroupFlags.DestinationObjective))
                {
                    spawnPoint = UnitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                        unitGroup.SpawnPoints,
                        mission.Objectives[i].Coordinates,
                        unitGroup.DistanceFromPoint);
                    if (!spawnPoint.HasValue)
                    {
                        throw new Exception($"Failed to find spawn point for moving objective unit");
                    }
                }

                group = UnitMaker.AddUnitGroup(
                    mission, units,
                    side,
                    spawnPoint != null? spawnPoint.Value.Coordinates : mission.Objectives[i].Coordinates,
                    Toolbox.RandomFrom(unitGroup.LuaGroup), unitGroup.LuaUnit,
                    skillLevel, flags, coordinates2: getDestination(unitGroup, mission, i));

                // Something went wrong, abort mission generation, objective unit groups are required for the mission to work properly.
                if (group == null)
                {
                    throw new Exception($"Failed to create objective unit group for objective #{i + 1} made of the following units: {string.Join(", ", units)}");
                }

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

                if (!unitGroup.Flags.HasFlag(DBUnitGroupFlags.NotObjectiveTarget))
                {
                    if (mission.ObjectiveIsStatic)
                    {
                        mission.CoreLuaScript += $"briefingRoom.mission.objectives[{i + 1}].groupID = {group.Units[0].ID}\r\n";
                    }
                    else
                    {
                        // Add the ID of the unit group associated with this objective to the Lua script
                        mission.CoreLuaScript += $"briefingRoom.mission.objectives[{i + 1}].groupID = {group.GroupID}\r\n";
                    }
                }
            }
        }