Esempio n. 1
0
        private Coordinates PlaceInAirbase(MissionTemplateRecord template, DBEntrySituation situationDB, DBEntryAirbase playerAirbase, List <KeyValuePair <string, object> > extraSettings, DBEntryObjectiveTarget targetDB, DBEntryObjectiveTargetBehavior targetBehaviorDB, ref string luaUnit, Coordinates objectiveCoordinates, int unitCount, UnitFamily objectiveTargetUnitFamily)
        {
            int airbaseID                  = 0;
            var parkingSpotIDsList         = new List <int>();
            var parkingSpotCoordinatesList = new List <Coordinates>();
            var targetAirbaseOptions       =
                (from DBEntryAirbase airbaseDB in situationDB.GetAirbases(template.OptionsMission.Contains("InvertCountriesCoalitions"))
                 where airbaseDB.DCSID != playerAirbase.DCSID
                 select airbaseDB).OrderBy(x => x.Coordinates.GetDistanceFrom(objectiveCoordinates));
            DBEntryAirbase targetAirbase = targetAirbaseOptions.FirstOrDefault(x => template.OptionsMission.Contains("SpawnAnywhere") ? true : x.Coalition == template.ContextPlayerCoalition.GetEnemy());

            airbaseID = targetAirbase.DCSID;

            var parkingSpots = UnitMaker.SpawnPointSelector.GetFreeParkingSpots(
                targetAirbase.DCSID,
                unitCount, objectiveTargetUnitFamily,
                targetBehaviorDB.Location == DBEntryObjectiveTargetBehaviorLocation.SpawnOnAirbaseParkingNoHardenedShelter);

            parkingSpotIDsList         = parkingSpots.Select(x => x.DCSID).ToList();
            parkingSpotCoordinatesList = parkingSpots.Select(x => x.Coordinates).ToList();
            luaUnit += "Parked";

            extraSettings.Add("GroupAirbaseID".ToKeyValuePair(airbaseID));
            extraSettings.Add("ParkingID".ToKeyValuePair(parkingSpotIDsList.ToArray()));
            extraSettings.Add("UnitX".ToKeyValuePair((from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.X).ToArray()));
            extraSettings.Add("UnitY".ToKeyValuePair((from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.Y).ToArray()));
            return(targetAirbase.Coordinates);
        }
Esempio n. 2
0
        private static void CreateLua(DCSMission mission, MissionTemplateRecord template, DBEntryObjectiveTarget targetDB, DBEntryObjectiveTask taskDB, int objectiveIndex, string objectiveName, UnitMakerGroupInfo?targetGroupInfo, string taskString)
        {
            // Add Lua table for this objective
            string objectiveLua = $"briefingRoom.mission.objectives[{objectiveIndex + 1}] = {{ ";

            objectiveLua += $"complete = false, ";
            objectiveLua += $"groupID = {targetGroupInfo.Value.GroupID}, ";
            objectiveLua += $"hideTargetCount = false, ";
            objectiveLua += $"name = \"{objectiveName}\", ";
            objectiveLua += $"targetCategory = Unit.Category.{targetDB.UnitCategory.ToLuaName()}, ";
            objectiveLua += $"taskType = \"{taskDB.ID}\", ";
            objectiveLua += $"task = \"{taskString}\", ";
            objectiveLua += $"unitsCount = {targetGroupInfo.Value.UnitsID.Length}, ";
            objectiveLua += $"unitsID = {{ {string.Join(", ", targetGroupInfo.Value.UnitsID)} }} ";
            objectiveLua += "}\n";

            // Add F10 sub-menu for this objective
            objectiveLua += $"briefingRoom.f10Menu.objectives[{objectiveIndex + 1}] = missionCommands.addSubMenuForCoalition(coalition.side.{template.ContextPlayerCoalition.ToString().ToUpperInvariant()}, \"Objective {objectiveName}\", nil)\n";
            mission.AppendValue("ScriptObjectives", objectiveLua);

            // Add objective trigger Lua for this objective
            string triggerLua = Toolbox.ReadAllTextIfFileExists($"{BRPaths.INCLUDE_LUA_OBJECTIVETRIGGERS}{taskDB.CompletionTriggerLua}");

            GeneratorTools.ReplaceKey(ref triggerLua, "ObjectiveIndex", objectiveIndex + 1);
            mission.AppendValue("ScriptObjectivesTriggers", triggerLua);
        }
Esempio n. 3
0
        internal static string[] GetEmbeddedAirDefenseUnits(MissionTemplateRecord template, Side side, Country?country = null)
        {
            DBCommonAirDefenseLevel airDefenseInfo = (side == Side.Ally) ?
                                                     Database.Instance.Common.AirDefense.AirDefenseLevels[(int)template.SituationFriendlyAirDefense.Get()] :
                                                     Database.Instance.Common.AirDefense.AirDefenseLevels[(int)template.SituationEnemyAirDefense.Get()];

            DBEntryCoalition unitsCoalitionDB = Database.Instance.GetEntry <DBEntryCoalition>(template.GetCoalitionID(side));

            if (unitsCoalitionDB == null)
            {
                return(new string[0]);
            }

            List <string> units = new List <string>();

            if (Toolbox.RandomDouble() >= airDefenseInfo.EmbeddedChance)
            {
                return(new string[0]);
            }

            int airDefenseUnitsCount = airDefenseInfo.EmbeddedUnitCount.GetValue();

            for (int i = 0; i < airDefenseUnitsCount; i++)
            {
                var families = new List <UnitFamily> {
                    UnitFamily.VehicleAAA, UnitFamily.VehicleAAA, UnitFamily.VehicleSAMShortIR, UnitFamily.VehicleSAMShortIR, UnitFamily.VehicleSAMShort
                };
                units.AddRange(unitsCoalitionDB.GetRandomUnits(families, template.ContextDecade, 1, template.Mods, country).Item2);
            }

            return(units.ToArray());
        }
