Beispiel #1
0
        internal DBCommonCAPLevel(INIFile ini, AmountNR capLevel)
        {
            if ((capLevel == AmountNR.None) || (capLevel == AmountNR.Random))
            {
                SkillLevel = new DCSSkillLevel[] { DCSSkillLevel.Average };
                UnitCount  = new MinMaxI(0, 0);
                return;
            }

            SkillLevel = ini.GetValueArray <DCSSkillLevel>("CAPLevels", $"{capLevel}.SkillLevel").Distinct().ToArray();
            if (SkillLevel.Length == 0)
            {
                SkillLevel = new DCSSkillLevel[] { DCSSkillLevel.Average, DCSSkillLevel.Good, DCSSkillLevel.High, DCSSkillLevel.Excellent }
            }
            ;
            UnitCount = ini.GetValue <MinMaxI>("CAPLevels", $"{capLevel}.UnitCount");
        }
    }
Beispiel #2
0
        private string MakeUnitsUnitsLua(DCSMissionUnitGroup group, bool singlePlayer)
        {
            string unitsLua = "";

            for (int i = 0; i < group.UnitCount; i++)
            {
                string singleUnitLua = HQTools.ReadIncludeLuaFile($"Mission\\{group.LuaUnit}.lua");

                DCSSkillLevel skillLevel = group.UnitsSkill;
                if (group.Flags.Contains(UnitGroupFlag.FirstUnitIsClient) && (i == 0))
                {
                    skillLevel = DCSSkillLevel.Client;
                }

                HQTools.ReplaceKey(ref singleUnitLua, "Name", group.Name); // Must be replaced before "Index" because some unit names contain "$INDEX$"
                HQTools.ReplaceKey(ref singleUnitLua, "UnitID", UnitID);
                HQTools.ReplaceKey(ref singleUnitLua, "Unit", group.Units[i]);
                HQTools.ReplaceKey(ref singleUnitLua, "Heading", group.GetUnitHeading(i));
                HQTools.ReplaceKey(ref singleUnitLua, "Skill", skillLevel.ToString());
                HQTools.ReplaceKey(ref singleUnitLua, "X", group.GetUnitCoordinates(i).X);
                HQTools.ReplaceKey(ref singleUnitLua, "Y", group.GetUnitCoordinates(i).Y);
                foreach (DCSMissionUnitGroupCustomValueKey k in group.CustomValues.Keys)
                {
                    if (k.UnitIndex != i)
                    {
                        continue;                   // Replacement does not target this unit, continue
                    }
                    HQTools.ReplaceKey(ref singleUnitLua, k.Key, group.CustomValues[k]);
                }

                HQTools.ReplaceKey(ref singleUnitLua, "Index", i + 1); // Must be last, used by other values

                unitsLua += singleUnitLua + "\r\n";
                UnitID++;
            }

            return(unitsLua);
        }
Beispiel #3
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";
                    }
                }
            }
        }
Beispiel #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);
        }
