mirror of
https://github.com/akaAgar/the-universal-mission-for-dcs-world.git
synced 2026-09-03 18:30:38 +00:00
Compare commits
37 Commits
jtac-lasing
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 83c49bdd1f | |||
| d7941c3485 | |||
| 3fd0d39be0 | |||
| a51ff5cff0 | |||
| a7bf94de5f | |||
| a66c3000c2 | |||
| 2d96f23d2f | |||
| 392f06d4e2 | |||
| 32248a9b72 | |||
| 5b2b17a8b0 | |||
| 806421062b | |||
| 591ec6e10a | |||
| 92a00160ef | |||
| 085172f033 | |||
| 526651c6da | |||
| b343d700a0 | |||
| da20586d51 | |||
| 69ea6b6d19 | |||
| 5f5b940ef7 | |||
| 014495246d | |||
| 3484e2544c | |||
| 185685b706 | |||
| 6b52970520 | |||
| 1c6b06a1a6 | |||
| 525484385a | |||
| 6ce6a8d2a1 | |||
| 7bfe0813d8 | |||
| 12e20a32ce | |||
| 13d341c4a8 | |||
| 0bc9780dd4 | |||
| aa544e6c0c | |||
| c80d036feb | |||
| c557c3d74d | |||
| 1892d97d15 | |||
| db5ee882c4 | |||
| 83ddfe7598 | |||
| d0355af8e3 |
@@ -11,8 +11,9 @@
|
|||||||
if not net then net = {} end
|
if not net then net = {} end
|
||||||
|
|
||||||
net.allow_unsafe_api = { -- this defines the secure zones where net.dostring_in() can be called from
|
net.allow_unsafe_api = { -- this defines the secure zones where net.dostring_in() can be called from
|
||||||
|
"scripting",
|
||||||
}
|
}
|
||||||
|
|
||||||
net.allow_dostring_in = { -- and this defines the zones that should be addressed from net.dostring_in()
|
net.allow_dostring_in = { -- and this defines the zones that should be addressed from net.dostring_in()
|
||||||
"mission"
|
"mission",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
-- do
|
||||||
|
-- Library.factions.tables["NATO"] = {}
|
||||||
|
-- Library.factions.tables["NATO"].theaters = {}
|
||||||
|
-- Library.factions.tables["NATO"].timePeriods = {}
|
||||||
|
|
||||||
|
-- Library.factions.tables["NATO"].units = {}
|
||||||
|
|
||||||
|
-- Library.factions.tables["NATO"].units[DCSEx.enums.timePeriod.WORLD_WAR_2] = {}
|
||||||
|
-- Library.factions.tables["NATO"].units[DCSEx.enums.timePeriod.KOREA_WAR] = {}
|
||||||
|
-- Library.factions.tables["NATO"].units[DCSEx.enums.timePeriod.VIETNAM_WAR] = {}
|
||||||
|
-- Library.factions.tables["NATO"].units[DCSEx.enums.timePeriod.COLD_WAR] = {}
|
||||||
|
|
||||||
|
-- Library.factions.tables["NATO"].units[DCSEx.enums.timePeriod.MODERN] = {
|
||||||
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_AAA_MOBILE] = { "Gepard", "Vulcan" },
|
||||||
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_AAA_STATIC] = { "Gepard", "Vulcan" },
|
||||||
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_MANPADS] = { "Soldier stinger" },
|
||||||
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_SAM_LONG] = { "*Patriot" },
|
||||||
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_SAM_MEDIUM] = { "*HAWK", "*NASAMS" },
|
||||||
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_SAM_SHORT] = { "rapier_fsa", "Roland ADS" },
|
||||||
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_SAM_SHORT_IR] = { "M6 Linebacker", "M48 Chaparral", "M1097 Avenger" },
|
||||||
|
|
||||||
|
-- [DCSEx.enums.unitFamily.GROUND_APC] = { "AAV7", "Cobra", "LAV-25", "M-2 Bradley", "M-113", "M1045 HMMWV TOW", "M1126 Stryker ICV", "M1128 Stryker MGS", "Marder", "MCV-80", "MLRS FDDM", "TPZ", "CHAP_M1130", "CHAP_MATV" },
|
||||||
|
-- [DCSEx.enums.unitFamily.GROUND_ARTILLERY] = { "M-109", "MLRS", "CHAP_M142_ATACMS_M48", "CHAP_M142_GMLRS_M31" },
|
||||||
|
-- [DCSEx.enums.unitFamily.GROUND_INFANTRY] = { "Soldier M4 GRG", "Soldier M4", "Soldier M249", "Soldier RPG" },
|
||||||
|
-- [DCSEx.enums.unitFamily.GROUND_MBT] = { "Challenger2", "Leclerc", "Leopard-2", "Leopard1A3", "M-1 Abrams", "Merkava_Mk4" },
|
||||||
|
-- [DCSEx.enums.unitFamily.GROUND_SS_MISSILE] = { "Scud_B" },
|
||||||
|
-- [DCSEx.enums.unitFamily.GROUND_UNARMED] = { "Land_Rover_101_FC", "Land_Rover_109_S3", "M 818", "CHAP_M1083" },
|
||||||
|
|
||||||
|
-- [DCSEx.enums.unitFamily.HELICOPTER_ATTACK] = { "AH-1W", "AH-64D", "OH-58D", "SA342L", "SA342M", "SA342Minigun", "SA342Mistral" },
|
||||||
|
-- [DCSEx.enums.unitFamily.HELICOPTER_TRANSPORT] = { "CH-47D", "CH-53E", "SH-60B", "UH-60A" },
|
||||||
|
|
||||||
|
-- [DCSEx.enums.unitFamily.PLANE_ATTACK] = { "A-10C_2" },
|
||||||
|
-- [DCSEx.enums.unitFamily.PLANE_AWACS] = { "E-2C", "E-3A" },
|
||||||
|
-- [DCSEx.enums.unitFamily.PLANE_BOMBER] = { "B-1B Lancer", "B-52H" },
|
||||||
|
-- [DCSEx.enums.unitFamily.PLANE_FIGHTER] = { "F-16C_50", "FA-18C_hornet" },
|
||||||
|
-- [DCSEx.enums.unitFamily.PLANE_TANKER] = { "KC-135", "KC135MPRS" },
|
||||||
|
-- [DCSEx.enums.unitFamily.PLANE_TRANSPORT] = { "C-17A", "C-130" },
|
||||||
|
-- [DCSEx.enums.unitFamily.PLANE_UAV] = { "RQ-1A Predator" },
|
||||||
|
|
||||||
|
-- [DCSEx.enums.unitFamily.SHIP_CARGO] = { "Dry-cargo ship-1", "Dry-cargo ship-2", "ELNYA", "Ship_Tilde_Supply" },
|
||||||
|
-- [DCSEx.enums.unitFamily.SHIP_CARRIER] = { "CVN_71", "CVN_72", "CVN_73", "CVN_75", "hms_invincible", "LHA_Tarawa", "Stennis" },
|
||||||
|
-- [DCSEx.enums.unitFamily.SHIP_CRUISER] = { "TICONDEROG" },
|
||||||
|
-- [DCSEx.enums.unitFamily.SHIP_FRIGATE] = { "PERRY", "USS_Arleigh_Burke_IIa" },
|
||||||
|
-- [DCSEx.enums.unitFamily.SHIP_LIGHT] = { "speedboat" },
|
||||||
|
-- [DCSEx.enums.unitFamily.SHIP_MISSILE_BOAT] = { "CastleClass_01", "La_Combattante_II" },
|
||||||
|
-- [DCSEx.enums.unitFamily.SHIP_SUBMARINE] = { "santafe" },
|
||||||
|
|
||||||
|
-- -- [DCSEx.enums.unitFamily.STATIC_STRUCTURE] = { "af_hq", ".Command Center", "Building01_PBR", "Building02_PBR", "Building03_PBR", "Building04_PBR", "Building05_PBR", "Bunker", "Chemical tank A", "Comms tower M", "FARP Fuel Depot", "outpost", "Sandbox", "Workshop A" },
|
||||||
|
-- [DCSEx.enums.unitFamily.STATIC_STRUCTURE] = { "af_hq", ".Command Center", "Building01_PBR", "Building02_PBR", "Building03_PBR", "Building04_PBR", "Building05_PBR", "Chemical tank A", "Comms tower M", "FARP Fuel Depot", "outpost", "Workshop A" },
|
||||||
|
-- }
|
||||||
|
-- end
|
||||||
@@ -21,7 +21,7 @@ do
|
|||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_MOBILE] = { "Ural-375 ZU-23", "ZSU_57_2", "ZSU-23-4 Shilka" },
|
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_MOBILE] = { "Ural-375 ZU-23", "ZSU_57_2", "ZSU-23-4 Shilka" },
|
||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_STATIC] = { "ZU-23 Emplacement Closed", "ZU-23 Emplacement" },
|
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_STATIC] = { "ZU-23 Emplacement Closed", "ZU-23 Emplacement" },
|
||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_MANPADS] = { "SA-18 Igla manpad", "SA-18 Igla-S manpad" },
|
[DCSEx.enums.unitFamily.AIRDEFENSE_MANPADS] = { "SA-18 Igla manpad", "SA-18 Igla-S manpad" },
|
||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_LONG] = { "*SA-2", "*SA-10" },
|
-- [DCSEx.enums.unitFamily.AIRDEFENSE_SAM_LONG] = { "*SA-2", "*SA-10" },
|
||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_LONG] = { "*SA-10" },
|
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_LONG] = { "*SA-10" },
|
||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_MEDIUM] = { "*SA-3", "*SA-6", "*SA-11" },
|
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_MEDIUM] = { "*SA-3", "*SA-6", "*SA-11" },
|
||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_SHORT] = { "2S6 Tunguska", "Osa 9A33 ln", "Tor 9A331", "CHAP_PantsirS1", "CHAP_TorM2" },
|
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_SHORT] = { "2S6 Tunguska", "Osa 9A33 ln", "Tor 9A331", "CHAP_PantsirS1", "CHAP_TorM2" },
|
||||||
@@ -45,8 +45,6 @@ do
|
|||||||
[DCSEx.enums.unitFamily.PLANE_TRANSPORT] = { "An-26B", "An-30M", "IL-76MD" },
|
[DCSEx.enums.unitFamily.PLANE_TRANSPORT] = { "An-26B", "An-30M", "IL-76MD" },
|
||||||
[DCSEx.enums.unitFamily.PLANE_UAV] = { "WingLoong-I" },
|
[DCSEx.enums.unitFamily.PLANE_UAV] = { "WingLoong-I" },
|
||||||
|
|
||||||
[DCSEx.enums.unitFamily.HELICOPTER_ATTACK] = { "Ka-50", "Mi-24V", "Mi-28N" },
|
|
||||||
|
|
||||||
[DCSEx.enums.unitFamily.SHIP_CARGO] = { "Dry-cargo ship-1", "Dry-cargo ship-2", "ELNYA", "Ship_Tilde_Supply" },
|
[DCSEx.enums.unitFamily.SHIP_CARGO] = { "Dry-cargo ship-1", "Dry-cargo ship-2", "ELNYA", "Ship_Tilde_Supply" },
|
||||||
[DCSEx.enums.unitFamily.SHIP_CARRIER] = { "CV_1143_5", "KUZNECOW" },
|
[DCSEx.enums.unitFamily.SHIP_CARRIER] = { "CV_1143_5", "KUZNECOW" },
|
||||||
[DCSEx.enums.unitFamily.SHIP_CRUISER] = { "MOSCOW", "PIOTR" },
|
[DCSEx.enums.unitFamily.SHIP_CRUISER] = { "MOSCOW", "PIOTR" },
|
||||||
|
|||||||
@@ -10,7 +10,45 @@ do
|
|||||||
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.WORLD_WAR_2] = {}
|
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.WORLD_WAR_2] = {}
|
||||||
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.KOREA_WAR] = {}
|
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.KOREA_WAR] = {}
|
||||||
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.VIETNAM_WAR] = {}
|
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.VIETNAM_WAR] = {}
|
||||||
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.COLD_WAR] = {}
|
|
||||||
|
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.COLD_WAR] = {
|
||||||
|
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_MOBILE] = { "Gepard", "Vulcan" },
|
||||||
|
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_STATIC] = { "Gepard", "Vulcan" },
|
||||||
|
[DCSEx.enums.unitFamily.AIRDEFENSE_MANPADS] = { "Soldier stinger" },
|
||||||
|
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_LONG] = { "*Patriot" },
|
||||||
|
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_MEDIUM] = { "*HAWK", "*NASAMS" },
|
||||||
|
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_SHORT] = { "rapier_fsa", "Roland ADS" },
|
||||||
|
[DCSEx.enums.unitFamily.AIRDEFENSE_SAM_SHORT_IR] = { "M6 Linebacker", "M48 Chaparral", "M1097 Avenger" },
|
||||||
|
|
||||||
|
[DCSEx.enums.unitFamily.GROUND_APC] = { "AAV7", "Cobra", "LAV-25", "M-2 Bradley", "M-113", "M1045 HMMWV TOW", "M1126 Stryker ICV", "M1128 Stryker MGS", "Marder", "MCV-80", "MLRS FDDM", "TPZ", "CHAP_M1130", "CHAP_MATV" },
|
||||||
|
[DCSEx.enums.unitFamily.GROUND_ARTILLERY] = { "M-109", "MLRS", "CHAP_M142_ATACMS_M48", "CHAP_M142_GMLRS_M31" },
|
||||||
|
[DCSEx.enums.unitFamily.GROUND_INFANTRY] = { "Soldier M4 GRG", "Soldier M4", "Soldier M249", "Soldier RPG" },
|
||||||
|
[DCSEx.enums.unitFamily.GROUND_MBT] = { "Challenger2", "Leclerc", "Leopard-2", "Leopard1A3", "M-1 Abrams", "Merkava_Mk4" },
|
||||||
|
[DCSEx.enums.unitFamily.GROUND_SS_MISSILE] = { "Scud_B" },
|
||||||
|
[DCSEx.enums.unitFamily.GROUND_UNARMED] = { "Land_Rover_101_FC", "Land_Rover_109_S3", "M 818", "CHAP_M1083" },
|
||||||
|
|
||||||
|
[DCSEx.enums.unitFamily.HELICOPTER_ATTACK] = { "AH-1W", "AH-64D", "OH-58D", "SA342L", "SA342M", "SA342Minigun", "SA342Mistral" },
|
||||||
|
[DCSEx.enums.unitFamily.HELICOPTER_TRANSPORT] = { "CH-47D", "CH-53E", "SH-60B", "UH-60A" },
|
||||||
|
|
||||||
|
[DCSEx.enums.unitFamily.PLANE_ATTACK] = { "A-10C_2" },
|
||||||
|
[DCSEx.enums.unitFamily.PLANE_AWACS] = { "E-2C", "E-3A" },
|
||||||
|
[DCSEx.enums.unitFamily.PLANE_BOMBER] = { "B-1B Lancer", "B-52H" },
|
||||||
|
[DCSEx.enums.unitFamily.PLANE_FIGHTER] = { "F-16C_50", "FA-18C_hornet" },
|
||||||
|
[DCSEx.enums.unitFamily.PLANE_TANKER] = { "KC-135", "KC135MPRS" },
|
||||||
|
[DCSEx.enums.unitFamily.PLANE_TRANSPORT] = { "C-17A", "C-130" },
|
||||||
|
[DCSEx.enums.unitFamily.PLANE_UAV] = { "RQ-1A Predator" },
|
||||||
|
|
||||||
|
[DCSEx.enums.unitFamily.SHIP_CARGO] = { "Dry-cargo ship-1", "Dry-cargo ship-2", "ELNYA", "Ship_Tilde_Supply" },
|
||||||
|
[DCSEx.enums.unitFamily.SHIP_CARRIER] = { "CVN_71", "CVN_72", "CVN_73", "CVN_75", "hms_invincible", "LHA_Tarawa", "Stennis" },
|
||||||
|
[DCSEx.enums.unitFamily.SHIP_CRUISER] = { "TICONDEROG" },
|
||||||
|
[DCSEx.enums.unitFamily.SHIP_FRIGATE] = { "PERRY", "USS_Arleigh_Burke_IIa" },
|
||||||
|
[DCSEx.enums.unitFamily.SHIP_LIGHT] = { "speedboat" },
|
||||||
|
[DCSEx.enums.unitFamily.SHIP_MISSILE_BOAT] = { "CastleClass_01", "La_Combattante_II" },
|
||||||
|
[DCSEx.enums.unitFamily.SHIP_SUBMARINE] = { "santafe" },
|
||||||
|
|
||||||
|
-- [DCSEx.enums.unitFamily.STATIC_STRUCTURE] = { "af_hq", ".Command Center", "Building01_PBR", "Building02_PBR", "Building03_PBR", "Building04_PBR", "Building05_PBR", "Bunker", "Chemical tank A", "Comms tower M", "FARP Fuel Depot", "outpost", "Sandbox", "Workshop A" },
|
||||||
|
[DCSEx.enums.unitFamily.STATIC_STRUCTURE] = { "af_hq", ".Command Center", "Building01_PBR", "Building02_PBR", "Building03_PBR", "Building04_PBR", "Building05_PBR", "Chemical tank A", "Comms tower M", "FARP Fuel Depot", "outpost", "Workshop A" },
|
||||||
|
}
|
||||||
|
|
||||||
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.MODERN] = {
|
Library.factions.tables["USA"].units[DCSEx.enums.timePeriod.MODERN] = {
|
||||||
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_MOBILE] = { "Gepard", "Vulcan" },
|
[DCSEx.enums.unitFamily.AIRDEFENSE_AAA_MOBILE] = { "Gepard", "Vulcan" },
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
-- Library.tasks.helicopterDestroyInfantry = {
|
||||||
|
-- taskFamily = DCSEx.enums.taskFamily.HELICOPTER,
|
||||||
|
-- description =
|
||||||
|
-- {
|
||||||
|
-- briefing = {
|
||||||
|
-- "",
|
||||||
|
-- },
|
||||||
|
-- short = "Neutralize enemy infantry",
|
||||||
|
-- },
|
||||||
|
-- conditions = {
|
||||||
|
-- difficultyMinimum = 0,
|
||||||
|
-- eras = {},
|
||||||
|
-- },
|
||||||
|
-- completionEvent = DCSEx.enums.taskEvent.DESTROY,
|
||||||
|
-- flags = { },
|
||||||
|
-- minimumDistance = DCSEx.converter.nmToMeters(5.0),
|
||||||
|
-- safeRadius = 100,
|
||||||
|
-- surfaceType = nil,
|
||||||
|
-- targetCount = { 6, 8 },
|
||||||
|
-- targetFamilies = { DCSEx.enums.unitFamily.GROUND_INFANTRY },
|
||||||
|
-- waypointInaccuracy = DCSEx.converter.nmToMeters(1.5)
|
||||||
|
-- }
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
-- Library.tasks.helicopterPickUpInfantry = {
|
||||||
|
-- taskFamily = DCSEx.enums.taskFamily.HELICOPTER,
|
||||||
|
-- description =
|
||||||
|
-- {
|
||||||
|
-- briefing = {
|
||||||
|
-- "",
|
||||||
|
-- },
|
||||||
|
-- short = "Land and pick up friendly infantry",
|
||||||
|
-- },
|
||||||
|
-- conditions = {
|
||||||
|
-- difficultyMinimum = 0,
|
||||||
|
-- eras = {},
|
||||||
|
-- },
|
||||||
|
-- completionEvent = DCSEx.enums.taskEvent.LAND,
|
||||||
|
-- flags = { DCSEx.enums.taskFlag.FRIENDLY_TARGET },
|
||||||
|
-- minimumDistance = DCSEx.converter.nmToMeters(5.0),
|
||||||
|
-- safeRadius = 100,
|
||||||
|
-- surfaceType = nil,
|
||||||
|
-- targetCount = { 6, 8 },
|
||||||
|
-- targetFamilies = { DCSEx.enums.unitFamily.GROUND_INFANTRY },
|
||||||
|
-- waypointInaccuracy = DCSEx.converter.nmToMeters(1.5)
|
||||||
|
-- }
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
Library.tasks.ocaFighterStrike = {
|
-- Library.tasks.ocaFighterStrike = {
|
||||||
taskFamily = DCSEx.enums.taskFamily.OCA,
|
-- taskFamily = DCSEx.enums.taskFamily.OCA,
|
||||||
description =
|
-- description =
|
||||||
{
|
-- {
|
||||||
briefing = {
|
-- briefing = {
|
||||||
"Destroying enemy fighters on the ramp will prevent immediate sortie generation and blunt their ability to provide CAS against our advancing forces.",
|
-- "Destroying enemy fighters on the ramp will prevent immediate sortie generation and blunt their ability to provide CAS against our advancing forces.",
|
||||||
"A ramp strike against enemy aircraft will pre-empt an imminent scramble warning we have intel for, preventing a coordinated mass launch.",
|
-- "A ramp strike against enemy aircraft will pre-empt an imminent scramble warning we have intel for, preventing a coordinated mass launch.",
|
||||||
"Removing enemy fighters on the ramp will degrade enemy air superiority over the battlespace and protects our medevac and resupply corridors.",
|
-- "Removing enemy fighters on the ramp will degrade enemy air superiority over the battlespace and protects our medevac and resupply corridors.",
|
||||||
"Priority is to eliminate immediate airborne threats on the ramp to safeguard coalition force freedom of maneuver.",
|
-- "Priority is to eliminate immediate airborne threats on the ramp to safeguard coalition force freedom of maneuver.",
|
||||||
},
|
-- },
|
||||||
short = "Destroy enemy fighter on the ramp",
|
-- short = "Destroy enemy fighter on the ramp",
|
||||||
},
|
-- },
|
||||||
conditions = {
|
-- conditions = {
|
||||||
difficultyMinimum = 0,
|
-- difficultyMinimum = 0,
|
||||||
eras = {},
|
-- eras = {},
|
||||||
},
|
-- },
|
||||||
completionEvent = DCSEx.enums.taskEvent.DESTROY,
|
-- completionEvent = DCSEx.enums.taskEvent.DAMAGE,
|
||||||
flags = { DCSEx.enums.taskFlag.ALLOW_JTAC, DCSEx.enums.taskFlag.PARKED_AIRCRAFT_TARGET },
|
-- flags = { DCSEx.enums.taskFlag.ALLOW_JTAC, DCSEx.enums.taskFlag.PARKED_AIRCRAFT_TARGET },
|
||||||
minimumDistance = 0.0,
|
-- minimumDistance = 0.0,
|
||||||
safeRadius = 0,
|
-- safeRadius = 0,
|
||||||
surfaceType = land.SurfaceType.LAND,
|
-- surfaceType = land.SurfaceType.LAND,
|
||||||
targetCount = { 1, 1 },
|
-- targetCount = { 1, 1 },
|
||||||
targetFamilies = { DCSEx.enums.unitFamily.PLANE_FIGHTER },
|
-- targetFamilies = { DCSEx.enums.unitFamily.PLANE_FIGHTER },
|
||||||
waypointInaccuracy = 0.0
|
-- waypointInaccuracy = 0.0
|
||||||
}
|
-- }
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
Library.tasks.ocaBomberStrike = {
|
Library.tasks.ocaStrategicAircraftStrike = {
|
||||||
taskFamily = DCSEx.enums.taskFamily.OCA,
|
taskFamily = DCSEx.enums.taskFamily.OCA,
|
||||||
description =
|
description =
|
||||||
{
|
{
|
||||||
briefing = {
|
briefing = {
|
||||||
""
|
""
|
||||||
},
|
},
|
||||||
short = "Destroy enemy bomber on the ramp",
|
short = "Destroy enemy aircraft on the ramp",
|
||||||
},
|
},
|
||||||
conditions = {
|
conditions = {
|
||||||
difficultyMinimum = 0,
|
difficultyMinimum = 0,
|
||||||
eras = {},
|
eras = {},
|
||||||
},
|
},
|
||||||
completionEvent = DCSEx.enums.taskEvent.DESTROY,
|
completionEvent = DCSEx.enums.taskEvent.DAMAGE,
|
||||||
flags = { DCSEx.enums.taskFlag.ALLOW_JTAC, DCSEx.enums.taskFlag.PARKED_AIRCRAFT_TARGET },
|
flags = { DCSEx.enums.taskFlag.ALLOW_JTAC, DCSEx.enums.taskFlag.PARKED_AIRCRAFT_TARGET },
|
||||||
minimumDistance = 0.0,
|
minimumDistance = 0.0,
|
||||||
safeRadius = 0,
|
safeRadius = 0,
|
||||||
surfaceType = land.SurfaceType.LAND,
|
surfaceType = land.SurfaceType.LAND,
|
||||||
targetCount = { 1, 1 },
|
targetCount = { 1, 1 },
|
||||||
targetFamilies = { DCSEx.enums.unitFamily.PLANE_BOMBER },
|
targetFamilies = { DCSEx.enums.unitFamily.PLANE_BOMBER, DCSEx.enums.unitFamily.PLANE_TRANSPORT },
|
||||||
waypointInaccuracy = 0.0
|
waypointInaccuracy = 0.0
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ IF %ERRORLEVEL% NEQ 0 goto ERROR-NO-PHP
|
|||||||
@REM CREATE SCENARIOS
|
@REM CREATE SCENARIOS
|
||||||
@REM -------------------------------------------
|
@REM -------------------------------------------
|
||||||
set buildConfig=p
|
set buildConfig=p
|
||||||
echo THE ULTIMATE MISSION BUILDER SCRIPT:
|
echo THE UNIVERSAL MISSION BUILDER SCRIPT:
|
||||||
echo - Build [P]ersianGulf debug theater only (default)
|
echo - Build [P]ersianGulf debug theater only (default)
|
||||||
echo - Build all [D]ebug theaters
|
echo - Build all [D]ebug theaters
|
||||||
echo - Build all [R]elease theaters
|
echo - Build all [R]elease theaters
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# The Universal Mission for DCS World
|
# The Universal Mission for DCS World
|
||||||
|
|
||||||
**Current version: open beta 0.3.250914** (see the "version history" section at the end of this file for a list of the latest changes)
|
**Current version: open beta 0.3.251019** (see the "version history" section at the end of this file for a list of the latest changes)
|
||||||
|
|
||||||
**This is a BETA version, there may be bugs and there WILL be unbalanced stuff.**
|
**This is a BETA version, there may be bugs and there WILL be unbalanced stuff.**
|
||||||
|
|
||||||
@@ -42,7 +42,6 @@ The Universal Mission for DCS World is a fully dynamic single-player/PvE mission
|
|||||||
|
|
||||||
- Download the latest release from this GitHub page.
|
- Download the latest release from this GitHub page.
|
||||||
- Copy the provided autoexec.cfg file to your **[Saved Games]\DCS\Config directory**
|
- Copy the provided autoexec.cfg file to your **[Saved Games]\DCS\Config directory**
|
||||||
- Please note: as of DCS 2.9.18.12899, it seems the autoexec.cfg file [is no longer needed](https://www.digitalcombatsimulator.com/en/news/changelog/release/2.9.18.12899/) but I advise you to copy it anyway, ED might change its mind again.
|
|
||||||
- Copy the .miz files for your theater(s) of choice to your **[Saved Games]\DCS\Missions directory**
|
- Copy the .miz files for your theater(s) of choice to your **[Saved Games]\DCS\Missions directory**
|
||||||
- _**(Optional but strongly recommended)**_ Unsanitize the Lua IO module. You don't have to do this, but the persistent career system won't work if you don't. To do it, open the file **[DCS World installation directory]\Scripts\MissionScripting.lua** with a text editor and comment or remove the line "sanitizeModule('io')". Make sure you restart DCS World once you've modified the file.
|
- _**(Optional but strongly recommended)**_ Unsanitize the Lua IO module. You don't have to do this, but the persistent career system won't work if you don't. To do it, open the file **[DCS World installation directory]\Scripts\MissionScripting.lua** with a text editor and comment or remove the line "sanitizeModule('io')". Make sure you restart DCS World once you've modified the file.
|
||||||
- Please note: should you want to backup, delete or transfer it, career progress is saved in **[DCS World installation directory]\TheUniversalMission.sav**
|
- Please note: should you want to backup, delete or transfer it, career progress is saved in **[DCS World installation directory]\TheUniversalMission.sav**
|
||||||
@@ -75,17 +74,17 @@ Please also note that PvP is not supported at the moment and that the mission wi
|
|||||||
|
|
||||||
- Additional content
|
- Additional content
|
||||||
- [ ] More objectives types
|
- [ ] More objectives types
|
||||||
- [x] Helicopter hunt
|
- [ ] Close air support
|
||||||
- [ ] Offensive counter-air
|
- [ ] Helicopter-specific tasking (land and pick up units, suppress infantry...)
|
||||||
|
- [ ] Improved OCA missions: bomb enemy airbases
|
||||||
- Balance improvements
|
- Balance improvements
|
||||||
|
- [ ] Night missions should award more XP
|
||||||
- [ ] Tweaked XP requirements for medals/promotions
|
- [ ] Tweaked XP requirements for medals/promotions
|
||||||
- Bug fixes
|
- Bug fixes
|
||||||
- [ ] AWACS datalinked contacts not showing on SA pages
|
|
||||||
- [X] AWACS can now detect enemy helicopters
|
|
||||||
- Extras
|
- Extras
|
||||||
- [ ] GitHub page
|
- [ ] GitHub page
|
||||||
- Improvements
|
- Improvements
|
||||||
- [ ] Better weather reports (cloud cover, rain, etc)
|
- Misc
|
||||||
- New features
|
- New features
|
||||||
- [ ] Administrative settings menu
|
- [ ] Administrative settings menu
|
||||||
- [ ] Friendly air defenses
|
- [ ] Friendly air defenses
|
||||||
@@ -97,17 +96,15 @@ Please also note that PvP is not supported at the moment and that the mission wi
|
|||||||
|
|
||||||
- Additional/improved radio messages
|
- Additional/improved radio messages
|
||||||
- More "flavor" radio messages ("fence in" when player approaches the AO, etc) so the world will feel more alive
|
- More "flavor" radio messages ("fence in" when player approaches the AO, etc) so the world will feel more alive
|
||||||
- Better balancing of the player career awards and promotions
|
|
||||||
- Better use of context for "ambient" radio messages (should only warn of a SAM launch if an AI pilot is there to witness it, etc)
|
- Better use of context for "ambient" radio messages (should only warn of a SAM launch if an AI pilot is there to witness it, etc)
|
||||||
- Improved score multiplier taking into account various aspects of mission difficulty (weather, nighttime ops...)
|
|
||||||
- Laser designation of targets by JTAC
|
- Laser designation of targets by JTAC
|
||||||
- New objectives: helicopter (drop/pickup units...), CAP, CAS, OCA (airbase attack)
|
- New objectives: CAP
|
||||||
- Support for all missing DCS World theaters
|
- Support for all missing DCS World theaters
|
||||||
- Support for more factions and five different time periods (World War 2, Korea war, Vietnam war, late Cold war, Modern)
|
- Support for more factions and five different time periods (World War 2, Korea war, Vietnam war, late Cold war, Modern)
|
||||||
|
|
||||||
### Medium priority
|
### Medium priority
|
||||||
|
|
||||||
- Combined Arms support
|
- Combined arms support
|
||||||
- Modded units support (other than player-controlled aircraft, those are already supported: just add them to the mission)
|
- Modded units support (other than player-controlled aircraft, those are already supported: just add them to the mission)
|
||||||
- Spawning of tankers for long-range missions
|
- Spawning of tankers for long-range missions
|
||||||
- (maybe) Text (not voiceover) localization, if there's enough popular demand
|
- (maybe) Text (not voiceover) localization, if there's enough popular demand
|
||||||
@@ -157,6 +154,22 @@ The core script is quite simple and small, I probably won't need too much help w
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
- **0.3.251019** (10/19/2025)
|
||||||
|
- Additional content
|
||||||
|
- New mission types
|
||||||
|
- "Helicopter hunt" missions: locate and intercept enemy attack and transport helicopters
|
||||||
|
- Offensive counter-air: destroy enemy aircraft on the ramp before they take off **(Requires a target location with at least one enemy land airbase, or mission type will automatically be changed to ground attack)**
|
||||||
|
- Balance improvements
|
||||||
|
- Missions with higher cloud cover and wind speed now award more XP
|
||||||
|
- Bug fixes
|
||||||
|
- AWACS datalinked now showing on SA pages
|
||||||
|
- AWACS can now detect enemy helicopters
|
||||||
|
- Added missing net.allow_unsafe_api value in autoexec.cfg that prevented some advanced scripts from working
|
||||||
|
- "On landing" actions (medal/promotions check, AI wingmen removal, etc) no longer triggered when player lands away from an airfield (e.g. in a Harrier on a helicopter)
|
||||||
|
- Improvements
|
||||||
|
- ATC weather reports now include informations about cloud cover and rain
|
||||||
|
- Misc
|
||||||
|
- AWACS unit now spawned when mission is loaded
|
||||||
- **0.3.250914** (09/14/2025)
|
- **0.3.250914** (09/14/2025)
|
||||||
- **MAJOR CHANGE:**
|
- **MAJOR CHANGE:**
|
||||||
- Use of "Client" slots instead of "Player" slots even in single-player missions, allowing the player to respawn on death/ejection instead of having to start the whole mission again
|
- Use of "Client" slots instead of "Player" slots even in single-player missions, allowing the player to respawn on death/ejection instead of having to start the whole mission again
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ DCSEx.enums.lineType = {
|
|||||||
-- Event to check to see if a task/objective is complete
|
-- Event to check to see if a task/objective is complete
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
DCSEx.enums.taskEvent = {
|
DCSEx.enums.taskEvent = {
|
||||||
DESTROY = 1,
|
DAMAGE = 1,
|
||||||
DESTROY_SCENERY = 2,
|
DESTROY = 2,
|
||||||
LAND = 3,
|
DESTROY_SCENERY = 3,
|
||||||
|
LAND = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
@@ -42,7 +43,7 @@ DCSEx.enums.taskFamily = {
|
|||||||
-- CAP = XXX,
|
-- CAP = XXX,
|
||||||
-- CAS = XXX,
|
-- CAS = XXX,
|
||||||
GROUND_ATTACK = 2,
|
GROUND_ATTACK = 2,
|
||||||
-- HELICOPTER = XXX,
|
-- HELICOPTER = 3,
|
||||||
HELO_HUNT = 3,
|
HELO_HUNT = 3,
|
||||||
INTERCEPTION = 4,
|
INTERCEPTION = 4,
|
||||||
OCA = 5,
|
OCA = 5,
|
||||||
@@ -61,6 +62,7 @@ DCSEx.enums.taskFlag = {
|
|||||||
ON_ROADS = 5,
|
ON_ROADS = 5,
|
||||||
PARKED_AIRCRAFT_TARGET = 6,
|
PARKED_AIRCRAFT_TARGET = 6,
|
||||||
SCENERY_TARGET = 7,
|
SCENERY_TARGET = 7,
|
||||||
|
FRIENDLY_TARGET = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- DCSEX.ZONES - FUNCTIONS RELATED TO MAP TRIGGER ZONES
|
-- DCSEX.ZONES - FUNCTIONS RELATED TO MAP TRIGGER ZONES
|
||||||
-- ====================================================================================
|
-- ====================================================================================
|
||||||
-- DCSEx.zones.drawOnMap(zoneTable, lineColor, fillColor, lineType, drawName, readOnly)
|
-- DCSEx.zones.drawOnMap(zoneTable, lineColor, fillColor, lineType, drawName, readOnly)
|
||||||
-- DCSEx.zones.getAirbases(zone, coalition)
|
-- DCSEx.zones.getAirbases(zone, coalID, allowShips)
|
||||||
-- DCSEx.zones.getAll()
|
-- DCSEx.zones.getAll()
|
||||||
-- DCSEx.zones.getByName(name)
|
-- DCSEx.zones.getByName(name)
|
||||||
-- DCSEx.zones.getCenter(zoneTable)
|
-- DCSEx.zones.getCenter(zoneTable)
|
||||||
@@ -77,20 +77,33 @@ end
|
|||||||
-- Returns all airbases in the zone
|
-- Returns all airbases in the zone
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
-- @param zoneTable Table of the zone in which to search
|
-- @param zoneTable Table of the zone in which to search
|
||||||
-- @param coalition Coalition (from the coalition.side enum) the airbase must belong to. Default is nil, which means "all coalitions"
|
-- @param coalID Coalition (from the coalition.side enum) the airbase must belong to. Default is nil, which means "all coalitions"
|
||||||
|
-- @param allowShips Should ships be allowed?
|
||||||
-- @return Table of airbases
|
-- @return Table of airbases
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
function DCSEx.zones.getAirbases(zoneTable, coalition)
|
function DCSEx.zones.getAirbases(zoneTable, coalID, allowShips)
|
||||||
coalition = coalition or nil
|
coalID = coalID or nil
|
||||||
|
allowShips = allowShips or false
|
||||||
|
|
||||||
local coalitions = { coalition.side.RED, coalition.side.BLUE }
|
local coalitionSides = { coalition.side.RED, coalition.side.BLUE }
|
||||||
if coalition then coalitions = { coalition } end
|
if coalID then coalitionSides = { coalID } end
|
||||||
|
|
||||||
local validAirbases = {}
|
local validAirbases = {}
|
||||||
for _,side in ipairs(coalitions) do
|
for _,side in ipairs(coalitionSides) do
|
||||||
for _,ab in ipairs(coalition.getAirbases(side)) do
|
for _,ab in ipairs(coalition.getAirbases(side)) do
|
||||||
if DCSEx.zones.isPointInside(zoneTable, ab:getPoint()) then
|
local abDesc = ab:getDesc()
|
||||||
table.insert(validAirbases, ab)
|
local isValid = true
|
||||||
|
|
||||||
|
if ab:getDesc().category == Airbase.Category.HELIPAD then
|
||||||
|
isValid = false
|
||||||
|
elseif ab:getDesc().category == Airbase.Category.SHIP and not allowShips then
|
||||||
|
isValid = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if isValid then
|
||||||
|
if DCSEx.zones.isPointInside(zoneTable, ab:getPoint()) then
|
||||||
|
table.insert(validAirbases, ab)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ function TUM.initialize()
|
|||||||
timer.scheduleFunction(TUM.onClockTick, nil, timer.getTime() + math.random(10, 15))
|
timer.scheduleFunction(TUM.onClockTick, nil, timer.getTime() + math.random(10, 15))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
TUM.supportAWACS.create()
|
||||||
end
|
end
|
||||||
|
|
||||||
if TUM.administrativeSettings.getValue(TUM.administrativeSettings.INITIALIZE_AUTOMATICALLY) then
|
if TUM.administrativeSettings.getValue(TUM.administrativeSettings.INITIALIZE_AUTOMATICALLY) then
|
||||||
|
|||||||
@@ -132,14 +132,17 @@ do
|
|||||||
commonWeatherInfo = commonWeatherInfo.." (day, sunset at "..DCSEx.string.getTimeString(Library.environment.getDayTime(nil, true))..")\n"
|
commonWeatherInfo = commonWeatherInfo.." (day, sunset at "..DCSEx.string.getTimeString(Library.environment.getDayTime(nil, true))..")\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
commonWeatherInfo = commonWeatherInfo.."- Cloud cover: "..TUM.weather.getWeatherName(nil, true).."\n"
|
||||||
|
commonWeatherInfo = commonWeatherInfo.."- Wind: "..TUM.weather.getWindName()..", with avg. speed of "..tostring(math.floor(Library.environment.getWindAverage())).."m/s\n"
|
||||||
|
commonWeatherInfo = commonWeatherInfo.."- Average ground-level temperature is "..getTemperatureCelsiusAndFarenheit(env.mission.weather.season.temperature).."\n"
|
||||||
|
|
||||||
local players = coalition.getPlayers(TUM.settings.getPlayerCoalition())
|
local players = coalition.getPlayers(TUM.settings.getPlayerCoalition())
|
||||||
for _,p in ipairs(players) do
|
for _,p in ipairs(players) do
|
||||||
local lTemperature, _ = atmosphere.getTemperatureAndPressure(p:getPoint())
|
local lTemperature, _ = atmosphere.getTemperatureAndPressure(p:getPoint())
|
||||||
|
|
||||||
local localWeatherInfo = "- Average windspeed is "..tostring(math.floor(Library.environment.getWindAverage())).."m/s\n"
|
local localWeatherInfo = ""
|
||||||
localWeatherInfo = localWeatherInfo.."- Windspeed at your location is "..DCSEx.math.getLength3D(atmosphere.getWind(p:getPoint())).."m/s\n"
|
localWeatherInfo = localWeatherInfo.."- Wind speed at your location is "..tostring(math.floor(DCSEx.math.getLength3D(atmosphere.getWind(p:getPoint())))).."m/s\n"
|
||||||
localWeatherInfo = localWeatherInfo.."- Average ground-level temperature is "..getTemperatureCelsiusAndFarenheit(env.mission.weather.season.temperature).."\n"
|
localWeatherInfo = localWeatherInfo.."- Temperature at your location is "..getTemperatureCelsiusAndFarenheit(lTemperature, true).."\n"
|
||||||
localWeatherInfo = localWeatherInfo.."- Temperature at your location is "..getTemperatureCelsiusAndFarenheit(lTemperature, true)
|
|
||||||
|
|
||||||
TUM.radio.playForUnit(DCSEx.dcs.getObjectIDAsNumber(p), "atcWeatherUpdate", { commonWeatherInfo..localWeatherInfo }, "Control", delayRadioAnswer)
|
TUM.radio.playForUnit(DCSEx.dcs.getObjectIDAsNumber(p), "atcWeatherUpdate", { commonWeatherInfo..localWeatherInfo }, "Control", delayRadioAnswer)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -225,11 +225,9 @@ do
|
|||||||
if not event.initiator then return end -- No event initiator
|
if not event.initiator then return end -- No event initiator
|
||||||
if Object.getCategory(event.initiator) ~= Object.Category.UNIT then return end -- Initiator isn't an unit
|
if Object.getCategory(event.initiator) ~= Object.Category.UNIT then return end -- Initiator isn't an unit
|
||||||
if event.initiator:getCoalition() ~= TUM.settings.getPlayerCoalition() then return end -- Not a friendly
|
if event.initiator:getCoalition() ~= TUM.settings.getPlayerCoalition() then return end -- Not a friendly
|
||||||
|
if not event.place then return end -- Not landed at an airbase (e.g. helicopter landing on the ground)
|
||||||
|
|
||||||
local baseName = "AIRBASE"
|
local baseName = event.place:getName():upper()
|
||||||
if event.place then
|
|
||||||
baseName = event.place:getName():upper()
|
|
||||||
end
|
|
||||||
|
|
||||||
if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) or not event.initiator:getPlayerName() then
|
if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) or not event.initiator:getPlayerName() then
|
||||||
doAmbientChatter("atcSafeLanding", {event.initiator:getCallsign(), baseName}, baseName.." ATC", 1)
|
doAmbientChatter("atcSafeLanding", {event.initiator:getCallsign(), baseName}, baseName.." ATC", 1)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Called when a unit is destroyed
|
-- Called when an unit is destroyed
|
||||||
local function onEventDead(event)
|
local function onEventDead(event)
|
||||||
if not event.initiator then return end -- Nothing was hit
|
if not event.initiator then return end -- Nothing was hit
|
||||||
|
|
||||||
@@ -53,6 +53,17 @@ do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Called when an unit takes damage
|
||||||
|
local function onEventHit(event)
|
||||||
|
if not event.initiator then return end -- Nothing was hit
|
||||||
|
if Object.getCategory(event.initiator) ~= Object.Category.UNIT then return end -- Target wasn't an unit
|
||||||
|
if event.initiator:getCoalition() ~= TUM.settings.getEnemyCoalition() then return end -- Unit is not an enemy
|
||||||
|
if event.initiator:getDesc().category ~= Unit.Category.AIRPLANE and event.initiator:getDesc().category ~= Unit.Category.HELICOPTER then return end -- Wasn't an aircraft
|
||||||
|
if event.initiator:inAir() then return end -- Unit is currently in air
|
||||||
|
|
||||||
|
trigger.action.explosion(event.initiator:getPoint(), 100) -- Detonate the parked aircraft, to make it easier to kill
|
||||||
|
end
|
||||||
|
|
||||||
function TUM.ambientWorld.removeAll()
|
function TUM.ambientWorld.removeAll()
|
||||||
for _,id in ipairs(groupIDs) do
|
for _,id in ipairs(groupIDs) do
|
||||||
DCSEx.world.destroyGroupByID(id)
|
DCSEx.world.destroyGroupByID(id)
|
||||||
@@ -70,6 +81,8 @@ do
|
|||||||
|
|
||||||
if event.id == world.event.S_EVENT_DEAD then
|
if event.id == world.event.S_EVENT_DEAD then
|
||||||
onEventDead(event)
|
onEventDead(event)
|
||||||
|
elseif event.id == world.event.S_EVENT_HIT then
|
||||||
|
onEventHit(event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -68,7 +68,10 @@ do
|
|||||||
local runwayTouchEvent = { id = world.event.S_EVENT_RUNWAY_TOUCH, initiator = playerUnit }
|
local runwayTouchEvent = { id = world.event.S_EVENT_RUNWAY_TOUCH, initiator = playerUnit }
|
||||||
TUM.onEvent(runwayTouchEvent)
|
TUM.onEvent(runwayTouchEvent)
|
||||||
|
|
||||||
local landingEvent = { id = world.event.S_EVENT_LAND, initiator = playerUnit }
|
local friendlyAirbases = coalition.getAirbases(TUM.settings.getPlayerCoalition())
|
||||||
|
if not friendlyAirbases or #friendlyAirbases == 0 then return end
|
||||||
|
|
||||||
|
local landingEvent = { id = world.event.S_EVENT_LAND, place = friendlyAirbases[1], initiator = playerUnit }
|
||||||
timer.scheduleFunction(TUM.onEvent, landingEvent, timer.getTime() + 1)
|
timer.scheduleFunction(TUM.onEvent, landingEvent, timer.getTime() + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,16 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
trigger.action.outText("Generating mission and loading assets, this can take some time...", 5)
|
-- If an OCA mission has been selected and the selected target zone doesn't contain any enemy airfield, default to ground attack
|
||||||
|
if TUM.settings.getValue(TUM.settings.id.TASKING) == DCSEx.enums.taskFamily.OCA then
|
||||||
|
local zone = DCSEx.zones.getByName(TUM.settings.getValue(TUM.settings.id.TARGET_LOCATION, true))
|
||||||
|
if #DCSEx.zones.getAirbases(zone, TUM.settings.getEnemyCoalition()) == 0 then
|
||||||
|
trigger.action.outText("OCA tasking selected in a zone without any enemy airfields, defaulting to GROUND ATTACK tasking.", 3)
|
||||||
|
TUM.settings.setValue(TUM.settings.id.TASKING, DCSEx.enums.taskFamily.GROUND_ATTACK, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
trigger.action.outText("Generating mission and loading assets, this can take some time...", 3)
|
||||||
|
|
||||||
-- Add a little delay for the "Generating mission..." message be printed out. Once generation begins, the main DCS thread will be to busy to output anything.
|
-- Add a little delay for the "Generating mission..." message be printed out. Once generation begins, the main DCS thread will be to busy to output anything.
|
||||||
timer.scheduleFunction(TUM.mission.beginMission, false, timer.getTime() + 1)
|
timer.scheduleFunction(TUM.mission.beginMission, false, timer.getTime() + 1)
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ do
|
|||||||
closeMission(true)
|
closeMission(true)
|
||||||
TUM.intermission.removeMissionZonesMarkers()
|
TUM.intermission.removeMissionZonesMarkers()
|
||||||
|
|
||||||
|
TUM.objectivesMaker.clear()
|
||||||
for _=1,TUM.settings.getValue(TUM.settings.id.TARGET_COUNT) do
|
for _=1,TUM.settings.getValue(TUM.settings.id.TARGET_COUNT) do
|
||||||
TUM.objectives.add()
|
TUM.objectives.add()
|
||||||
end
|
end
|
||||||
@@ -72,7 +73,7 @@ do
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
TUM.supportAWACS.create() -- Create the AWACS aircraft if it wasn't airborne already
|
-- TUM.supportAWACS.create() -- Create the AWACS aircraft if it wasn't airborne already
|
||||||
TUM.enemyAirDefense.create() -- Must be called once objectives have been created
|
TUM.enemyAirDefense.create() -- Must be called once objectives have been created
|
||||||
TUM.airForce.create() -- Must be called once objectives have been created
|
TUM.airForce.create() -- Must be called once objectives have been created
|
||||||
TUM.missionMenu.create() -- Must be called once objectives have been created
|
TUM.missionMenu.create() -- Must be called once objectives have been created
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ do
|
|||||||
-- @param event A DCS World event, possibly a S_EVENT_LAND event
|
-- @param event A DCS World event, possibly a S_EVENT_LAND event
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
local function removeAIAircraftOnLandEvent(event)
|
local function removeAIAircraftOnLandEvent(event)
|
||||||
if event.id ~= world.event.S_EVENT_LAND then return end
|
|
||||||
if not event.initiator then return end
|
if not event.initiator then return end
|
||||||
if Object.getCategory(event.initiator) ~= Object.Category.UNIT then return end -- Not an unit
|
if Object.getCategory(event.initiator) ~= Object.Category.UNIT then return end -- Not an unit
|
||||||
if event.initiator:getPlayerName() then return end -- Don't remove player aircraft, that would cause horrendous bugs
|
if event.initiator:getPlayerName() then return end -- Don't remove player aircraft, that would cause horrendous bugs
|
||||||
@@ -73,6 +72,8 @@ do
|
|||||||
-- @param event The DCS World event
|
-- @param event The DCS World event
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
function TUM.mizCleaner.onEvent(event)
|
function TUM.mizCleaner.onEvent(event)
|
||||||
removeAIAircraftOnLandEvent(event)
|
if event.id == world.event.S_EVENT_LAND and event.place then
|
||||||
|
removeAIAircraftOnLandEvent(event)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -168,11 +168,36 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function onObjectiveEvent(index, event)
|
local function onObjectiveEvent(index, event)
|
||||||
|
if not event.initiator then return end
|
||||||
|
|
||||||
if index < 1 or index > #objectives then return end -- Out of bounds
|
if index < 1 or index > #objectives then return end -- Out of bounds
|
||||||
if objectives[index].completed then return end -- Objective already completed
|
if objectives[index].completed then return end -- Objective already completed
|
||||||
|
|
||||||
if event.id ~= world.event.S_EVENT_DEAD and event.id ~= world.event.S_EVENT_UNIT_LOST then return end
|
local completionEvent = Library.tasks[objectives[index].taskID].completionEvent
|
||||||
if not event.initiator then return end
|
|
||||||
|
if completionEvent == DCSEx.enums.taskEvent.DAMAGE then
|
||||||
|
if event.id ~= world.event.S_EVENT_DEAD and event.id ~= world.event.S_EVENT_HIT and event.id ~= world.event.S_EVENT_UNIT_LOST then return end
|
||||||
|
elseif completionEvent == DCSEx.enums.taskEvent.DESTROY then
|
||||||
|
if event.id ~= world.event.S_EVENT_DEAD and event.id ~= world.event.S_EVENT_UNIT_LOST then return end
|
||||||
|
elseif completionEvent == DCSEx.enums.taskEvent.LAND then
|
||||||
|
if event.id ~= world.event.S_EVENT_LAND then return end
|
||||||
|
if Object.getCategory(event.initiator) ~= Object.Category.UNIT then return end
|
||||||
|
if event.initiator:getDesc().category ~= Unit.Category.HELICOPTER then return end
|
||||||
|
if event.initiator:getCoalition() ~= TUM.settings.getPlayerCoalition() then return end
|
||||||
|
if DCSEx.math.getDistance2D(DCSEx.math.vec3ToVec2(event.initiator:getPoint()), objectives[index].point2) > 500 then return end -- Too far from objective
|
||||||
|
|
||||||
|
-- Remove target group if it exists (to simulate it was picked up/captured)
|
||||||
|
if objectives[index].groupID then
|
||||||
|
local targetGroup = DCSEx.world.getGroupByID(objectives[index].groupID)
|
||||||
|
if targetGroup then
|
||||||
|
targetGroup:destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
timer.scheduleFunction(markObjectiveAsComplete, index, timer.getTime() + 3)
|
||||||
|
updateObjectiveText(index)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if objectives[index].isAirbaseTarget then
|
if objectives[index].isAirbaseTarget then
|
||||||
if Object.getCategory(event.initiator) == Object.Category.BASE then
|
if Object.getCategory(event.initiator) == Object.Category.BASE then
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
TUM.objectivesMaker = {}
|
TUM.objectivesMaker = {}
|
||||||
|
|
||||||
do
|
do
|
||||||
|
local usedParkingSpots = {}
|
||||||
|
|
||||||
local function pickRandomTask()
|
local function pickRandomTask()
|
||||||
local taskFamily = TUM.settings.getValue(TUM.settings.id.TASKING)
|
local taskFamily = TUM.settings.getValue(TUM.settings.id.TASKING)
|
||||||
|
|
||||||
@@ -41,6 +43,10 @@ do
|
|||||||
return possiblePoints[1]
|
return possiblePoints[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function TUM.objectivesMaker.clear()
|
||||||
|
usedParkingSpots = {}
|
||||||
|
end
|
||||||
|
|
||||||
function TUM.objectivesMaker.create()
|
function TUM.objectivesMaker.create()
|
||||||
local zone = DCSEx.zones.getByName(TUM.settings.getValue(TUM.settings.id.TARGET_LOCATION, true))
|
local zone = DCSEx.zones.getByName(TUM.settings.getValue(TUM.settings.id.TARGET_LOCATION, true))
|
||||||
|
|
||||||
@@ -88,13 +94,17 @@ do
|
|||||||
local parkings = pickedAirbase:getParking()
|
local parkings = pickedAirbase:getParking()
|
||||||
local validParkings = {}
|
local validParkings = {}
|
||||||
for _,p in pairs(parkings) do
|
for _,p in pairs(parkings) do
|
||||||
if p.Term_Type == 104 then table.insert(validParkings, p) end
|
local parkingUniqueID = pickedAirbase:getID() * 10000 + p.Term_Index
|
||||||
|
if p.Term_Type == 104 and not DCSEx.table.contains(usedParkingSpots, parkingUniqueID) then
|
||||||
|
table.insert(validParkings, p)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if #validParkings == 0 then
|
if #validParkings == 0 then
|
||||||
TUM.log("Failed to find a valid airbase parking to spawn a target.", TUM.logger.logLevel.WARNING)
|
TUM.log("Failed to find a valid airbase parking to spawn a target.", TUM.logger.logLevel.WARNING)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local pickedParking = DCSEx.table.getRandom(validParkings)
|
local pickedParking = DCSEx.table.getRandom(validParkings)
|
||||||
|
table.insert(usedParkingSpots, pickedAirbase:getID() * 10000 + pickedParking.Term_Index) -- Mark parking spot as used so it won't be taken by another objective
|
||||||
parkingInfo = { airbaseID = pickedAirbase:getID(), parkingID = pickedParking.Term_Index }
|
parkingInfo = { airbaseID = pickedAirbase:getID(), parkingID = pickedParking.Term_Index }
|
||||||
spawnPoint3 = pickedParking.vTerminalPos
|
spawnPoint3 = pickedParking.vTerminalPos
|
||||||
spawnPoint2 = DCSEx.math.vec3ToVec2(spawnPoint3)
|
spawnPoint2 = DCSEx.math.vec3ToVec2(spawnPoint3)
|
||||||
@@ -160,10 +170,23 @@ do
|
|||||||
-- Parked aircraft only
|
-- Parked aircraft only
|
||||||
if parkingInfo then
|
if parkingInfo then
|
||||||
groupOptions.airbaseID = parkingInfo.airbaseID
|
groupOptions.airbaseID = parkingInfo.airbaseID
|
||||||
|
groupOptions.invisible = true -- Not ideal because wingmen can't be tasked with attacking targets, but only way I've found to prevent friendly CAP from attacking parked aircraft
|
||||||
groupOptions.parkingID = parkingInfo.parkingID
|
groupOptions.parkingID = parkingInfo.parkingID
|
||||||
end
|
end
|
||||||
|
|
||||||
local units = Library.factions.getUnits(TUM.settings.getEnemyFaction(), objectiveDB.targetFamilies, math.random(objectiveDB.targetCount[1], objectiveDB.targetCount[2]))
|
-- Target group belongs to the enemy coalition, unless DCSEx.enums.taskFlag.FRIENDLY_TARGET is set
|
||||||
|
local groupCoalition = TUM.settings.getEnemyCoalition()
|
||||||
|
local groupFaction = TUM.settings.getEnemyFaction()
|
||||||
|
if DCSEx.table.contains(objectiveDB.flags, DCSEx.enums.taskFlag.FRIENDLY_TARGET) then
|
||||||
|
groupCoalition = TUM.settings.getPlayerCoalition()
|
||||||
|
groupFaction = TUM.settings.getPlayerFaction()
|
||||||
|
|
||||||
|
-- Friendly target groups are immortal and invisible, so AI won't kill them before the player got a chance to interact with them
|
||||||
|
groupOptions.immortal = true
|
||||||
|
groupOptions.invisible = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local units = Library.factions.getUnits(groupFaction, objectiveDB.targetFamilies, math.random(objectiveDB.targetCount[1], objectiveDB.targetCount[2]))
|
||||||
|
|
||||||
local groupInfo = nil
|
local groupInfo = nil
|
||||||
if objectiveDB.targetFamilies[1] == DCSEx.enums.unitFamily.STATIC_STRUCTURE then
|
if objectiveDB.targetFamilies[1] == DCSEx.enums.unitFamily.STATIC_STRUCTURE then
|
||||||
@@ -172,7 +195,7 @@ do
|
|||||||
groupInfo.unitsID = { DCSEx.unitGroupMaker.createStatic(TUM.settings.getEnemyCoalition(), objective.point2, units[1], "") }
|
groupInfo.unitsID = { DCSEx.unitGroupMaker.createStatic(TUM.settings.getEnemyCoalition(), objective.point2, units[1], "") }
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
groupInfo = DCSEx.unitGroupMaker.create(TUM.settings.getEnemyCoalition(), DCSEx.dcs.getUnitCategoryFromFamily(objectiveDB.targetFamilies[1]), objective.point2, units, groupOptions)
|
groupInfo = DCSEx.unitGroupMaker.create(groupCoalition, DCSEx.dcs.getUnitCategoryFromFamily(objectiveDB.targetFamilies[1]), objective.point2, units, groupOptions)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not groupInfo then
|
if not groupInfo then
|
||||||
|
|||||||
@@ -55,7 +55,12 @@ do
|
|||||||
if not objectDesc or not objectDesc.attributes then return 10 end -- No description, assume a default value of 10 points
|
if not objectDesc or not objectDesc.attributes then return 10 end -- No description, assume a default value of 10 points
|
||||||
|
|
||||||
local groundMultiplier = 1
|
local groundMultiplier = 1
|
||||||
if not killedObject:inAir() then groundMultiplier = 0.5 end -- Aircraft killed on the ground are worth less points
|
if not killedObject:inAir() then
|
||||||
|
-- Aircraft killed on the ground are worth less points, except AWACS, bombers and transports
|
||||||
|
if not objectDesc.attributes["AWACS"] and not objectDesc.attributes["Transports"] and not objectDesc.attributes["Strategic bombers"] then
|
||||||
|
groundMultiplier = 0.5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Misc
|
-- Misc
|
||||||
if objectDesc.attributes["Missiles"] then return 10 end
|
if objectDesc.attributes["Missiles"] then return 10 end
|
||||||
@@ -295,11 +300,18 @@ do
|
|||||||
if not DCSEx.io.canReadAndWrite() then return 1.0 end -- IO disabled, career and scoring disabled
|
if not DCSEx.io.canReadAndWrite() then return 1.0 end -- IO disabled, career and scoring disabled
|
||||||
if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return 1.0 end -- No scoring in multiplayer
|
if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return 1.0 end -- No scoring in multiplayer
|
||||||
|
|
||||||
|
-- Base XP multiplier is 1.0 (100%)
|
||||||
local scoreMultiplier = 1.0
|
local scoreMultiplier = 1.0
|
||||||
|
|
||||||
|
-- Add XP multipliers for game settings
|
||||||
for _,v in pairs(TUM.settings.id) do
|
for _,v in pairs(TUM.settings.id) do
|
||||||
scoreMultiplier = scoreMultiplier + (TUM.playerScore.getScoreMultiplier(v) or 0.0)
|
scoreMultiplier = scoreMultiplier + (TUM.playerScore.getScoreMultiplier(v) or 0.0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Add XP multipliers for weather
|
||||||
|
scoreMultiplier = scoreMultiplier + TUM.weather.getWeatherXPModifier()
|
||||||
|
scoreMultiplier = scoreMultiplier + TUM.weather.getWindXPModifier()
|
||||||
|
|
||||||
return math.max(0.0, scoreMultiplier)
|
return math.max(0.0, scoreMultiplier)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -335,7 +347,7 @@ do
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if event.id == world.event.S_EVENT_LAND then
|
if event.id == world.event.S_EVENT_LAND and event.place then
|
||||||
onLandEvent(event)
|
onLandEvent(event)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ do
|
|||||||
[TUM.settings.id.PLAYER_COALITION] = { "Red", "Blue" }, -- Must match values in the coalition.side enum
|
[TUM.settings.id.PLAYER_COALITION] = { "Red", "Blue" }, -- Must match values in the coalition.side enum
|
||||||
[TUM.settings.id.TARGET_COUNT] = { "1", "2", "3", "4" },
|
[TUM.settings.id.TARGET_COUNT] = { "1", "2", "3", "4" },
|
||||||
[TUM.settings.id.TARGET_LOCATION] = { },
|
[TUM.settings.id.TARGET_LOCATION] = { },
|
||||||
[TUM.settings.id.TASKING] = { "Antiship strike", "Ground attack", "Helicopter hunt", "Interception", "OCA", "SEAD", "Strike" }, -- Must match values in the DCSEx.enums.taskFamily enum
|
-- [TUM.settings.id.TASKING] = { "Antiship strike", "Ground attack", "Helicopter-specific tasks", "Helo hunt", "Interception", "Offensive counter-air", "SEAD", "Strike" }, -- Must match values in the DCSEx.enums.taskFamily enum
|
||||||
|
[TUM.settings.id.TASKING] = { "Antiship strike", "Ground attack", "Helo hunt", "Interception", "Offensive counter-air", "SEAD", "Strike" }, -- Must match values in the DCSEx.enums.taskFamily enum
|
||||||
[TUM.settings.id.TIME_PERIOD] = { "World War 2", "Korea War", "Vietnam War", "Late Cold War", "Modern" }, -- Must match values in the DCSEx.enums.timePeriod enum
|
[TUM.settings.id.TIME_PERIOD] = { "World War 2", "Korea War", "Vietnam War", "Late Cold War", "Modern" }, -- Must match values in the DCSEx.enums.timePeriod enum
|
||||||
[TUM.settings.id.WINGMEN] = { "None", "1", "2", "3" }
|
[TUM.settings.id.WINGMEN] = { "None", "1", "2", "3" }
|
||||||
}
|
}
|
||||||
@@ -193,6 +194,10 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Weather
|
||||||
|
summary = summary.."\n\nWEATHER: "..TUM.weather.getWeatherName().." (+"..tostring(math.ceil(TUM.weather.getWeatherXPModifier() * 100)).."% xp)"
|
||||||
|
summary = summary.."\nWIND: "..DCSEx.string.firstToUpper(TUM.weather.getWindName()).." (+"..tostring(math.ceil(TUM.weather.getWindXPModifier() * 100)).."% xp)"
|
||||||
|
|
||||||
if showScoreMultiplier then
|
if showScoreMultiplier then
|
||||||
summary = summary.."\n\nTotal XP modifier: "..tostring(math.ceil(TUM.playerScore.getTotalScoreMultiplier() * 100)).."%"
|
summary = summary.."\n\nTotal XP modifier: "..tostring(math.ceil(TUM.playerScore.getTotalScoreMultiplier() * 100)).."%"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
-- ====================================================================================
|
-- ====================================================================================
|
||||||
-- TUM.SUPPORTJTAC - HANDLES FRIENDLY JTAC SMOKE MARKERS AND LASING
|
-- TUM.SUPPORTJTAC - HANDLES FRIENDLY JTAC SMOKE MARKERS AND LASING
|
||||||
-- ====================================================================================
|
-- ====================================================================================
|
||||||
-- (local) destroyAllLasers()
|
|
||||||
-- (local) doCommandLaser(index)
|
|
||||||
-- (local) doCommandLaserStop(index)
|
|
||||||
-- (local) doCommandSmoke(index)
|
|
||||||
-- (local) spawnSmoke(args)
|
|
||||||
-- (local) updateLaserPositions()
|
|
||||||
-- TUM.supportJTAC.setupJTACOnObjective(index, menuRoot)
|
|
||||||
-- ====================================================================================
|
-- ====================================================================================
|
||||||
|
|
||||||
TUM.supportJTAC = {}
|
TUM.supportJTAC = {}
|
||||||
@@ -35,57 +28,14 @@ do
|
|||||||
"Whiplash",
|
"Whiplash",
|
||||||
}
|
}
|
||||||
|
|
||||||
local LASER_CODE = 1688
|
|
||||||
local LASER_DESIGNATION_PENALTY = -15
|
|
||||||
local SMOKE_DURATION = 300 -- in seconds
|
local SMOKE_DURATION = 300 -- in seconds
|
||||||
local SMOKE_MARKER_PENALTY = -25
|
local SMOKE_MARKER_PENALTY = -25
|
||||||
|
|
||||||
local jtacName = {}
|
local jtacName = {}
|
||||||
local lastSmoke = {}
|
local lastSmoke = {}
|
||||||
local laserSpots = {}
|
|
||||||
local laserTargets = {}
|
|
||||||
|
|
||||||
local function destroyAllLasers()
|
local function spawnSmoke(args)
|
||||||
if #laserSpots == 0 and #laserTargets == 0 then return end
|
trigger.action.smoke(args.point3, args.smokeColor)
|
||||||
|
|
||||||
for _,l in pairs(laserSpots) do
|
|
||||||
if l then l:destroy() end
|
|
||||||
end
|
|
||||||
|
|
||||||
laserSpots = {}
|
|
||||||
laserTargets = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function doCommandLaser(index)
|
|
||||||
local obj = TUM.objectives.getObjective(index)
|
|
||||||
if not obj then return end
|
|
||||||
|
|
||||||
if laserSpots[index] then
|
|
||||||
laserSpots[index]:destroy()
|
|
||||||
laserSpots[index] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local sourceObject = nil
|
|
||||||
local targetPoint = {x = 0, y = 0, z = 0}
|
|
||||||
|
|
||||||
laserSpots[index] = Spot.createLaser(sourceObject, {x = 0, y = 1, z = 0}, targetPoint, LASER_CODE)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function doCommandLaserStop(index)
|
|
||||||
local obj = TUM.objectives.getObjective(index)
|
|
||||||
if not obj then return end
|
|
||||||
|
|
||||||
TUM.radio.playForCoalition(TUM.settings.getPlayerCoalition(), "playerJTACLaserStop", { jtacName[index], obj.name }, TUM.mission.getPlayerCallsign(), false)
|
|
||||||
|
|
||||||
-- Not lasing this objective at the moment
|
|
||||||
if not laserSpots[index] then
|
|
||||||
TUM.radio.playForCoalition(TUM.settings.getPlayerCoalition(), "jtacLaserStopNoLaser", { jtacName[index], obj.name }, jtacName[index], true)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
laserSpots[index]:destroy()
|
|
||||||
laserSpots[index] = nil
|
|
||||||
TUM.radio.playForCoalition(TUM.settings.getPlayerCoalition(), "jtacLaserStop", { jtacName[index], obj.name }, jtacName[index], true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function doCommandSmoke(index)
|
local function doCommandSmoke(index)
|
||||||
@@ -129,24 +79,6 @@ do
|
|||||||
TUM.radio.playForCoalition(TUM.settings.getPlayerCoalition(), "jtacSmokeNoTarget", { jtacName[index] }, jtacName[index], true)
|
TUM.radio.playForCoalition(TUM.settings.getPlayerCoalition(), "jtacSmokeNoTarget", { jtacName[index] }, jtacName[index], true)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function spawnSmoke(args)
|
|
||||||
trigger.action.smoke(args.point3, args.smokeColor)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function updateLaserPositions()
|
|
||||||
-- Not in a mission? Destroy all lasers
|
|
||||||
if TUM.mission.getStatus() == TUM.mission.status.NONE then
|
|
||||||
destroyAllLasers()
|
|
||||||
return timer.getTime() + 0.5
|
|
||||||
end
|
|
||||||
|
|
||||||
for i=1,TUM.objectives.getCount() do
|
|
||||||
-- TODO
|
|
||||||
end
|
|
||||||
|
|
||||||
return timer.getTime() + 0.5
|
|
||||||
end
|
|
||||||
|
|
||||||
function TUM.supportJTAC.setupJTACOnObjective(index, menuRoot)
|
function TUM.supportJTAC.setupJTACOnObjective(index, menuRoot)
|
||||||
local obj = TUM.objectives.getObjective(index)
|
local obj = TUM.objectives.getObjective(index)
|
||||||
if not obj then return end
|
if not obj then return end
|
||||||
@@ -157,10 +89,5 @@ do
|
|||||||
if not DCSEx.table.contains(objectiveDB.flags, DCSEx.enums.taskFlag.ALLOW_JTAC) then return end -- No JTAC for this objective
|
if not DCSEx.table.contains(objectiveDB.flags, DCSEx.enums.taskFlag.ALLOW_JTAC) then return end -- No JTAC for this objective
|
||||||
|
|
||||||
missionCommands.addCommand("Smoke marker on target ("..tostring(SMOKE_MARKER_PENALTY).."xp)", menuRoot, doCommandSmoke, index)
|
missionCommands.addCommand("Smoke marker on target ("..tostring(SMOKE_MARKER_PENALTY).."xp)", menuRoot, doCommandSmoke, index)
|
||||||
missionCommands.addCommand("Designate target with laser (code "..tostring(LASER_CODE)..", "..tostring(LASER_DESIGNATION_PENALTY).."xp)", menuRoot, doCommandLaser, index)
|
|
||||||
missionCommands.addCommand("Stop designating target with laser", menuRoot, doCommandLaserStop, index)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Schedule the laser updating function to be called every 0.5 seconds
|
|
||||||
timer.scheduleFunction(updateLaserPositions, {}, timer.getTime() + 0.5)
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,322 @@
|
|||||||
|
-- ====================================================================================
|
||||||
|
-- TUM.WEATHER - HANDLES THE MISSION'S WEATHER SETTINGS
|
||||||
|
-- ====================================================================================
|
||||||
|
-- ====================================================================================
|
||||||
|
|
||||||
|
TUM.weather = {}
|
||||||
|
|
||||||
|
do
|
||||||
|
local cloudPresets = {
|
||||||
|
-- "Light Scattered 1",
|
||||||
|
Preset1 = {
|
||||||
|
readableName = "Few scattered clouds (METAR: FEW/SCT 7/8)",
|
||||||
|
readableNameShort = "Light scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Light Scattered 2",
|
||||||
|
Preset2 = {
|
||||||
|
readableName = "Two layers few and scattered (METAR: FEW/SCT 8/10 SCT 23/24)",
|
||||||
|
readableNameShort = "Light scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "High Scattered 1",
|
||||||
|
Preset3 = {
|
||||||
|
readableName = "Two layers scattered (METAR: SCT 8/9 FEW 21)",
|
||||||
|
readableNameShort = "High Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "High Scattered 2",
|
||||||
|
Preset4 = {
|
||||||
|
readableName = "Two layers scattered (METAR: SCT 8/10 FEW/SCT 24/26)",
|
||||||
|
readableNameShort = "High Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Scattered 1",
|
||||||
|
Preset5 = {
|
||||||
|
readableName = "Three layers high altitude scattered (METAR: SCT 14/17 FEW 27/29 BKN 40)",
|
||||||
|
readableNameShort = "Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Scattered 2",
|
||||||
|
Preset6 = {
|
||||||
|
readableName = "One layer scattered/broken (METAR: SCT/BKN 8/10 FEW 40)",
|
||||||
|
readableNameShort = "Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Scattered 3",
|
||||||
|
Preset7 = {
|
||||||
|
readableName = "Two layers scattered/broken (METAR: BKN 7.5/12 SCT/BKN 21/23 SCT 40)",
|
||||||
|
readableNameShort = "Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "High Scattered 3",
|
||||||
|
Preset8 = {
|
||||||
|
readableName = "Two layers scattered/broken high altitude (METAR: SCT/BKN 18/20 FEW 36/38 FEW 40)",
|
||||||
|
readableNameShort = "High Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Scattered 4",
|
||||||
|
Preset9 = {
|
||||||
|
readableName = "Two layers broken/scattered (METAR: BKN 7.5/10 SCT 20/22 FEW41)",
|
||||||
|
readableNameShort = "Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Scattered 5",
|
||||||
|
Preset10 = {
|
||||||
|
readableName = "Two layers scattered large thick clouds (METAR: SCT/BKN 18/20 FEW36/38 FEW 40)",
|
||||||
|
readableNameShort = "Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Scattered 6",
|
||||||
|
Preset11 = {
|
||||||
|
readableName = "Two layers scattered large clouds high ceiling (METAR: BKN 18/20 BKN 32/33 FEW 41)",
|
||||||
|
readableNameShort = "Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Scattered 7",
|
||||||
|
Preset12 = {
|
||||||
|
readableName = "Two layers scattered large clouds high ceiling (METAR: BKN 12/14 SCT 22/23 FEW 41)",
|
||||||
|
readableNameShort = "Scattered",
|
||||||
|
xpBonus = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 1",
|
||||||
|
Preset13 = {
|
||||||
|
readableName = "Two layers broken clouds (METAR: BKN 12/14 BKN 26/28 FEW 41)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 2",
|
||||||
|
Preset14 = {
|
||||||
|
readableName = "Broken thick low layer with few high layers\nMETAR: BKN LYR 7/16 FEW 41)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 3",
|
||||||
|
Preset15 = {
|
||||||
|
readableName = "Two layers broken large clouds (METAR: SCT/BKN 14/18 BKN 24/27 FEW 40)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 4",
|
||||||
|
Preset16 = {
|
||||||
|
readableName = "Two layers broken large clouds (METAR: BKN 14/18 BKN 28/30 FEW 40)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 5",
|
||||||
|
Preset17 = {
|
||||||
|
readableName = "Three layers broken/overcast (METAR: BKN/OVC LYR 7/13 20/22 32/34)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 6",
|
||||||
|
Preset18 = {
|
||||||
|
readableName = "Three layers broken/overcast (METAR: BKN/OVC LYR 13/15 25/29 38/41)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 7",
|
||||||
|
Preset19 = {
|
||||||
|
readableName = "Three layers overcast at low level (METAR: OVC 9/16 BKN/OVC LYR 23/24 31/33)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Broken 8",
|
||||||
|
Preset20 = {
|
||||||
|
readableName = "Three layers overcast low level (METAR: BKN/OVC 13/18 BKN 28/30 SCT FEW 38)",
|
||||||
|
readableNameShort = "Broken",
|
||||||
|
xpBonus = 0.05,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast 1",
|
||||||
|
Preset21 = {
|
||||||
|
readableName = "Overcast low level (METAR: BKN/OVC LYR 7/8 17/19)",
|
||||||
|
readableNameShort = "Overcast",
|
||||||
|
xpBonus = 0.10,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast 2",
|
||||||
|
Preset22 = {
|
||||||
|
readableName = "Overcast low level (METAR: BKN LYR 7/10 17/20)",
|
||||||
|
readableNameShort = "Overcast",
|
||||||
|
xpBonus = 0.10,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast 3",
|
||||||
|
Preset23 = {
|
||||||
|
readableName = "Three layers broken low level scattered high (METAR: BKN LYR 11/14 18/25 SCT 32/35)",
|
||||||
|
readableNameShort = "Overcast",
|
||||||
|
xpBonus = 0.10,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast 4",
|
||||||
|
Preset24 = {
|
||||||
|
readableName = "Three layers overcast (METAR: BKN/OVC 3/7 17/22 BKN 34)",
|
||||||
|
readableNameShort = "Overcast",
|
||||||
|
xpBonus = 0.10,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast 5",
|
||||||
|
Preset25 = {
|
||||||
|
readableName = "Three layers overcast (METAR: OVC LYR 12/14 22/25 40/42)",
|
||||||
|
readableNameShort = "Overcast",
|
||||||
|
xpBonus = 0.10,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast 6",
|
||||||
|
Preset26 = {
|
||||||
|
readableName = "Three layers overcast (METAR: OVC 9/15 BKN 23/25 SCT 32)",
|
||||||
|
readableNameShort = "Overcast",
|
||||||
|
xpBonus = 0.10,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast 7",
|
||||||
|
Preset27 = {
|
||||||
|
readableName = "Three layer overcast (METAR: OVC 8/15 SCT/BKN 25/26 34/36)",
|
||||||
|
readableNameShort = "Overcast",
|
||||||
|
xpBonus = 0.10,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast And Rain 1",
|
||||||
|
RainyPreset1 = {
|
||||||
|
readableName = "Overcast with rain (METAR: VIS 3-5KM RA OVC 3/15 28/30 FEW 40)",
|
||||||
|
readableNameShort = "Overcast and rain",
|
||||||
|
xpBonus = 0.25,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast And Rain 2",
|
||||||
|
RainyPreset2 = {
|
||||||
|
readableName = "Overcast with rain (METAR: VIS 1-5KM RA BKN/OVC 3/11 SCT 18/29 FEW 40)",
|
||||||
|
readableNameShort = "Overcast and rain",
|
||||||
|
xpBonus = 0.25,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Overcast And Rain 3",
|
||||||
|
RainyPreset3 = {
|
||||||
|
readableName = "Overcast with rain (METAR: VIS 3-5KM RA OVC LYR 6/18 19/21 SCT 34)",
|
||||||
|
readableNameShort = "Overcast and rain",
|
||||||
|
xpBonus = 0.25,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Light Rain 1",
|
||||||
|
RainyPreset4 = {
|
||||||
|
readableName = "Two layers scattered large thick clouds (METAR: SCT/BKN 18/20 FEW36/38 FEW 40)",
|
||||||
|
readableNameShort = "Light rain",
|
||||||
|
xpBonus = 0.15,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Light Rain 2",
|
||||||
|
RainyPreset5 = {
|
||||||
|
readableName = "Three layers broken/overcast (METAR: BKN/OVC LYR 7/13 20/22 32/34)",
|
||||||
|
readableNameShort = "Light rain",
|
||||||
|
xpBonus = 0.15,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Light Rain 3",
|
||||||
|
RainyPreset6 = {
|
||||||
|
readableName = "Three layers overcast at low level (METAR: OVC 9/16 BKN/OVC LYR 23/24 31/33)",
|
||||||
|
readableNameShort = "Light rain",
|
||||||
|
xpBonus = 0.15,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- "Light Rain 4",
|
||||||
|
NEWRAINPRESET4 = {
|
||||||
|
readableName = "Two layers overcast at low level (METAR: OVC 9/16 BKN/OVC LYR 23/24 31/33)",
|
||||||
|
readableNameShort = "Light rain",
|
||||||
|
xpBonus = 0.15,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local function getWindBeaufortScale(speedInMS)
|
||||||
|
local speedInKMH = DCSEx.converter.mpsToKmph(speedInMS or Library.environment.getWindAverage())
|
||||||
|
|
||||||
|
if speedInKMH < 1 then return 0
|
||||||
|
elseif speedInKMH <= 5 then return 1
|
||||||
|
elseif speedInKMH <= 11 then return 2
|
||||||
|
elseif speedInKMH <= 19 then return 3
|
||||||
|
elseif speedInKMH <= 28 then return 4
|
||||||
|
elseif speedInKMH <= 38 then return 5
|
||||||
|
elseif speedInKMH <= 49 then return 6
|
||||||
|
elseif speedInKMH <= 61 then return 7
|
||||||
|
elseif speedInKMH <= 74 then return 8
|
||||||
|
elseif speedInKMH <= 88 then return 9
|
||||||
|
elseif speedInKMH <= 102 then return 10
|
||||||
|
elseif speedInKMH <= 117 then return 11
|
||||||
|
else return 12
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function TUM.weather.getWeatherName(presetID, longForm)
|
||||||
|
presetID = presetID or env.mission.weather.clouds.preset
|
||||||
|
longForm = longForm or false
|
||||||
|
|
||||||
|
if cloudPresets[presetID] == nil then return "Unknown" end
|
||||||
|
if longForm then return cloudPresets[presetID].readableName end
|
||||||
|
return cloudPresets[presetID].readableNameShort
|
||||||
|
end
|
||||||
|
|
||||||
|
function TUM.weather.getWeatherXPModifier(presetID)
|
||||||
|
presetID = presetID or env.mission.weather.clouds.preset
|
||||||
|
|
||||||
|
if cloudPresets[presetID] == nil then return 0 end
|
||||||
|
|
||||||
|
return cloudPresets[presetID].xpBonus
|
||||||
|
end
|
||||||
|
|
||||||
|
function TUM.weather.getWindName(speedInMS)
|
||||||
|
local windBeaufort = getWindBeaufortScale(speedInMS)
|
||||||
|
|
||||||
|
if windBeaufort == 0 then return "calm"
|
||||||
|
elseif windBeaufort == 1 then return "light air"
|
||||||
|
elseif windBeaufort == 2 then return "light breeze"
|
||||||
|
elseif windBeaufort == 3 then return "gentle breeze"
|
||||||
|
elseif windBeaufort == 4 then return "moderate breeze"
|
||||||
|
elseif windBeaufort == 5 then return "fresh breeze"
|
||||||
|
elseif windBeaufort == 6 then return "strong breeze"
|
||||||
|
elseif windBeaufort == 7 then return "moderate gale"
|
||||||
|
elseif windBeaufort == 8 then return "fresh gale"
|
||||||
|
elseif windBeaufort == 9 then return "strong gale"
|
||||||
|
elseif windBeaufort == 10 then return "storm"
|
||||||
|
elseif windBeaufort == 11 then return "violent storm"
|
||||||
|
elseif windBeaufort == 12 then return "hurricane"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function TUM.weather.getWindXPModifier(speedInMS)
|
||||||
|
local windBeaufort = getWindBeaufortScale(speedInMS)
|
||||||
|
|
||||||
|
if windBeaufort == 0 then return 0.00
|
||||||
|
elseif windBeaufort == 1 then return 0.02
|
||||||
|
elseif windBeaufort == 2 then return 0.04
|
||||||
|
elseif windBeaufort == 3 then return 0.08
|
||||||
|
elseif windBeaufort == 4 then return 0.10
|
||||||
|
elseif windBeaufort == 5 then return 0.12
|
||||||
|
elseif windBeaufort == 6 then return 0.15
|
||||||
|
elseif windBeaufort == 7 then return 0.18
|
||||||
|
elseif windBeaufort == 8 then return 0.21
|
||||||
|
elseif windBeaufort == 9 then return 0.24
|
||||||
|
elseif windBeaufort == 10 then return 0.27
|
||||||
|
elseif windBeaufort == 11 then return 0.30
|
||||||
|
elseif windBeaufort == 12 then return 0.33
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -177,7 +177,7 @@ do
|
|||||||
if not event.initiator:getPlayerName() then return end
|
if not event.initiator:getPlayerName() then return end
|
||||||
if TUM.mission.getStatus() == TUM.mission.status.NONE then return end -- Mission not in progress, no wingman needed
|
if TUM.mission.getStatus() == TUM.mission.status.NONE then return end -- Mission not in progress, no wingman needed
|
||||||
TUM.wingmen.create()
|
TUM.wingmen.create()
|
||||||
elseif event.id == world.event.S_EVENT_LAND then -- Remove wingmen on player landing
|
elseif event.id == world.event.S_EVENT_LAND and event.place then -- Remove wingmen on player landing
|
||||||
if not event.initiator:getPlayerName() then return end
|
if not event.initiator:getPlayerName() then return end
|
||||||
TUM.wingmen.removeAll()
|
TUM.wingmen.removeAll()
|
||||||
elseif event.id == world.event.S_EVENT_PLAYER_ENTER_UNIT then -- Remove wingmen when player takes control of a new unit
|
elseif event.id == world.event.S_EVENT_PLAYER_ENTER_UNIT then -- Remove wingmen when player takes control of a new unit
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
User's manual
|
User's manual
|
||||||
</p>
|
</p>
|
||||||
<p class="heavy">
|
<p class="heavy">
|
||||||
The Universal Mission v0.3.250914<br />
|
The Universal Mission v0.3.251019<br />
|
||||||
Created and maintained by Ambroise Garel (<a href='mailto:akaagarmail@gmail.com'>akaagarmail@gmail.com</a>)
|
Created and maintained by Ambroise Garel (<a href='mailto:akaagarmail@gmail.com'>akaagarmail@gmail.com</a>)
|
||||||
</p>
|
</p>
|
||||||
<p class="heavy">
|
<p class="heavy">
|
||||||
@@ -73,7 +73,6 @@ I hope you'll like it.
|
|||||||
|
|
||||||
- Download the latest release from this GitHub page.
|
- Download the latest release from this GitHub page.
|
||||||
- Copy the provided autoexec.cfg file to your **[Saved Games]\DCS\Config directory**
|
- Copy the provided autoexec.cfg file to your **[Saved Games]\DCS\Config directory**
|
||||||
- Please note: as of DCS 2.9.18.12899, it seems the autoexec.cfg file [is no longer needed](https://www.digitalcombatsimulator.com/en/news/changelog/release/2.9.18.12899/) but I advise you to copy it anyway, ED might change its mind again.
|
|
||||||
- Copy the .miz files for your theater(s) of choice to your **[Saved Games]\DCS\Missions directory**
|
- Copy the .miz files for your theater(s) of choice to your **[Saved Games]\DCS\Missions directory**
|
||||||
- _**(Optional but strongly recommended)**_ Unsanitize the Lua IO module. You don't have to do this, but the persistent career system won't work if you don't. To do it, open the file **[DCS World installation directory]\Scripts\MissionScripting.lua** with a text editor and comment or remove the line "sanitizeModule('io')". Make sure you restart DCS World once you've modified the file.
|
- _**(Optional but strongly recommended)**_ Unsanitize the Lua IO module. You don't have to do this, but the persistent career system won't work if you don't. To do it, open the file **[DCS World installation directory]\Scripts\MissionScripting.lua** with a text editor and comment or remove the line "sanitizeModule('io')". Make sure you restart DCS World once you've modified the file.
|
||||||
- Please note: should you want to backup, delete or transfer it, career progress is saved in **[DCS World installation directory]\TheUniversalMission.sav**
|
- Please note: should you want to backup, delete or transfer it, career progress is saved in **[DCS World installation directory]\TheUniversalMission.sav**
|
||||||
@@ -113,7 +112,10 @@ The exact content of the menu will depend on the current phase of the mission.
|
|||||||
- **Mission type**: What will your mission be?
|
- **Mission type**: What will your mission be?
|
||||||
- **Antiship strike**: Sink enemy warships and cargo ships.
|
- **Antiship strike**: Sink enemy warships and cargo ships.
|
||||||
- **Ground attack**: Interdiction missions against armor, artillery and convoys.
|
- **Ground attack**: Interdiction missions against armor, artillery and convoys.
|
||||||
|
- **Helicopter-specific tasks**: Tasks specifically designed for helicopters (lift/pick up friendly units, suppress infantry...)
|
||||||
|
- **Helicopter hunt**: Shoot down enemy transport and attack helicopters.
|
||||||
- **Interception**: Shoot down strategic airplanes (bombers, transports...) and enemy attack planes on interdiction missions.
|
- **Interception**: Shoot down strategic airplanes (bombers, transports...) and enemy attack planes on interdiction missions.
|
||||||
|
- **Offensive counter-air**: Bomb enemy airbases and destroy parked aircraft. **(Requires a target area with at least one enemy land airbase, or mission type will automatically be changed to ground attack)**
|
||||||
- **SEAD**: Destroy enemy SAM sites.
|
- **SEAD**: Destroy enemy SAM sites.
|
||||||
- **Strike**: Destroy enemy structures and civilian buildings occupied by enemy forces.
|
- **Strike**: Destroy enemy structures and civilian buildings occupied by enemy forces.
|
||||||
- **Target location**: Where on the map will the targets be spawned? Approximate distance to possible regions is displayed in the menu.
|
- **Target location**: Where on the map will the targets be spawned? Approximate distance to possible regions is displayed in the menu.
|
||||||
|
|||||||
Reference in New Issue
Block a user