Esempio n. 4
0
        internal Tuple <DBEntryAirbase, List <int>, List <Coordinates> > GetAirbaseAndParking(
            MissionTemplateRecord template, Coordinates coordinates,
            int unitCount, Coalition coalition, UnitFamily unitFamily)
        {
            var targetAirbaseOptions =
                (from DBEntryAirbase airbaseDB in SituationDB.GetAirbases(template.OptionsMission.Contains("InvertCountriesCoalitions"))
                 where airbaseDB.Coalition == coalition && ValidateAirfieldParking(AirbaseParkingSpots[airbaseDB.DCSID], unitFamily, unitCount) && ValidateAirfieldRunway(airbaseDB, unitFamily)
                 select airbaseDB).OrderBy(x => x.Coordinates.GetDistanceFrom(coordinates));

            if (targetAirbaseOptions.Count() == 0)
            {
                throw new BriefingRoomException("No airbase found for aircraft.");
            }

            var targetAirbase              = targetAirbaseOptions.First();
            var objectiveCoordinates       = targetAirbase.Coordinates;
            var airbaseID                  = targetAirbase.DCSID;
            var parkingSpotIDsList         = new List <int>();
            var parkingSpotCoordinatesList = new List <Coordinates>();
            var parkingSpots               = GetFreeParkingSpots(airbaseID, unitCount, unitFamily);

            parkingSpotIDsList         = parkingSpots.Select(x => x.DCSID).ToList();
            parkingSpotCoordinatesList = parkingSpots.Select(x => x.Coordinates).ToList();

            return(Tuple.Create(targetAirbase, parkingSpotIDsList, parkingSpotCoordinatesList));
        }
Esempio n. 5
0
        internal static void GenerateTitle(DCSMission mission, MissionTemplateRecord template)
        {
            ImageMaker imageMaker = new();

            imageMaker.TextOverlay.Alignment = ContentAlignment.MiddleCenter;
            imageMaker.TextOverlay.Text      = mission.Briefing.Name;

            List <ImageMakerLayer> imageLayers = new List <ImageMakerLayer>();

            string[] theaterImages = Directory.GetFiles($"{BRPaths.INCLUDE_JPG}Theaters\\", $"{Database.Instance.GetEntry<DBEntryTheater>(template.ContextTheater).DCSID}*.jpg");
            if (theaterImages.Length == 0)
            {
                imageLayers.Add(new ImageMakerLayer("_default.jpg"));
            }
            else
            {
                imageLayers.Add(new ImageMakerLayer("Theaters\\" + Path.GetFileName(Toolbox.RandomFrom(theaterImages))));
            }

            imageLayers.Add(new ImageMakerLayer($"Flags\\{template.GetCoalitionID(template.ContextPlayerCoalition)}.png", ContentAlignment.TopLeft, 8, 8, 0, .5));

            byte[] imageBytes = imageMaker.GetImageBytes(imageLayers.ToArray());

            mission.AddMediaFile($"l10n/DEFAULT/title_{mission.UniqueID}.jpg", imageBytes);
        }
Esempio n. 6
0
        internal static int GenerateWeather(DCSMission mission, MissionTemplateRecord template, DBEntryTheater theaterDB, Month month, DBEntryAirbase playerAirbase)
        {
            var baseAlt = template.OptionsMission.Contains("SeaLevelRefCloud") ? 0.0 : playerAirbase.Elevation;

            if (template.OptionsMission.Contains("HighCloud"))
            {
                baseAlt += 2000;
            }
            DBEntryWeatherPreset weatherDB;

            if (string.IsNullOrEmpty(template.EnvironmentWeatherPreset)) // Random weather
            {
                weatherDB = Toolbox.RandomFrom(Database.Instance.GetAllEntries <DBEntryWeatherPreset>());
            }
            else
            {
                weatherDB = Database.Instance.GetEntry <DBEntryWeatherPreset>(template.EnvironmentWeatherPreset);
            }

            mission.SetValue("WeatherName", weatherDB.BriefingDescription);
            mission.SetValue("WeatherCloudsBase", weatherDB.CloudsBase.GetValue() + baseAlt);
            mission.SetValue("WeatherCloudsPreset", Toolbox.RandomFrom(weatherDB.CloudsPresets));
            mission.SetValue("WeatherCloudsThickness", weatherDB.CloudsThickness.GetValue());
            mission.SetValue("WeatherDust", weatherDB.Dust);
            mission.SetValue("WeatherDustDensity", weatherDB.DustDensity.GetValue());
            mission.SetValue("WeatherFog", weatherDB.Fog);
            mission.SetValue("WeatherFogThickness", weatherDB.FogThickness.GetValue());
            mission.SetValue("WeatherFogVisibility", weatherDB.FogVisibility.GetValue());
            mission.SetValue("WeatherQNH", weatherDB.QNH.GetValue());
            mission.SetValue("WeatherTemperature", theaterDB.Temperature[(int)month].GetValue());
            mission.SetValue("WeatherVisibility", weatherDB.Visibility.GetValue());

            return(weatherDB.Turbulence.GetValue());
        }