Beispiel #5
0
        internal static void GeneratePlayerFlightGroup(
            UnitMaker unitMaker,
            DCSMission mission,
            MissionTemplateRecord template,
            MissionTemplateFlightGroupRecord flightGroup,
            DBEntryAirbase playerAirbase,
            List <Waypoint> waypoints,
            Dictionary <string, UnitMakerGroupInfo> carrierDictionary,
            Coordinates averageInitialLocation,
            Coordinates objectivesCenter)
        {
            DBEntryAirbase  airbase             = playerAirbase;
            List <Waypoint> flightWaypoints     = new List <Waypoint>(waypoints);
            Coordinates     groupStartingCoords = playerAirbase.Coordinates;

            var package = template.AircraftPackages.FirstOrDefault(x => x.FlightGroupIndexes.Contains(template.PlayerFlightGroups.IndexOf(flightGroup)));

            if (package is not null)
            {
                var missionPackage = mission.MissionPackages.First(x => x.RecordIndex == template.AircraftPackages.IndexOf(package));
                flightWaypoints     = missionPackage.Waypoints;
                airbase             = missionPackage.Airbase;
                groupStartingCoords = missionPackage.Airbase.Coordinates;
            }
            DBEntryUnit unitDB = Database.Instance.GetEntry <DBEntryUnit>(flightGroup.Aircraft);

            // Not an unit, or not a player-controllable unit, abort.
            if ((unitDB == null) || !unitDB.AircraftData.PlayerControllable)
            {
                throw new BriefingRoomException($"Player flight group unit {flightGroup.Aircraft} does not exist or is not player-controllable.");
            }
            if (unitDB.AircraftData.MinimumRunwayLengthFt > 0 && airbase.RunwayLengthFt < unitDB.AircraftData.MinimumRunwayLengthFt)
            {
                BriefingRoom.PrintToLog($"Runway at {airbase.Name}({airbase.RunwayLengthFt}ft) is shorter than {unitDB.UIDisplayName}({unitDB.AircraftData.MinimumRunwayLengthFt}ft) required runway length.", LogMessageErrorLevel.Warning);
            }

            List <int>         parkingSpotIDsList         = new List <int>();
            List <Coordinates> parkingSpotCoordinatesList = new List <Coordinates>();
            var    groupLuaFile  = "GroupAircraftPlayer";
            var    carrierUnitID = 0;
            string carrierName   = null;
            var    side          = flightGroup.Hostile ? Side.Enemy : Side.Ally;
            var    country       = flightGroup.Country;
            var    payload       = flightGroup.Payload;
            var    extraSettings = new Dictionary <string, object>();
            UnitMakerGroupFlags unitMakerGroupFlags = flightGroup.AIWingmen ? UnitMakerGroupFlags.FirstUnitIsClient : 0;
            DCSSkillLevel       skillLevel          = flightGroup.AIWingmen ? Toolbox.RandomFrom(DCSSkillLevel.High, DCSSkillLevel.Excellent) : DCSSkillLevel.Client;

            if (!string.IsNullOrEmpty(flightGroup.Carrier) && carrierDictionary.ContainsKey(flightGroup.Carrier) && !flightGroup.Hostile) // Carrier take off
            {
                var carrier = carrierDictionary[flightGroup.Carrier];
                if (carrier.UnitDB.Families.Contains(UnitFamily.ShipCarrierSTOVL) && flightGroup.Carrier != "LHA_Tarawa")
                {
                    extraSettings.AddIfKeyUnused("Speed", 0);
                    unitMakerGroupFlags = 0;
                    skillLevel          = DCSSkillLevel.Client;
                    if (flightGroup.Aircraft == "AV8BNA")
                    {
                        payload = "EMPTY";
                    }
                }
                groupLuaFile  = "GroupAircraftPlayerCarrier";
                carrierUnitID = carrier.UnitsID[0];
                carrierName   = carrier.UnitDB.UIDisplayName;

                for (int i = 0; i < flightGroup.Count; i++)
                {
                    parkingSpotIDsList.Add(i + 1);
                    parkingSpotCoordinatesList.Add(carrier.Coordinates);
                }
                groupStartingCoords = carrier.Coordinates;
            }
            else if (flightGroup.Hostile)
            {
                var coalition = GeneratorTools.GetSpawnPointCoalition(template, side, true);
                var(hostileAirbase, hostileParkingSpotIDsList, hostileParkingSpotCoordinatesList) = unitMaker.SpawnPointSelector.GetAirbaseAndParking(template, objectivesCenter, flightGroup.Count, coalition.Value, unitDB.Families.First());
                parkingSpotIDsList         = hostileParkingSpotIDsList;
                parkingSpotCoordinatesList = hostileParkingSpotCoordinatesList;
                groupStartingCoords        = hostileParkingSpotCoordinatesList.First();
                airbase = hostileAirbase;

                if (country == Country.CJTFBlue || country == Country.CJTFRed)
                {
                    country = coalition == Coalition.Blue ? Country.CJTFBlue : Country.CJTFRed;
                }
            }
            else // Land airbase take off
            {
                var parkingSpots = unitMaker.SpawnPointSelector.GetFreeParkingSpots(airbase.DCSID, flightGroup.Count, unitDB.Families[0]);
                parkingSpotIDsList         = parkingSpots.Select(x => x.DCSID).ToList();
                parkingSpotCoordinatesList = parkingSpots.Select(x => x.Coordinates).ToList();
                groupStartingCoords        = parkingSpotCoordinatesList.First();
            }



            extraSettings.AddIfKeyUnused("Payload", payload);
            extraSettings.AddIfKeyUnused("Skill", skillLevel);
            extraSettings.AddIfKeyUnused("PlayerStartingAction", GeneratorTools.GetPlayerStartingAction(flightGroup.StartLocation));
            extraSettings.AddIfKeyUnused("PlayerStartingType", GeneratorTools.GetPlayerStartingType(flightGroup.StartLocation));
            extraSettings.AddIfKeyUnused("Country", country);
            extraSettings.AddIfKeyUnused("InitialWPName", Database.Instance.Common.Names.WPInitialName);
            extraSettings.AddIfKeyUnused("FinalWPName", Database.Instance.Common.Names.WPFinalName);
            extraSettings.AddIfKeyUnused("ParkingID", parkingSpotIDsList.ToArray());
            extraSettings.AddIfKeyUnused("PlayerWaypoints", GenerateFlightPlanLua(flightWaypoints));
            extraSettings.AddIfKeyUnused("LastPlayerWaypointIndex", flightWaypoints.Count + 2);
            extraSettings.AddIfKeyUnused("LinkUnit", carrierUnitID);
            extraSettings.AddIfKeyUnused("UnitX", (from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.X).ToArray());
            extraSettings.AddIfKeyUnused("UnitY", (from Coordinates coordinates in parkingSpotCoordinatesList select coordinates.Y).ToArray());
            extraSettings.AddIfKeyUnused("MissionAirbaseX", groupStartingCoords.X);
            extraSettings.AddIfKeyUnused("MissionAirbaseY", groupStartingCoords.Y);
            extraSettings.AddIfKeyUnused("MissionAirbaseID", airbase.DCSID);
            extraSettings.AddIfKeyUnused("Livery", flightGroup.Livery);

            UnitMakerGroupInfo?groupInfo = unitMaker.AddUnitGroup(
                Enumerable.Repeat(flightGroup.Aircraft, flightGroup.Count).ToArray(), side, unitDB.Families[0],
                groupLuaFile, "UnitAircraftParked", groupStartingCoords,
                unitMakerGroupFlags,
                extraSettings.ToArray()
                );

            if (!groupInfo.HasValue)
            {
                BriefingRoom.PrintToLog("Failed to generate player flight group.", LogMessageErrorLevel.Warning);
                return;
            }

            SaveFlightGroup(mission, groupInfo, flightGroup, unitDB, carrierName ?? airbase.Name);
            SaveWaypointsToBriefing(
                mission,
                groupStartingCoords,
                flightWaypoints,
                template.OptionsMission.Contains("ImperialUnitsForBriefing"),
                groupInfo);
        }