/// <summary> /// Generate a random mission name if none is provided in the template, or returns the provided name if there is one. /// </summary> /// <param name="mission">The mission.</param> /// <param name="template">The provided mission name in the template.</param> public void GenerateMissionName(DCSMission mission, string templateMissionName) { DebugLog.Instance.Log("Generating mission name..."); if (templateMissionName == null) { templateMissionName = ""; } // If a custom mission name was provided, use it... if (!string.IsNullOrEmpty(templateMissionName.Trim())) { mission.BriefingName = templateMissionName.Trim(); return; } // ...else generate a random name. // First get a random template then replace parts 1 to MAX_MISSION_NAME_PARTS ($PART1$, $PART2$, $PART3$...) by random parts. string name = HQTools.RandomFrom(Language.GetStringArray("Mission", "Name.Template")); for (int i = 1; i <= MAX_MISSION_NAME_PARTS; i++) { name = name.Replace( $"$P{i.ToString()}$", HQTools.RandomFrom(Language.GetStringArray("Mission", $"Name.Part{i.ToString()}"))); } mission.BriefingName = name; DebugLog.Instance.Log(""); }
public DCSMissionUnitGroup( string luaGroup, string luaUnit, UnitCategory category, int groupID, Coalition coalition, Coordinates coordinates, params string[] units) { LuaGroup = luaGroup; LuaUnit = luaUnit; Category = category; Coalition = coalition; GroupID = groupID; Units = units.ToList(); Name = $"Group #{HQTools.ValToString(GroupID)}"; Coordinates = coordinates; if (units.Length == 0) { DebugLog.Instance.Log($" WARNING: Tried to create an empty unit group at {Coordinates.ToString("F0")}."); } else { DebugLog.Instance.Log($" Added a group of {units.Length} unit(s) ({string.Join(", ", Units)}) with ID #{GroupID} at {Coordinates.ToString("F0")}."); } CheckAbsolueMaxUnitCount(); }
/// <summary> /// Generates wind settings for the mission. Must be called once mission weather level has been set, as weather is used for auto wind. /// </summary> /// <param name="mission">The mission.</param> /// <param name="wind">The preferred wind speed.</param> /// <param name="theater">Theater definition from which to get wind info for this part of the world.</param> public void GenerateWind(DCSMission mission, Wind wind, DefinitionTheater theater) { DebugLog.Instance.Log("Generating wind..."); DebugLog.Instance.Log($" Wind speed should be {wind.ToString().ToUpperInvariant()}"); // If auto, speed depends on weather, so we never end up with no wind in a storm mission.WindLevel = (wind == Wind.Auto) ? (Wind)(HQTools.Clamp((int)mission.WeatherLevel + HQTools.RandomMinMax(-1, 1), 0, (int)Wind.StrongGale)) : wind; DebugLog.Instance.Log($" Wind speed level set to {mission.WindLevel}"); for (int i = 0; i < 3; i++) { mission.WeatherWindSpeed[i] = Math.Max(0, theater.Wind[(int)mission.WindLevel].Wind.GetValue()); mission.WeatherWindDirection[i] = (mission.WeatherWindSpeed[i] > 0) ? HQTools.RandomInt(0, 360) : 0; DebugLog.Instance.Log($" Wind speed at {WIND_ALTITUDE[i]} meters set to {mission.WeatherWindSpeed[i]} m/s, direction of {mission.WeatherWindDirection[i]}"); } // Turbulence = max(weatherTurbulence, windTurbulence) mission.WeatherTurbulence = Math.Max(mission.WeatherTurbulence, theater.Wind[(int)mission.WindLevel].Turbulence.GetValue()); DebugLog.Instance.Log($" Turbulence updated to {mission.WeatherTurbulence} m/s"); DebugLog.Instance.Log(); }
/// <summary> /// Constructor. /// </summary> /// <param name="coordinates">X,Y coordinates of the objective (NOT the waypoint for this objective).</param> /// <param name="name">Name of this objective.</param> /// <param name="altitude">Altitude multiplier for this objective.</param> /// <param name="airdromeID">ID of the airdrome linked to this objective, if any.</param> public DCSMissionObjectiveLocation(Coordinates coordinates, string name = "", double altitude = 1f, int airdromeID = 0) { Coordinates = coordinates; Name = name.ToUpperInvariant(); Altitude = HQTools.Clamp(altitude, 0f, 2f); AirdromeID = airdromeID; }
/// <summary> /// Returns an unique callsign in the NATO format (Callsign Number Number) /// </summary> /// <param name="csFamily">The type of aircraft (AWACS, tanker, fighter...)</param> /// <returns>The callsign</returns> private MGCallsign GetNATOCallsign(CallsignFamily csFamily) { int callsignIndex; do { callsignIndex = HQTools.RandomInt(NATO_CALLSIGN_NAMES[(int)csFamily].Length); } while (NATOCallsigns[(int)csFamily][callsignIndex] >= 9); NATOCallsigns[(int)csFamily][callsignIndex]++; string groupName = NATO_CALLSIGN_NAMES[(int)csFamily][callsignIndex] + " " + HQTools.ValToString(NATOCallsigns[(int)csFamily][callsignIndex]); string unitName = groupName + " $INDEX$"; //string onboardNum = HQTools.ValToString((callsignIndex % 9) + 1) + // NATOCallsigns[(int)csFamily][callsignIndex] + "$INDEX$"; string lua = $"{{ [1]= {HQTools.ValToString(callsignIndex + 1)}, " + $"[2]={HQTools.ValToString(NATOCallsigns[(int)csFamily][callsignIndex])}, " + "[3]=$INDEX$, " + $"[\"name\"] = \"{unitName.Replace(" ", "")}\", }}"; return(new MGCallsign(groupName, unitName /*, onboardNum*/, lua)); }
// Adds "embedded" air defense to ground vehicle groups public void AddAirDefenseUnits(DefinitionCoalition army, TimePeriod timePeriod, LibraryCommonSettingsEnemyAirDefense airDefenseSettings) { if (Category != UnitCategory.Vehicle) { return; } List <string> unitList = new List <string>(Units); if (HQTools.RandomDouble() < airDefenseSettings.EmbeddedChance) { int airDefCount = airDefenseSettings.EmbeddedCount.GetValue(); for (int i = 0; i < airDefCount; i++) { string airDefUnit = HQTools.RandomFrom( army.GetUnits(timePeriod, HQTools.RandomFrom(airDefenseSettings.EmbeddedFamilies), true, false)); if (airDefUnit == null) { continue; } unitList.Add(airDefUnit); } } // Randomize list order so air defense units are not always at the end Units = unitList.OrderBy(x => HQTools.RandomInt()).ToList(); CheckAbsolueMaxUnitCount(); }
/// <summary> /// Converts /// </summary> /// <returns>A string to display in the PropertyGrid.</returns> public override string ToString() { string acName = Library.Instance.DefinitionExists <DefinitionUnit>(AircraftType) ? Library.Instance.GetDefinition <DefinitionUnit>(AircraftType).DisplayName : AircraftType; return($"{HQTools.ValToString(Count)}x {acName}, {GUITools.SplitEnumCamelCase(Task)} " + $"({GUITools.SplitEnumCamelCase(StartLocation).ToLowerInvariant()}{(WingmenAI ? ", AI wingmen" : "")})"); }
private string CreatePlayerWaypointsLua(DCSMissionWaypoint[] waypoints) { // FIXME: first and last WP // FIXME: EPLRS on first WP? string flightPlanLua = ""; //string baseWPLuaFirst = HQTools.ReadIncludeLuaFile("Mission\\WaypointPlayerTakeoff.lua"); //string baseWPLuaLast = HQTools.ReadIncludeLuaFile("Mission\\WaypointPlayerLanding.lua"); string baseWPLua = HQTools.ReadIncludeLuaFile("Mission\\WaypointPlayer.lua"); for (int i = 0; i < waypoints.Length; i++) { string wpLua = baseWPLua; //if (i == 0) continue; // First waypoint is included in GroupAircraftPlayer.lua //// FIXME: Remove - wpLua = baseWPLuaFirst; //else if (i == waypoints.Length - 1) wpLua = baseWPLuaLast; //else wpLua = baseWPLua; HQTools.ReplaceKey(ref wpLua, "Action", waypoints[i].WPAction); HQTools.ReplaceKey(ref wpLua, "Altitude", waypoints[i].AltitudeMultiplier); HQTools.ReplaceKey(ref wpLua, "AltitudeType", (waypoints[i].AltitudeMultiplier > 0) ? "BARO" : "RADIO"); HQTools.ReplaceKey(ref wpLua, "AirdromeID", waypoints[i].AirdromeID); HQTools.ReplaceKey(ref wpLua, "Name", waypoints[i].Name); HQTools.ReplaceKey(ref wpLua, "Speed", waypoints[i].SpeedMultiplier); HQTools.ReplaceKey(ref wpLua, "Type", waypoints[i].WPType); HQTools.ReplaceKey(ref wpLua, "X", waypoints[i].Coordinates.X); HQTools.ReplaceKey(ref wpLua, "Y", waypoints[i].Coordinates.Y); HQTools.ReplaceKey(ref wpLua, "Index", i + 2); // Must be last, used by other values flightPlanLua += wpLua + "\n"; } return(flightPlanLua); }
/// <summary> /// Constructor. Loads data from a .ini file. /// </summary> /// <param name="ini">The .ini file to load from.</param> /// <param name="section">The .ini section to load from.</param> /// <param name="key">The top level .ini key to load from.</param> public LibraryCommonSettingsEnemyAirDefense(INIFile ini, string section, string key) { EmbeddedChance = HQTools.Clamp(ini.GetValue <int>(section, $"{key}.Embedded.Chance") / 100.0, 0.0, 1.0); EmbeddedCount = ini.GetValue <MinMaxI>(section, $"{key}.Embedded.Count"); EmbeddedFamilies = ini.GetValueArray <UnitFamily>(section, $"{key}.Embedded.Families"); EmbeddedFamilies = (from f in EmbeddedFamilies where VALID_EMBEDDED_FAMILIES.Contains(f) select f).ToArray(); if (EmbeddedFamilies.Length == 0) { EmbeddedFamilies = new UnitFamily[] { UnitFamily.VehicleAAA } } ; InAreaGroupCount = new MinMaxI[AIR_DEFENSE_RANGE_COUNT]; InAreaGroupSize = new MinMaxI[AIR_DEFENSE_RANGE_COUNT]; InAreaFamilies = new UnitFamily[AIR_DEFENSE_RANGE_COUNT][]; for (int i = 0; i < AIR_DEFENSE_RANGE_COUNT; i++) { string subKey = $"{key}.InArea.{((AirDefenseRange)i).ToString()}"; InAreaGroupCount[i] = ini.GetValue <MinMaxI>(section, $"{subKey}.GroupCount"); InAreaGroupSize[i] = ini.GetValue <MinMaxI>(section, $"{subKey}.GroupSize"); InAreaFamilies[i] = ini.GetValueArray <UnitFamily>(section, $"{subKey}.Families"); InAreaFamilies[i] = (from f in InAreaFamilies[i] where VALID_INAREA_FAMILIES.Contains(f) select f).ToArray(); if (InAreaFamilies[i].Length == 0) { InAreaFamilies[i] = new UnitFamily[] { UnitFamily.VehicleAAA } } ; } } } }
/// <summary> /// Generates the title image for the mission. /// </summary> /// <param name="missionName">The name of the mission.</param> /// <returns>The mission title image, as an array of bytes for a JPEG file.</returns> private byte[] GetTitleImage(string missionName) { byte[] imageBytes; Rectangle rect; int x, y; using (Image titleImage = GetImageIfItExists("Jpg\\Title.jpg")) { using (Graphics g = Graphics.FromImage(titleImage)) { using (Font font = new Font("Arial", 48, FontStyle.Regular, GraphicsUnit.Point)) { for (x = -1; x <= 1; x++) { for (y = -1; y <= 1; y++) { if ((x == 0) && (y == 0)) { continue; } rect = new Rectangle(x * 1, y * 1, 512, 512); TextRenderer.DrawText(g, missionName, font, rect, Color.Black, HQTools.CENTER_TEXT_FLAGS); } } rect = new Rectangle(0, 0, 512, 512); TextRenderer.DrawText(g, missionName, font, rect, Color.White, HQTools.CENTER_TEXT_FLAGS); } } imageBytes = HQTools.ImageToBytes(titleImage, ImageFormat.Jpeg); } return(imageBytes); }
/// <summary> /// Adds an entry to the .miz file. /// </summary> /// <param name="entryPath">The path to the entry in the .miz file.</param> /// <param name="text">The (UTF-8) text of the entry.</param> /// <returns>True if everything went well, false if an error happened.</returns> private bool AddMIZEntry(string entryPath, string text) { DebugLog.Instance.Log($"Adding text file {entryPath} to the .miz file"); if (string.IsNullOrEmpty(text)) { text = ""; } else { text = text.Replace("\r\n", "\n"); // Convert CRLF end of lines to LF, CRLF can cause problems } #if DEBUG // In debug builds, write all text entries to the DebugOutput path for easier debugging/comparisons string debugDumpFileName = entryPath.Replace('\\', '/').Replace('/', '_'); if (Path.GetExtension(entryPath).Length == 0) { debugDumpFileName += ".lua"; } HQTools.CreateDirectoryIfMissing(HQTools.PATH_DEBUG); File.WriteAllText(HQTools.PATH_DEBUG + debugDumpFileName, text); #endif return(AddMIZEntry(entryPath, Encoding.UTF8.GetBytes(text))); }
/// <summary> /// Constructor. /// </summary> /// <param name="aircraftType">ID of the aircraft type.</param> /// <param name="count">Number of aircraft in the flight group.</param> /// <param name="task">Task assigned to the flight group.</param> /// <param name="aiWingmen">If true, all aircraft but the first will be AI-controlled. If false, all aircraft will be client-controlled.</param> /// <param name="startLocation">Where should the flight group start from?</param> public MissionTemplatePlayerFlightGroup(string aircraftType, int count, PlayerFlightGroupTask task, bool aiWingmen, PlayerFlightGroupStartLocation startLocation) { AircraftType = aircraftType; Count = HQTools.Clamp(count, 1, MAX_AIRCRAFT_COUNT); Task = task; WingmenAI = aiWingmen; StartLocation = startLocation; }
/// <summary> /// Read values from the mission and make replacements in the Lua file /// </summary> /// <param name="lua">Lua string</param> /// <param name="mission">HQ4DCS mission to use</param> private void MakeCommonReplacements(ref string lua, DCSMission mission) { HQTools.ReplaceKey(ref lua, "UnitNames", CreateUnitNamesTable(mission.UseNATOCallsigns)); HQTools.ReplaceKey(ref lua, "ObjectiveNames", CreateObjectiveNamesTable(mission)); HQTools.ReplaceKey(ref lua, "PlayerCoalition", mission.CoalitionPlayer.ToString().ToUpperInvariant()); HQTools.ReplaceKey(ref lua, "EnemyCoalition", mission.CoalitionEnemy.ToString().ToUpperInvariant()); HQTools.ReplaceKey(ref lua, "ObjectiveCount", mission.Objectives.Length); }
/// <summary> /// Loads data required by this definition. /// </summary> /// <param name="ini">INI file to load definition from.</param> /// <returns>True is successful, false if an error happened.</returns> protected override bool OnLoad(INIFile ini) { int i; // [Theater] section DCSID = ini.GetValue <string>("Theater", "DCSID"); DefaultMapCenter = ini.GetValue <Coordinates>("Theater", "DefaultMapCenter"); RequiredModules = ini.GetValueArray <string>("Theater", "RequiredModules"); MagneticDeclination = ini.GetValue <float>("Theater", "MagneticDeclination"); // [Daytime] section DayTime = new MinMaxI[12]; for (i = 0; i < 12; i++) { DayTime[i] = ini.GetValue <MinMaxI>("Daytime", ((Month)i).ToString()); } // [Temperature] section Temperature = new MinMaxI[12]; for (i = 0; i < 12; i++) { Temperature[i] = ini.GetValue <MinMaxI>("Temperature", ((Month)i).ToString()); } // [Weather] section Weather = new DefinitionTheaterWeather[HQTools.EnumCount <Weather>() - 1]; // -1 because we don't want "Random" for (i = 0; i < Weather.Length; i++) { Weather[i] = new DefinitionTheaterWeather(ini, ((Weather)i).ToString()); } // [Wind] section Wind = new DefinitionTheaterWind[HQTools.EnumCount <Wind>() - 1]; // -1 because we don't want "Auto" for (i = 0; i < Wind.Length; i++) { Wind[i] = new DefinitionTheaterWind(ini, ((Wind)i).ToString()); } // [Airbases] section Airbases = new DefinitionTheaterAirbase[ini.GetTopLevelKeysInSection("Airbases").Length]; i = 0; foreach (string k in ini.GetTopLevelKeysInSection("Airbases")) { Airbases[i] = new DefinitionTheaterAirbase(ini, k); i++; } // [SpawnPoints] section SpawnPoints = new DefinitionTheaterSpawnPoint[ini.GetKeysInSection("SpawnPoints").Length]; i = 0; foreach (string k in ini.GetKeysInSection("SpawnPoints")) { SpawnPoints[i] = new DefinitionTheaterSpawnPoint(ini, k); i++; } ResetUsedSpawnPoints(); return(true); }
private string MakeUnitsLua(DCSMission missHQ, Coalition coalition) { string allUnitsLua = HQTools.ReadIncludeLuaFile("Mission\\CoalitionUnits.lua"); foreach (UnitCategory uc in Enum.GetValues(typeof(UnitCategory))) { HQTools.ReplaceKey(ref allUnitsLua, uc.ToString(), MakeUnitsCategoryLua(missHQ, coalition, uc)); } return(allUnitsLua); }
/// <summary> /// Generate the script common to all missions at the beginning of the Lua code. /// </summary> /// <param name="lua">Mission Lua script.</param> /// <param name="mission">HQ4DCS mission</param> private void GenerateCommonScript(ref string lua, DCSMission mission) { string scriptLua = ""; scriptLua += $"hq.objectiveCount = {mission.Objectives.Length}\n"; scriptLua += $"hq.objectiveLeft = {mission.Objectives.Length}\n"; scriptLua += $"hq.objectiveNames = {{ \"{string.Join("\", \"", (from DCSMissionObjectiveLocation o in mission.Objectives select o.Name.ToUpperInvariant()))}\" }}\n"; scriptLua += $"hq.objectiveStatus = {{ {string.Join(", ", Enumerable.Repeat("false", mission.Objectives.Length))} }}\n"; HQTools.ReplaceKey(ref lua, "ScriptCommon", scriptLua); }
private string FormatTime(DCSMission mission, bool longFormat) { string formattedString = Language.GetString("Briefing", longFormat ? "Format.Time.Long" : "Format.Time.Short"); formattedString = formattedString .Replace("$H$", HQTools.ValToString(mission.TimeHour, "0")) .Replace("$HH$", HQTools.ValToString(mission.TimeHour, "00")) .Replace("$M$", HQTools.ValToString(mission.TimeMinute, "0")) .Replace("$MM$", HQTools.ValToString(mission.TimeMinute, "00")); return(formattedString); }
/// <summary> /// Generates weather settings (precipitation, cloud coverage, temperature...) for the mission. /// Must be called after mission date has been set because min/max temperature changes every month. /// </summary> /// <param name="mission">The mission.</param> /// <param name="weather">The preferred type of weather (clear, cloudy, storm...).</param> /// <param name="theater">Theater definition from which to get weather info for this part of the world.</param> public void GenerateWeather(DCSMission mission, Weather weather, DefinitionTheater theater) { DebugLog.Instance.Log("Generating weather conditions..."); mission.WeatherTemperature = theater.Temperature[(int)mission.DateMonth].GetValue(); DebugLog.Instance.Log($" Weather should be {weather.ToString().ToUpperInvariant()}"); mission.WeatherLevel = (weather == Weather.Random) ? HQTools.RandomFrom(RANDOM_WEATHER) : weather; DebugLog.Instance.Log($" Weather quality set to {mission.WeatherLevel}"); // Clouds and precipitations mission.WeatherCloudBase = theater.Weather[(int)mission.WeatherLevel].CloudsBase.GetValue(); mission.WeatherCloudsDensity = theater.Weather[(int)mission.WeatherLevel].CloudsDensity.GetValue(); mission.WeatherCloudsPrecipitation = HQTools.RandomFrom(theater.Weather[(int)mission.WeatherLevel].CloudsPrecipitation); mission.WeatherCloudsThickness = theater.Weather[(int)mission.WeatherLevel].CloudsThickness.GetValue(); // Dust mission.WeatherDustEnabled = HQTools.RandomFrom(theater.Weather[(int)mission.WeatherLevel].DustEnabled); mission.WeatherDustDensity = mission.WeatherDustEnabled ? theater.Weather[(int)mission.WeatherLevel].DustDensity.GetValue() : 0; // Fog mission.WeatherFogEnabled = HQTools.RandomFrom(theater.Weather[(int)mission.WeatherLevel].FogEnabled); mission.WeatherFogThickness = mission.WeatherFogEnabled ? theater.Weather[(int)mission.WeatherLevel].FogThickness.GetValue() : 0; mission.WeatherFogVisibility = mission.WeatherFogEnabled ? theater.Weather[(int)mission.WeatherLevel].FogVisibility.GetValue() : 0; // Pressure, turbulence and visiblity mission.WeatherQNH = theater.Weather[(int)mission.WeatherLevel].QNH.GetValue(); mission.WeatherTurbulence = theater.Weather[(int)mission.WeatherLevel].Turbulence.GetValue(); mission.WeatherVisibility = theater.Weather[(int)mission.WeatherLevel].Visibility.GetValue(); DebugLog.Instance.Log($" Cloud base altitude set to {mission.WeatherCloudBase} m"); DebugLog.Instance.Log($" Cloud density set to {mission.WeatherCloudBase}"); DebugLog.Instance.Log($" Precipitation set to {mission.WeatherCloudsPrecipitation}"); DebugLog.Instance.Log($" Cloud thickness set to {mission.WeatherCloudsThickness} m"); DebugLog.Instance.Log($" Dust set to {mission.WeatherDustEnabled}"); DebugLog.Instance.Log($" Dust density set to {mission.WeatherDustDensity}"); DebugLog.Instance.Log($" Fog set to {mission.WeatherFogEnabled}"); DebugLog.Instance.Log($" Fog thickness set to {mission.WeatherFogThickness}"); DebugLog.Instance.Log($" Fog visibility set to {mission.WeatherFogVisibility} m"); DebugLog.Instance.Log($" QNH set to {mission.WeatherQNH}"); DebugLog.Instance.Log($" Turbulence set to {mission.WeatherTurbulence} m/s"); DebugLog.Instance.Log($" Visibility set to {mission.WeatherVisibility} m"); DebugLog.Instance.Log(); }
/// <summary> /// Generates the content of the Lua file. /// </summary> /// <param name="mission">An HQ4DCS mission.</param> /// <returns>The contents of the Lua file.</returns> public string MakeLua(DCSMission mission) { string lua = HQTools.ReadIncludeLuaFile("Script.lua"); GenerateCommonScript(ref lua, mission); CopyMissionLuaScripts(ref lua, mission); #if DEBUG // Add the debug script to scripts generated with the debug build. lua += HQTools.ReadIncludeLuaFile("Script\\DebugMenu.lua") + "\n\n"; #endif MakeCommonReplacements(ref lua, mission); DoLocalizationReplacements(ref lua); return(lua); }
public static string GetDCSTaskAdditionalTasksString(DCSFlightGroupTask dcsTask, int firstTaskIndex = 1) { string taskInfo = ""; switch (dcsTask) { case DCSFlightGroupTask.CAS: taskInfo = "[$1$] = { [\"enabled\"] = true, [\"key\"] = \"CAS\", [\"id\"] = \"EngageTargets\", [\"number\"] = $1$, " + "[\"auto\"] = true, [\"params\"] = { [\"targetTypes\"] = { [1] = \"Helicopters\", [2] = \"Ground Units\", [3] = \"Light armed ships\", }, [\"priority\"] = 0, }, },"; break; } taskInfo = taskInfo.Replace("$1$", HQTools.ValToString(firstTaskIndex)); return(taskInfo); }
/// <summary> /// Generates the content of the Lua file. /// </summary> /// <param name="missHQ">An HQ4DCS mission.</param> /// <returns>The contents of the Lua file.</returns> public string MakeLua(DCSMission missHQ) { string lua = HQTools.ReadIncludeLuaFile("MapResource.lua"); string resourcesLua = ""; // Write the names of all included Ogg files into the resources table. foreach (string f in missHQ.OggFiles) { resourcesLua += $"[\"ResKey_Snd_{f.ToLowerInvariant()}\"] = \"{f.ToLowerInvariant()}.ogg\",\n"; } HQTools.ReplaceKey(ref lua, "Resources", resourcesLua); return(lua); }
/// <summary> /// Constructor. /// </summary> /// <param name="coordinates">X,Y coordinates of the waypoint.</param> /// <param name="name">Name of the waypoint.</param> /// <param name="altitudeMultiplier">Altitude multiplier (1.0 = default altitude for aircraft, 0.0 = ground)</param> /// <param name="speedMultiplier">Speed multiplier (1.0 = default speed for aircraft, 0.0 = no speed)</param> /// <param name="wpAction">Waypoint action (as written in Mission.lua file)</param> /// <param name="wpType">Waypoint action type (as written in Mission.lua file)</param> /// <param name="airdromeID">ID of the airdrome to use for this waypoint, if any.</param> public DCSMissionWaypoint( Coordinates coordinates, string name = "WP$INDEX$", double altitudeMultiplier = 1.0, double speedMultiplier = 1.0, string wpAction = DEFAULT_WP_ACTION, string wpType = DEFAULT_WP_ACTION_TYPE, int airdromeID = 0) { Coordinates = coordinates; Name = name; AltitudeMultiplier = HQTools.Clamp(altitudeMultiplier, MIN_ALTITUDE_MULTIPLIER, MAX_ALTITUDE_MULTIPLIER); SpeedMultiplier = HQTools.Clamp(speedMultiplier, MIN_SPEED_MULTIPLIER, MAX_SPEED_MULTIPLIER); WPAction = wpAction; WPType = wpType; AirdromeID = airdromeID; }
/// <summary> /// Generates the content of the Lua file. /// </summary> /// <param name="missHQ">An HQ4DCS mission.</param> /// <returns>The contents of the Lua file.</returns> public string MakeLua(DCSMission missHQ) { string airportsLua = ""; foreach (int id in missHQ.AirbasesCoalition.Keys) { string apLua = WarehouseAirportLua; HQTools.ReplaceKey(ref apLua, "Index", id); HQTools.ReplaceKey(ref apLua, "Coalition", missHQ.AirbasesCoalition[id].ToString().ToUpperInvariant()); airportsLua += apLua + "\n"; } string lua = WarehouseLua; HQTools.ReplaceKey(ref lua, "Airports", airportsLua); return(lua); }
private string MakeUnitsCategoryLua(DCSMission missHQ, Coalition coalition, UnitCategory categ) { string categoryUnitsLua = ""; DCSMissionUnitGroup[] groups = (from g in missHQ.UnitGroups where g.Coalition == coalition && g.Category == categ select g).ToArray(); int categIndex = 1; foreach (DCSMissionUnitGroup g in groups) { string groupLua = HQTools.ReadIncludeLuaFile($"Mission\\{g.LuaGroup}.lua"); HQTools.ReplaceKey(ref groupLua, "Units", MakeUnitsUnitsLua(g, missHQ.SinglePlayer)); // Must be first, so full-group replacements come after unit-specific ones //if (g.Waypoints.Count > 0) // HQTools.ReplaceKey(ref groupLua, "Waypoints", CreatePlayerWaypointsLua(g.Waypoints)); // Must be first after units HQTools.ReplaceKey(ref groupLua, "Name", g.Name); HQTools.ReplaceKey(ref groupLua, "GroupID", g.GroupID); HQTools.ReplaceKey(ref groupLua, "Frequency", g.RadioFrequency, "F2"); HQTools.ReplaceKey(ref groupLua, "X", g.Coordinates.X); HQTools.ReplaceKey(ref groupLua, "Y", g.Coordinates.Y); HQTools.ReplaceKey(ref groupLua, "ObjectiveCenterX", missHQ.ObjectivesCenterPoint.X + HQTools.RandomDouble(-UNIT_RANDOM_WAYPOINT_VARIATION, UNIT_RANDOM_WAYPOINT_VARIATION)); HQTools.ReplaceKey(ref groupLua, "ObjectiveCenterY", missHQ.ObjectivesCenterPoint.Y + HQTools.RandomDouble(-UNIT_RANDOM_WAYPOINT_VARIATION, UNIT_RANDOM_WAYPOINT_VARIATION)); HQTools.ReplaceKey(ref groupLua, "Hidden", g.Hidden); foreach (DCSMissionUnitGroupCustomValueKey k in g.CustomValues.Keys) { if (k.UnitIndex != -1) { continue; // Replacement applies only to a single unit, don't apply it to the whole group } HQTools.ReplaceKey(ref groupLua, k.Key, g.CustomValues[k]); } HQTools.ReplaceKey(ref groupLua, "Index", categIndex); // Must be last, used by other values categoryUnitsLua += groupLua + "\r\n"; categIndex++; } return(categoryUnitsLua); }
/// <summary> /// Picks a starting time for the mission. /// Must be called after mission date has been set because sunrise/sunset time changes every month. /// </summary> /// <param name="mission">The mission.</param> /// <param name="timeOfDay">The preferred time of day (noon, dawn, twilight, night, random...)</param> /// <param name="theater">Theater definition from which to get sunrise/sunset time.</param> public void GenerateMissionTime(DCSMission mission, TimeOfDay timeOfDay, DefinitionTheater theater) { DebugLog.Instance.Log("Generating mission starting time..."); double fullTime; DebugLog.Instance.Log($" Mission should start at {timeOfDay.ToString().ToUpperInvariant()}"); switch (timeOfDay) { default: // aka TimeOfDay.Random; mission.TimeHour = HQTools.RandomInt(0, 24); mission.TimeMinute = HQTools.RandomInt(0, 4) * 15; return; case TimeOfDay.RandomDaytime: fullTime = HQTools.RandomInt(theater.DayTime[(int)mission.DateMonth].Min, theater.DayTime[(int)mission.DateMonth].Max - 60); break; case TimeOfDay.Dawn: fullTime = HQTools.RandomInt(theater.DayTime[(int)mission.DateMonth].Min, theater.DayTime[(int)mission.DateMonth].Min + 120); break; case TimeOfDay.Noon: fullTime = HQTools.RandomInt( (theater.DayTime[(int)mission.DateMonth].Min + theater.DayTime[(int)mission.DateMonth].Max) / 2 - 90, (theater.DayTime[(int)mission.DateMonth].Min + theater.DayTime[(int)mission.DateMonth].Max) / 2 + 90); break; case TimeOfDay.Twilight: fullTime = HQTools.RandomInt(theater.DayTime[(int)mission.DateMonth].Max - 120, theater.DayTime[(int)mission.DateMonth].Max + 30); break; case TimeOfDay.Night: fullTime = HQTools.RandomInt(0, theater.DayTime[(int)mission.DateMonth].Min - 120); break; } mission.TimeHour = HQTools.Clamp((int)Math.Floor(fullTime / 60), 0, 23); mission.TimeMinute = HQTools.Clamp((int)Math.Floor((fullTime - mission.TimeHour * 60) / 15) * 15, 0, 45); DebugLog.Instance.Log($" Starting time set to {mission.TimeHour.ToString("00")}:{mission.TimeMinute.ToString("00")}"); DebugLog.Instance.Log(); }
/// <summary> /// Constructor. /// Loads all data from Library\Settings.ini /// </summary> public LibraryCommonSettings() { int i; using (INIFile ini = new INIFile($"{HQTools.PATH_LIBRARY}Settings.ini")) { // Default values DefaultCoalitionBlue = ini.GetValue("Defaults", "Coalition.Blue", "USA"); DefaultCoalitionRed = ini.GetValue("Defaults", "Coalition.Red", "Russia"); DefaultLanguage = ini.GetValue("Defaults", "Language", "English"); DefaultObjective = ini.GetValue("Defaults", "Objective", "CAP"); DefaultPlayerAircraft = ini.GetValue("Defaults", "Aircraft.Player", "Su-25T"); DefaultPlayerFlightGroupStartLocation = ini.GetValue("Defaults", "PlayerFlightGroup.StartLocation", PlayerFlightGroupStartLocation.FromParking); DefaultTheater = ini.GetValue("Defaults", "Theater", "Caucasus"); // Common media files SharedOggFiles = ini.GetValueArray <string>("Shared", "OggFiles"); AirDefense = new LibraryCommonSettingsEnemyAirDefense[HQTools.EnumCount <AmountNR>() - 1]; // -1 because we don't need "Random" for (i = 0; i < AirDefense.Length; i++) { AirDefense[i] = new LibraryCommonSettingsEnemyAirDefense(ini, "EnemyAirDefense", ((AmountNR)i).ToString()); } AirDefenseDistance = new LibraryCommonSettingsEnemyAirDefenseDistance[HQTools.EnumCount <AirDefenseRange>()]; for (i = 0; i < AirDefenseDistance.Length; i++) { AirDefenseDistance[i] = new LibraryCommonSettingsEnemyAirDefenseDistance(ini, "EnemyAirDefenseDistance", ((AirDefenseRange)i).ToString()); } DistanceToObjective = new LibraryCommonSettingsDistanceToObjective[HQTools.EnumCount <AmountR>() - 1]; // -1 because we don't need "Random" for (i = 0; i < DistanceToObjective.Length; i++) { DistanceToObjective[i] = new LibraryCommonSettingsDistanceToObjective(ini, "DistanceToObjective", ((AmountR)i).ToString()); } EnemyCAPDistance = new LibraryCommonSettingsEnemyAirDefenseDistance(ini, "CombatAirPatrols", null); CAPCount = new MinMaxI[HQTools.EnumCount <AmountNR>() - 1]; // -1 because we don't need "Random" for (i = 0; i < CAPCount.Length; i++) { CAPCount[i] = ini.GetValue <MinMaxI>("CombatAirPatrols", $"Count.{((AmountNR)i).ToString()}"); } } }
private string FormatDate(DCSMission mission, bool longFormat) { string formattedString = Language.GetString("Briefing", longFormat ? "Format.Date.Long" : "Format.Date.Short"); DateTime dt = new DateTime(2003, 5, 1); formattedString = formattedString .Replace("$W$", Language.GetEnum(new DateTime(mission.DateYear, (int)mission.DateMonth + 1, mission.DateDay).DayOfWeek)) .Replace("$D$", HQTools.ValToString(mission.DateDay, "0")) .Replace("$DD$", HQTools.ValToString(mission.DateDay, "00")) .Replace("$DDD$", Language.GetOrdinalAdjective(mission.DateDay)) .Replace("$M$", HQTools.ValToString((int)mission.DateMonth + 1, "0")) .Replace("$MM$", HQTools.ValToString((int)mission.DateMonth + 1, "00")) .Replace("$MMM$", Language.GetEnum(mission.DateMonth)) .Replace("$YY$", HQTools.ValToString(mission.DateYear).Substring(2)) .Replace("$YYYY$", HQTools.ValToString(mission.DateYear)); return(formattedString); }
/// <summary> /// Returns an unique callsign in the russian format (3-digits) /// </summary> /// <returns>The callsign</returns> private MGCallsign GetRussianCallsign() { int[] fgNumber = new int[2]; string fgName = ""; do { fgNumber[0] = HQTools.RandomMinMax(1, 9); fgNumber[1] = HQTools.RandomMinMax(0, 9); fgName = HQTools.ValToString(fgNumber[0]) + HQTools.ValToString(fgNumber[1]); } while (RussianCallsigns.Contains(fgName)); RussianCallsigns.Add(fgName); string unitName = fgName + "$INDEX$"; return(new MGCallsign(fgName + "0", unitName /*, unitName*/, unitName)); }
/// <summary> /// Exports the mission briefing to an HTML or image file. /// </summary> /// <param name="fileFormat">The file format to export to.</param> private void ExportBriefing(BriefingExportFileFormat fileFormat) { if (Mission == null) { return; // No mission has been generated, nothing to export. } string defaultFileName = HQTools.RemoveInvalidFileNameCharacters(Mission.BriefingName ?? ""); if (string.IsNullOrEmpty(defaultFileName)) { defaultFileName = "NewMission"; } string briefingFilePath = GUITools.ShowSaveFileDialog( fileFormat.ToString().ToLowerInvariant(), HQTools.GetDCSMissionPath(), defaultFileName, $"{fileFormat.ToString().ToUpperInvariant()} files"); if (briefingFilePath == null) { return; } bool result; using (HTMLExporter briefingExporter = new HTMLExporter()) { switch (fileFormat) { default: return; case BriefingExportFileFormat.Html: result = briefingExporter.ExportToHTML(briefingFilePath, Mission.BriefingHTML); break; case BriefingExportFileFormat.Jpg: result = briefingExporter.ExportToJPEG(briefingFilePath, Mission.BriefingHTML); break; case BriefingExportFileFormat.Png: result = briefingExporter.ExportToPNG(briefingFilePath, Mission.BriefingHTML); break; } } if (!result) { MessageBox.Show("Failed to export briefing", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
/// <summary> /// Copy all included scripts into the mission Lua script. /// </summary> /// <param name="lua">The mission Lua script.</param> /// <param name="mission">A HQ4DCS mission.</param> private void CopyMissionLuaScripts(ref string lua, DCSMission mission) { DefinitionObjective objectiveDef = Library.Instance.GetDefinition <DefinitionObjective>(mission.ObjectiveDefinition); if (objectiveDef == null) { return; } int i; // For each script scope (global, event and timer)... foreach (ObjectiveScriptScope scope in HQTools.EnumValues <ObjectiveScriptScope>()) { string scriptLua = ""; // ...add once every script to include once... foreach (string scriptFile in objectiveDef.IncludeLua[(int)ObjectiveScriptRepetition.Once, (int)scope]) { scriptLua += HQTools.ReadIncludeLuaFile($"Script\\{scriptFile}"); } // ...and add each time for each objective the scripts to include once for each objective for (i = 0; i < mission.Objectives.Length; i++) { string objectiveScriptLua = ""; foreach (string scriptFile in objectiveDef.IncludeLua[(int)ObjectiveScriptRepetition.Each, (int)scope]) { objectiveScriptLua += HQTools.ReadIncludeLuaFile($"Script\\{scriptFile}"); } HQTools.ReplaceKey(ref objectiveScriptLua, "ObjectiveID", 1 + i); HQTools.ReplaceKey(ref objectiveScriptLua, "GroupID", 1001 + i); scriptLua += objectiveScriptLua + "\n"; } HQTools.ReplaceKey(ref lua, $"Script{scope.ToString()}", scriptLua); } }