Esempio n. 7
0
        internal static Tuple <double, double> GenerateWind(DCSMission mission, MissionTemplateRecord template, int turbulenceFromWeather)
        {
            var windSpeedAtSeaLevel     = 0.0;
            var windDirectionAtSeaLevel = 0.0;

            Wind windLevel = template.EnvironmentWind == Wind.Random ? PickRandomWindLevel() : template.EnvironmentWind;

            BriefingRoom.PrintToLog($"Wind speed level set to \"{windLevel}\".");

            int windAverage = 0;

            for (int i = 0; i < 3; i++)
            {
                int windSpeed     = Database.Instance.Common.Wind[(int)windLevel].Wind.GetValue();
                int windDirection = windSpeed > 0 ? Toolbox.RandomInt(0, 360) : 0;
                if (i == 0)
                {
                    windSpeedAtSeaLevel     = windSpeed;
                    windDirectionAtSeaLevel = windDirection * Toolbox.DEGREES_TO_RADIANS;
                }
                windAverage += windSpeed;

                mission.SetValue($"WeatherWindSpeed{i + 1}", windSpeed);
                mission.SetValue($"WeatherWindDirection{i + 1}", windDirection);
            }
            windAverage /= 3;

            mission.SetValue($"WeatherWindName", windLevel.ToString()); // TODO: get name from attribute
            mission.SetValue($"WeatherWindSpeedAverage", windAverage);

            mission.SetValue("WeatherGroundTurbulence", Database.Instance.Common.Wind[(int)windLevel].Turbulence.GetValue() + turbulenceFromWeather);
            return(new(windSpeedAtSeaLevel, windDirectionAtSeaLevel));
        }
Esempio n. 8
0
 internal static string GetTemplateCoalition(MissionTemplateRecord template, Coalition coalition)
 {
     if (coalition == Coalition.Red)
     {
         return(template.ContextCoalitionRed);
     }
     return(template.ContextCoalitionBlue);
 }
Esempio n. 9
0
        private static Tuple <Coordinates, Coordinates> GetSpawnAndDestination(
            UnitMaker unitMaker, MissionTemplateRecord template, DBEntryTheater theaterDB,
            List <Coordinates> usedCoordinates, Coordinates landbaseCoordinates, Coordinates objectivesCenter,
            double carrierPathDeg)
        {
            var         travelMinMax            = new MinMaxD(Database.Instance.Common.CarrierGroup.CourseLength, Database.Instance.Common.CarrierGroup.CourseLength * 2);
            Coordinates?carrierGroupCoordinates = null;
            Coordinates?destinationPath         = null;
            var         iteration   = 0;
            var         maxDistance = 25;

            while (iteration < 100)
            {
                carrierGroupCoordinates = unitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                    new SpawnPointType[] { SpawnPointType.Sea },
                    landbaseCoordinates,
                    new MinMaxD(10, maxDistance),
                    objectivesCenter,
                    new MinMaxD(10, 99999),
                    GeneratorTools.GetSpawnPointCoalition(template, Side.Ally));
                if (!carrierGroupCoordinates.HasValue)
                {
                    maxDistance += 25;
                    continue;
                }
                var minDist = usedCoordinates.Aggregate(99999999.0, (acc, x) => x.GetDistanceFrom(carrierGroupCoordinates.Value) < acc ? x.GetDistanceFrom(carrierGroupCoordinates.Value) : acc);
                if (minDist < Database.Instance.Common.CarrierGroup.ShipSpacing)
                {
                    continue;
                }

                destinationPath = Coordinates.FromAngleAndDistance(carrierGroupCoordinates.Value, travelMinMax, carrierPathDeg);
                if (ShapeManager.IsPosValid(destinationPath.Value, theaterDB.WaterCoordinates, theaterDB.WaterExclusionCoordinates))
                {
                    break;
                }
                iteration++;
                if (iteration > 10)
                {
                    maxDistance += 1;
                }
            }

            if (!carrierGroupCoordinates.HasValue)
            {
                throw new BriefingRoomException($"Carrier spawnpoint could not be found.");
            }
            if (!destinationPath.HasValue)
            {
                throw new BriefingRoomException($"Carrier destination could not be found.");
            }
            if (!ShapeManager.IsPosValid(destinationPath.Value, theaterDB.WaterCoordinates, theaterDB.WaterExclusionCoordinates))
            {
                throw new BriefingRoomException($"Carrier waypoint is on shore");
            }

            return(new(carrierGroupCoordinates.Value, destinationPath.Value));
        }
Esempio n. 10
0
        private static void GenerateFOB(
            UnitMaker unitMaker, ZoneMaker zoneMaker, MissionTemplateFlightGroupRecord flightGroup, Dictionary <string, UnitMakerGroupInfo> carrierDictionary,
            DCSMission mission, MissionTemplateRecord template, Coordinates landbaseCoordinates, Coordinates objectivesCenter)
        {
            DBEntryTheater theaterDB = Database.Instance.GetEntry <DBEntryTheater>(template.ContextTheater);

            if (theaterDB == null)
            {
                return;                    // Theater doesn't exist. Should never happen.
            }
            Coordinates?spawnPoint =
                unitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                    new SpawnPointType[] { SpawnPointType.LandLarge },
                    landbaseCoordinates,
                    new MinMaxD(5, template.FlightPlanObjectiveDistance),
                    objectivesCenter,
                    new MinMaxD(10, template.FlightPlanObjectiveDistance / 2), template.ContextPlayerCoalition);

            if (!spawnPoint.HasValue)
            {
                BriefingRoom.PrintToLog($"No spawn point found for FOB air defense unit groups", LogMessageErrorLevel.Warning);
                return;
            }

            DBEntryUnit unitDB = Database.Instance.GetEntry <DBEntryUnit>(flightGroup.Carrier);

            if (unitDB == null)
            {
                return;                 // Unit doesn't exist or is not a carrier
            }
            double radioFrequency = 127.5 + carrierDictionary.Count;
            var    FOBNames       = new List <string> {
                "FOB_London",
                "FOB_Dallas",
                "FOB_Paris",
                "FOB_Moscow",
                "FOB_Berlin"
            };

            UnitMakerGroupInfo?groupInfo =
                unitMaker.AddUnitGroup(
                    unitDB.Families[0], 1, Side.Ally,
                    "GroupStatic", "UnitStaticFOB",
                    spawnPoint.Value, 0,
                    "FOBCallSignIndex".ToKeyValuePair(FOBNames.IndexOf(flightGroup.Carrier) + 1),
                    "RadioBand".ToKeyValuePair((int)RadioModulation.AM),
                    "RadioFrequency".ToKeyValuePair(GeneratorTools.GetRadioFrenquency(radioFrequency)));

            if (!groupInfo.HasValue || (groupInfo.Value.UnitsID.Length == 0))
            {
                return;                                                               // Couldn't generate group
            }
            zoneMaker.AddCTLDPickupZone(spawnPoint.Value, true);
            mission.Briefing.AddItem(
                DCSMissionBriefingItemType.Airbase,
                $"{unitDB.UIDisplayName}\t-\t{GeneratorTools.FormatRadioFrequency(radioFrequency)}\t\t");
            carrierDictionary.Add(flightGroup.Carrier, groupInfo.Value); // This bit limits FOBS to one per game think about how we can fix this
        }
Esempio n. 11
0
 internal static void GenerateAircraftPackageWaypoints(MissionTemplateRecord template, DCSMission mission, List <List <Waypoint> > objectiveGroupedWaypoints, Coordinates averageInitialLocation, Coordinates objectivesCenter)
 {
     foreach (var package in template.AircraftPackages)
     {
         var missionPackage = mission.MissionPackages.First(x => x.RecordIndex == template.AircraftPackages.IndexOf(package));
         missionPackage.Waypoints = objectiveGroupedWaypoints.Where((v, i) => package.ObjectiveIndexes.Contains(i)).SelectMany(x => x).ToList(); // THIS IS WHERE THE OBJECTIVES ARE BROKEN
         GenerateIngressAndEgressWaypoints(template, missionPackage.Waypoints, averageInitialLocation, objectivesCenter);
     }
 }
Esempio n. 12
0
 internal DrawingMaker(
     DCSMission mission, MissionTemplateRecord template, DBEntryTheater theaterDB, DBEntrySituation situationDB)
 {
     Mission     = mission;
     Template    = template;
     TheaterDB   = theaterDB;
     SituationDB = situationDB;
     Clear();
     AddTheaterZones();
 }
Esempio n. 13
0
        internal static Coalition?GetSpawnPointCoalition(MissionTemplateRecord template, Side side, bool forceSide = false)
        {
            // No countries spawning restriction
            if (template.OptionsMission.Contains("SpawnAnywhere") && !forceSide)
            {
                return(null);
            }

            Coalition coalition = side == Side.Ally ? template.ContextPlayerCoalition : template.ContextPlayerCoalition.GetEnemy();

            return(coalition);
        }
Esempio n. 14
0
        internal static Country[][] GenerateCountries(DCSMission mission, MissionTemplateRecord template)
        {
            int i;

            List <Country>[] countries = new List <Country>[] { new List <Country>(), new List <Country>() };

            // Add default country for each coalition
            for (i = 0; i < 2; i++)
            {
                countries[i].Add(DEFAULT_COUNTRIES[i]);
            }

            // Add countries for player FGs to player coalition
            foreach (MissionTemplateFlightGroupRecord flightGroup in template.PlayerFlightGroups)
            {
                var group = flightGroup.Hostile ? template.ContextPlayerCoalition.GetEnemy() : template.ContextPlayerCoalition;
                countries[(int)group].Add(flightGroup.Country);
            }


            countries[(int)Coalition.Blue].AddRange(Database.Instance.GetEntry <DBEntryCoalition>(template.ContextCoalitionBlue).Countries);
            countries[(int)Coalition.Red].AddRange(Database.Instance.GetEntry <DBEntryCoalition>(template.ContextCoalitionRed).Countries);


            // Make sure each country doesn't contain the other's coalition default country
            for (i = 0; i < 2; i++)
            {
                countries[i].Remove(Country.ALL);
                countries[i] = countries[i].Distinct().ToList();
            }

            var intersect = countries[(int)Coalition.Blue].Intersect(countries[(int)Coalition.Red]).ToList();

            if (intersect.Count > 0)
            {
                throw new BriefingRoomException($"Countries can't be on both sides {string.Join(",", intersect)}. Check Red and Blue Coalitions as well as flight groups countries.");
            }

            // Add all non-aligned countries to the list of neutral countries
            List <Country> neutralCountries = new List <Country>(Toolbox.GetEnumValues <Country>());

            for (i = 0; i < 2; i++)
            {
                neutralCountries = neutralCountries.Except(countries[i]).ToList();
            }

            mission.SetValue("CoalitionNeutral", GetCountriesLuaTable(neutralCountries));
            mission.SetValue("CoalitionBlue", GetCountriesLuaTable(countries[(int)Coalition.Blue]));
            mission.SetValue("CoalitionRed", GetCountriesLuaTable(countries[(int)Coalition.Red]));

            return(new Country[][] { countries[0].ToArray(), countries[1].ToArray(), });
        }
Esempio n. 15
0
        private Coordinates GetNearestSpawnCoordinates(MissionTemplateRecord template, Coordinates coreCoordinates, DBEntryObjectiveTarget targetDB)
        {
            Coordinates?spawnPoint = UnitMaker.SpawnPointSelector.GetNearestSpawnPoint(
                targetDB.ValidSpawnPoints,
                coreCoordinates);

            if (!spawnPoint.HasValue)
            {
                throw new BriefingRoomException($"Failed to spawn objective unit group. {String.Join(",", targetDB.ValidSpawnPoints.Select(x => x.ToString()).ToList())} Please try again (Consider Adusting Flight Plan)");
            }

            Coordinates objectiveCoordinates = spawnPoint.Value;

            return(objectiveCoordinates);
        }
Esempio n. 16
0
        internal static async Task <DCSMission> GenerateRetryableAsync(MissionTemplate template, bool useObjectivePresets)
        {
            var templateRecord = new MissionTemplateRecord(template);
            var mission        = await Policy
                                 .HandleResult <DCSMission>(x => x.IsExtremeDistance(template, out double distance))
                                 .Or <BriefingRoomException>()
                                 .RetryAsync(3)
                                 .ExecuteAsync(() => GenerateAsync(templateRecord, useObjectivePresets));

            if (mission.IsExtremeDistance(template, out double distance))
            {
                BriefingRoom.PrintToLog($"Distance to objectives exceeds 1.7x of requested distance. ({Math.Round(distance, 2)}NM)", LogMessageErrorLevel.Warning);
            }

            return(mission);
        }
Esempio n. 17
0
        private void AddEmbeddedAirDefenseUnits(MissionTemplateRecord template, DBEntryObjectiveTarget targetDB, DBEntryObjectiveTargetBehavior targetBehaviorDB, DBEntryObjectiveTask taskDB, ObjectiveOption[] objectiveOptions, Coordinates objectiveCoordinates, UnitMakerGroupFlags groupFlags, List <KeyValuePair <string, object> > extraSettings)
        {
            // Static targets (aka buildings) need to have their "embedded" air defenses spawned in another group
            string[] airDefenseUnits = GeneratorTools.GetEmbeddedAirDefenseUnits(template, taskDB.TargetSide);

            if (airDefenseUnits.Length > 0)
            {
                UnitMaker.AddUnitGroup(
                    airDefenseUnits,
                    taskDB.TargetSide, UnitFamily.VehicleAAA,
                    targetBehaviorDB.GroupLua[(int)targetDB.UnitCategory], targetBehaviorDB.UnitLua[(int)targetDB.UnitCategory],
                    objectiveCoordinates + Coordinates.CreateRandom(100, 500),
                    groupFlags,
                    extraSettings.ToArray());
            }
        }
Esempio n. 18
0
        internal static void GenerateAirDefense(MissionTemplateRecord template, UnitMaker unitMaker, Coordinates averageInitialPosition, Coordinates objectivesCenter)
        {
            foreach (Coalition coalition in Toolbox.GetEnumValues <Coalition>())
            {
                bool ally = coalition == template.ContextPlayerCoalition;

                Side        side             = ally ? Side.Ally : Side.Enemy;
                AmountNR    airDefenseAmount = ally ? template.SituationFriendlyAirDefense.Get() : template.SituationEnemyAirDefense.Get();
                Coordinates centerPoint      = ally ? averageInitialPosition : objectivesCenter;
                Coordinates opposingPoint    = ally ? objectivesCenter : averageInitialPosition;

                foreach (AirDefenseRange airDefenseRange in Toolbox.GetEnumValues <AirDefenseRange>())
                {
                    CreateAirDefenseGroups(template, unitMaker, side, coalition, airDefenseAmount, airDefenseRange, centerPoint, opposingPoint);
                }
            }
        }
Esempio n. 19
0
        internal static void GenerateObjectiveWPCoordinatesLua(MissionTemplateRecord template, DCSMission mission, List <Waypoint> waypoints, DrawingMaker DrawingMaker)
        {
            var scriptWaypoints = waypoints.Where(x => !x.ScriptIgnore).ToList();

            for (int i = 0; i < scriptWaypoints.Count; i++)
            {
                mission.AppendValue("ScriptObjectives",
                                    $"briefingRoom.mission.objectives[{i + 1}].waypoint = {scriptWaypoints[i].Coordinates.ToLuaTable()}\n");
            }
            if (template.OptionsMission.Contains("MarkWaypoints"))
            {
                foreach (var waypoint in waypoints)
                {
                    DrawingMaker.AddDrawing(waypoint.Name, DrawingType.TextBox, waypoint.Coordinates, "Text".ToKeyValuePair(waypoint.Name));
                }
            }
        }
Esempio n. 20
0
        internal static async Task <DCSCampaign> GenerateAsync(CampaignTemplate campaignTemplate)
        {
            DCSCampaign campaign = new();

            campaign.Name = GeneratorTools.GenerateMissionName(campaignTemplate.BriefingCampaignName);;
            string baseFileName = Toolbox.RemoveInvalidPathCharacters(campaign.Name);

            DateTime date = GenerateCampaignDate(campaignTemplate);

            campaignTemplate.Player.AIWingmen = true; //Make sure wingmen is always true for campaign

            for (int i = 0; i < campaignTemplate.MissionsCount; i++)
            {
                // Increment the date by a few days for each mission after the first
                if (i > 0)
                {
                    date = IncrementDate(date);
                }

                MissionTemplateRecord template = CreateMissionTemplate(campaignTemplate, campaign.Name, i, (int)campaignTemplate.MissionsObjectiveCount);

                DCSMission mission = await MissionGenerator.GenerateAsync(template, true);

                // TODO: mission.DateTime.Day = date.Day; mission.DateTime.Month = date.Month; mission.DateTime.Year = date.Year;
                if (mission == null)
                {
                    BriefingRoom.PrintToLog($"Failed to generate mission {i + 1} in the campaign.", LogMessageErrorLevel.Warning);
                    continue;
                }

                campaign.AddMission(mission);
            }

            if (campaign.MissionCount < 1) // No missions generated, something went very wrong.
            {
                throw new BriefingRoomException($"Campaign has no valid mission.");
            }


            CreateImageFiles(campaignTemplate, campaign, baseFileName);

            campaign.CMPFile = GetCMPFile(campaignTemplate, campaign.Name);

            return(campaign);
        }
Esempio n. 21
0
        internal static Month GenerateMissionDate(DCSMission mission, MissionTemplateRecord template)
        {
            int   day;
            Month month;

            // Select a random year from the most recent coalition's decade.
            var year = Toolbox.GetRandomYearFromDecade(template.ContextDecade);

            BriefingRoom.PrintToLog($"No fixed date provided in the mission template, generating date in decade {template.ContextDecade}");

            if (template.EnvironmentSeason == Season.Random) // Random season, pick any day of the year.
            {
                month = (Month)Toolbox.RandomInt(12);
                day   = Toolbox.RandomMinMax(1, GeneratorTools.GetDaysPerMonth(month, year));
            }
            else // Pick a date according to the desired season
            {
                Month[] seasonMonths = GetMonthsForSeason(template.EnvironmentSeason);

                int monthIndex = Toolbox.RandomInt(4);
                month = seasonMonths[monthIndex];
                switch (monthIndex)
                {
                case 0:     // First month of the season, season begins on the 21st
                    day = Toolbox.RandomMinMax(21, GeneratorTools.GetDaysPerMonth(month, year)); break;

                case 3:     // Last month of the season, season ends on the 20th
                    day = Toolbox.RandomMinMax(1, 20); break;

                default:
                    day = Toolbox.RandomMinMax(1, GeneratorTools.GetDaysPerMonth(month, year)); break;
                }
            }

            mission.SetValue("DateDay", day);
            mission.SetValue("DateMonth", (int)month + 1);
            mission.SetValue("DateYear", year);
            mission.SetValue("BriefingDate", $"{(int)month + 1:00}/{day:00}/{year:0000}");

            BriefingRoom.PrintToLog($"Misson date set to {day} {month} {year}.");
            return(month);
        }
Esempio n. 22
0
        internal UnitMaker(
            DCSMission mission, MissionTemplateRecord template,
            DBEntryCoalition[] coalitionsDB, DBEntryTheater theaterDB, DBEntrySituation situationDB,
            Coalition playerCoalition, Country[][] coalitionsCountries,
            bool singlePlayerMission)
        {
            CallsignGenerator  = new UnitMakerCallsignGenerator(coalitionsDB);
            SpawnPointSelector = new UnitMakerSpawnPointSelector(theaterDB, situationDB, template.OptionsMission.Contains("InvertCountriesCoalitions"));

            Mission  = mission;
            Template = template;

            CoalitionsDB        = coalitionsDB;
            PlayerCoalition     = playerCoalition;
            CoalitionsCountries = coalitionsCountries;
            SinglePlayerMission = singlePlayerMission;

            GroupID = 1;
            UnitID  = 1;
        }
Esempio n. 23
0
        internal static void GenerateMissionTime(DCSMission mission, MissionTemplateRecord template, DBEntryTheater theaterDB, Month month)
        {
            double totalMinutes;
            int    hour, minute;

            switch (template.EnvironmentTimeOfDay)
            {
            default:     // case TimeOfDay.Random
                totalMinutes = Toolbox.RandomInt(Toolbox.MINUTES_PER_DAY);
                break;

            case TimeOfDay.RandomDaytime:
                totalMinutes = Toolbox.RandomInt(theaterDB.DayTime[(int)month].Min, theaterDB.DayTime[(int)month].Max - 60);
                break;

            case TimeOfDay.Dawn:
                totalMinutes = Toolbox.RandomInt(theaterDB.DayTime[(int)month].Min, theaterDB.DayTime[(int)month].Min + 120);
                break;

            case TimeOfDay.Noon:
                totalMinutes = Toolbox.RandomInt(
                    (theaterDB.DayTime[(int)month].Min + theaterDB.DayTime[(int)month].Max) / 2 - 90,
                    (theaterDB.DayTime[(int)month].Min + theaterDB.DayTime[(int)month].Max) / 2 + 90);
                break;

            case TimeOfDay.Twilight:
                totalMinutes = Toolbox.RandomInt(theaterDB.DayTime[(int)month].Max - 120, theaterDB.DayTime[(int)month].Max + 30);
                break;

            case TimeOfDay.Night:
                totalMinutes = Toolbox.RandomInt(0, theaterDB.DayTime[(int)month].Min - 120);
                break;
            }

            hour   = Toolbox.Clamp((int)Math.Floor(totalMinutes / 60), 0, 23);
            minute = Toolbox.Clamp((int)Math.Floor((totalMinutes - hour * 60) / 15) * 15, 0, 45);

            mission.SetValue("BriefingTime", $"{hour:00}:{minute:00}");
            mission.SetValue("StartTime", hour * 3600 + minute * 60); // DCS World time is stored in seconds since midnight
        }
Esempio n. 24
0
        internal static int[] GenerateCAP(UnitMaker unitMaker, MissionTemplateRecord template, Coordinates averageInitialPosition, Coordinates objectivesCenter)
        {
            List <int> capAircraftGroupIDs = new List <int>();
            var        commonCAPDB         = Database.Instance.Common.CAP;

            foreach (Coalition coalition in Toolbox.GetEnumValues <Coalition>())
            {
                if (coalition == Coalition.Neutural) // Skip Neutural
                {
                    continue;
                }

                bool ally = coalition == template.ContextPlayerCoalition;

                Side        side                = ally ? Side.Ally : Side.Enemy;
                AmountNR    capAmount           = ally ? template.SituationFriendlyAirForce.Get() : template.SituationEnemyAirForce.Get();
                Coordinates flyPathtoObjectives = (objectivesCenter - averageInitialPosition).Normalize() * Toolbox.NM_TO_METERS * commonCAPDB.MinDistanceFromOpposingPoint; // TODO: distance according to decade
                Coordinates centerPoint         = objectivesCenter;
                if (ally)
                {
                    centerPoint -= flyPathtoObjectives;
                }
                else
                {
                    centerPoint += flyPathtoObjectives;
                }

                Coordinates opposingPoint = objectivesCenter;

                CreateCAPGroups(
                    unitMaker,
                    template, side, coalition, capAmount,
                    centerPoint, opposingPoint,
                    objectivesCenter,
                    ref capAircraftGroupIDs);
            }

            return(capAircraftGroupIDs.ToArray());
        }
Esempio n. 25
0
        internal static void GenerateMissionBriefingDescription(DCSMission mission, MissionTemplateRecord template, List <UnitFamily> objectiveTargetUnitFamilies, DBEntrySituation situationDB)
        {
            // Try to get the provided custom mission description.
            string briefingDescription = (template.BriefingMissionDescription ?? "").Replace("\r\n", "\n").Replace("\n", " ").Trim();

            // No custom description found, generate one from the most frequent objective task/target combination.
            if (string.IsNullOrEmpty(briefingDescription))
            {
                if (template.Objectives.Count == 0)
                {
                    briefingDescription = "";
                }
                else
                {
                    var familyCount = 0;
                    Dictionary <string, List <string> > descriptionsMap = new Dictionary <string, List <string> >();
                    foreach (var obj in template.Objectives)
                    {
                        DBEntryBriefingDescription descriptionDB =
                            Database.Instance.GetEntry <DBEntryBriefingDescription>(
                                Database.Instance.GetEntry <DBEntryObjectiveTask>(obj.Task).BriefingDescription);
                        AppendDescription(obj.Task, descriptionDB.DescriptionText[(int)objectiveTargetUnitFamilies[familyCount]], ref descriptionsMap);
                        familyCount++;
                        AddSubTasks(obj, objectiveTargetUnitFamilies, ref descriptionsMap, ref familyCount);
                    }

                    briefingDescription = ConstructTaskDescriptions(descriptionsMap, mission);
                }
            }

            if (situationDB.BriefingDescriptions != null && situationDB.BriefingDescriptions.Count > 0)
            {
                briefingDescription = GeneratorTools.ParseRandomString(string.Join(" ", Toolbox.RandomFrom(situationDB.BriefingDescriptions), briefingDescription), mission);
            }

            mission.Briefing.Description = briefingDescription;
            mission.SetValue("BRIEFINGDESCRIPTION", briefingDescription);
        }
Esempio n. 26
0
        internal static void GenerateIngressAndEgressWaypoints(MissionTemplateRecord template, List <Waypoint> waypoints, Coordinates averageInitialLocation, Coordinates objectivesCenter)
        {
            if (!template.MissionFeatures.Contains("IngressEgressWaypoints"))
            {
                return;
            }

            BriefingRoom.PrintToLog($"Generating ingress and egress waypoints...");

            double      flightPathLength    = (objectivesCenter - averageInitialLocation).GetLength();
            double      ingressDeviation    = Math.Max(4.0, flightPathLength * .15);
            Coordinates baseIngressPosition = averageInitialLocation + (objectivesCenter - averageInitialLocation) * .7f;

            waypoints.Insert(0,
                             new Waypoint(
                                 Database.Instance.Common.Names.WPIngressName,
                                 baseIngressPosition + Coordinates.CreateRandom(ingressDeviation * 0.9, ingressDeviation * 1.1)));

            waypoints.Add(
                new Waypoint(
                    Database.Instance.Common.Names.WPEgressName,
                    baseIngressPosition + Coordinates.CreateRandom(ingressDeviation * 0.9, ingressDeviation * 1.1)));
        }
Esempio n. 27
0
        private Coordinates GetSpawnCoordinates(MissionTemplateRecord template, Coordinates lastCoordinates, DBEntryAirbase playerAirbase, DBEntryObjectiveTarget targetDB)
        {
            int objectiveDistance = template.FlightPlanObjectiveDistance;

            if (objectiveDistance < 1)
            {
                objectiveDistance = Toolbox.RandomInt(40, 160);
            }

            int objectiveSeperation = template.FlightPlanObjectiveSeperation;

            if (objectiveSeperation < 1)
            {
                objectiveSeperation = Toolbox.RandomInt(10, 100);
            }

            Coordinates?spawnPoint = UnitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                targetDB.ValidSpawnPoints,
                playerAirbase.Coordinates,
                new MinMaxD(
                    objectiveDistance * OBJECTIVE_DISTANCE_VARIATION_MIN,
                    objectiveDistance * OBJECTIVE_DISTANCE_VARIATION_MAX),
                lastCoordinates,
                new MinMaxD(
                    objectiveSeperation * OBJECTIVE_DISTANCE_VARIATION_MIN,
                    objectiveSeperation * OBJECTIVE_DISTANCE_VARIATION_MAX),
                GeneratorTools.GetSpawnPointCoalition(template, Side.Enemy));

            if (!spawnPoint.HasValue)
            {
                throw new BriefingRoomException($"Failed to spawn objective unit group. {String.Join(",", targetDB.ValidSpawnPoints.Select(x => x.ToString()).ToList())} Please try again (Consider Adusting Flight Plan)");
            }

            Coordinates objectiveCoordinates = spawnPoint.Value;

            return(objectiveCoordinates);
        }
Esempio n. 28
0
 internal MissionGeneratorFeatures(UnitMaker unitMaker, MissionTemplateRecord template)
 {
     _unitMaker = unitMaker;
     _template  = template;
 }
Esempio n. 29
0
        private static void CreateCAPGroups(
            UnitMaker unitMaker, MissionTemplateRecord template, Side side,
            Coalition coalition, AmountNR capAmount, Coordinates centerPoint,
            Coordinates opposingPoint, Coordinates destination, ref List <int> capAircraftGroupIDs)
        {
            var commonCAPDB             = Database.Instance.Common.CAP;
            DBCommonCAPLevel capLevelDB = commonCAPDB.CAPLevels[(int)capAmount];

            int unitsLeftToSpawn = capLevelDB.UnitCount.GetValue();

            if (unitsLeftToSpawn < 1)
            {
                return;                        // No groups to add, no need to go any further
            }
            do
            {
                int groupSize = Toolbox.RandomFrom(commonCAPDB.GroupSize);
                groupSize         = Math.Min(unitsLeftToSpawn, groupSize);
                unitsLeftToSpawn -= groupSize;

                // Find spawn point at the proper distance from the objective(s), but not to close from starting airbase
                Coordinates?spawnPoint =
                    unitMaker.SpawnPointSelector.GetRandomSpawnPoint(
                        new SpawnPointType[] { SpawnPointType.Air },
                        centerPoint,
                        commonCAPDB.DistanceFromCenter,
                        opposingPoint,
                        new MinMaxD(commonCAPDB.MinDistanceFromOpposingPoint, 99999),
                        GeneratorTools.GetSpawnPointCoalition(template, side));

                // No spawn point found, stop here.
                if (!spawnPoint.HasValue)
                {
                    BriefingRoom.PrintToLog($"No spawn point found for {coalition} combat air patrols.", LogMessageErrorLevel.Warning);
                    return;
                }

                Coordinates groupDestination = destination + Coordinates.CreateRandom(10, 20) * Toolbox.NM_TO_METERS;

                var extraSettings = new Dictionary <string, object> {
                    { "Payload", "Air-To-Air" },
                    { "GroupX2", groupDestination.X },
                    { "GroupY2", groupDestination.Y }
                };

                var luaUnit  = commonCAPDB.LuaUnit;
                var luaGroup = commonCAPDB.LuaGroup;
                var spawnpointCoordinates = spawnPoint.Value;
                var unitFamilies          = commonCAPDB.UnitFamilies.ToList();
                if (template.MissionFeatures.Contains("ContextGroundStartAircraft"))
                {
                    luaGroup += "Parked";
                    luaUnit  += "Parked";
                    var(airbase, parkingSpotIDsList, parkingSpotCoordinatesList) = unitMaker.SpawnPointSelector.GetAirbaseAndParking(template, spawnPoint.Value, groupSize, coalition, unitFamilies.First());
                    spawnpointCoordinates = airbase.Coordinates;
                    extraSettings.AddIfKeyUnused("ParkingID", parkingSpotIDsList.ToArray());
                    extraSettings.AddIfKeyUnused("GroupAirbaseID", airbase.DCSID);
                    extraSettings.AddIfKeyUnused("UnitX", (from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.X).ToArray());
                    extraSettings.AddIfKeyUnused("UnitY", (from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.Y).ToArray());
                }


                UnitMakerGroupInfo?groupInfo = unitMaker.AddUnitGroup(
                    unitFamilies, groupSize, side,
                    luaGroup, luaUnit,
                    spawnpointCoordinates,
                    0,
                    extraSettings.ToArray());

                if (!groupInfo.HasValue) // Failed to generate a group
                {
                    BriefingRoom.PrintToLog($"Failed to find units for {coalition} air defense unit group.", LogMessageErrorLevel.Warning);
                }

                capAircraftGroupIDs.Add(groupInfo.Value.GroupID);
            } while (unitsLeftToSpawn > 0);
        }
Esempio n. 30
0
 internal MissionGeneratorFeaturesObjectives(UnitMaker unitMaker, MissionTemplateRecord template) : base(unitMaker, template)
 {
 }