diff --git a/changelog.md b/changelog.md index f0cfa0bb..096caf61 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,54 @@ +# 2.0.10 + +## Features/Improvements : +* **[Misc]** Now possible to save game in a different file, and to open DCS Liberation savegame files. (You are not restricted to a single save file anymore) +* **[UI/UX]** New dark UI Theme and default theme improvement by Deus +* **[UI/UX]** New "satellite" map backgrounds +* **[UX]** Base menu is opened with a single mouse click +* **[Units/Factions/Mods]** Added Community A-4E-C support for faction Bluefor Cold War +* **[Units/Factions/Mods]** Added MB-339PAN support for faction Bluefor Cold War +* **[Units/Factions/Mods]** Added Rafale AI mod support +* **[Units/Factions/Mods]** Added faction "France Modded" with units from frenchpack v3.5 mod +* **[Units/Factions/Mods]** Added faction "Insurgent modded" with Insurgent units from frenchpack v3.5 mod (Toyota truck) +* **[Units/Factions/Mods]** Added factions Canada 2005, Australia 2005, Japan 2005, USA Aggressors +* **[New Game Wizard]** Added the list of required mods for modded factions. +* **[New Game Wizard]** No more RED vs BLUE opposing faction restrictions. +* **[New Game Wizard]** New campaign generation settings added : No aircraft carrier, no lha, no navy, invert map starting positions. +* **[Mission Generator]** Artillery units will start firing mission after a random delay. It should reduces lag spikes induced by artillery strikes by spreading them out. +* **[Mission Generator]** Ground units will retreat after taking too much casualties. Artillery units will retreat if engaged. +* **[Mission Generator]** The briefing will now contain the carrier ATC frequency +* **[Mission Generator]** The briefing contains a small situation update. +* **[Mission Generator]** Previously destroyed units are visible in the mission. (And added a performance settings to disable this behaviour) +* **[Campaign Generator]** Added Tarawa in caucasus campaigns +* **[Campaign Generator]** Tuned the various existing campaign parameters +* **[Campaign Generator]** Added small campaign : "Russia" on Caucasus Theater + +## Fixed issues : +* **[Mission Generator]** Carrier will sail into the wind, not in the same direction +* **[Mission Generator]** Carrier cold start was not working (flight was starting warm even when cold was selected) +* **[Mission Generator]** Carrier group ships are more spread out +* **[Mission Generator]** Fixed wrong radio frequency for german WW2 warbirds +* **[Mission Generator]** Fixed FW-190A8 spawning with bomb rack for CAP missions +* **[Mission Generator]** Fixed A-20G spawning with no payload +* **[Mission Generator]** Fixed Su-33 spawning too heavy to take off from carrier +* **[Mission Generator]** Fixed Harrier AV-8B spawning too heavy to take off from tarawa +* **[Mission Generator]** Base defense units were not controllable with Combined Arms +* **[Mission Generator]** Tanker speed was too low +* **[Mission Generator]** Tanker TACAN settings were wrong +* **[Mission Generator]** AI aircraft should start datalink ON (EPLRS) +* **[Mission Generator]** Base defense units should not spawn on runway and or taxyway. (The chance for this to happen should now be really really low) +* **[Mission Generator]** Fixed all flights starting "In flight" after playing a few missions (parking slot reset issue) +* **[Mission Script/Performance]** Mission lua script will not listen to weapons fired event anymore and register every fired weapons. This should improve performance especially in WW2 scenarios or when rocket artillery is firing. +* **[Campaign Generator]** Carrier name will now not appear for faction who do not have carriers +* **[Campaign Generator]** SA-10 sites will now have a tracking radar. +* **[Units/Factions]** Remove JF-17 from USA 2005 faction +* **[Units/Factions]** Remove AJS-37 from Russia 2010 +* **[Units/Factions]** Removed Oliver Hazard Perry from cold war factions (too powerful sam system for the era) +* **[Bug]** On the persian gulf full map campaign, the two carriers were sharing the same id, this was causing a lot of bugs +* **[Performance]** Tuned the culling setting so that you cannot run into situation where no friendly or enemy AI flights are generated +* **[Other]** Application doesn't gracefully exit. +* **[Other]** Other minor fixes, and multiples factions small changes + # 2.0 RC 9 ## Features/Improvements : diff --git a/game/data/cap_capabilities_db.py b/game/data/cap_capabilities_db.py new file mode 100644 index 00000000..eb367238 --- /dev/null +++ b/game/data/cap_capabilities_db.py @@ -0,0 +1,33 @@ +from dcs.planes import * +from pydcs_extensions.a4ec.a4ec import A_4E_C + +""" +This list contains the aircraft that do not use the guns as the last resort weapons, but as a main weapon +They'll RTB when they don't have gun ammo left +""" +GUNFIGHTERS = [ + + # Cold War + MiG_15bis, + MiG_19P, + MiG_21Bis, + F_86F_Sabre, + A_4E_C, + F_5E_3, + + # Trainers + C_101CC, + L_39ZA, + + # WW2 + P_51D_30_NA, + P_51D, + P_47D_30, + SpitfireLFMkIXCW, + SpitfireLFMkIX, + Bf_109K_4, + FW_190D9, + FW_190A8, + I_16, + +] \ No newline at end of file diff --git a/game/data/radar_db.py b/game/data/radar_db.py index 0c6e0709..c3c9e25a 100644 --- a/game/data/radar_db.py +++ b/game/data/radar_db.py @@ -49,6 +49,5 @@ UNITS_WITH_RADAR = [ LHA_1_Tarawa, Type_052B_Destroyer, Type_054A_Frigate, - Type_052C_Destroyer, - Type_093, + Type_052C_Destroyer ] \ No newline at end of file diff --git a/game/db.py b/game/db.py index 8b4d16f6..9e2735b0 100644 --- a/game/db.py +++ b/game/db.py @@ -13,20 +13,29 @@ from dcs.unit import * from dcs.unittype import * from dcs.unitgroup import * +from game.factions.australia_2005 import Australia_2005 from game.factions.bluefor_coldwar import BLUEFOR_COLDWAR -from game.factions.china_2000 import China_2000 +from game.factions.bluefor_coldwar_a4 import BLUEFOR_COLDWAR_A4 +from game.factions.bluefor_coldwar_mods import BLUEFOR_COLDWAR_MODS +from game.factions.canada_2005 import Canada_2005 +from game.factions.china_2010 import China_2010 from game.factions.france_1995 import France_1995 from game.factions.france_2005 import France_2005 +from game.factions.france_modded import France_2005_Modded from game.factions.germany_1944_easy import Germany_1944_Easy from game.factions.germany_1990 import Germany_1990 from game.factions.insurgent import Insurgent +from game.factions.insurgent_modded import Insurgent_modded from game.factions.iran_2015 import Iran_2015 from game.factions.israel_2000 import Israel_2000 from game.factions.italy_1990 import Italy_1990 +from game.factions.italy_1990_mb339 import Italy_1990_MB339 +from game.factions.japan_2005 import Japan_2005 from game.factions.libya_2011 import Lybia_2011 from game.factions.netherlands_1990 import Netherlands_1990 from game.factions.north_korea_2000 import NorthKorea_2000 from game.factions.pakistan_2015 import Pakistan_2015 +from game.factions.private_miltary_companies import PMC_WESTERN_B, PMC_RUSSIAN, PMC_WESTERN_A from game.factions.russia_1975 import Russia_1975 from game.factions.germany_1944 import Germany_1944 from game.factions.india_2010 import India_2010 @@ -38,9 +47,11 @@ from game.factions.spain_1990 import Spain_1990 from game.factions.sweden_1990 import Sweden_1990 from game.factions.turkey_2005 import Turkey_2005 from game.factions.uae_2005 import UAE_2005 +from game.factions.uk_1944 import UK_1944 from game.factions.uk_1990 import UnitedKingdom_1990 from game.factions.ukraine_2010 import Ukraine_2010 -from game.factions.usa_1944 import USA_1944 +from game.factions.us_aggressors import US_Aggressors +from game.factions.usa_1944 import USA_1944, ALLIES_1944 from game.factions.usa_1955 import USA_1955 from game.factions.usa_1960 import USA_1960 from game.factions.usa_1965 import USA_1965 @@ -48,6 +59,53 @@ from game.factions.usa_1990 import USA_1990 from game.factions.usa_2005 import USA_2005 from game.factions.bluefor_modern import BLUEFOR_MODERN +# PATCH pydcs data with MODS +from pydcs_extensions.a4ec.a4ec import A_4E_C +from pydcs_extensions.mb339.mb339 import MB_339PAN +import pydcs_extensions.frenchpack.frenchpack as frenchpack +from pydcs_extensions.rafale.rafale import Rafale_A_S, Rafale_M + +plane_map["A-4E-C"] = A_4E_C +plane_map["MB-339PAN"] = MB_339PAN +plane_map["Rafale_M"] = Rafale_M +plane_map["Rafale_A_S"] = Rafale_A_S + +vehicle_map["FieldHL"] = frenchpack._FIELD_HIDE +vehicle_map["HARRIERH"] = frenchpack._FIELD_HIDE_SMALL +vehicle_map["SMOKESAM"] = frenchpack.SMOKE_SAM_IR +vehicle_map["SmokeD1"] = frenchpack.SmokeD1 +vehicle_map["SmokeD3"] = frenchpack.SmokeD3 +vehicle_map["AMX10RCR"] = frenchpack.AMX_10RCR +vehicle_map["SEPAR"] = frenchpack.AMX_10RCR_SEPAR +vehicle_map["ERC"] = frenchpack.ERC_90 +vehicle_map["M120"] = frenchpack.MO_120_RT +vehicle_map["AA20"] = frenchpack._53T2 +vehicle_map["TRM2000"] = frenchpack.TRM_2000 +vehicle_map["TRM2000_Citerne"] = frenchpack.TRM_2000_Fuel +vehicle_map["TRM2000_AA20"] = frenchpack.TRM_2000_53T2 +vehicle_map["TRMMISTRAL"] = frenchpack.TRM_2000_PAMELA +vehicle_map["VABH"] = frenchpack.VAB_MEDICAL +vehicle_map["VAB_RADIO"] = frenchpack.VAB +vehicle_map["VAB_50"] = frenchpack.VAB__50 +vehicle_map["VIB_VBR"] = frenchpack.VAB_T20_13 +vehicle_map["VAB_HOT"] = frenchpack.VAB_MEPHISTO +vehicle_map["VAB_MORTIER"] = frenchpack.VAB_MORTIER +vehicle_map["VBL50"] = frenchpack.VBL__50 +vehicle_map["VBLANF1"] = frenchpack.VBL_AANF1 +vehicle_map["VBL-radio"] = frenchpack.VBL +vehicle_map["VBAE"] = frenchpack.VBAE_CRAB +vehicle_map["VBAE_MMP"] = frenchpack.VBAE_CRAB_MMP +vehicle_map["AMX-30B2"] = frenchpack.AMX_30B2 +vehicle_map["Tracma"] = frenchpack.Tracma_TD_1500 +vehicle_map["JTACFP"] = frenchpack.Infantry_Soldier_JTAC +vehicle_map["SHERIDAN"] = frenchpack.Char_M551_Sheridan +vehicle_map["Leclerc_XXI"] = frenchpack.Leclerc_Serie_XXI +vehicle_map["Toyota_bleu"] = frenchpack.DIM__TOYOTA_BLUE +vehicle_map["Toyota_vert"] = frenchpack.DIM__TOYOTA_GREEN +vehicle_map["Toyota_desert"] = frenchpack.DIM__TOYOTA_DESERT +vehicle_map["Kamikaze"] = frenchpack.DIM__KAMIKAZE + + """ ---------- BEGINNING OF CONFIGURATION SECTION """ @@ -103,6 +161,8 @@ PRICES = { F_4E: 10, AJS37: 12, C_101CC: 6, + A_4E_C: 8, + MB_339PAN: 6, AV8BNA: 14, M_2000C: 16, @@ -131,13 +191,15 @@ PRICES = { Ka_50: 13, SA342M: 8, SA342L: 5, + SA342Minigun: 4, + SA342Mistral: 8, UH_1H: 4, Mi_8MT: 5, - Mi_24V: 12, - Mi_28N: 16, - AH_1W: 10, - AH_64A: 12, - AH_64D: 16, + Mi_24V: 18, + Mi_28N: 24, + AH_1W: 20, + AH_64A: 24, + AH_64D: 30, OH_58D: 6, # Bombers @@ -164,6 +226,10 @@ PRICES = { P_47D_30: 18, B_17G: 30, + # Modded + Rafale_M: 26, + Rafale_A_S: 26, + # armor Armor.APC_MTLB: 4, Armor.FDDM_Grad: 5, @@ -171,15 +237,15 @@ PRICES = { Armor.ARV_BTR_RD: 8, Armor.APC_BTR_80: 8, Armor.MBT_T_55: 18, - Armor.MBT_T_72B: 25, - Armor.MBT_T_80U: 30, - Armor.MBT_T_90: 35, + Armor.MBT_T_72B: 22, + Armor.MBT_T_80U: 25, + Armor.MBT_T_90: 30, Armor.IFV_BMD_1: 8, Armor.IFV_BMP_1: 14, Armor.IFV_BMP_2: 16, Armor.IFV_BMP_3: 18, Armor.ZBD_04A: 12, - Armor.ZTZ_96B: 35, + Armor.ZTZ_96B: 30, Armor.APC_Cobra: 4, Armor.APC_M113: 6, @@ -188,14 +254,14 @@ PRICES = { Armor.IFV_M2A2_Bradley: 12, Armor.APC_M1126_Stryker_ICV: 10, Armor.ATGM_M1134_Stryker: 12, - Armor.MBT_M60A3_Patton: 18, - Armor.MBT_M1A2_Abrams: 35, - Armor.MBT_Leclerc: 35, - Armor.MBT_Leopard_1A3: 24, - Armor.MBT_Leopard_2: 35, - Armor.MBT_Merkava_Mk__4: 35, + Armor.MBT_M60A3_Patton: 16, + Armor.MBT_M1A2_Abrams: 25, + Armor.MBT_Leclerc: 25, + Armor.MBT_Leopard_1A3: 20, + Armor.MBT_Leopard_2: 25, + Armor.MBT_Merkava_Mk__4: 25, Armor.TPz_Fuchs: 5, - Armor.MBT_Challenger_II: 30, + Armor.MBT_Challenger_II: 25, Armor.IFV_Marder: 10, Armor.IFV_MCV_80: 10, Armor.IFV_LAV_25: 7, @@ -208,7 +274,7 @@ PRICES = { Artillery.SPH_2S3_Akatsia: 24, Artillery.SPH_2S19_Msta: 30, Artillery.MLRS_BM_21_Grad: 15, - Artillery.MLRS_9K57_Uragan_BM_27: 40, + Artillery.MLRS_9K57_Uragan_BM_27: 50, Artillery.MLRS_9A52_Smerch: 40, Unarmed.Transport_UAZ_469: 3, @@ -270,6 +336,38 @@ PRICES = { Armed_speedboat: 10, Dry_cargo_ship_Ivanov: 10, Tanker_Elnya_160: 10, + + + # FRENCH PACK MOD + frenchpack.AMX_10RCR: 10, + frenchpack.AMX_10RCR_SEPAR: 12, + frenchpack.ERC_90: 12, + frenchpack.MO_120_RT: 10, + frenchpack._53T2: 4, + frenchpack.TRM_2000: 4, + frenchpack.TRM_2000_Fuel: 4, + frenchpack.TRM_2000_53T2: 8, + frenchpack.TRM_2000_PAMELA: 14, + frenchpack.VAB_MEDICAL: 8, + frenchpack.VAB: 6, + frenchpack.VAB__50: 4, + frenchpack.VAB_T20_13: 6, + frenchpack.VAB_MEPHISTO: 8, + frenchpack.VAB_MORTIER: 10, + frenchpack.VBL__50: 4, + frenchpack.VBL_AANF1: 2, + frenchpack.VBL: 1, + frenchpack.VBAE_CRAB: 8, + frenchpack.VBAE_CRAB_MMP: 12, + frenchpack.AMX_30B2: 18, + frenchpack.Tracma_TD_1500: 2, + frenchpack.Infantry_Soldier_JTAC: 1, + frenchpack.Leclerc_Serie_XXI: 35, + frenchpack.DIM__TOYOTA_BLUE: 2, + frenchpack.DIM__TOYOTA_GREEN: 2, + frenchpack.DIM__TOYOTA_DESERT: 2, + frenchpack.DIM__KAMIKAZE: 6, + } """ @@ -317,6 +415,9 @@ UNIT_BY_TASK = { FW_190A8, SpitfireLFMkIXCW, SpitfireLFMkIX, + A_4E_C, + Rafale_M, + SA342Mistral ], CAS: [ F_86F_Sabre, @@ -333,6 +434,7 @@ UNIT_BY_TASK = { Ka_50, SA342M, SA342L, + SA342Minigun, Su_24M, Su_24MR, AH_64A, @@ -350,7 +452,9 @@ UNIT_BY_TASK = { A_20G, P_47D_30, Ju_88A4, - B_17G + B_17G, + MB_339PAN, + Rafale_A_S ], Transport: [ IL_76MD, @@ -513,6 +617,29 @@ UNIT_BY_TASK = { Artillery.M12_GMC, Artillery.Sturmpanzer_IV_Brummbär, + frenchpack.DIM__TOYOTA_BLUE, + frenchpack.DIM__TOYOTA_DESERT, + frenchpack.DIM__TOYOTA_GREEN, + frenchpack.DIM__KAMIKAZE, + + frenchpack.AMX_10RCR, + frenchpack.AMX_10RCR_SEPAR, + frenchpack.ERC_90, + frenchpack.TRM_2000_PAMELA, + frenchpack.VAB__50, + frenchpack.VAB_MEPHISTO, + frenchpack.VAB_T20_13, + frenchpack.VBL__50, + frenchpack.VBL_AANF1, + frenchpack.VBAE_CRAB, + frenchpack.VBAE_CRAB_MMP, + frenchpack.AMX_30B2, + frenchpack.Leclerc_Serie_XXI, + frenchpack.DIM__TOYOTA_BLUE, + frenchpack.DIM__TOYOTA_GREEN, + frenchpack.DIM__TOYOTA_DESERT, + frenchpack.DIM__KAMIKAZE, + ], AirDefence: [ @@ -602,46 +729,83 @@ Units separated by country. country : DCS Country name """ FACTIONS = { + + "Bluefor Modern": BLUEFOR_MODERN, + "Bluefor Cold War 1970s": BLUEFOR_COLDWAR, + "Bluefor Cold War (with A-4)": BLUEFOR_COLDWAR_A4, + "Bluefor Cold War (with A-4 and MB339)": BLUEFOR_COLDWAR_MODS, + + "USA 1955 (WW2 Pack)": USA_1955, + "USA 1960": USA_1960, + "USA 1965": USA_1965, + "USA 1990": USA_1990, + "USA 2005": USA_2005, + "USA Aggressors 2005": US_Aggressors, + "Russia 1955": Russia_1955, "Russia 1965": Russia_1965, "Russia 1975": Russia_1975, "Russia 1990": Russia_1990, "Russia 2010": Russia_2010, - "Iran 2015": Iran_2015, + + "France 1995": France_1995, + "France 2005": France_2005, + "France 2005 (Modded)": France_2005_Modded, + + "Germany 1990": Germany_1990, + + "Netherlands 1990": Netherlands_1990, + + "United Kingdown 1990": UnitedKingdom_1990, + + "Spain 1990": Spain_1990, + + "Italy 1990": Italy_1990, + "Italy 1990 (With MB339)": Italy_1990_MB339, + + "Israel 2000": Israel_2000, + + "China 2010": China_2010, + + "Sweden 1990": Sweden_1990, + + "Australia 2005": Australia_2005, + + "Canada 2005": Canada_2005, + + "Japan 2005": Japan_2005, + + "Turkey 2005": Turkey_2005, + + "United Arab Emirates 2005": UAE_2005, + + "Ukraine 2010": Ukraine_2010, + + "India 2010": India_2010, + "Lybia 2011": Lybia_2011, - "China 2000": China_2000, + + "Pakistan 2015": Pakistan_2015, + + "Iran 2015": Iran_2015, + "North Korea 2000": NorthKorea_2000, + "Insurgent": Insurgent, + "Insurgent (Modded)": Insurgent_modded, + + "PMC (American)": PMC_WESTERN_A, + "PMC (American) - MB339": PMC_WESTERN_B, + "PMC (Russian)": PMC_RUSSIAN, + + "Allies 1944 (WW2 Pack)": USA_1944, + "USA 1944 (WW2 Pack)": ALLIES_1944, + "UK 1944 (WW2 Pack)": UK_1944, + "Germany 1944 (WW2 Pack)": Germany_1944, "Germany 1944 Easy (WW2 Pack)": Germany_1944_Easy, - "Bluefor Modern": BLUEFOR_MODERN, - "Bluefor Cold War 1970s": BLUEFOR_COLDWAR, - "USA 2005": USA_2005, - "USA 1990": USA_1990, - "USA 1965": USA_1965, - "USA 1960": USA_1960, - "USA 1955 (WW2 Pack)": USA_1955, - "Allies 1944 (WW2 Pack)": USA_1944, - - "France 2005": France_2005, - "France 1995": France_1995, - "Germany 1990": Germany_1990, - "Netherlands 1990": Netherlands_1990, - "United Kingdown 1990": UnitedKingdom_1990, - "Spain 1990": Spain_1990, - "Italy 1990": Italy_1990, - "Sweden 1990": Sweden_1990, - "Ukraine 2010": Ukraine_2010, - "India 2010": India_2010, - "Pakistan 2015": Pakistan_2015, - "Israel 2000": Israel_2000, - "Turkey 2005": Turkey_2005, - "United Arab Emirates 2005": UAE_2005, - } -BLUEFOR_FACTIONS = [FACTIONS[f]["country"] for f in FACTIONS if FACTIONS[f]["side"] == "blue"] -print(BLUEFOR_FACTIONS) CARRIER_TYPE_BY_PLANE = { @@ -749,6 +913,12 @@ PLANE_PAYLOAD_OVERRIDES = { Bf_109K_4: COMMON_OVERRIDE, SpitfireLFMkIXCW: COMMON_OVERRIDE, SpitfireLFMkIX: COMMON_OVERRIDE, + A_20G: COMMON_OVERRIDE, + A_4E_C: COMMON_OVERRIDE, + MB_339PAN: COMMON_OVERRIDE, + Rafale_M: COMMON_OVERRIDE, + Rafale_A_S: COMMON_OVERRIDE, + OH_58D: COMMON_OVERRIDE, AH_64D:{ CAS: "AGM-114K*16" @@ -825,12 +995,14 @@ CARRIER_CAPABLE = [ F_14B, AV8BNA, Su_33, + A_4E_C, UH_1H, Mi_8MT, Ka_50, AH_1W, OH_58D, + UH_60A, SA342L, SA342M, @@ -846,6 +1018,7 @@ LHA_CAPABLE = [ Ka_50, AH_1W, OH_58D, + UH_60A, SA342L, SA342M, @@ -919,6 +1092,8 @@ def find_infantry(country_name: str) -> typing.List[UnitType]: def unit_type_name(unit_type) -> str: return unit_type.id and unit_type.id or unit_type.name +def unit_type_name_2(unit_type) -> str: + return unit_type.name and unit_type.name or unit_type.id def unit_type_from_name(name: str) -> UnitType: if name in vehicle_map: diff --git a/game/event/event.py b/game/event/event.py index 69768d27..01be1f59 100644 --- a/game/event/event.py +++ b/game/event/event.py @@ -206,10 +206,10 @@ class Event: # ------------------------------ # Captured bases - if self.game.player_country in db.BLUEFOR_FACTIONS: - coalition = 2 # Value in DCS mission event for BLUE - else: - coalition = 1 # Value in DCS mission event for RED + #if self.game.player_country in db.BLUEFOR_FACTIONS: + coalition = 2 # Value in DCS mission event for BLUE + #else: + # coalition = 1 # Value in DCS mission event for RED for captured in debriefing.base_capture_events: try: @@ -253,6 +253,12 @@ class Event: except Exception as e: print(e) + # Destroyed units carcass + # ------------------------- + + for destroyed_unit in debriefing.destroyed_units: + self.game.add_destroyed_units(destroyed_unit) + # ----------------------------------- # Compute damage to bases for cp in self.game.theater.player_points(): diff --git a/game/factions/australia_2005.py b/game/factions/australia_2005.py new file mode 100644 index 00000000..df4972e6 --- /dev/null +++ b/game/factions/australia_2005.py @@ -0,0 +1,50 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +Australia_2005 = { + "country": "Australia", + "side": "blue", + "units": [ + FA_18C_hornet, + + KC_135, + KC130, + C_130, + E_3A, + + Armor.MBT_M1A2_Abrams, + Armor.MBT_Leopard_1A3, + Armor.APC_M113, + Armor.IFV_LAV_25, + Armor.IFV_MCV_80, + + UH_1H, + AH_1W, # Standing as EC Tiger + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Hawk_PCP, + AirDefence.Rapier_FSA_Launcher, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ], "shorad": [ + AirDefence.Rapier_FSA_Launcher, + ], "helicopter_carrier": [ + LHA_1_Tarawa, + ], "destroyer": [ + USS_Arleigh_Burke_IIa, + ], "cruiser": [ + Ticonderoga_class, + ], "lhanames": [ + "HMAS Canberra", + "HMAS Adelaide" + ], "boat":[ + "ArleighBurkeGroupGenerator" + ], "has_jtac": True +} diff --git a/game/factions/bluefor_coldwar.py b/game/factions/bluefor_coldwar.py index cc2361a9..70bf9467 100644 --- a/game/factions/bluefor_coldwar.py +++ b/game/factions/bluefor_coldwar.py @@ -42,10 +42,6 @@ BLUEFOR_COLDWAR = { CVN_74_John_C__Stennis, ], "helicopter_carrier": [ LHA_1_Tarawa, - ], "destroyer": [ - Oliver_Hazzard_Perry_class, - ], "cruiser": [ - Ticonderoga_class, ], "carrier_names": [ "CVN-71 Theodore Roosevelt", "CVN-72 Abraham Lincoln", @@ -57,7 +53,6 @@ BLUEFOR_COLDWAR = { "LHA-3 Belleau Wood", "LHA-4 Nassau", "LHA-5 Peleliu" - ], "boat":[ - "OliverHazardPerryGroupGenerator" - ] + ], "boat": [ + ], "has_jtac": True } diff --git a/game/factions/bluefor_coldwar_a4.py b/game/factions/bluefor_coldwar_a4.py new file mode 100644 index 00000000..5bf366f5 --- /dev/null +++ b/game/factions/bluefor_coldwar_a4.py @@ -0,0 +1,65 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +from pydcs_extensions.a4ec.a4ec import A_4E_C + +BLUEFOR_COLDWAR_A4 = { + "country": "USA", + "side": "blue", + "units": [ + + F_14B, + F_4E, + F_5E_3, + A_10A, + AJS37, + A_4E_C, + + KC_135, + KC130, + C_130, + E_3A, + + UH_1H, + SA342M, + SA342L, + + Armor.MBT_M60A3_Patton, + Armor.APC_M113, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Hawk_PCP, + AirDefence.SAM_Chaparral_M48, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ], "shorad": [ + AirDefence.AAA_Vulcan_M163, + ], "aircraft_carrier": [ + CVN_74_John_C__Stennis, + ], "helicopter_carrier": [ + LHA_1_Tarawa, + ], "cruiser": [ + Ticonderoga_class, + ], "carrier_names": [ + "CVN-71 Theodore Roosevelt", + "CVN-72 Abraham Lincoln", + "CVN-73 George Washington", + "CVN-74 John C. Stennis", + ], "lhanames": [ + "LHA-1 Tarawa", + "LHA-2 Saipan", + "LHA-3 Belleau Wood", + "LHA-4 Nassau", + "LHA-5 Peleliu" + ], "boat": [ + ], "requirements": { + "Community A-4E": "https://heclak.github.io/community-a4e-c/", + }, "has_jtac": True +} diff --git a/game/factions/bluefor_coldwar_mods.py b/game/factions/bluefor_coldwar_mods.py new file mode 100644 index 00000000..aece4e46 --- /dev/null +++ b/game/factions/bluefor_coldwar_mods.py @@ -0,0 +1,68 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +from pydcs_extensions.a4ec.a4ec import A_4E_C +from pydcs_extensions.mb339.mb339 import MB_339PAN + +BLUEFOR_COLDWAR_MODS = { + "country": "USA", + "side": "blue", + "units": [ + + F_14B, + F_4E, + F_5E_3, + A_10A, + AJS37, + A_4E_C, + MB_339PAN, + + KC_135, + KC130, + C_130, + E_3A, + + UH_1H, + SA342M, + SA342L, + + Armor.MBT_M60A3_Patton, + Armor.APC_M113, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Hawk_PCP, + AirDefence.SAM_Chaparral_M48, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ], "shorad": [ + AirDefence.AAA_Vulcan_M163, + ], "aircraft_carrier": [ + CVN_74_John_C__Stennis, + ], "helicopter_carrier": [ + LHA_1_Tarawa, + ], "cruiser": [ + Ticonderoga_class, + ], "carrier_names": [ + "CVN-71 Theodore Roosevelt", + "CVN-72 Abraham Lincoln", + "CVN-73 George Washington", + "CVN-74 John C. Stennis", + ], "lhanames": [ + "LHA-1 Tarawa", + "LHA-2 Saipan", + "LHA-3 Belleau Wood", + "LHA-4 Nassau", + "LHA-5 Peleliu" + ], "boat": [ + ], "requirements": { + "MB-339A": "http://www.freccetricolorivirtuali.net/", + "Community A-4E": "https://heclak.github.io/community-a4e-c/", + }, "has_jtac": True +} diff --git a/game/factions/bluefor_modern.py b/game/factions/bluefor_modern.py index 3d04bb3b..ca64e2f5 100644 --- a/game/factions/bluefor_modern.py +++ b/game/factions/bluefor_modern.py @@ -78,5 +78,5 @@ BLUEFOR_MODERN = { "LHA-5 Peleliu" ], "boat":[ "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } diff --git a/game/factions/canada_2005.py b/game/factions/canada_2005.py new file mode 100644 index 00000000..ea4497ca --- /dev/null +++ b/game/factions/canada_2005.py @@ -0,0 +1,43 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +Canada_2005 = { + "country": "Canada", + "side": "blue", + "units": [ + FA_18C_hornet, + + KC_135, + KC130, + C_130, + E_3A, + + Armor.MBT_Leopard_1A3, + Armor.MBT_Leopard_2, + Armor.IFV_LAV_25, + Armor.APC_M113, + Armor.IFV_MCV_80, + + UH_1H, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Avenger_M1097, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ], "shorad": [ + AirDefence.SAM_Avenger_M1097, + ], "destroyer": [ + USS_Arleigh_Burke_IIa, + ], "cruiser": [ + Ticonderoga_class, + ], "boat":[ + "ArleighBurkeGroupGenerator" + ], "has_jtac": True +} diff --git a/game/factions/china_2000.py b/game/factions/china_2010.py similarity index 77% rename from game/factions/china_2000.py rename to game/factions/china_2010.py index f1b4e04f..b13faec4 100644 --- a/game/factions/china_2000.py +++ b/game/factions/china_2010.py @@ -3,7 +3,7 @@ from dcs.planes import * from dcs.ships import * from dcs.vehicles import * -China_2000 = { +China_2010 = { "country": "China", "side": "red", "units": [ @@ -37,7 +37,9 @@ China_2000 = { Unarmed.Transport_Ural_375, Unarmed.Transport_UAZ_469, - Infantry.Soldier_AK, + + Infantry.Paratrooper_AKS, + Infantry.Infantry_Soldier_Rus, Infantry.Paratrooper_RPG_16, CV_1143_5_Admiral_Kuznetsov, @@ -56,10 +58,20 @@ China_2000 = { Type_052C_Destroyer ], "cruiser": [ Type_054A_Frigate, + ], "helicopter_carrier": [ + Type_071_Amphibious_Transport_Dock, + ], "lhanames": [ + "Kunlun Shan", + "Jinggang Shan", + "Changbai Shan", + "Yimeng Shan", + "Longhu Shan", + "Wuzhi Shan", + "Wudang Shan" ], "carrier_names": [ "001 Liaoning", "002 Shandong", ], "boat":[ - "ChineseNavyGroupGenerator", "Type54GroupGenerator" - ] + "Type54GroupGenerator" + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/france_1995.py b/game/factions/france_1995.py index 8ba1e71b..acf56495 100644 --- a/game/factions/france_1995.py +++ b/game/factions/france_1995.py @@ -17,6 +17,7 @@ France_1995 = { SA342M, SA342L, + SA342Mistral, Armor.MBT_Leclerc, Armor.TPz_Fuchs, # Standing as VAB @@ -42,5 +43,5 @@ France_1995 = { AirDefence.SAM_Roland_ADS ], "boat":[ "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/france_2005.py b/game/factions/france_2005.py index 2ae2e7fd..b2f4b87a 100644 --- a/game/factions/france_2005.py +++ b/game/factions/france_2005.py @@ -18,6 +18,7 @@ France_2005 = { SA342M, SA342L, + SA342Mistral, Armor.MBT_Leclerc, Armor.TPz_Fuchs, # Standing as VAB @@ -50,12 +51,12 @@ France_2005 = { ], "cruiser": [ Ticonderoga_class, ], "carrier_names": [ - "R91 Charles de Gaulle", + "PA Charles de Gaulle", ], "lhanames": [ "L9013 Mistral", "L9014 Tonerre", "L9015 Dixmude" ], "boat":[ "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/france_modded.py b/game/factions/france_modded.py new file mode 100644 index 00000000..ad0f7de5 --- /dev/null +++ b/game/factions/france_modded.py @@ -0,0 +1,80 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +import pydcs_extensions.frenchpack.frenchpack as frenchpack +from pydcs_extensions.rafale.rafale import Rafale_M, Rafale_A_S + +France_2005_Modded = { + "country": "France", + "side": "blue", + "units": [ + M_2000C, + Mirage_2000_5, + Rafale_M, + Rafale_A_S, + + KC_135, + KC130, + C_130, + E_3A, + + SA342M, + SA342L, + SA342Mistral, + + Armor.MBT_Leclerc, + Artillery.SPH_M109_Paladin, # Standing as AMX30 AuF1 + Artillery.MLRS_M270, + + frenchpack.AMX_10RCR, + frenchpack.AMX_10RCR_SEPAR, + frenchpack.ERC_90, + frenchpack.TRM_2000_PAMELA, + frenchpack.VAB__50, + frenchpack.VAB_MEPHISTO, + frenchpack.VAB_T20_13, + frenchpack.VBL__50, + frenchpack.VBL_AANF1, + frenchpack.VBAE_CRAB, + frenchpack.VBAE_CRAB_MMP, + frenchpack.AMX_30B2, + frenchpack.Leclerc_Serie_XXI, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Roland_ADS, + AirDefence.SAM_Hawk_PCP, + AirDefence.HQ_7_Self_Propelled_LN, # Standing as Crotale + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + + ], "shorad": [ + AirDefence.HQ_7_Self_Propelled_LN, + AirDefence.SAM_Roland_ADS + ], "aircraft_carrier": [ + CVN_74_John_C__Stennis, # Standing as CDG Aircraft Carrier + ], "helicopter_carrier": [ + LHA_1_Tarawa, # Standing as Mistral Class + ], "destroyer": [ + Oliver_Hazzard_Perry_class, + ], "cruiser": [ + Ticonderoga_class, + ], "carrier_names": [ + "PA Charles de Gaulle", + ], "lhanames": [ + "L9013 Mistral", + "L9014 Tonerre", + "L9015 Dixmude" + ], "boat": [ + "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" + ], "requirements": { + "frenchpack V3.5": "https://forums.eagle.ru/showthread.php?t=279974", + "RAFALE 2.5.5": "https://www.digitalcombatsimulator.com/fr/files/3307478/", + }, "has_jtac": True +} \ No newline at end of file diff --git a/game/factions/germany_1944.py b/game/factions/germany_1944.py index df48c434..f5f95669 100644 --- a/game/factions/germany_1944.py +++ b/game/factions/germany_1944.py @@ -39,7 +39,7 @@ Germany_1944 = { "objects": WW2_GERMANY_BUILDINGS, "doctrine": WWII_DOCTRINE, "boat": ["UBoatGroupGenerator", "SchnellbootGroupGenerator"], - "boat_count": 4, + "boat_count": 2, "missiles": ["V1GroupGenerator"], "missiles_count": 1 } \ No newline at end of file diff --git a/game/factions/germany_1944_easy.py b/game/factions/germany_1944_easy.py index ca929c13..6e4474bb 100644 --- a/game/factions/germany_1944_easy.py +++ b/game/factions/germany_1944_easy.py @@ -32,7 +32,7 @@ Germany_1944_Easy = { "objects": WW2_GERMANY_BUILDINGS, "doctrine": WWII_DOCTRINE, "boat": ["UBoatGroupGenerator", "SchnellbootGroupGenerator"], - "boat_count": 4, + "boat_count": 1, "missiles": ["V1GroupGenerator"], "missiles_count": 1 } \ No newline at end of file diff --git a/game/factions/india_2010.py b/game/factions/india_2010.py index 47a1d5b2..2dc756ec 100644 --- a/game/factions/india_2010.py +++ b/game/factions/india_2010.py @@ -51,5 +51,5 @@ India_2010 = { "INS Vikramaditya" ], "boat":[ "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator", "MolniyaGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/insurgent_modded.py b/game/factions/insurgent_modded.py new file mode 100644 index 00000000..39e1e174 --- /dev/null +++ b/game/factions/insurgent_modded.py @@ -0,0 +1,33 @@ +from dcs.ships import * +from dcs.vehicles import * + +from pydcs_extensions.frenchpack.frenchpack import DIM__TOYOTA_BLUE, DIM__TOYOTA_DESERT, DIM__TOYOTA_GREEN, \ + DIM__KAMIKAZE + +Insurgent_modded = { + "country": "Insurgents", + "side": "red", + "units": [ + + AirDefence.AAA_ZU_23_Insurgent_Closed, + AirDefence.AAA_ZU_23_Insurgent_on_Ural_375, + + DIM__TOYOTA_BLUE, + DIM__TOYOTA_DESERT, + DIM__TOYOTA_GREEN, + DIM__KAMIKAZE, + Armor.ARV_BRDM_2, + Armor.APC_Cobra, + + Unarmed.Transport_Ural_375, + Unarmed.Transport_UAZ_469, + Infantry.Soldier_AK, + Infantry.Infantry_Soldier_Insurgents, + + Bulk_cargo_ship_Yakushev, + Dry_cargo_ship_Ivanov, + Tanker_Elnya_160 + ], "requirements": { + "frenchpack V3.5": "https://forums.eagle.ru/showthread.php?t=279974", + } +} \ No newline at end of file diff --git a/game/factions/israel_2000.py b/game/factions/israel_2000.py index f135432e..163bbfe3 100644 --- a/game/factions/israel_2000.py +++ b/game/factions/israel_2000.py @@ -35,5 +35,5 @@ Israel_2000 = { AirDefence.SAM_Avenger_M1097 ], "boat": [ "ArleighBurkeGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/italy_1990.py b/game/factions/italy_1990.py index 594baa9e..2c2175a8 100644 --- a/game/factions/italy_1990.py +++ b/game/factions/italy_1990.py @@ -39,10 +39,10 @@ Italy_1990 = { Oliver_Hazzard_Perry_class, ], "cruiser": [ Ticonderoga_class, - ], "lha_names": [ + ], "lhanames": [ "Giuseppe Garibaldi", "Cavour", ], "boat":[ "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } diff --git a/game/factions/italy_1990_mb339.py b/game/factions/italy_1990_mb339.py new file mode 100644 index 00000000..92307749 --- /dev/null +++ b/game/factions/italy_1990_mb339.py @@ -0,0 +1,52 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +from pydcs_extensions.mb339.mb339 import MB_339PAN + +Italy_1990_MB339 = { + "country": "Italy", + "side": "blue", + "units": [ + Tornado_IDS, + AV8BNA, + MB_339PAN, + + KC_135, + S_3B_Tanker, + C_130, + E_3A, + + AH_1W, + UH_1H, + + Armor.MBT_Leopard_1A3, # OF-40 MBT + Armor.APC_M113, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + + AirDefence.SAM_Hawk_PCP, + AirDefence.SAM_Avenger_M1097, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ], "shorad":[ + AirDefence.SAM_Avenger_M1097, + ], "helicopter_carrier": [ + LHA_1_Tarawa, + ], "destroyer": [ + Oliver_Hazzard_Perry_class, + ], "cruiser": [ + Ticonderoga_class, + ], "lhanames": [ + "Giuseppe Garibaldi", + "Cavour", + ], "boat": [ + "OliverHazardPerryGroupGenerator" + ], "requirements": { + "MB-339A": "http://www.freccetricolorivirtuali.net/", + }, "has_jtac": True +} diff --git a/game/factions/japan_2005.py b/game/factions/japan_2005.py new file mode 100644 index 00000000..c9657348 --- /dev/null +++ b/game/factions/japan_2005.py @@ -0,0 +1,54 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +Japan_2005 = { + "country": "Japan", + "side": "blue", + "units": [ + F_15C, # F-15J/DJ + F_16C_50, # F-2A/B + F_4E, # F-4EJ + + KC_135, + KC130, + C_130, + E_3A, + + AH_1W, + AH_64D, + + Armor.MBT_Merkava_Mk__4, # Standing as Type 10 MBT + Armor.MBT_M1A2_Abrams, # Standing as Type 90 MBT + Armor.IFV_Marder, # Standing as Type 89 IFV + Armor.TPz_Fuchs, # Standing as Type 96 APC + Armor.IFV_LAV_25, # Standing as Type 16 or Type 87 + Armor.APC_M1043_HMMWV_Armament, + + Artillery.MLRS_M270, + Artillery.SPH_M109_Paladin, # Standing as Type 99 SPH + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Hawk_PCP, + AirDefence.SAM_Patriot_EPP_III, + + LHA_1_Tarawa, + ], "shorad": [ + AirDefence.SPAAA_Gepard, # Type 87 SPAG + ], "helicopter_carrier": [ + LHA_1_Tarawa, # Standing as Hyuga-class helicopter carrier + ], "destroyer": [ + USS_Arleigh_Burke_IIa, + ], "cruiser": [ + Ticonderoga_class, + ], "lhanames": [ + "Hyuga", + "Ise", + ], "boat":[ + "ArleighBurkeGroupGenerator" + ], "has_jtac": True +} diff --git a/game/factions/libya_2011.py b/game/factions/libya_2011.py index b84a83fd..9e14e0af 100644 --- a/game/factions/libya_2011.py +++ b/game/factions/libya_2011.py @@ -3,7 +3,7 @@ from dcs.planes import * from dcs.vehicles import * Lybia_2011 = { - "country": "Russia", + "country": "Lybia", "side": "red", "units": [ diff --git a/game/factions/netherlands_1990.py b/game/factions/netherlands_1990.py index 2ef42ba0..b32fe7d0 100644 --- a/game/factions/netherlands_1990.py +++ b/game/factions/netherlands_1990.py @@ -34,5 +34,5 @@ Netherlands_1990 = { AirDefence.SAM_Avenger_M1097 ], "boat": [ "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } diff --git a/game/factions/pakistan_2015.py b/game/factions/pakistan_2015.py index 549deebd..b5fa5f29 100644 --- a/game/factions/pakistan_2015.py +++ b/game/factions/pakistan_2015.py @@ -36,5 +36,5 @@ Pakistan_2015 = { AirDefence.AAA_ZU_23_Closed ], "boat": [ "Type54GroupGenerator", "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } diff --git a/game/factions/private_miltary_companies.py b/game/factions/private_miltary_companies.py new file mode 100644 index 00000000..4f2860ca --- /dev/null +++ b/game/factions/private_miltary_companies.py @@ -0,0 +1,91 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +from pydcs_extensions.mb339.mb339 import MB_339PAN + +PMC_WESTERN_A = { + "country": "USA", + "side": "blue", + "units": [ + C_101CC, + + UH_1H, + Mi_8MT, + OH_58D, + SA342M, + + Armor.APC_M1043_HMMWV_Armament, + Armor.IFV_MCV_80, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Avenger_M1097, + + Armed_speedboat, + ], "shorad":[ + AirDefence.SAM_Avenger_M1097, + ], "has_jtac": True +} + +PMC_WESTERN_B = { + "country": "USA", + "side": "blue", + "units": [ + MB_339PAN, + C_101CC, + + UH_1H, + Mi_8MT, + OH_58D, + SA342M, + + Armor.APC_M1043_HMMWV_Armament, + Armor.IFV_MCV_80, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Avenger_M1097, + + Armed_speedboat, + ], "shorad":[ + AirDefence.SAM_Avenger_M1097, + ], "has_jtac": True, + "requirements": { + "MB-339A": "http://www.freccetricolorivirtuali.net/", + } +} + +PMC_RUSSIAN = { + "country": "Russia", + "side": "blue", + "units": [ + L_39C, + L_39ZA, + + Mi_8MT, + Mi_24V, + Ka_50, + + Armor.APC_Cobra, + Armor.APC_BTR_80, + Armor.ARV_BRDM_2, + + Unarmed.Transport_Ural_375, + Infantry.Paratrooper_AKS, + Infantry.Paratrooper_RPG_16, + + AirDefence.AAA_ZU_23_on_Ural_375, + + Armed_speedboat, + ], "shorad":[ + AirDefence.AAA_ZU_23_on_Ural_375, + AirDefence.AAA_ZU_23_Closed, + ], "has_jtac": True +} + diff --git a/game/factions/russia_1990.py b/game/factions/russia_1990.py index 2884ad3d..21b8b257 100644 --- a/game/factions/russia_1990.py +++ b/game/factions/russia_1990.py @@ -58,6 +58,9 @@ Russia_1990 = { AirDefence.SAM_SA_9_Strela_1_9P31, AirDefence.SAM_SA_13_Strela_10M3_9A35M3, AirDefence.SPAAA_ZSU_23_4_Shilka + ], "carrier_names": [ + "Admiral Kuznetov", + "Admiral Gorshkov" ], "aircraft_carrier": [ CV_1143_5_Admiral_Kuznetsov, ], "destroyer": [ diff --git a/game/factions/russia_2010.py b/game/factions/russia_2010.py index 28745b9a..ee219fd4 100644 --- a/game/factions/russia_2010.py +++ b/game/factions/russia_2010.py @@ -7,7 +7,6 @@ Russia_2010 = { "country": "Russia", "side": "red", "units": [ - AJS37, MiG_23MLD, Su_25, Su_27, @@ -37,6 +36,9 @@ Russia_2010 = { Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_72B, + Armor.IFV_BMP_1, + Armor.IFV_BMP_2, + Armor.IFV_BMP_3, Artillery.MLRS_9K57_Uragan_BM_27, Artillery.SPH_2S19_Msta, @@ -59,6 +61,8 @@ Russia_2010 = { AirDefence.SAM_SA_13_Strela_10M3_9A35M3 ], "aircraft_carrier": [ CV_1143_5_Admiral_Kuznetsov, + ], "carrier_names": [ + "Admiral Kuznetov" ], "destroyer": [ FF_1135M_Rezky, ], "cruiser": [ diff --git a/game/factions/spain_1990.py b/game/factions/spain_1990.py index b46e3dd1..f016cb8a 100644 --- a/game/factions/spain_1990.py +++ b/game/factions/spain_1990.py @@ -46,5 +46,5 @@ Spain_1990 = { "Juan Carlos I", ], "boat":[ "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/sweden_1990.py b/game/factions/sweden_1990.py index 8df60107..5bafb20b 100644 --- a/game/factions/sweden_1990.py +++ b/game/factions/sweden_1990.py @@ -27,5 +27,5 @@ Sweden_1990 = { ], "shorad": [ AirDefence.SAM_Avenger_M1097 - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/turkey_2005.py b/game/factions/turkey_2005.py index 38176ea8..9a0504bf 100644 --- a/game/factions/turkey_2005.py +++ b/game/factions/turkey_2005.py @@ -38,5 +38,5 @@ Turkey_2005 = { AirDefence.SPAAA_ZSU_23_4_Shilka ], "boat":[ "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/uae_2005.py b/game/factions/uae_2005.py index a4152fa9..90990493 100644 --- a/game/factions/uae_2005.py +++ b/game/factions/uae_2005.py @@ -32,5 +32,5 @@ UAE_2005 = { Armed_speedboat, ], "boat":[ "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/uk_1944.py b/game/factions/uk_1944.py new file mode 100644 index 00000000..abfaac59 --- /dev/null +++ b/game/factions/uk_1944.py @@ -0,0 +1,42 @@ +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +from game.data.building_data import WW2_ALLIES_BUILDINGS +from game.data.doctrine import WWII_DOCTRINE + +UK_1944 = { + "country": "UK", + "side": "blue", + "units": [ + P_51D, + P_51D_30_NA, + P_47D_30, + SpitfireLFMkIX, + SpitfireLFMkIXCW, + A_20G, + B_17G, + + Armor.MT_M4A4_Sherman_Firefly, + Armor.MT_M4_Sherman, + Armor.APC_M2A1, + Armor.CT_Cromwell_IV, + Armor.ST_Centaur_IV, + Armor.HIT_Churchill_VII, + + Infantry.Infantry_SMLE_No_4_Mk_1, + + LS_Samuel_Chase, + LST_Mk_II, + LCVP__Higgins_boat, + + Unarmed.CCKW_353, + AirDefence.AAA_Bofors_40mm, + ], "shorad":[ + AirDefence.AAA_Bofors_40mm, + ], + "objects": WW2_ALLIES_BUILDINGS, + "doctrine": WWII_DOCTRINE, + "boat": ["WW2LSTGroupGenerator"], + "boat_count": 1 +} \ No newline at end of file diff --git a/game/factions/uk_1990.py b/game/factions/uk_1990.py index 9e9702eb..f2bcc57a 100644 --- a/game/factions/uk_1990.py +++ b/game/factions/uk_1990.py @@ -16,7 +16,7 @@ UnitedKingdom_1990 = { C_130, E_3A, - SA342L, + SA342M, AH_64A, Armor.MBT_Challenger_II, @@ -42,11 +42,11 @@ UnitedKingdom_1990 = { Oliver_Hazzard_Perry_class, ], "cruiser": [ Ticonderoga_class, - ], "lha_names": [ + ], "lhanames": [ "HMS Invincible", "HMS Illustrious", "HMS Ark Royal", ], "boat":[ "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/us_aggressors.py b/game/factions/us_aggressors.py new file mode 100644 index 00000000..ab4e6ffd --- /dev/null +++ b/game/factions/us_aggressors.py @@ -0,0 +1,72 @@ +from dcs.helicopters import * +from dcs.planes import * +from dcs.ships import * +from dcs.vehicles import * + +US_Aggressors = { + "country": "USAF Aggressors", + "side": "red", + "units": [ + + F_15C, + F_5E_3, + FA_18C_hornet, + F_16C_50, + Su_27, + + KC_135, + KC130, + C_130, + E_3A, + + UH_1H, + AH_64D, + Ka_50, + SA342M, + SA342L, + + Armor.MBT_M1A2_Abrams, + Armor.MBT_Leopard_2, + Armor.ATGM_M1134_Stryker, + Armor.IFV_M2A2_Bradley, + Armor.APC_M1043_HMMWV_Armament, + + Artillery.MLRS_M270, + Artillery.SPH_M109_Paladin, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + Infantry.Soldier_M249, + + AirDefence.SAM_Hawk_PCP, + AirDefence.SAM_Patriot_EPP_III, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ], "shorad": [ + AirDefence.SAM_Avenger_M1097, + ], "aircraft_carrier": [ + CVN_74_John_C__Stennis, + ], "helicopter_carrier": [ + LHA_1_Tarawa, + ], "destroyer": [ + Oliver_Hazzard_Perry_class, + USS_Arleigh_Burke_IIa, + ], "cruiser": [ + Ticonderoga_class, + ], "carrier_names": [ + "CVN-71 Theodore Roosevelt", + "CVN-72 Abraham Lincoln", + "CVN-73 George Washington", + "CVN-74 John C. Stennis", + ], "lhanames": [ + "LHA-1 Tarawa", + "LHA-2 Saipan", + "LHA-3 Belleau Wood", + "LHA-4 Nassau", + "LHA-5 Peleliu" + ], "boat":[ + "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" + ] +} diff --git a/game/factions/usa_1944.py b/game/factions/usa_1944.py index 385d6c7d..5ba73237 100644 --- a/game/factions/usa_1944.py +++ b/game/factions/usa_1944.py @@ -6,6 +6,40 @@ from game.data.building_data import WW2_ALLIES_BUILDINGS from game.data.doctrine import WWII_DOCTRINE USA_1944 = { + "country": "USA", + "side": "blue", + "units": [ + P_51D, + P_51D_30_NA, + P_47D_30, + A_20G, + B_17G, + + Armor.MT_M4_Sherman, + Armor.M30_Cargo_Carrier, + Armor.APC_M2A1, + Armor.LAC_M8_Greyhound, + Armor.TD_M10_GMC, + Artillery.M12_GMC, + + Infantry.Infantry_M1_Garand, + + LS_Samuel_Chase, + LST_Mk_II, + LCVP__Higgins_boat, + + Unarmed.CCKW_353, + AirDefence.AAA_Bofors_40mm, + ], "shorad":[ + AirDefence.AAA_Bofors_40mm, + ], + "objects": WW2_ALLIES_BUILDINGS, + "doctrine": WWII_DOCTRINE, + "boat": ["WW2LSTGroupGenerator"], + "boat_count": 2 +} + +ALLIES_1944 = { "country": "USA", "side": "blue", "units": [ diff --git a/game/factions/usa_1965.py b/game/factions/usa_1965.py index 74b12fe3..59dc651a 100644 --- a/game/factions/usa_1965.py +++ b/game/factions/usa_1965.py @@ -37,6 +37,5 @@ USA_1965 = { AirDefence.AAA_Vulcan_M163, AirDefence.SAM_Chaparral_M48 ], "boat":[ - "OliverHazardPerryGroupGenerator" ] } \ No newline at end of file diff --git a/game/factions/usa_1990.py b/game/factions/usa_1990.py index b0383148..ae090e17 100644 --- a/game/factions/usa_1990.py +++ b/game/factions/usa_1990.py @@ -61,5 +61,5 @@ USA_1990 = { "LHA-5 Peleliu" ], "boat":[ "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" - ] + ], "has_jtac": True } \ No newline at end of file diff --git a/game/factions/usa_2005.py b/game/factions/usa_2005.py index 2e9475ae..5425aa92 100644 --- a/game/factions/usa_2005.py +++ b/game/factions/usa_2005.py @@ -11,7 +11,6 @@ USA_2005 = { F_14B, FA_18C_hornet, F_16C_50, - JF_17, A_10C, AV8BNA, @@ -67,5 +66,5 @@ USA_2005 = { "LHA-5 Peleliu" ], "boat":[ "ArleighBurkeGroupGenerator" - ] + ], "has_jtac": True } diff --git a/game/game.py b/game/game.py index d825c3f9..1dbb397d 100644 --- a/game/game.py +++ b/game/game.py @@ -1,7 +1,7 @@ from datetime import datetime, timedelta from game.db import REWARDS, PLAYER_BUDGET_BASE, sys -from game.game_stats import GameStats +from game.models.game_stats import GameStats from gen.flights.ai_flight_planner import FlightPlanner from gen.ground_forces.ai_ground_planner import GroundPlanner from .event import * @@ -56,8 +56,8 @@ class Game: current_unit_id = 0 current_group_id = 0 - def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater, start_date: datetime): - self.settings = Settings() + def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater, start_date: datetime, settings): + self.settings = settings self.events = [] self.theater = theater self.player_name = player_name @@ -73,7 +73,26 @@ class Game: self.informations = [] self.informations.append(Information("Game Start", "-" * 40, 0)) self.__culling_points = self.compute_conflicts_position() + self.__frontlineData = [] + self.__destroyed_units = [] + self.jtacs = [] + self.savepath = "" + self.sanitize_sides() + + + def sanitize_sides(self): + """ + Make sure the opposing factions are using different countries + :return: + """ + if self.player_country == self.enemy_country: + if self.player_country == "USA": + self.enemy_country = "USAF Aggressors" + elif self.player_country == "Russia": + self.enemy_country = "USSR" + else: + self.enemy_country = "Russia" @property def player_faction(self): @@ -175,18 +194,6 @@ class Game: else: return event.name == self.player_name - def get_player_coalition_id(self): - if self.player_country in db.BLUEFOR_FACTIONS: - return 2 - else: - return 1 - - def get_enemy_coalition_id(self): - if self.get_player_coalition_id() == 1: - return 2 - else: - return 1 - def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint] = None): logging.info("Pass turn") @@ -237,6 +244,9 @@ class Game: gplanner.plan_groundwar() self.ground_planners[cp.id] = gplanner + # Autosave progress + persistency.autosave(self) + def _enemy_reinforcement(self): """ Compute and commision reinforcement for enemy bases @@ -340,6 +350,8 @@ class Game: # By default, use the existing frontline conflict position for conflict in self.theater.conflicts(): points.append(Conflict.frontline_position(self.theater, conflict[0], conflict[1])[0]) + points.append(conflict[0].position) + points.append(conflict[1].position) # If there is no conflict take the center point between the two nearest opposing bases if len(points) == 0: @@ -351,6 +363,11 @@ class Game: if d < min_distance: min_distance = d cpoint = Point((cp.position.x + cp2.position.x) / 2, (cp.position.y + cp2.position.y) / 2) + points.append(cp.position) + points.append(cp2.position) + break + if cpoint is not None: + break if cpoint is not None: points.append(cpoint) @@ -361,6 +378,12 @@ class Game: return points + def add_destroyed_units(self, destroyed_unit_data): + self.__destroyed_units.append(destroyed_unit_data) + + def get_destroyed_units(self): + return self.__destroyed_units + def position_culled(self, pos): """ Check if unit can be generated at given position depending on culling performance settings @@ -375,3 +398,21 @@ class Game: return False return True + # 1 = red, 2 = blue + def get_player_coalition_id(self): + return 2 + + def get_enemy_coalition_id(self): + return 1 + + def get_player_coalition(self): + return dcs.action.Coalition.Blue + + def get_enemy_coalition(self): + return dcs.action.Coalition.Red + + def get_player_color(self): + return "blue" + + def get_enemy_color(self): + return "red" \ No newline at end of file diff --git a/game/models/destroyed_units.py b/game/models/destroyed_units.py new file mode 100644 index 00000000..ade75cc4 --- /dev/null +++ b/game/models/destroyed_units.py @@ -0,0 +1,14 @@ +class DestroyedUnit: + """ + Store info about a destroyed unit + """ + + x: int + y: int + name: str + + def __init__(self, x , y, name): + self.x = x + self.y = y + self.name = name + diff --git a/game/models/frontline_data.py b/game/models/frontline_data.py new file mode 100644 index 00000000..94947135 --- /dev/null +++ b/game/models/frontline_data.py @@ -0,0 +1,13 @@ +from theater import ControlPoint + + +class FrontlineData: + """ + This Data structure will store information about an existing frontline + """ + + def __init__(self, from_cp:ControlPoint, to_cp: ControlPoint): + self.to_cp = to_cp + self.from_cp = from_cp + self.enemy_units_position = [] + self.blue_units_position = [] diff --git a/game/game_stats.py b/game/models/game_stats.py similarity index 100% rename from game/game_stats.py rename to game/models/game_stats.py diff --git a/game/operation/frontlineattack.py b/game/operation/frontlineattack.py index d687fc95..53dc2d63 100644 --- a/game/operation/frontlineattack.py +++ b/game/operation/frontlineattack.py @@ -47,29 +47,6 @@ class FrontlineAttackOperation(Operation): conflict=conflict) def generate(self): - #if self.is_player_attack: - # self.prepare_carriers(db.unitdict_from(self.strikegroup)) - - # ground units - # self.armorgen.generate_vec(self.attackers, self.defenders) - - ## strike group w/ heli support - #planes_flights = {k: v for k, v in self.strikegroup.items() if k in plane_map.values()} - #self.airgen.generate_cas_strikegroup(*assigned_units_split(planes_flights), at=self.attackers_starting_position) - - #heli_flights = {k: v for k, v in self.strikegroup.items() if k in helicopters.helicopter_map.values()} - #if heli_flights: - # self.briefinggen.append_frequency("FARP + Heli flights", "127.5 MHz AM") - # for farp, dict in zip(self.groundobjectgen.generate_farps(sum([x[0] for x in heli_flights.values()])), - # db.assignedunits_split_to_count(heli_flights, self.groundobjectgen.FARP_CAPACITY)): - # self.airgen.generate_cas_strikegroup(*assigned_units_split(dict), - # at=farp, - # escort=len(planes_flights) == 0) - - #self.airgen.generate_attackers_escort(*assigned_units_split(self.escort), at=self.attackers_starting_position) - - #self.airgen.generate_defense(*assigned_units_split(self.interceptors), at=self.defenders_starting_position) - self.briefinggen.title = "Frontline CAS" self.briefinggen.description = "Provide CAS for the ground forces attacking enemy lines. Operation will be considered successful if total number of enemy units will be lower than your own by a factor of 1.5 (i.e. with 12 units from both sides, enemy forces need to be reduced to at least 8), meaning that you (and, probably, your wingmans) should concentrate on destroying the enemy units. Target base strength will be lowered as a result. Be advised that your flight will not attack anything until you explicitly tell them so by comms menu." self.briefinggen.append_waypoint("CAS AREA IP") diff --git a/game/operation/operation.py b/game/operation/operation.py index 9046cc1a..d69c406d 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -18,7 +18,6 @@ class Operation: conflict = None # type: Conflict armorgen = None # type: ArmorConflictGenerator airgen = None # type: AircraftConflictGenerator - shipgen = None # type: ShipGenerator triggersgen = None # type: TriggersGenerator airsupportgen = None # type: AirSupportConflictGenerator visualgen = None # type: VisualGenerator @@ -65,7 +64,6 @@ class Operation: self.current_mission = mission self.conflict = conflict self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings, self.game) - self.shipgen = ShipGenerator(mission, conflict) self.airsupportgen = AirSupportConflictGenerator(mission, conflict, self.game) self.triggersgen = TriggersGenerator(mission, conflict, self.game) self.visualgen = VisualGenerator(mission, conflict, self.game) @@ -90,12 +88,12 @@ class Operation: # Setup coalition : self.current_mission.coalition["blue"] = Coalition("blue") self.current_mission.coalition["red"] = Coalition("red") - if self.game.player_country and self.game.player_country in db.BLUEFOR_FACTIONS: - self.current_mission.coalition["blue"].add_country(country_dict[db.country_id_from_name(self.game.player_country)]()) - self.current_mission.coalition["red"].add_country(country_dict[db.country_id_from_name(self.game.enemy_country)]()) - else: - self.current_mission.coalition["blue"].add_country(country_dict[db.country_id_from_name(self.game.enemy_country)]()) - self.current_mission.coalition["red"].add_country(country_dict[db.country_id_from_name(self.game.player_country)]()) + + p_country = self.game.player_country + e_country = self.game.enemy_country + self.current_mission.coalition["blue"].add_country(country_dict[db.country_id_from_name(p_country)]()) + self.current_mission.coalition["red"].add_country(country_dict[db.country_id_from_name(e_country)]()) + print([c for c in self.current_mission.coalition["blue"].countries.keys()]) print([c for c in self.current_mission.coalition["red"].countries.keys()]) @@ -125,6 +123,26 @@ class Operation: # Generate ground object first self.groundobjectgen.generate() + # Generate destroyed units + for d in self.game.get_destroyed_units(): + try: + utype = db.unit_type_from_name(d["type"]) + except KeyError: + continue + + pos = Point(d["x"], d["z"]) + if utype is not None and not self.game.position_culled(pos) and self.game.settings.perf_destroyed_units: + self.current_mission.static_group( + country=self.current_mission.country(self.game.player_country), + name="", + _type=utype, + hidden=True, + position=pos, + heading=d["orientation"], + dead=True, + ) + + # Air Support (Tanker & Awacs) self.airsupportgen.generate(self.is_awacs_enabled) @@ -139,6 +157,7 @@ class Operation: self.airgen.generate_flights(cp, country, self.game.planners[cp.id]) # Generate ground units on frontline everywhere + self.game.jtacs = [] for player_cp, enemy_cp in self.game.theater.conflicts(True): conflict = Conflict.frontline_cas_conflict(self.attacker_name, self.defender_name, self.current_mission.country(self.attacker_country), @@ -157,14 +176,14 @@ class Operation: else: self.current_mission.groundControl.red_tactical_commander = self.ca_slots - # triggers + # Triggers if self.game.is_player_attack(self.conflict.attackers_country): cp = self.conflict.from_cp else: cp = self.conflict.to_cp self.triggersgen.generate() - # options + # Options self.forcedoptionsgen.generate() # Generate Visuals Smoke Effects @@ -177,6 +196,18 @@ class Operation: load_mist.add_action(DoScript(String(f.read()))) self.current_mission.triggerrules.triggers.append(load_mist) + # Load Ciribob's JTACAutoLase script + load_autolase = TriggerStart(comment="Load JTAC script") + with open("./resources/scripts/JTACAutoLase.lua") as f: + + script = f.read() + script = script + "\n" + for jtac in self.game.jtacs: + script = script + "\n" + "JTACAutoLase('" + str(jtac[2]) + "', " + str(jtac[1]) + ", true, \"vehicle\")" + "\n" + + load_autolase.add_action(DoScript(String(script))) + self.current_mission.triggerrules.triggers.append(load_autolase) + load_dcs_libe = TriggerStart(comment="Load DCS Liberation Script") with open("./resources/scripts/dcs_liberation.lua") as f: script = f.read() @@ -189,10 +220,10 @@ class Operation: # Briefing Generation for i, tanker_type in enumerate(self.airsupportgen.generated_tankers): - self.briefinggen.append_frequency("Tanker {} ({})".format(TANKER_CALLSIGNS[i], tanker_type), "{}X/{} MHz AM".format(97+i, 130+i)) + self.briefinggen.append_frequency("Tanker {} ({})".format(TANKER_CALLSIGNS[i], tanker_type), "{}X/{} MHz AM".format(60+i, 130+i)) if self.is_awacs_enabled: - self.briefinggen.append_frequency("AWACS", "133 MHz AM") + self.briefinggen.append_frequency("AWACS", "233 MHz AM") self.briefinggen.append_frequency("Flight", "251 MHz AM") diff --git a/game/settings.py b/game/settings.py index 3c497e1a..c42e727b 100644 --- a/game/settings.py +++ b/game/settings.py @@ -1,32 +1,42 @@ class Settings: - # Difficulty settings - player_skill = "Good" - enemy_skill = "Average" - enemy_vehicle_skill = "Average" - map_coalition_visibility = "All Units" - labels = "Full" - only_player_takeoff = True # Legacy parameter do not use - night_disabled = False - external_views_allowed = True - supercarrier = False - multiplier = 1 - generate_marks = True - sams = True # Legacy parameter do not use - cold_start = False # Legacy parameter do not use - version = None + def __init__(self): + # Generator settings + self.inverted = False + self.do_not_generate_carrier = False # TODO : implement + self.do_not_generate_lha = False # TODO : implement + self.do_not_generate_player_navy = True # TODO : implement + self.do_not_generate_enemy_navy = True # TODO : implement - # Performance oriented - perf_red_alert_state = True - perf_smoke_gen = True - perf_artillery = True - perf_moving_units = True - perf_infantry = True - perf_ai_parking_start = True + # Difficulty settings + self.player_skill = "Good" + self.enemy_skill = "Average" + self.enemy_vehicle_skill = "Average" + self.map_coalition_visibility = "All Units" + self.labels = "Full" + self.only_player_takeoff = True # Legacy parameter do not use + self.night_disabled = False + self.external_views_allowed = True + self.supercarrier = False + self.multiplier = 1 + self.generate_marks = True + self.sams = True # Legacy parameter do not use + self.cold_start = False # Legacy parameter do not use + self.version = None + self.include_jtac_if_available = True - # Performance culling - perf_culling = False - perf_culling_distance = 100 + # Performance oriented + self.perf_red_alert_state = True + self.perf_smoke_gen = True + self.perf_artillery = True + self.perf_moving_units = True + self.perf_infantry = True + self.perf_ai_parking_start = True + self.perf_destroyed_units = True + + # Performance culling + self.perf_culling = False + self.perf_culling_distance = 100 diff --git a/gen/__init__.py b/gen/__init__.py index ccddeab9..d910a19d 100644 --- a/gen/__init__.py +++ b/gen/__init__.py @@ -3,7 +3,6 @@ from .aircraft import * from .armor import * from .airsupportgen import * from .conflictgen import * -from .shipgen import * from .visualgen import * from .triggergen import * from .environmentgen import * diff --git a/gen/aircraft.py b/gen/aircraft.py index b7c969b3..e26d74ef 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -1,10 +1,12 @@ -from dcs.action import ActivateGroup, AITaskPush -from dcs.condition import TimeAfter, CoalitionHasAirdrome +from dcs.action import ActivateGroup, AITaskPush, MessageToCoalition, MessageToAll +from dcs.condition import TimeAfter, CoalitionHasAirdrome, PartOfCoalitionInZone from dcs.helicopters import UH_1H from dcs.terrain.terrain import NoParkingSlotError from dcs.triggers import TriggerOnce, Event +from game.data.cap_capabilities_db import GUNFIGHTERS from game.settings import Settings +from game.utils import nm_to_meter from gen.flights.ai_flight_planner import FlightPlanner from gen.flights.flight import Flight, FlightType, FlightWaypointType from .conflictgen import * @@ -36,7 +38,7 @@ class AircraftConflictGenerator: return self.settings.cold_start and StartType.Cold or StartType.Warm - def _setup_group(self, group: FlyingGroup, for_task: typing.Type[Task], client_count: int): + def _setup_group(self, group: FlyingGroup, for_task: typing.Type[Task], flight: Flight): did_load_loadout = False unit_type = group.units[0].unit_type @@ -70,8 +72,8 @@ class AircraftConflictGenerator: for unit_instance in group.units: unit_instance.livery_id = db.PLANE_LIVERY_OVERRIDES[unit_type] - single_client = client_count == 1 - for idx in range(0, min(len(group.units), client_count)): + single_client = flight.client_count == 1 + for idx in range(0, min(len(group.units), flight.client_count)): if single_client: group.units[idx].set_player() else: @@ -85,16 +87,32 @@ class AircraftConflictGenerator: if unit_type is F_14B: group.units[idx].set_property(F_14B.Properties.INSAlignmentStored.id, True) + group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) + # TODO : refactor this following bad specific special case code :( + if unit_type in helicopters.helicopter_map.values() and unit_type not in [UH_1H]: group.set_frequency(127.5) else: - if unit_type not in [P_51D_30_NA, P_51D, SpitfireLFMkIX, SpitfireLFMkIXCW, FW_190A8, FW_190D9, Bf_109K_4, P_47D_30]: + if unit_type not in [P_51D_30_NA, P_51D, SpitfireLFMkIX, SpitfireLFMkIXCW, P_47D_30, I_16, FW_190A8, FW_190D9, Bf_109K_4]: group.set_frequency(251.0) else: # WW2 - group.set_frequency(124.0) + if unit_type in [FW_190A8, FW_190D9, Bf_109K_4, Ju_88A4]: + group.set_frequency(40) + else: + group.set_frequency(124.0) + + # Special case so Su 33 carrier take off + if unit_type is Su_33: + if task is not CAP: + for unit in group.units: + unit.fuel = Su_33.fuel_max / 2.2 + else: + for unit in group.units: + unit.fuel = Su_33.fuel_max * 0.8 + def _generate_at_airport(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, airport: Airport = None, start_type = None) -> FlyingGroup: assert count > 0 @@ -108,7 +126,7 @@ class AircraftConflictGenerator: country=side, name=name, aircraft_type=unit_type, - airport=self.m.terrain.airport_by_id(airport.id), + airport=airport, maintask=None, start_type=start_type, group_size=count, @@ -143,10 +161,13 @@ class AircraftConflictGenerator: group.points[0].alt_type = "RADIO" return group - def _generate_at_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: typing.Union[ShipGroup, StaticGroup]) -> FlyingGroup: + def _generate_at_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: typing.Union[ShipGroup, StaticGroup], start_type=None) -> FlyingGroup: assert count > 0 assert unit is not None + if start_type is None: + start_type = self._start_type() + logging.info("airgen: {} for {} at unit {}".format(unit_type, side.id, at)) return self.m.flight_group_from_unit( country=side, @@ -154,7 +175,7 @@ class AircraftConflictGenerator: aircraft_type=unit_type, pad_group=at, maintask=None, - start_type=self._start_type(), + start_type=start_type, group_size=count) def _generate_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: db.StartingPosition): @@ -233,6 +254,11 @@ class AircraftConflictGenerator: def generate_flights(self, cp, country, flight_planner:FlightPlanner): + # Clear pydcs parking slots + if cp.airport is not None: + for ps in cp.airport.parking_slots: + ps.unit_id = None + for flight in flight_planner.flights: if flight.client_count == 0 and self.game.position_culled(flight.from_cp.position): @@ -240,11 +266,7 @@ class AircraftConflictGenerator: continue group = self.generate_planned_flight(cp, country, flight) - if flight.flight_type == FlightType.INTERCEPTION: - self.setup_group_as_intercept_flight(group, flight) - self._setup_custom_payload(flight, group) - else: - self.setup_flight_group(group, flight, flight.flight_type) + self.setup_flight_group(group, flight, flight.flight_type) self.setup_group_activation_trigger(flight, group) @@ -255,7 +277,7 @@ class AircraftConflictGenerator: group.late_activation = False group.uncontrolled = True - activation_trigger = TriggerOnce(Event.NoEvent, "LiberationControlTriggerForGroup" + str(group.id)) + activation_trigger = TriggerOnce(Event.NoEvent, "FlightStartTrigger" + str(group.id)) activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in * 60)) if (flight.from_cp.cptype == ControlPointType.AIRBASE): if flight.from_cp.captured: @@ -265,12 +287,16 @@ class AircraftConflictGenerator: activation_trigger.add_condition( CoalitionHasAirdrome(self.game.get_enemy_coalition_id(), flight.from_cp.id)) + if flight.flight_type == FlightType.INTERCEPTION: + self.setup_interceptor_triggers(group, flight, activation_trigger) + group.add_trigger_action(StartCommand()) activation_trigger.add_action(AITaskPush(group.id, len(group.tasks))) + self.m.triggerrules.triggers.append(activation_trigger) else: group.late_activation = True - activation_trigger = TriggerOnce(Event.NoEvent, "LiberationActivationTriggerForGroup" + str(group.id)) + activation_trigger = TriggerOnce(Event.NoEvent, "FlightLateActivationTrigger" + str(group.id)) activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in*60)) if(flight.from_cp.cptype == ControlPointType.AIRBASE): @@ -279,9 +305,22 @@ class AircraftConflictGenerator: else: activation_trigger.add_condition(CoalitionHasAirdrome(self.game.get_enemy_coalition_id(), flight.from_cp.id)) + if flight.flight_type == FlightType.INTERCEPTION: + self.setup_interceptor_triggers(group, flight, activation_trigger) + activation_trigger.add_action(ActivateGroup(group.id)) self.m.triggerrules.triggers.append(activation_trigger) + def setup_interceptor_triggers(self, group, flight, activation_trigger): + + detection_zone = self.m.triggers.add_triggerzone(flight.from_cp.position, radius=25000, hidden=False, name="ITZ") + if flight.from_cp.captured: + activation_trigger.add_condition(PartOfCoalitionInZone(self.game.get_enemy_color(), detection_zone.id)) # TODO : support unit type in part of coalition + activation_trigger.add_action(MessageToAll(String("WARNING : Enemy aircrafts have been detected in the vicinity of " + flight.from_cp.name + ". Interceptors are taking off."), 20)) + else: + activation_trigger.add_condition(PartOfCoalitionInZone(self.game.get_player_color(), detection_zone.id)) + activation_trigger.add_action(MessageToAll(String("WARNING : We have detected that enemy aircrafts are scrambling for an interception on " + flight.from_cp.name + " airbase."), 20)) + def generate_planned_flight(self, cp, country, flight:Flight): try: if flight.client_count == 0 and self.game.settings.perf_ai_parking_start: @@ -310,7 +349,8 @@ class AircraftConflictGenerator: unit_type=flight.unit_type, count=flight.count, client_count=0, - at=self.m.find_group(group_name),) + at=self.m.find_group(group_name), + start_type=st) else: group = self._generate_at_airport( name=namegen.next_unit_name(country, cp.id, flight.unit_type), @@ -318,7 +358,7 @@ class AircraftConflictGenerator: unit_type=flight.unit_type, count=flight.count, client_count=0, - airport=self.m.terrain.airport_by_id(cp.at.id), + airport=cp.airport, start_type=st) except Exception: # Generated when there is no place on Runway or on Parking Slots @@ -332,56 +372,70 @@ class AircraftConflictGenerator: at=cp.position) group.points[0].alt = 1500 + flight.group = group return group def setup_group_as_intercept_flight(self, group, flight): group.points[0].ETA = 0 group.late_activation = True - self._setup_group(group, Intercept, flight.client_count) + self._setup_group(group, Intercept, flight) for point in flight.points: group.add_waypoint(Point(point.x,point.y), point.alt) def setup_flight_group(self, group, flight, flight_type): - if flight_type in [FlightType.CAP, FlightType.BARCAP, FlightType.TARCAP]: + if flight_type in [FlightType.CAP, FlightType.BARCAP, FlightType.TARCAP, FlightType.INTERCEPTION]: group.task = CAP.name - self._setup_group(group, CAP, flight.client_count) + self._setup_group(group, CAP, flight) # group.points[0].tasks.clear() - # group.tasks.clear() - # group.tasks.append(EngageTargets(max_distance=40, targets=[Targets.All.Air])) + group.points[0].tasks.clear() + group.points[0].tasks.append(EngageTargets(max_distance=nm_to_meter(50), targets=[Targets.All.Air])) # group.tasks.append(EngageTargets(max_distance=nm_to_meter(120), targets=[Targets.All.Air])) - pass + if flight.unit_type not in GUNFIGHTERS: + group.points[0].tasks.append(OptRTBOnOutOfAmmo(OptRTBOnOutOfAmmo.Values.AAM)) + else: + group.points[0].tasks.append(OptRTBOnOutOfAmmo(OptRTBOnOutOfAmmo.Values.Cannon)) + elif flight_type in [FlightType.CAS, FlightType.BAI]: group.task = CAS.name - self._setup_group(group, CAS, flight.client_count) + self._setup_group(group, CAS, flight) group.points[0].tasks.clear() - group.points[0].tasks.append(CASTaskAction()) + group.points[0].tasks.append(EngageTargets(max_distance=nm_to_meter(10), targets=[Targets.All.GroundUnits.GroundVehicles])) group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFireWeaponFree)) + group.points[0].tasks.append(OptRTBOnOutOfAmmo(OptRTBOnOutOfAmmo.Values.Unguided)) + group.points[0].tasks.append(OptRestrictJettison(True)) elif flight_type in [FlightType.SEAD, FlightType.DEAD]: group.task = SEAD.name - self._setup_group(group, SEAD, flight.client_count) + self._setup_group(group, SEAD, flight) group.points[0].tasks.clear() group.points[0].tasks.append(NoTask()) group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) group.points[0].tasks.append(OptRestrictJettison(True)) + group.points[0].tasks.append(OptRTBOnOutOfAmmo(OptRTBOnOutOfAmmo.Values.ASM)) elif flight_type in [FlightType.STRIKE]: group.task = PinpointStrike.name - self._setup_group(group, GroundAttack, flight.client_count) + self._setup_group(group, GroundAttack, flight) group.points[0].tasks.clear() group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) group.points[0].tasks.append(OptRestrictJettison(True)) elif flight_type in [FlightType.ANTISHIP]: group.task = AntishipStrike.name - self._setup_group(group, AntishipStrike, flight.client_count) + self._setup_group(group, AntishipStrike, flight) group.points[0].tasks.clear() group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) group.points[0].tasks.append(OptRestrictJettison(True)) + group.points[0].tasks.append(OptRTBOnBingoFuel(True)) + + if hasattr(flight.unit_type, 'eplrs'): + if flight.unit_type.eplrs: + group.points[0].tasks.append(EPLRS(group.id)) + for i, point in enumerate(flight.points): if not point.only_for_player or (point.only_for_player and flight.client_count > 0): pt = group.add_waypoint(Point(point.x, point.y), point.alt) @@ -420,6 +474,8 @@ class AircraftConflictGenerator: group.add_nav_target_point(t.position, "PP" + str(j + 1)) if group.units[0].unit_type == F_14B and j == 0: group.add_nav_target_point(t.position, "ST") + if group.units[0].unit_type == AJS37 and j < 9: + group.add_nav_target_point(t.position, "M" + str(j + 1)) elif point.waypoint_type == FlightWaypointType.INGRESS_SEAD: tgroup = self.m.find_group(point.targetGroup.group_identifier) @@ -438,6 +494,8 @@ class AircraftConflictGenerator: group.add_nav_target_point(t.position, "PP" + str(j + 1)) if group.units[0].unit_type == F_14B and j == 0: group.add_nav_target_point(t.position, "ST") + if group.units[0].unit_type == AJS37 and j < 9: + group.add_nav_target_point(t.position, "M" + str(j + 1)) if pt is not None: pt.alt_type = point.alt_type @@ -448,7 +506,7 @@ class AircraftConflictGenerator: def setup_group_as_antiship_flight(self, group, flight): group.task = AntishipStrike.name - self._setup_group(group, AntishipStrike, flight.client_count) + self._setup_group(group, AntishipStrike, flight) group.points[0].tasks.clear() group.points[0].tasks.append(AntishipStrikeTaskAction()) diff --git a/gen/airsupportgen.py b/gen/airsupportgen.py index a79fff09..dabf7f48 100644 --- a/gen/airsupportgen.py +++ b/gen/airsupportgen.py @@ -32,6 +32,7 @@ class AirSupportConflictGenerator: def generate(self, is_awacs_enabled): player_cp = self.conflict.from_cp if self.conflict.from_cp.captured else self.conflict.to_cp + CALLSIGNS = ["TKR", "TEX", "FUL", "FUE", ""] for i, tanker_unit_type in enumerate(db.find_unittype(Refueling, self.conflict.attackers_side)): self.generated_tankers.append(db.unit_type_name(tanker_unit_type)) tanker_heading = self.conflict.to_cp.position.heading_between_point(self.conflict.from_cp.position) + TANKER_HEADING_OFFSET * i @@ -43,12 +44,17 @@ class AirSupportConflictGenerator: plane_type=tanker_unit_type, position=tanker_position, altitude=TANKER_ALT, + race_distance=58000, frequency=130 + i, start_type=StartType.Warm, - tacanchannel="{}X".format(97 + i), + speed=574, + tacanchannel="{}X".format(60 + i), ) - tanker_group.points[0].tasks.append(ActivateBeaconCommand(channel=97 + i, unit_id=tanker_group.id, aa=False)) + if tanker_unit_type != IL_78M: + tanker_group.points[0].tasks.pop() # Override PyDCS tacan channel + tanker_group.points[0].tasks.append(ActivateBeaconCommand(97+1, "X", CALLSIGNS[i], True, tanker_group.units[0].id, True)) + tanker_group.points[0].tasks.append(SetInvisibleCommand(True)) tanker_group.points[0].tasks.append(SetImmortalCommand(True)) @@ -62,7 +68,7 @@ class AirSupportConflictGenerator: altitude=AWACS_ALT, airport=None, position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE), - frequency=133, + frequency=233, start_type=StartType.Warm, ) awacs_flight.points[0].tasks.append(SetInvisibleCommand(True)) diff --git a/gen/armor.py b/gen/armor.py index 5fcdf9d4..7c2e0f89 100644 --- a/gen/armor.py +++ b/gen/armor.py @@ -1,4 +1,7 @@ +from dcs.action import AITaskPush, AITaskSet +from dcs.condition import TimeAfter, UnitDamaged, Or, GroupLifeLess from dcs.task import * +from dcs.triggers import TriggerOnce, Event from gen import namegen from gen.ground_forces.ai_ground_planner import CombatGroupRole, DISTANCE_FROM_FRONTLINE @@ -17,10 +20,12 @@ AGGRESIVE_MOVE_DISTANCE = 16000 FIGHT_DISTANCE = 3500 +RANDOM_OFFSET_ATTACK = 250 + class GroundConflictGenerator: def __init__(self, mission: Mission, conflict: Conflict, game, player_planned_combat_groups, enemy_planned_combat_groups, player_stance): - self.m = mission + self.mission = mission self.conflict = conflict self.enemy_planned_combat_groups = enemy_planned_combat_groups self.player_planned_combat_groups = player_planned_combat_groups @@ -58,7 +63,7 @@ class GroundConflictGenerator: if final_position is not None: g = self._generate_group( - side=self.m.country(self.game.player_country), + side=self.mission.country(self.game.player_country), unit=group.units[0], heading=self.conflict.heading+90, count=len(group.units), @@ -66,7 +71,7 @@ class GroundConflictGenerator: g.set_skill(self.game.settings.player_skill) player_groups.append((g,group)) - self.gen_infantry_group_for_group(g, True, self.m.country(self.game.player_country), self.conflict.heading + 90) + self.gen_infantry_group_for_group(g, True, self.mission.country(self.game.player_country), self.conflict.heading + 90) # Create enemy groups at random position for group in self.enemy_planned_combat_groups: @@ -78,7 +83,7 @@ class GroundConflictGenerator: if final_position is not None: g = self._generate_group( - side=self.m.country(self.game.enemy_country), + side=self.mission.country(self.game.enemy_country), unit=group.units[0], heading=self.conflict.heading - 90, count=len(group.units), @@ -86,14 +91,26 @@ class GroundConflictGenerator: g.set_skill(self.game.settings.enemy_vehicle_skill) enemy_groups.append((g, group)) - self.gen_infantry_group_for_group(g, False, self.m.country(self.game.enemy_country), self.conflict.heading - 90) - + self.gen_infantry_group_for_group(g, False, self.mission.country(self.game.enemy_country), self.conflict.heading - 90) # Plan combat actions for groups self.plan_action_for_groups(self.player_stance, player_groups, enemy_groups, self.conflict.heading + 90, self.conflict.from_cp, self.conflict.to_cp) self.plan_action_for_groups(self.enemy_stance, enemy_groups, player_groups, self.conflict.heading - 90, self.conflict.to_cp, self.conflict.from_cp) - + # Add JTAC + if "has_jtac" in self.game.player_faction and self.game.player_faction["has_jtac"] and self.game.settings.include_jtac_if_available: + n = "JTAC" + str(self.conflict.from_cp.id) + str(self.conflict.to_cp.id) + code = 1688 + len(self.game.jtacs) + jtac = self.mission.flight_group(country=self.mission.country(self.game.player_country), + name=n, + aircraft_type=MQ_9_Reaper, + position=position[0], + airport=None, + altitude=5000) + jtac.points[0].tasks.append(OrbitAction(5000, 300, OrbitAction.OrbitPattern.Circle)) + jtac.points[0].tasks.append(SetInvisibleCommand(True)) + jtac.points[0].tasks.append(SetImmortalCommand(True)) + self.game.jtacs.append(("Frontline " + self.conflict.from_cp.name + "/" + self.conflict.to_cp.name, code, n)) def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading): @@ -118,7 +135,7 @@ class GroundConflictGenerator: return u = random.choice(possible_infantry_units) - self.m.vehicle_group( + self.mission.vehicle_group( side, namegen.next_infantry_name(side, cp, u), u, position=infantry_position, @@ -129,7 +146,7 @@ class GroundConflictGenerator: for i in range(randint(3, 10)): u = random.choice(possible_infantry_units) position = infantry_position.random_point_within(55, 5) - self.m.vehicle_group( + self.mission.vehicle_group( side, namegen.next_infantry_name(side, cp, u), u, position=position, @@ -149,14 +166,63 @@ class GroundConflictGenerator: if self.game.settings.perf_artillery: target = self.get_artillery_target_in_range(dcs_group, group, enemy_groups) if target is not None: - dcs_group.points[0].tasks.append(FireAtPoint(target, len(group.units) * 10, 100)) + + if stance != CombatStance.RETREAT: + hold_task = Hold() + hold_task.number = 1 + dcs_group.add_trigger_action(hold_task) + + # Artillery strike random start + artillery_trigger = TriggerOnce(Event.NoEvent, "ArtilleryFireTask #" + str(dcs_group.id)) + artillery_trigger.add_condition(TimeAfter(seconds=random.randint(1, 45)* 60)) + + fire_task = FireAtPoint(target, len(group.units) * 10, 100) + if stance != CombatStance.RETREAT: + fire_task.number = 2 + else: + fire_task.number = 1 + dcs_group.add_trigger_action(fire_task) + artillery_trigger.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks))) + self.mission.triggerrules.triggers.append(artillery_trigger) + + # Artillery will fall back when under attack + if stance != CombatStance.RETREAT: + + # Hold position + dcs_group.points[0].tasks.append(Hold()) + retreat = self.find_retreat_point(dcs_group, forward_heading, (int)(RETREAT_DISTANCE/3)) + dcs_group.add_waypoint(dcs_group.position.point_from_heading(forward_heading, 1), PointAction.OffRoad) + dcs_group.points[1].tasks.append(Hold()) + dcs_group.add_waypoint(retreat, PointAction.OffRoad) + + artillery_fallback = TriggerOnce(Event.NoEvent, "ArtilleryRetreat #" + str(dcs_group.id)) + for i, u in enumerate(dcs_group.units): + artillery_fallback.add_condition(UnitDamaged(u.id)) + if i < len(dcs_group.units) - 1: + artillery_fallback.add_condition(Or()) + + hold_2 = Hold() + hold_2.number = 3 + dcs_group.add_trigger_action(hold_2) + + retreat_task = GoToWaypoint(toIndex=3) + retreat_task.number = 4 + dcs_group.add_trigger_action(retreat_task) + + artillery_fallback.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks))) + self.mission.triggerrules.triggers.append(artillery_fallback) + + for u in dcs_group.units: + u.initial = True + u.heading = forward_heading + random.randint(-5,5) + elif group.role in [CombatGroupRole.TANK, CombatGroupRole.IFV]: if stance == CombatStance.AGGRESIVE: # Attack nearest enemy if any # Then move forward OR Attack enemy base if it is not too far away target = self.find_nearest_enemy_group(dcs_group, enemy_groups) if target is not None: - rand_offset = Point(random.randint(-50, 50), random.randint(-50, 50)) + rand_offset = Point(random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK), random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK)) dcs_group.add_waypoint(target.points[0].position + rand_offset, PointAction.OffRoad) dcs_group.points[1].tasks.append(AttackGroup(target.id)) @@ -179,13 +245,17 @@ class GroundConflictGenerator: targets = self.find_n_nearest_enemy_groups(dcs_group, enemy_groups, 3) i = 1 for target in targets: - rand_offset = Point(random.randint(-50, 50), random.randint(-50, 50)) - dcs_group.add_waypoint(target.points[0].position+rand_offset,PointAction.OffRoad) + rand_offset = Point(random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK), random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK)) + dcs_group.add_waypoint(target.points[0].position+rand_offset, PointAction.OffRoad) dcs_group.points[i].tasks.append(AttackGroup(target.id)) i = i + 1 if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE: attack_point = to_cp.position.random_point_within(500, 0) dcs_group.add_waypoint(attack_point) + + if stance != CombatStance.RETREAT: + self.add_morale_trigger(dcs_group, forward_heading) + elif group.role in [CombatGroupRole.APC, CombatGroupRole.ATGM]: if stance in [CombatStance.AGGRESIVE, CombatStance.BREAKTHROUGH, CombatStance.ELIMINATION]: @@ -196,6 +266,9 @@ class GroundConflictGenerator: attack_point = self.find_offensive_point(dcs_group, forward_heading, AGGRESIVE_MOVE_DISTANCE) dcs_group.add_waypoint(attack_point, PointAction.OnRoad) + if stance != CombatStance.RETREAT: + self.add_morale_trigger(dcs_group, forward_heading) + if stance == CombatStance.RETREAT: # In retreat mode, the units will fall back # If the ally base is close enough, the units will even regroup there @@ -208,14 +281,51 @@ class GroundConflictGenerator: dcs_group.add_waypoint(reposition_point, PointAction.OffRoad) - def find_retreat_point(self, dcs_group, frontline_heading): + def add_morale_trigger(self, dcs_group, forward_heading): + """ + This add a trigger to manage units fleeing whenever their group is hit hard, or being engaged by CAS + """ + + if len(dcs_group.units) == 1: + return + + # Units should hold position on last waypoint + dcs_group.points[len(dcs_group.points) - 1].tasks.append(Hold()) + + # Force unit heading + for unit in dcs_group.units: + unit.heading = forward_heading + dcs_group.manualHeading = True + + # We add a new retreat waypoint + dcs_group.add_waypoint(self.find_retreat_point(dcs_group, forward_heading, (int)(RETREAT_DISTANCE / 8)), PointAction.OffRoad) + + # Fallback task + fallback = ControlledTask(GoToWaypoint(toIndex=len(dcs_group.points))) + fallback.enabled = False + dcs_group.add_trigger_action(Hold()) + dcs_group.add_trigger_action(fallback) + + # Create trigger + fallback = TriggerOnce(Event.NoEvent, "Morale manager #" + str(dcs_group.id)) + + # Usually more than 50% casualties = RETREAT + fallback.add_condition(GroupLifeLess(dcs_group.id, random.randint(51, 76))) + + # Do retreat to the configured retreat waypoint + fallback.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks))) + + self.mission.triggerrules.triggers.append(fallback) + + + def find_retreat_point(self, dcs_group, frontline_heading, distance=RETREAT_DISTANCE): """ Find a point to retreat to :param dcs_group: DCS mission group we are searching a retreat point for :param frontline_heading: Heading of the frontline :return: dcs.mapping.Point object with the desired position """ - return dcs_group.points[0].position.point_from_heading(frontline_heading-180, RETREAT_DISTANCE) + return dcs_group.points[0].position.point_from_heading(frontline_heading-180, distance) def find_offensive_point(self, dcs_group, frontline_heading, distance): """ @@ -310,7 +420,7 @@ class GroundConflictGenerator: cp = self.conflict.to_cp logging.info("armorgen: {} for {}".format(unit, side.id)) - group = self.m.vehicle_group( + group = self.mission.vehicle_group( side, namegen.next_unit_name(side, cp.id, unit), unit, position=self._group_point(at), diff --git a/gen/briefinggen.py b/gen/briefinggen.py index 2c9712bf..c3e10931 100644 --- a/gen/briefinggen.py +++ b/gen/briefinggen.py @@ -24,6 +24,8 @@ class BriefingGenerator: self.targets = [] self.waypoints = [] + self.jtacs = [] + def append_frequency(self, name: str, frequency: str): self.freqs.append((name, frequency)) @@ -45,8 +47,13 @@ class BriefingGenerator: self.description += "#0 -- TAKEOFF : Take off from " + flight.from_cp.name + "\n" for i, wpt in enumerate(flight.points): self.description += "#" + str(1+i) + " -- " + wpt.name + " : " + wpt.description + "\n" - self.description += "#" + str(len(flight.points) + 1) + " -- RTB\n" + self.description += "#" + str(len(flight.points) + 1) + " -- RTB\n\n" + group = flight.group + if group is not None: + for i, nav_target in enumerate(group.nav_target_points): + self.description += nav_target.text_comment + "\n" + self.description += "\n" self.description += "-" * 50 + "\n" def add_ally_flight_description(self, flight): @@ -54,7 +61,6 @@ class BriefingGenerator: flight_unit_name = db.unit_type_name(flight.unit_type) self.description += flight.flight_type.name + " " + flight_unit_name + " x " + str(flight.count) + ", departing in " + str(flight.scheduled_in) + " minutes \n" - def generate(self): self.description = "" @@ -62,8 +68,7 @@ class BriefingGenerator: self.description += "DCS Liberation turn #" + str(self.game.turn) + "\n" self.description += "=" * 15 + "\n\n" - self.description += "Current situation:\n" - self.description += "=" * 15 + "\n\n" + self.generate_ongoing_war_text() self.description += "\n"*2 self.description += "Your flights:" + "\n" @@ -89,11 +94,12 @@ class BriefingGenerator: for name, freq in self.freqs: self.description += "{}: {}\n".format(name, freq) self.description += ("-" * 50) + "\n" + for cp in self.game.theater.controlpoints: if cp.captured and cp.cptype in [ControlPointType.LHA_GROUP, ControlPointType.AIRCRAFT_CARRIER_GROUP]: self.description += cp.name + "\n" + self.description += "RADIO : 127.5 Mhz AM\n" self.description += "TACAN : " - self.description += str(cp.tacanN) if cp.tacanY: self.description += "Y" @@ -105,6 +111,80 @@ class BriefingGenerator: self.description += "ICLS Channel : " + str(cp.icls) + "\n" self.description += "-" * 50 + "\n" + + self.description += "JTACS [F-10 Menu] : \n" + self.description += "===================\n\n" + for jtac in self.game.jtacs: + self.description += str(jtac[0]) + " -- Code : " + str(jtac[1]) + "\n" + self.m.set_description_text(self.description) + self.m.add_picture_blue(os.path.abspath("./resources/ui/splash_screen.png")) + + + def generate_ongoing_war_text(self): + + self.description += "Current situation:\n" + self.description += "=" * 15 + "\n\n" + + conflict_number = 0 + + for c in self.game.theater.conflicts(): + conflict_number = conflict_number + 1 + if c[0].captured: + player_base = c[0] + enemy_base = c[1] + else: + player_base = c[1] + enemy_base = c[0] + + has_numerical_superiority = player_base.base.total_armor > enemy_base.base.total_armor + self.description += self.__random_frontline_sentence(player_base.name, enemy_base.name) + + if enemy_base.id in player_base.stances.keys(): + stance = player_base.stances[enemy_base.id] + + if player_base.base.total_armor == 0: + self.description += "We do not have a single vehicle available to hold our position, the situation is critical, and we will lose ground inevitably.\n" + elif enemy_base.base.total_armor == 0: + self.description += "The enemy forces have been crushed, we will be able to make significant progress toward " + enemy_base.name + ". \n" + if stance == CombatStance.AGGRESIVE: + if has_numerical_superiority: + self.description += "On this location, our ground forces will try to make progress against the enemy" + self.description += ". As the enemy is outnumbered, our forces should have no issue making progress.\n" + elif has_numerical_superiority: + self.description += "On this location, our ground forces will try an audacious assault against enemies in superior numbers. The operation is risky, and the enemy might counter attack.\n" + elif stance == CombatStance.ELIMINATION: + if has_numerical_superiority: + self.description += "On this location, our ground forces will focus on the destruction of enemy assets, before attempting to make progress toward " + enemy_base.name + ". " + self.description += "The enemy is already outnumbered, and this maneuver might draw a final blow to their forces.\n" + elif has_numerical_superiority: + self.description += "On this location, our ground forces will try an audacious assault against enemies in superior numbers. The operation is risky, and the enemy might counter attack.\n" + elif stance == CombatStance.BREAKTHROUGH: + if has_numerical_superiority: + self.description += "On this location, our ground forces will focus on progression toward " + enemy_base.name + ".\n" + elif has_numerical_superiority: + self.description += "On this location, our ground forces have been ordered to rush toward " + enemy_base.name + ". Wish them luck... We are also expecting a counter attack.\n" + elif stance in [CombatStance.DEFENSIVE, CombatStance.AMBUSH]: + if has_numerical_superiority: + self.description += "On this location, our ground forces will hold position. We are not expecting an enemy assault.\n" + elif has_numerical_superiority: + self.description += "On this location, our ground forces have been ordered to hold still, and defend against enemy attacks. An enemy assault might be iminent.\n" + + if conflict_number == 0: + self.description += "There are currently no fights on the ground.\n" + + self.description += "\n\n" + + + def __random_frontline_sentence(self, player_base_name, enemy_base_name): + templates = [ + "There are combats between {} and {}. ", + "The war on the ground is still going on between {} an {}. ", + "Our ground forces in {} are opposed to enemy forces based in {}. ", + "Our forces from {} are fighting enemies based in {}. ", + "There is an active frontline between {} and {}. ", + ] + return random.choice(templates).format(player_base_name, enemy_base_name) + diff --git a/gen/fleet/carrier_group.py b/gen/fleet/carrier_group.py index 30cffdaa..119bc2d4 100644 --- a/gen/fleet/carrier_group.py +++ b/gen/fleet/carrier_group.py @@ -23,11 +23,12 @@ class CarrierGroupGenerator(GroupGenerator): return # Add destroyers escort - dd_type = random.choice(self.faction["destroyer"]) - self.add_unit(dd_type, "DD1", self.position.x + 250, self.position.y + 450, self.heading) - self.add_unit(dd_type, "DD2", self.position.x + 250, self.position.y - 450, self.heading) + if "destroyer" in self.faction.keys(): + dd_type = random.choice(self.faction["destroyer"]) + self.add_unit(dd_type, "DD1", self.position.x + 2500, self.position.y + 4500, self.heading) + self.add_unit(dd_type, "DD2", self.position.x + 2500, self.position.y - 4500, self.heading) - self.add_unit(dd_type, "DD3", self.position.x + 450, self.position.y + 850, self.heading) - self.add_unit(dd_type, "DD4", self.position.x + 450, self.position.y - 850, self.heading) + self.add_unit(dd_type, "DD3", self.position.x + 4500, self.position.y + 8500, self.heading) + self.add_unit(dd_type, "DD4", self.position.x + 4500, self.position.y - 8500, self.heading) self.get_generated_group().points[0].speed = 20 \ No newline at end of file diff --git a/gen/fleet/cn_dd_group.py b/gen/fleet/cn_dd_group.py index 49125525..efef82d2 100644 --- a/gen/fleet/cn_dd_group.py +++ b/gen/fleet/cn_dd_group.py @@ -31,7 +31,7 @@ class ChineseNavyGroupGenerator(GroupGenerator): self.add_unit(dd_type, "FF2", self.position.x + 2400, self.position.y - 900, self.heading) if include_cc: - cc_type = random.choice([Type_093, CGN_1144_2_Pyotr_Velikiy]) + cc_type = random.choice([CGN_1144_2_Pyotr_Velikiy]) self.add_unit(cc_type, "CC1", self.position.x, self.position.y, self.heading) self.get_generated_group().points[0].speed = 20 diff --git a/gen/fleet/lha_group.py b/gen/fleet/lha_group.py index e8d46764..8945c8f2 100644 --- a/gen/fleet/lha_group.py +++ b/gen/fleet/lha_group.py @@ -19,7 +19,7 @@ class LHAGroupGenerator(GroupGenerator): # Add destroyers escort if "destroyer" in self.faction.keys(): dd_type = random.choice(self.faction["destroyer"]) - self.add_unit(dd_type, "DD1", self.position.x + 250, self.position.y + 450, self.heading) - self.add_unit(dd_type, "DD2", self.position.x + 250, self.position.y - 450, self.heading) + self.add_unit(dd_type, "DD1", self.position.x + 1250, self.position.y + 1450, self.heading) + self.add_unit(dd_type, "DD2", self.position.x + 1250, self.position.y - 1450, self.heading) self.get_generated_group().points[0].speed = 20 \ No newline at end of file diff --git a/gen/flights/ai_flight_planner.py b/gen/flights/ai_flight_planner.py index bef13954..06d0355b 100644 --- a/gen/flights/ai_flight_planner.py +++ b/gen/flights/ai_flight_planner.py @@ -56,7 +56,7 @@ class FlightPlanner: self.compute_strike_targets() # The priority is to assign air-superiority fighter or interceptor to interception roles, so they can scramble if there is an attacker - #self.commision_interceptors() + # self.commision_interceptors() # Then some CAP patrol for the next 2 hours self.commision_cap() @@ -106,6 +106,7 @@ class FlightPlanner: break inventory[unit] = inventory[unit] - 2 flight = Flight(unit, 2, self.from_cp, FlightType.INTERCEPTION) + flight.scheduled_in = 1 flight.points = [] self.interceptor_flights.append(flight) diff --git a/gen/flights/ai_flight_planner_db.py b/gen/flights/ai_flight_planner_db.py index b207fc0c..c73cece4 100644 --- a/gen/flights/ai_flight_planner_db.py +++ b/gen/flights/ai_flight_planner_db.py @@ -3,13 +3,22 @@ from dcs.helicopters import * # Interceptor are the aircraft prioritized for interception tasks # If none is available, the AI will use regular CAP-capable aircraft instead +from pydcs_extensions.a4ec.a4ec import A_4E_C +from pydcs_extensions.mb339.mb339 import MB_339PAN +from pydcs_extensions.rafale.rafale import Rafale_A_S, Rafale_M + INTERCEPT_CAPABLE = [ MiG_21Bis, MiG_25PD, MiG_31, + MiG_29S, + MiG_29A, + MiG_29G, + MiG_29K, M_2000C, Mirage_2000_5, + Rafale_M, F_14B, F_15C, @@ -56,6 +65,9 @@ CAP_CAPABLE = [ Bf_109K_4, FW_190D9, FW_190A8, + + A_4E_C, + Rafale_M, ] # USed for CAS (Close air support) and BAI (Battlefield Interdiction) @@ -89,6 +101,7 @@ CAS_CAPABLE = [ FA_18C_hornet, C_101CC, + MB_339PAN, L_39ZA, AJS37, @@ -116,6 +129,9 @@ CAS_CAPABLE = [ Bf_109K_4, FW_190D9, FW_190A8, + + A_4E_C, + Rafale_A_S ] # Aircraft used for SEAD / DEAD tasks @@ -133,14 +149,16 @@ SEAD_CAPABLE = [ Su_30, Su_34, MiG_27K, + + A_4E_C, + Rafale_A_S ] # Aircraft used for Strike mission STRIKE_CAPABLE = [ MiG_15bis, - MiG_29A, MiG_27K, - MiG_29S, + MB_339PAN, Su_17M4, Su_24M, @@ -180,6 +198,9 @@ STRIKE_CAPABLE = [ FW_190D9, FW_190A8, + A_4E_C, + Rafale_A_S + ] ANTISHIP_CAPABLE = [ @@ -193,4 +214,5 @@ ANTISHIP_CAPABLE = [ A_10A, Ju_88A4, + Rafale_A_S ] \ No newline at end of file diff --git a/gen/flights/flight.py b/gen/flights/flight.py index 16b4e4f9..57c7097f 100644 --- a/gen/flights/flight.py +++ b/gen/flights/flight.py @@ -91,6 +91,7 @@ class Flight: loadout = {} preset_loadout_name = "" start_type = "Runway" + group = False # Contains DCS Mission group data after mission has been generated # How long before this flight should take off scheduled_in = 0 diff --git a/gen/ground_forces/ai_ground_planner.py b/gen/ground_forces/ai_ground_planner.py index 46c12d51..bdc3a18d 100644 --- a/gen/ground_forces/ai_ground_planner.py +++ b/gen/ground_forces/ai_ground_planner.py @@ -7,6 +7,8 @@ from gen import Conflict from gen.ground_forces.combat_stance import CombatStance from theater import ControlPoint +import pydcs_extensions.frenchpack.frenchpack as frenchpack + TYPE_TANKS = [ Armor.MBT_T_55, Armor.MBT_T_72B, @@ -32,6 +34,18 @@ TYPE_TANKS = [ Armor.ST_Centaur_IV, Armor.CT_Cromwell_IV, Armor.HIT_Churchill_VII, + + # Mods + frenchpack.DIM__TOYOTA_BLUE, + frenchpack.DIM__TOYOTA_GREEN, + frenchpack.DIM__TOYOTA_DESERT, + frenchpack.DIM__KAMIKAZE, + + frenchpack.AMX_10RCR, + frenchpack.AMX_10RCR_SEPAR, + frenchpack.AMX_30B2, + frenchpack.Leclerc_Serie_XXI, + ] TYPE_ATGM = [ @@ -44,6 +58,12 @@ TYPE_ATGM = [ Armor.TD_Jagdpanzer_IV, Armor.TD_Jagdpanther_G1, Armor.TD_M10_GMC, + + # Mods + frenchpack.VBAE_CRAB_MMP, + frenchpack.VAB_MEPHISTO, + frenchpack.TRM_2000_PAMELA, + ] TYPE_IFV = [ @@ -61,6 +81,12 @@ TYPE_IFV = [ # WW2 Armor.IFV_Sd_Kfz_234_2_Puma, Armor.LAC_M8_Greyhound, + + # Mods + frenchpack.ERC_90, + frenchpack.VBAE_CRAB, + frenchpack.VAB_T20_13 + ] TYPE_APC = [ @@ -81,6 +107,12 @@ TYPE_APC = [ # WW2 Armor.APC_M2A1, Armor.APC_Sd_Kfz_251, + + # Mods + frenchpack.VAB__50, + frenchpack.VBL__50, + frenchpack.VBL_AANF1, + ] TYPE_ARTILLERY = [ @@ -117,6 +149,11 @@ TYPE_LOGI = [ Unarmed.Willys_MB, Unarmed.Land_Rover_109_S3, Unarmed.Land_Rover_101_FC, + + # Mods + frenchpack.VBL, + frenchpack.VAB, + ] TYPE_INFANTRY = [ @@ -148,14 +185,14 @@ class CombatGroupRole(Enum): DISTANCE_FROM_FRONTLINE = { - CombatGroupRole.TANK:2800, - CombatGroupRole.APC:7000, - CombatGroupRole.IFV:3000, - CombatGroupRole.ARTILLERY:14000, - CombatGroupRole.SHORAD:12000, - CombatGroupRole.LOGI:18000, - CombatGroupRole.INFANTRY:2800, - CombatGroupRole.ATGM:5500 + CombatGroupRole.TANK:3200, + CombatGroupRole.APC:8000, + CombatGroupRole.IFV:3700, + CombatGroupRole.ARTILLERY:18000, + CombatGroupRole.SHORAD:13000, + CombatGroupRole.LOGI:20000, + CombatGroupRole.INFANTRY:3000, + CombatGroupRole.ATGM:6200 } GROUP_SIZES_BY_COMBAT_STANCE = { diff --git a/gen/groundobjectsgen.py b/gen/groundobjectsgen.py index 64939fc0..458e5ae9 100644 --- a/gen/groundobjectsgen.py +++ b/gen/groundobjectsgen.py @@ -45,12 +45,6 @@ class GroundObjectsGenerator: def generate(self): - cp = None # type: ControlPoint - if self.conflict.attackers_country.name == self.game.player_country: - cp = self.conflict.to_cp - else: - cp = self.conflict.from_cp - for cp in self.game.theater.controlpoints: if cp.captured: @@ -78,6 +72,7 @@ class GroundObjectsGenerator: vehicle.position.x = u.position.x vehicle.position.y = u.position.y vehicle.heading = u.heading + vehicle.player_can_drive = True vg.add_unit(vehicle) else: vg = self.m.ship_group(side, g.name, utype, position=g.position, @@ -121,7 +116,7 @@ class GroundObjectsGenerator: found_carrier_destination = False attempt = 0 while not found_carrier_destination and attempt < 5: - point = sg.points[0].position.point_from_heading(self.m.weather.wind_at_ground.direction, 100000-attempt*20000) + point = sg.points[0].position.point_from_heading(self.m.weather.wind_at_ground.direction + 180, 100000-attempt*20000) if self.game.theater.is_in_sea(point): found_carrier_destination = True sg.add_waypoint(point) diff --git a/gen/sam/sam_sa10.py b/gen/sam/sam_sa10.py index d85def5c..a5332546 100644 --- a/gen/sam/sam_sa10.py +++ b/gen/sam/sam_sa10.py @@ -20,6 +20,12 @@ class SA10Generator(GroupGenerator): # Search radar for missiles (optionnal) self.add_unit(AirDefence.SAM_SA_10_S_300PS_SR_64H6E, "SR2", self.position.x - 40, self.position.y, self.heading) + # 2 Tracking radars + self.add_unit(AirDefence.SAM_SA_10_S_300PS_TR_30N6, "TR1", self.position.x - 40, self.position.y - 40, self.heading) + + self.add_unit(AirDefence.SAM_SA_10_S_300PS_TR_30N6, "TR2", self.position.x + 40, self.position.y - 40, + self.heading) + # 2 different launcher type (C & D) num_launchers = random.randint(6, 8) positions = self.get_circular_position(num_launchers, launcher_distance=120, coverage=360) @@ -40,4 +46,4 @@ class SA10Generator(GroupGenerator): num_launchers = random.randint(6, 8) positions = self.get_circular_position(num_launchers, launcher_distance=350, coverage=360) for i, position in enumerate(positions): - self.add_unit(AirDefence.AAA_ZU_23_Emplacement, "AA#" + str(i), position[0], position[1], position[2]) + self.add_unit(AirDefence.SPAAA_ZSU_23_4_Shilka, "AA#" + str(i), position[0], position[1], position[2]) diff --git a/gen/shipgen.py b/gen/shipgen.py deleted file mode 100644 index 110c1fb1..00000000 --- a/gen/shipgen.py +++ /dev/null @@ -1,53 +0,0 @@ -import logging - -from game import db -from .conflictgen import * -from .naming import * - -from dcs.mission import * -from dcs.unitgroup import * -from dcs.task import * - -SHIP_RANDOM_SPREAD = 300 - - -class ShipGenerator: - def __init__(self, mission: Mission, conflict: Conflict): - self.m = mission - self.conflict = conflict - - def generate_carrier(self, for_units: typing.Collection[UnitType], country: str, at: Point) -> ShipGroup: - type = db.find_unittype(Carriage, country)[0] - for unit_type in for_units: - if unit_type in db.CARRIER_TYPE_BY_PLANE: - type = db.CARRIER_TYPE_BY_PLANE[unit_type] - break - - group = self.m.ship_group( - country=self.m.country(country), - name=namegen.next_carrier_name(self.m.country(country)), - _type=type, - position=at) - - group.points[0].tasks.append(ActivateBeaconCommand(unit_id=group.id, channel=20, callsign="SHDW", aa=False)) - group.points[0].tasks.append(ActivateICLSCommand(unit_id=group.id, channel=1)) - return group - - def generate_cargo(self, units: db.ShipDict) -> typing.Collection[ShipGroup]: - groups = [] - offset = 0 - for unit_type, unit_count in units.items(): - for _ in range(unit_count): - offset += 1 - logging.info("shipgen: {} ({}) for {}".format(unit_type, unit_count, self.conflict.defenders_side)) - group = self.m.ship_group( - country=self.conflict.defenders_country, - name=namegen.next_unit_name(self.conflict.defenders_country, unit_type), - _type=unit_type, - position=self.conflict.ground_defenders_location.random_point_within(SHIP_RANDOM_SPREAD, SHIP_RANDOM_SPREAD).point_from_heading(0, offset * SHIP_RANDOM_SPREAD) - ) - - group.add_waypoint(self.conflict.to_cp.position) - groups.append(group) - - return groups diff --git a/gen/triggergen.py b/gen/triggergen.py index a88d2029..c62afe7b 100644 --- a/gen/triggergen.py +++ b/gen/triggergen.py @@ -95,8 +95,8 @@ class TriggersGenerator: self.mission.triggerrules.triggers.append(mark_trigger) def generate(self): - player_coalition = self.game.player_country in db.BLUEFOR_FACTIONS and "blue" or "red" - enemy_coalition = player_coalition == "blue" and "red" or "blue" + player_coalition = "blue" + enemy_coalition = "red" self.mission.coalition["blue"].bullseye = {"x": self.conflict.position.x, "y": self.conflict.position.y} diff --git a/liberation_theme.json b/liberation_theme.json new file mode 100644 index 00000000..7fa657ab --- /dev/null +++ b/liberation_theme.json @@ -0,0 +1 @@ +{"theme_index": 1} \ No newline at end of file diff --git a/pydcs_extensions/a4ec/a4ec.py b/pydcs_extensions/a4ec/a4ec.py new file mode 100644 index 00000000..01e0c88f --- /dev/null +++ b/pydcs_extensions/a4ec/a4ec.py @@ -0,0 +1,782 @@ +from enum import Enum + +from dcs import task +from dcs.planes import PlaneType +from dcs.weapons_data import Weapons + + +class WeaponsA4EC: + AN_M57__2__TER_ = {"clsid": "{AN-M57_TER_2_L}", "name": "AN-M57 *2 (TER)", "weight": 273.6} + AN_M57__2__TER__ = {"clsid": "{AN-M57_TER_2_R}", "name": "AN-M57 *2 (TER)", "weight": 273.6} + AN_M57__3__TER_ = {"clsid": "{AN-M57_TER_3_C}", "name": "AN-M57 *3 (TER)", "weight": 386.6} + AN_M57__5__MER_ = {"clsid": "{AN-M57_MER_5_L}", "name": "AN-M57 *5 (MER)", "weight": 664.8} + AN_M57__5__MER__ = {"clsid": "{AN-M57_MER_5_R}", "name": "AN-M57 *5 (MER)", "weight": 664.8} + AN_M57__6__MER_ = {"clsid": "{AN-M57_MER_6_C}", "name": "AN-M57 *6 (MER)", "weight": 777.8} + AN_M66A2 = {"clsid": "{AN-M66A2}", "name": "AN-M66A2", "weight": 970.68688} + AN_M81 = {"clsid": "{AN-M81}", "name": "AN-M81", "weight": 117.93392} + AN_M81__5__MER_ = {"clsid": "{AN-M81_MER_5_L}", "name": "AN-M81 *5 (MER)", "weight": 689.3} + AN_M81__5__MER__ = {"clsid": "{AN-M81_MER_5_R}", "name": "AN-M81 *5 (MER)", "weight": 689.3} + AN_M81__6__MER_ = {"clsid": "{AN-M81_MER_6_C}", "name": "AN-M81 *6 (MER)", "weight": 807.2} + AN_M88 = {"clsid": "{AN-M88}", "name": "AN-M88", "weight": 98.0665904} + AN_M88__5__MER_ = {"clsid": "{AN-M88_MER_5_L}", "name": "AN-M88 *5 (MER)", "weight": 589.8} + AN_M88__5__MER__ = {"clsid": "{AN-M88_MER_5_R}", "name": "AN-M88 *5 (MER)", "weight": 589.8} + AN_M88__6__MER_ = {"clsid": "{AN-M88_MER_6_C}", "name": "AN-M88 *6 (MER)", "weight": 687.8} + CBU_1_A = {"clsid": "{CBU-1/A}", "name": "CBU-1/A", "weight": 458.921706} + CBU_1_A__2 = {"clsid": "{CBU-1/A_TER_2_L}", "name": "CBU-1/A *2", "weight": 713.473056} + CBU_1_A__2_ = {"clsid": "{CBU-1/A_TER_2_R}", "name": "CBU-1/A *2", "weight": 713.473056} + CBU_2B_A = {"clsid": "{CBU-2B/A}", "name": "CBU-2B/A", "weight": 379.543106} + CBU_2B_A__2 = {"clsid": "{CBU-2B/A_TER_2_L}", "name": "CBU-2B/A *2", "weight": 806.686212} + CBU_2B_A__2_ = {"clsid": "{CBU-2B/A_TER_2_R}", "name": "CBU-2B/A *2", "weight": 806.686212} + CBU_2_A = {"clsid": "{CBU-2/A}", "name": "CBU-2/A", "weight": 343.822736} + CBU_2_A__2 = {"clsid": "{CBU-2/A_TER_2_L}", "name": "CBU-2/A *2", "weight": 735.245472} + CBU_2_A__2_ = {"clsid": "{CBU-2/A_TER_2_R}", "name": "CBU-2/A *2", "weight": 735.245472} + D_704_Refueling_Pod = {"clsid": "{D-704_BUDDY_POD}", "name": "D-704 Refueling Pod", "weight": 1234.532648} + Fuel_Tank_150_gallons = {"clsid": "{DFT-150gal}", "name": "Fuel Tank 150 gallons", "weight": 515.888512} + Fuel_Tank_300_gallons = {"clsid": "{DFT-300gal}", "name": "Fuel Tank 300 gallons", "weight": 991.407336} + Fuel_Tank_300_gallons_ = {"clsid": "{DFT-300gal_LR}", "name": "Fuel Tank 300 gallons", "weight": 998.664808} + Fuel_Tank_400_gallons = {"clsid": "{DFT-400gal}", "name": "Fuel Tank 400 gallons", "weight": 1320.06208} + LAU_10_2___4_ZUNI_MK_71 = {"clsid": "{LAU-10 ZUNI_TER_2_C}", "name": "LAU-10*2 - 4 ZUNI MK 71", "weight": 927.6} + LAU_10_2___4_ZUNI_MK_71_ = {"clsid": "{LAU-10 ZUNI_TER_2_L}", "name": "LAU-10*2 - 4 ZUNI MK 71", "weight": 927.6} + LAU_10_2___4_ZUNI_MK_71__ = {"clsid": "{LAU-10 ZUNI_TER_2_R}", "name": "LAU-10*2 - 4 ZUNI MK 71", "weight": 927.6} + LAU_10_3___4_ZUNI_MK_71 = {"clsid": "{LAU-10 ZUNI_TER_3_C}", "name": "LAU-10*3 - 4 ZUNI MK 71", "weight": 1367.6} + LAU_3_2___19_FFAR_M156_WP = {"clsid": "{LAU-3 FFAR WP156_TER_2_C}", "name": "LAU-3*2 - 19 FFAR M156 WP", "weight": 673.3414512} + LAU_3_2___19_FFAR_M156_WP_ = {"clsid": "{LAU-3 FFAR WP156_TER_2_L}", "name": "LAU-3*2 - 19 FFAR M156 WP", "weight": 673.3414512} + LAU_3_2___19_FFAR_M156_WP__ = {"clsid": "{LAU-3 FFAR WP156_TER_2_R}", "name": "LAU-3*2 - 19 FFAR M156 WP", "weight": 673.3414512} + LAU_3_2___19_FFAR_Mk1_HE = {"clsid": "{LAU-3 FFAR Mk1 HE_TER_2_C}", "name": "LAU-3*2 - 19 FFAR Mk1 HE", "weight": 618.184664} + LAU_3_2___19_FFAR_Mk1_HE_ = {"clsid": "{LAU-3 FFAR Mk1 HE_TER_2_L}", "name": "LAU-3*2 - 19 FFAR Mk1 HE", "weight": 618.184664} + LAU_3_2___19_FFAR_Mk1_HE__ = {"clsid": "{LAU-3 FFAR Mk1 HE_TER_2_R}", "name": "LAU-3*2 - 19 FFAR Mk1 HE", "weight": 618.184664} + LAU_3_2___19_FFAR_Mk5_HEAT = {"clsid": "{LAU-3 FFAR Mk5 HEAT_TER_2_C}", "name": "LAU-3*2 - 19 FFAR Mk5 HEAT", "weight": 619.9083136} + LAU_3_2___19_FFAR_Mk5_HEAT_ = {"clsid": "{LAU-3 FFAR Mk5 HEAT_TER_2_L}", "name": "LAU-3*2 - 19 FFAR Mk5 HEAT", "weight": 619.9083136} + LAU_3_2___19_FFAR_Mk5_HEAT__ = {"clsid": "{LAU-3 FFAR Mk5 HEAT_TER_2_R}", "name": "LAU-3*2 - 19 FFAR Mk5 HEAT", "weight": 619.9083136} + LAU_3_3___19_FFAR_M156_WP = {"clsid": "{LAU-3 FFAR WP156_TER_3_C}", "name": "LAU-3*3 - 19 FFAR M156 WP", "weight": 986.2121768} + LAU_3_3___19_FFAR_Mk1_HE = {"clsid": "{LAU-3 FFAR Mk1 HE_TER_3_C}", "name": "LAU-3*3 - 19 FFAR Mk1 HE", "weight": 903.476996} + LAU_3_3___19_FFAR_Mk5_HEAT = {"clsid": "{LAU-3 FFAR Mk5 HEAT_TER_3_C}", "name": "LAU-3*3 - 19 FFAR Mk5 HEAT", "weight": 906.0624704} + LAU_68_2___7_FFAR_M156_WP = {"clsid": "{LAU-68 FFAR WP156_TER_2_C}", "name": "LAU-68*2 - 7 FFAR M156 WP", "weight": 287.9121136} + LAU_68_2___7_FFAR_M156_WP_ = {"clsid": "{LAU-68 FFAR WP156_TER_2_L}", "name": "LAU-68*2 - 7 FFAR M156 WP", "weight": 287.9121136} + LAU_68_2___7_FFAR_M156_WP__ = {"clsid": "{LAU-68 FFAR WP156_TER_2_R}", "name": "LAU-68*2 - 7 FFAR M156 WP", "weight": 287.9121136} + LAU_68_2___7_FFAR_Mk1_HE = {"clsid": "{LAU-68 FFAR Mk1 HE_TER_2_C}", "name": "LAU-68*2 - 7 FFAR Mk1 HE", "weight": 267.591192} + LAU_68_2___7_FFAR_Mk1_HE_ = {"clsid": "{LAU-68 FFAR Mk1 HE_TER_2_L}", "name": "LAU-68*2 - 7 FFAR Mk1 HE", "weight": 267.591192} + LAU_68_2___7_FFAR_Mk1_HE__ = {"clsid": "{LAU-68 FFAR Mk1 HE_TER_2_R}", "name": "LAU-68*2 - 7 FFAR Mk1 HE", "weight": 267.591192} + LAU_68_2___7_FFAR_Mk5_HEAT = {"clsid": "{LAU-68 FFAR Mk5 HEAT_TER_2_C}", "name": "LAU-68*2 - 7 FFAR Mk5 HEAT", "weight": 268.2262208} + LAU_68_2___7_FFAR_Mk5_HEAT_ = {"clsid": "{LAU-68 FFAR Mk5 HEAT_TER_2_L}", "name": "LAU-68*2 - 7 FFAR Mk5 HEAT", "weight": 268.2262208} + LAU_68_2___7_FFAR_Mk5_HEAT__ = {"clsid": "{LAU-68 FFAR Mk5 HEAT_TER_2_R}", "name": "LAU-68*2 - 7 FFAR Mk5 HEAT", "weight": 268.2262208} + LAU_68_3___7_FFAR_M156_WP = {"clsid": "{LAU-68 FFAR WP156_TER_3_C}", "name": "LAU-68*3 - 7 FFAR M156 WP", "weight": 408.0681704} + LAU_68_3___7_FFAR_Mk1_HE = {"clsid": "{LAU-68 FFAR Mk1 HE_TER_3_C}", "name": "LAU-68*3 - 7 FFAR Mk1 HE", "weight": 377.586788} + LAU_68_3___7_FFAR_Mk5_HEAT = {"clsid": "{LAU-68 FFAR Mk5 HEAT_TER_3_C}", "name": "LAU-68*3 - 7 FFAR Mk5 HEAT", "weight": 378.5393312} + MAK79_2_MK_20 = {"clsid": "{MAK79_MK20 2L}", "name": "MAK79 2 MK-20", "weight": 464} + MAK79_2_MK_20_ = {"clsid": "{MAK79_MK20 2R}", "name": "MAK79 2 MK-20", "weight": 464} + MAK79_MK_20 = {"clsid": "{MAK79_MK20 1R}", "name": "MAK79 MK-20", "weight": 232} + MAK79_MK_20_ = {"clsid": "{MAK79_MK20 1L}", "name": "MAK79 MK-20", "weight": 232} + Mk4_HIPEG = {"clsid": "{Mk4 HIPEG}", "name": "Mk4 HIPEG", "weight": 612.35} + Mk_20__2__TER_ = {"clsid": "{Mk-20_TER_2_L}", "name": "Mk-20 *2 (TER)", "weight": 491.6} + Mk_20__2__TER__ = {"clsid": "{Mk-20_TER_2_R}", "name": "Mk-20 *2 (TER)", "weight": 491.6} + Mk_20__2__TER___ = {"clsid": "{Mk-20_TER_2_C}", "name": "Mk-20 *2 (TER)", "weight": 491.6} + Mk_20__3__TER_ = {"clsid": "{Mk-20_TER_3_C}", "name": "Mk-20 *3 (TER)", "weight": 713.6} + Mk_77_mod_0 = {"clsid": "{mk77mod0}", "name": "Mk-77 mod 0", "weight": 340} + Mk_77_mod_1 = {"clsid": "{mk77mod1}", "name": "Mk-77 mod 1", "weight": 230} + Mk_77_mod_1__2__TER_ = {"clsid": "{Mk-77 mod 1_TER_2_L}", "name": "Mk-77 mod 1 *2 (TER)", "weight": 507.6} + Mk_77_mod_1__2__TER__ = {"clsid": "{Mk-77 mod 1_TER_2_R}", "name": "Mk-77 mod 1 *2 (TER)", "weight": 507.6} + Mk_77_mod_1__2__TER___ = {"clsid": "{Mk-77 mod 1_TER_2_C}", "name": "Mk-77 mod 1 *2 (TER)", "weight": 507.6} + Mk_77_mod_1__4__MER_ = {"clsid": "{Mk-77 mod 1_MER_4_C}", "name": "Mk-77 mod 1 *4 (MER)", "weight": 1019.8} + Mk_81SE = {"clsid": "{MK-81SE}", "name": "Mk-81SE", "weight": 113.398} + Mk_81SE__5__MER_ = {"clsid": "{Mk-81SE_MER_5_L}", "name": "Mk-81SE *5 (MER)", "weight": 689.8} + Mk_81SE__5__MER__ = {"clsid": "{Mk-81SE_MER_5_R}", "name": "Mk-81SE *5 (MER)", "weight": 689.8} + Mk_81SE__6__MER_ = {"clsid": "{Mk-81SE_MER_6_C}", "name": "Mk-81SE *6 (MER)", "weight": 807.8} + Mk_81__5__MER_ = {"clsid": "{Mk-81_MER_5_L}", "name": "Mk-81 *5 (MER)", "weight": 689.8} + Mk_81__5__MER__ = {"clsid": "{Mk-81_MER_5_R}", "name": "Mk-81 *5 (MER)", "weight": 689.8} + Mk_81__6__MER_ = {"clsid": "{Mk-81_MER_6_C}", "name": "Mk-81 *6 (MER)", "weight": 807.8} + Mk_82_Snakeye__2__TER_ = {"clsid": "{Mk-82 Snakeye_TER_2_L}", "name": "Mk-82 Snakeye *2 (TER)", "weight": 529.6} + Mk_82_Snakeye__2__TER__ = {"clsid": "{Mk-82 Snakeye_TER_2_R}", "name": "Mk-82 Snakeye *2 (TER)", "weight": 529.6} + Mk_82_Snakeye__3__TER_ = {"clsid": "{Mk-82 Snakeye_TER_3_C}", "name": "Mk-82 Snakeye *3 (TER)", "weight": 770.6} + Mk_82_Snakeye__4__MER_ = {"clsid": "{Mk-82 Snakeye_MER_4_C}", "name": "Mk-82 Snakeye *4 (MER)", "weight": 1063.8} + Mk_82_Snakeye__6__MER_ = {"clsid": "{Mk-82 Snakeye_MER_6_C}", "name": "Mk-82 Snakeye *6 (MER)", "weight": 1545.8} + Mk_82__2__TER_ = {"clsid": "{Mk-82_TER_2_L}", "name": "Mk-82 *2 (TER)", "weight": 529.6} + Mk_82__2__TER__ = {"clsid": "{Mk-82_TER_2_R}", "name": "Mk-82 *2 (TER)", "weight": 529.6} + Mk_82__3__TER_ = {"clsid": "{Mk-82_TER_3_C}", "name": "Mk-82 *3 (TER)", "weight": 770.6} + Mk_82__4__MER_ = {"clsid": "{Mk-82_MER_4_C}", "name": "Mk-82 *4 (MER)", "weight": 1063.8} + Mk_82__6__MER_ = {"clsid": "{Mk-82_MER_6_C}", "name": "Mk-82 *6 (MER)", "weight": 1545.8} + Mk_83__2__TER_ = {"clsid": "{Mk-83_TER_2_C}", "name": "Mk-83 *2 (TER)", "weight": 941.6} + Mk_83__3__TER_ = {"clsid": "{Mk-83_TER_3_C}", "name": "Mk-83 *3 (TER)", "weight": 1388.6} + _3_LAU_61 = {"clsid": "{TER,LAU-61*3}", "name": "3*LAU-61", "weight": 98} + +class A_4E_C(PlaneType): + id = "A-4E-C" + flyable = True + height = 4.57 + width = 8.38 + length = 12.22 + fuel_max = 2467.5454273299 + max_speed = 1082.88 + chaff = 30 + flare = 30 + charge_total = 60 + chaff_charge_size = 1 + flare_charge_size = 1 + category = "Interceptor" #{78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F} + radio_frequency = 254 + + panel_radio = { + 1: { + "channels": { + 1: 264, + 2: 265, + 4: 254, + 8: 258, + 16: 267, + 17: 251, + 9: 262, + 18: 253, + 5: 250, + 10: 259, + 20: 252, + 11: 268, + 3: 256, + 6: 270, + 12: 269, + 13: 260, + 7: 257, + 14: 263, + 19: 266, + 15: 261 + }, + }, + } + + property_defaults = { + "HideECMPanel": False, + "CBU2ATPP": 0, + "CBU2BATPP": 0, + "CMS_BURSTS": 1, + "CMS_BURST_INTERVAL": 1, + "CMS_SALVOS": 1, + "CMS_SALVO_INTERVAL": 1, + } + + class Properties: + + class HideECMPanel: + id = "HideECMPanel" + + class CBU2ATPP: + id = "CBU2ATPP" + + class Values: + _1_tube = 0 + _2_tubes = 1 + _3_tubes = 2 + _4_tubes = 3 + _6_tubes = 4 + _17_tubes__salvo = 5 + + class CBU2BATPP: + id = "CBU2BATPP" + + class Values: + _2_tubes = 0 + _4_tubes = 1 + _6_tubes = 2 + + class CMS_BURSTS: + id = "CMS_BURSTS" + + class Values: + _1 = 1 + _2 = 2 + _3 = 3 + _4 = 4 + + class CMS_BURST_INTERVAL: + id = "CMS_BURST_INTERVAL" + + class Values: + _0_2_seconds = 1 + _0_3_seconds = 2 + _0_4_seconds = 3 + _0_5_seconds = 4 + + class CMS_SALVOS: + id = "CMS_SALVOS" + + class Values: + _8 = 1 + _12 = 2 + _16 = 3 + _20 = 4 + _24 = 5 + _28 = 6 + _32 = 7 + + class CMS_SALVO_INTERVAL: + id = "CMS_SALVO_INTERVAL" + + class Values: + _2_seconds = 1 + _4_seconds = 2 + _6_seconds = 3 + _8_seconds = 4 + _10_seconds = 5 + _12_seconds = 6 + _14_seconds = 7 + + class Liveries: + + class Georgia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Syria(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Finland(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Australia(Enum): + Unmarked = "Unmarked" + International_Australia = "International Australia" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + International_New_Zealand = "International New Zealand" + International_New_Zealand_Kiwi_Red = "International New Zealand Kiwi Red" + International_New_Zealand_Sqn_75 = "International New Zealand Sqn 75" + + class Germany(Enum): + Unmarked = "Unmarked" + Trainer_BAE_Systems = "Trainer BAE Systems" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class SaudiArabia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Israel(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + International_Israel = "International Israel" + + class Croatia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class CzechRepublic(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Norway(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Romania(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Spain(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Ukraine(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Belgium(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Slovakia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Greece(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class UK(Enum): + Unmarked = "Unmarked" + Trainer_BAE_Systems = "Trainer BAE Systems" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Insurgents(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Hungary(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class France(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Abkhazia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Russia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Sweden(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Austria(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Switzerland(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Italy(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class SouthOssetia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class SouthKorea(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Iran(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class China(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Pakistan(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Belarus(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class NorthKorea(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Iraq(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Kazakhstan(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Bulgaria(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Serbia(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class India(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class USAFAggressors(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + Aggressor_USMC_TopGun_MiG_17 = "Aggressor USMC TopGun MiG-17" + Aggressor_USN_TopGun = "Aggressor USN TopGun" + Aggressor_USN_VF_126_Bandits = "Aggressor USN VF-126 Bandits" + Aggressor_USN_VF_127_Royal_Blues = "Aggressor USN VF-127 Royal Blues" + Aggressor_USN_VFA_127_Cyclons__Forest = "Aggressor USN VFA-127 Cyclons (Forest)" + Aggressor_USN_VFA_127_Cyclons__Sea = "Aggressor USN VFA-127 Cyclons (Sea)" + + class USA(Enum): + Unmarked = "Unmarked" + International_Argentina = "International Argentina" + International_Australia = "International Australia" + Trainer_BAE_Systems = "Trainer BAE Systems" + Blue_Angels_no_1 = "Blue Angels no 1" + Blue_Angels_no_2 = "Blue Angels no 2" + Blue_Angels_no_3 = "Blue Angels no 3" + Blue_Angels_no_4 = "Blue Angels no 4" + Blue_Angels_no_5 = "Blue Angels no 5" + Blue_Angels_no_6 = "Blue Angels no 6" + International_Brazil = "International Brazil" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + International_Israel = "International Israel" + International_Kuwait = "International Kuwait" + International_New_Zealand = "International New Zealand" + International_New_Zealand_Kiwi_Red = "International New Zealand Kiwi Red" + International_New_Zealand_Sqn_75 = "International New Zealand Sqn 75" + Trainer_USMC_PTMC = "Trainer USMC PTMC" + Aggressor_USMC_TopGun_MiG_17 = "Aggressor USMC TopGun MiG-17" + USMC_VMA_121_Green_Knights = "USMC VMA-121 Green Knights" + USMC_VMA_124_Memphis_Marines = "USMC VMA-124 Memphis Marines" + USMC_VMA_131_Diamondbacks = "USMC VMA-131 Diamondbacks" + USMC_VMA_142_Flying_Gators = "USMC VMA-142 Flying Gators" + USMC_VMA_211_Avengers = "USMC VMA-211 Avengers" + USMC_VMA_311_Tomcats = "USMC VMA-311 Tomcats" + USMC_VMA_322_Fighting_Gamecocks = "USMC VMA-322 Fighting Gamecocks" + Trainer_USMC_VMAT_102 = "Trainer USMC VMAT-102" + Trainer_USN_Bare_Metal_1956 = "Trainer USN Bare Metal 1956" + Trainer_USN_NFWS_Gray = "Trainer USN NFWS Gray" + Trainer_USN_NFWS_Green = "Trainer USN NFWS Green" + Aggressor_USN_TopGun = "Aggressor USN TopGun" + USN_VA_144_Roadrunners = "USN VA-144 Roadrunners" + USN_VA_153_Blue_Tail_Flies = "USN VA-153 Blue Tail Flies" + USN_VA_163_Saints = "USN VA-163 Saints" + USN_VA_164_Ghostriders = "USN VA-164 Ghostriders" + USN_VA_195_Dambusters = "USN VA-195 Dambusters" + USN_VA_212_Rampant_Raiders = "USN VA-212 Rampant Raiders" + USN_VA_45_Blackbirds = "USN VA-45 Blackbirds" + USN_VA_55_Warhorses = "USN VA-55 Warhorses" + USN_VA_64_Black_Lancers = "USN VA-64 Black Lancers" + Trainer_USN_VC_1_FLECOMPRON_One = "Trainer USN VC-1 FLECOMPRON One" + Trainer_USN_VC_5_Checkertails = "Trainer USN VC-5 Checkertails" + USN_VC_7_Tallyhoers = "USN VC-7 Tallyhoers" + Trainer_USN_VC_8_Redtails = "Trainer USN VC-8 Redtails" + Aggressor_USN_VF_126_Bandits = "Aggressor USN VF-126 Bandits" + Aggressor_USN_VF_127_Royal_Blues = "Aggressor USN VF-127 Royal Blues" + Aggressor_USN_VFA_127_Cyclons__Forest = "Aggressor USN VFA-127 Cyclons (Forest)" + Aggressor_USN_VFA_127_Cyclons__Sea = "Aggressor USN VFA-127 Cyclons (Sea)" + Trainer_USN_VT_7_Eagles = "Trainer USN VT-7 Eagles" + + class Denmark(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Egypt(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Canada(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class TheNetherlands(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Turkey(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Japan(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Poland(Enum): + Unmarked = "Unmarked" + Community_A_4E = "Community A-4E" + Community_A_4E_II = "Community A-4E II" + + class Pylon1: + LAU_10___4_ZUNI_MK_71 = (1, Weapons.LAU_10___4_ZUNI_MK_71) + LAU_3___19_FFAR_M156_WP = (1, Weapons.LAU_3___19_FFAR_M156_WP) + LAU_3___19_FFAR_Mk1_HE = (1, Weapons.LAU_3___19_FFAR_Mk1_HE) + LAU_3___19_FFAR_Mk5_HEAT = (1, Weapons.LAU_3___19_FFAR_Mk5_HEAT) + LAU_68___7_FFAR_M156_WP = (1, Weapons.LAU_68___7_FFAR_M156_WP) + LAU_68___7_FFAR_Mk1_HE = (1, Weapons.LAU_68___7_FFAR_Mk1_HE) + LAU_68___7_FFAR_Mk5_HEAT = (1, Weapons.LAU_68___7_FFAR_Mk5_HEAT) + AGM_45A = (1, Weapons.AGM_45A) +#ERRR {AGM12_B} + Mk_20 = (1, Weapons.Mk_20) + Mk_81 = (1, Weapons.Mk_81) + Mk_81SE = (1, WeaponsA4EC.Mk_81SE) + Mk_82 = (1, Weapons.Mk_82) + Mk_82_SnakeEye = (1, Weapons.Mk_82_SnakeEye) + Mk_77_mod_1 = (1, WeaponsA4EC.Mk_77_mod_1) + AN_M30A1 = (1, Weapons.AN_M30A1) + AN_M57 = (1, Weapons.AN_M57) + AN_M64 = (1, Weapons.AN_M64) + AN_M81 = (1, WeaponsA4EC.AN_M81) + AN_M88 = (1, WeaponsA4EC.AN_M88) + LAU_68___7_2_75__rockets_M257__Parachute_illumination_ = (1, Weapons.LAU_68___7_2_75__rockets_M257__Parachute_illumination_) + Smokewinder___red = (1, Weapons.Smokewinder___red) + Smokewinder___green = (1, Weapons.Smokewinder___green) + Smokewinder___blue = (1, Weapons.Smokewinder___blue) + Smokewinder___white = (1, Weapons.Smokewinder___white) + Smokewinder___yellow = (1, Weapons.Smokewinder___yellow) + Smokewinder___orange = (1, Weapons.Smokewinder___orange) +#ERRR + + class Pylon2: + Fuel_Tank_300_gallons_ = (2, WeaponsA4EC.Fuel_Tank_300_gallons_) + Fuel_Tank_150_gallons = (2, WeaponsA4EC.Fuel_Tank_150_gallons) + LAU_7_GAR_8_Sidewinder_IR_AAM = (2, Weapons.LAU_7_GAR_8_Sidewinder_IR_AAM) + LAU_7_AIM_9P_Sidewinder_IR_AAM = (2, Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM) + LAU_7_AIM_9P5_Sidewinder_IR_AAM = (2, Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM) + LAU_10___4_ZUNI_MK_71 = (2, Weapons.LAU_10___4_ZUNI_MK_71) + LAU_10_2___4_ZUNI_MK_71_ = (2, WeaponsA4EC.LAU_10_2___4_ZUNI_MK_71_) + LAU_3___19_FFAR_M156_WP = (2, Weapons.LAU_3___19_FFAR_M156_WP) + LAU_3___19_FFAR_Mk1_HE = (2, Weapons.LAU_3___19_FFAR_Mk1_HE) + LAU_3___19_FFAR_Mk5_HEAT = (2, Weapons.LAU_3___19_FFAR_Mk5_HEAT) + LAU_3_2___19_FFAR_M156_WP_ = (2, WeaponsA4EC.LAU_3_2___19_FFAR_M156_WP_) + LAU_3_2___19_FFAR_Mk1_HE_ = (2, WeaponsA4EC.LAU_3_2___19_FFAR_Mk1_HE_) + LAU_3_2___19_FFAR_Mk5_HEAT_ = (2, WeaponsA4EC.LAU_3_2___19_FFAR_Mk5_HEAT_) + LAU_68___7_FFAR_M156_WP = (2, Weapons.LAU_68___7_FFAR_M156_WP) + LAU_68___7_FFAR_Mk1_HE = (2, Weapons.LAU_68___7_FFAR_Mk1_HE) + LAU_68___7_FFAR_Mk5_HEAT = (2, Weapons.LAU_68___7_FFAR_Mk5_HEAT) + LAU_68_2___7_FFAR_M156_WP_ = (2, WeaponsA4EC.LAU_68_2___7_FFAR_M156_WP_) + LAU_68_2___7_FFAR_Mk1_HE_ = (2, WeaponsA4EC.LAU_68_2___7_FFAR_Mk1_HE_) + LAU_68_2___7_FFAR_Mk5_HEAT_ = (2, WeaponsA4EC.LAU_68_2___7_FFAR_Mk5_HEAT_) + AGM_45A = (2, Weapons.AGM_45A) +#ERRR {AGM12_C} +#ERRR {AGM12_B} + AGM_62 = (2, Weapons.AGM_62) + Mk_20 = (2, Weapons.Mk_20) + Mk_81 = (2, Weapons.Mk_81) + Mk_81SE = (2, WeaponsA4EC.Mk_81SE) + Mk_82 = (2, Weapons.Mk_82) + Mk_82_SnakeEye = (2, Weapons.Mk_82_SnakeEye) + Mk_83 = (2, Weapons.Mk_83) + Mk_84 = (2, Weapons.Mk_84) + M117 = (2, Weapons.M117) + Mk_77_mod_0 = (2, WeaponsA4EC.Mk_77_mod_0) + Mk_77_mod_1 = (2, WeaponsA4EC.Mk_77_mod_1) + AN_M30A1 = (2, Weapons.AN_M30A1) + AN_M57 = (2, Weapons.AN_M57) + AN_M64 = (2, Weapons.AN_M64) + AN_M65 = (2, Weapons.AN_M65) + AN_M81 = (2, WeaponsA4EC.AN_M81) + AN_M88 = (2, WeaponsA4EC.AN_M88) + CBU_1_A = (2, WeaponsA4EC.CBU_1_A) + CBU_2_A = (2, WeaponsA4EC.CBU_2_A) + CBU_2B_A = (2, WeaponsA4EC.CBU_2B_A) + CBU_1_A__2 = (2, WeaponsA4EC.CBU_1_A__2) + CBU_2_A__2 = (2, WeaponsA4EC.CBU_2_A__2) + CBU_2B_A__2 = (2, WeaponsA4EC.CBU_2B_A__2) + Mk_20__2__TER_ = (2, WeaponsA4EC.Mk_20__2__TER_) + Mk_81__5__MER_ = (2, WeaponsA4EC.Mk_81__5__MER_) + Mk_81SE__5__MER_ = (2, WeaponsA4EC.Mk_81SE__5__MER_) + Mk_82__2__TER_ = (2, WeaponsA4EC.Mk_82__2__TER_) + Mk_82_Snakeye__2__TER_ = (2, WeaponsA4EC.Mk_82_Snakeye__2__TER_) + AN_M57__5__MER_ = (2, WeaponsA4EC.AN_M57__5__MER_) + AN_M57__2__TER_ = (2, WeaponsA4EC.AN_M57__2__TER_) + AN_M81__5__MER_ = (2, WeaponsA4EC.AN_M81__5__MER_) + AN_M88__5__MER_ = (2, WeaponsA4EC.AN_M88__5__MER_) + Mk4_HIPEG = (2, WeaponsA4EC.Mk4_HIPEG) + Smokewinder___red = (2, Weapons.Smokewinder___red) + Smokewinder___green = (2, Weapons.Smokewinder___green) + Smokewinder___blue = (2, Weapons.Smokewinder___blue) + Smokewinder___white = (2, Weapons.Smokewinder___white) + Smokewinder___yellow = (2, Weapons.Smokewinder___yellow) + Smokewinder___orange = (2, Weapons.Smokewinder___orange) +#ERRR + + class Pylon3: + Fuel_Tank_400_gallons = (3, WeaponsA4EC.Fuel_Tank_400_gallons) + Fuel_Tank_300_gallons = (3, WeaponsA4EC.Fuel_Tank_300_gallons) + Fuel_Tank_150_gallons = (3, WeaponsA4EC.Fuel_Tank_150_gallons) + D_704_Refueling_Pod = (3, WeaponsA4EC.D_704_Refueling_Pod) +#ERRR {3*LAU-61} + LAU_68_3___7_2_75__rockets_MK5__HE_ = (3, Weapons.LAU_68_3___7_2_75__rockets_MK5__HE_) + LAU_10___4_ZUNI_MK_71 = (3, Weapons.LAU_10___4_ZUNI_MK_71) + LAU_10_2___4_ZUNI_MK_71 = (3, WeaponsA4EC.LAU_10_2___4_ZUNI_MK_71) + LAU_10_3___4_ZUNI_MK_71 = (3, WeaponsA4EC.LAU_10_3___4_ZUNI_MK_71) + LAU_3___19_FFAR_M156_WP = (3, Weapons.LAU_3___19_FFAR_M156_WP) + LAU_3___19_FFAR_Mk1_HE = (3, Weapons.LAU_3___19_FFAR_Mk1_HE) + LAU_3___19_FFAR_Mk5_HEAT = (3, Weapons.LAU_3___19_FFAR_Mk5_HEAT) + LAU_3_2___19_FFAR_M156_WP = (3, WeaponsA4EC.LAU_3_2___19_FFAR_M156_WP) + LAU_3_2___19_FFAR_Mk1_HE = (3, WeaponsA4EC.LAU_3_2___19_FFAR_Mk1_HE) + LAU_3_2___19_FFAR_Mk5_HEAT = (3, WeaponsA4EC.LAU_3_2___19_FFAR_Mk5_HEAT) + LAU_3_3___19_FFAR_M156_WP = (3, WeaponsA4EC.LAU_3_3___19_FFAR_M156_WP) + LAU_3_3___19_FFAR_Mk1_HE = (3, WeaponsA4EC.LAU_3_3___19_FFAR_Mk1_HE) + LAU_3_3___19_FFAR_Mk5_HEAT = (3, WeaponsA4EC.LAU_3_3___19_FFAR_Mk5_HEAT) + LAU_68___7_FFAR_M156_WP = (3, Weapons.LAU_68___7_FFAR_M156_WP) + LAU_68___7_FFAR_Mk1_HE = (3, Weapons.LAU_68___7_FFAR_Mk1_HE) + LAU_68___7_FFAR_Mk5_HEAT = (3, Weapons.LAU_68___7_FFAR_Mk5_HEAT) + LAU_68_2___7_FFAR_M156_WP = (3, WeaponsA4EC.LAU_68_2___7_FFAR_M156_WP) + LAU_68_2___7_FFAR_Mk1_HE = (3, WeaponsA4EC.LAU_68_2___7_FFAR_Mk1_HE) + LAU_68_2___7_FFAR_Mk5_HEAT = (3, WeaponsA4EC.LAU_68_2___7_FFAR_Mk5_HEAT) + LAU_68_3___7_FFAR_M156_WP = (3, WeaponsA4EC.LAU_68_3___7_FFAR_M156_WP) + LAU_68_3___7_FFAR_Mk1_HE = (3, WeaponsA4EC.LAU_68_3___7_FFAR_Mk1_HE) + LAU_68_3___7_FFAR_Mk5_HEAT = (3, WeaponsA4EC.LAU_68_3___7_FFAR_Mk5_HEAT) +#ERRR {AGM12_B} + AGM_62 = (3, Weapons.AGM_62) + Mk_20 = (3, Weapons.Mk_20) + Mk_81 = (3, Weapons.Mk_81) + Mk_81SE = (3, WeaponsA4EC.Mk_81SE) + Mk_82 = (3, Weapons.Mk_82) + Mk_82_SnakeEye = (3, Weapons.Mk_82_SnakeEye) + Mk_83 = (3, Weapons.Mk_83) + Mk_84 = (3, Weapons.Mk_84) + M117 = (3, Weapons.M117) + Mk_77_mod_0 = (3, WeaponsA4EC.Mk_77_mod_0) + Mk_77_mod_1 = (3, WeaponsA4EC.Mk_77_mod_1) + AN_M30A1 = (3, Weapons.AN_M30A1) + AN_M57 = (3, Weapons.AN_M57) + AN_M64 = (3, Weapons.AN_M64) + AN_M65 = (3, Weapons.AN_M65) + AN_M66A2 = (3, WeaponsA4EC.AN_M66A2) + AN_M81 = (3, WeaponsA4EC.AN_M81) + AN_M88 = (3, WeaponsA4EC.AN_M88) + Mk_20__3__TER_ = (3, WeaponsA4EC.Mk_20__3__TER_) + Mk_20__2__TER___ = (3, WeaponsA4EC.Mk_20__2__TER___) + Mk_81__6__MER_ = (3, WeaponsA4EC.Mk_81__6__MER_) + Mk_81SE__6__MER_ = (3, WeaponsA4EC.Mk_81SE__6__MER_) + Mk_82__6__MER_ = (3, WeaponsA4EC.Mk_82__6__MER_) + Mk_82__4__MER_ = (3, WeaponsA4EC.Mk_82__4__MER_) + Mk_82__3__TER_ = (3, WeaponsA4EC.Mk_82__3__TER_) + Mk_82_Snakeye__6__MER_ = (3, WeaponsA4EC.Mk_82_Snakeye__6__MER_) + Mk_82_Snakeye__4__MER_ = (3, WeaponsA4EC.Mk_82_Snakeye__4__MER_) + Mk_82_Snakeye__3__TER_ = (3, WeaponsA4EC.Mk_82_Snakeye__3__TER_) + Mk_83__3__TER_ = (3, WeaponsA4EC.Mk_83__3__TER_) + Mk_83__2__TER_ = (3, WeaponsA4EC.Mk_83__2__TER_) + Mk_77_mod_1__2__TER___ = (3, WeaponsA4EC.Mk_77_mod_1__2__TER___) + AN_M57__6__MER_ = (3, WeaponsA4EC.AN_M57__6__MER_) + AN_M57__3__TER_ = (3, WeaponsA4EC.AN_M57__3__TER_) + AN_M81__6__MER_ = (3, WeaponsA4EC.AN_M81__6__MER_) + AN_M88__6__MER_ = (3, WeaponsA4EC.AN_M88__6__MER_) + Mk4_HIPEG = (3, WeaponsA4EC.Mk4_HIPEG) + Smokewinder___red = (3, Weapons.Smokewinder___red) + Smokewinder___green = (3, Weapons.Smokewinder___green) + Smokewinder___blue = (3, Weapons.Smokewinder___blue) + Smokewinder___white = (3, Weapons.Smokewinder___white) + Smokewinder___yellow = (3, Weapons.Smokewinder___yellow) + Smokewinder___orange = (3, Weapons.Smokewinder___orange) +#ERRR + + class Pylon4: + Fuel_Tank_300_gallons_ = (4, WeaponsA4EC.Fuel_Tank_300_gallons_) + Fuel_Tank_150_gallons = (4, WeaponsA4EC.Fuel_Tank_150_gallons) + LAU_7_GAR_8_Sidewinder_IR_AAM = (4, Weapons.LAU_7_GAR_8_Sidewinder_IR_AAM) + LAU_7_AIM_9P_Sidewinder_IR_AAM = (4, Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM) + LAU_7_AIM_9P5_Sidewinder_IR_AAM = (4, Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM) + LAU_10___4_ZUNI_MK_71 = (4, Weapons.LAU_10___4_ZUNI_MK_71) + LAU_10_2___4_ZUNI_MK_71__ = (4, WeaponsA4EC.LAU_10_2___4_ZUNI_MK_71__) + LAU_3___19_FFAR_M156_WP = (4, Weapons.LAU_3___19_FFAR_M156_WP) + LAU_3___19_FFAR_Mk1_HE = (4, Weapons.LAU_3___19_FFAR_Mk1_HE) + LAU_3___19_FFAR_Mk5_HEAT = (4, Weapons.LAU_3___19_FFAR_Mk5_HEAT) + LAU_3_2___19_FFAR_M156_WP__ = (4, WeaponsA4EC.LAU_3_2___19_FFAR_M156_WP__) + LAU_3_2___19_FFAR_Mk1_HE__ = (4, WeaponsA4EC.LAU_3_2___19_FFAR_Mk1_HE__) + LAU_3_2___19_FFAR_Mk5_HEAT__ = (4, WeaponsA4EC.LAU_3_2___19_FFAR_Mk5_HEAT__) + LAU_68___7_FFAR_M156_WP = (4, Weapons.LAU_68___7_FFAR_M156_WP) + LAU_68___7_FFAR_Mk1_HE = (4, Weapons.LAU_68___7_FFAR_Mk1_HE) + LAU_68___7_FFAR_Mk5_HEAT = (4, Weapons.LAU_68___7_FFAR_Mk5_HEAT) + LAU_68_2___7_FFAR_M156_WP__ = (4, WeaponsA4EC.LAU_68_2___7_FFAR_M156_WP__) + LAU_68_2___7_FFAR_Mk1_HE__ = (4, WeaponsA4EC.LAU_68_2___7_FFAR_Mk1_HE__) + LAU_68_2___7_FFAR_Mk5_HEAT__ = (4, WeaponsA4EC.LAU_68_2___7_FFAR_Mk5_HEAT__) + AGM_45A = (4, Weapons.AGM_45A) +#ERRR {AGM12_C} +#ERRR {AGM12_B} + AGM_62 = (4, Weapons.AGM_62) + Mk_20 = (4, Weapons.Mk_20) + Mk_81 = (4, Weapons.Mk_81) + Mk_81SE = (4, WeaponsA4EC.Mk_81SE) + Mk_82 = (4, Weapons.Mk_82) + Mk_82_SnakeEye = (4, Weapons.Mk_82_SnakeEye) + Mk_83 = (4, Weapons.Mk_83) + Mk_84 = (4, Weapons.Mk_84) + M117 = (4, Weapons.M117) + Mk_77_mod_0 = (4, WeaponsA4EC.Mk_77_mod_0) + Mk_77_mod_1 = (4, WeaponsA4EC.Mk_77_mod_1) + AN_M30A1 = (4, Weapons.AN_M30A1) + AN_M57 = (4, Weapons.AN_M57) + AN_M64 = (4, Weapons.AN_M64) + AN_M65 = (4, Weapons.AN_M65) + AN_M81 = (4, WeaponsA4EC.AN_M81) + AN_M88 = (4, WeaponsA4EC.AN_M88) + CBU_1_A = (4, WeaponsA4EC.CBU_1_A) + CBU_2_A = (4, WeaponsA4EC.CBU_2_A) + CBU_2B_A = (4, WeaponsA4EC.CBU_2B_A) + CBU_1_A__2_ = (4, WeaponsA4EC.CBU_1_A__2_) + CBU_2_A__2_ = (4, WeaponsA4EC.CBU_2_A__2_) + CBU_2B_A__2_ = (4, WeaponsA4EC.CBU_2B_A__2_) + Mk_20__2__TER__ = (4, WeaponsA4EC.Mk_20__2__TER__) + Mk_81__5__MER__ = (4, WeaponsA4EC.Mk_81__5__MER__) + Mk_81SE__5__MER__ = (4, WeaponsA4EC.Mk_81SE__5__MER__) + Mk_82__2__TER__ = (4, WeaponsA4EC.Mk_82__2__TER__) + Mk_82_Snakeye__2__TER__ = (4, WeaponsA4EC.Mk_82_Snakeye__2__TER__) + AN_M57__5__MER__ = (4, WeaponsA4EC.AN_M57__5__MER__) + AN_M57__2__TER__ = (4, WeaponsA4EC.AN_M57__2__TER__) + AN_M81__5__MER__ = (4, WeaponsA4EC.AN_M81__5__MER__) + AN_M88__5__MER__ = (4, WeaponsA4EC.AN_M88__5__MER__) + Mk4_HIPEG = (4, WeaponsA4EC.Mk4_HIPEG) + Smokewinder___red = (4, Weapons.Smokewinder___red) + Smokewinder___green = (4, Weapons.Smokewinder___green) + Smokewinder___blue = (4, Weapons.Smokewinder___blue) + Smokewinder___white = (4, Weapons.Smokewinder___white) + Smokewinder___yellow = (4, Weapons.Smokewinder___yellow) + Smokewinder___orange = (4, Weapons.Smokewinder___orange) +#ERRR + + class Pylon5: + LAU_10___4_ZUNI_MK_71 = (5, Weapons.LAU_10___4_ZUNI_MK_71) + LAU_3___19_FFAR_M156_WP = (5, Weapons.LAU_3___19_FFAR_M156_WP) + LAU_3___19_FFAR_Mk1_HE = (5, Weapons.LAU_3___19_FFAR_Mk1_HE) + LAU_3___19_FFAR_Mk5_HEAT = (5, Weapons.LAU_3___19_FFAR_Mk5_HEAT) + LAU_68___7_FFAR_M156_WP = (5, Weapons.LAU_68___7_FFAR_M156_WP) + LAU_68___7_FFAR_Mk1_HE = (5, Weapons.LAU_68___7_FFAR_Mk1_HE) + LAU_68___7_FFAR_Mk5_HEAT = (5, Weapons.LAU_68___7_FFAR_Mk5_HEAT) + AGM_45A = (5, Weapons.AGM_45A) +#ERRR {AGM12_B} + Mk_20 = (5, Weapons.Mk_20) + Mk_81 = (5, Weapons.Mk_81) + Mk_81SE = (5, WeaponsA4EC.Mk_81SE) + Mk_82 = (5, Weapons.Mk_82) + Mk_82_SnakeEye = (5, Weapons.Mk_82_SnakeEye) + Mk_77_mod_1 = (5, WeaponsA4EC.Mk_77_mod_1) + AN_M30A1 = (5, Weapons.AN_M30A1) + AN_M57 = (5, Weapons.AN_M57) + AN_M64 = (5, Weapons.AN_M64) + AN_M81 = (5, WeaponsA4EC.AN_M81) + AN_M88 = (5, WeaponsA4EC.AN_M88) + LAU_68___7_2_75__rockets_M257__Parachute_illumination_ = (5, Weapons.LAU_68___7_2_75__rockets_M257__Parachute_illumination_) + Smokewinder___red = (5, Weapons.Smokewinder___red) + Smokewinder___green = (5, Weapons.Smokewinder___green) + Smokewinder___blue = (5, Weapons.Smokewinder___blue) + Smokewinder___white = (5, Weapons.Smokewinder___white) + Smokewinder___yellow = (5, Weapons.Smokewinder___yellow) + Smokewinder___orange = (5, Weapons.Smokewinder___orange) +#ERRR + + pylons = {1, 2, 3, 4, 5} + + tasks = [task.CAP, task.CAS, task.SEAD, task.GroundAttack, task.AFAC, task.Refueling] + task_default = task.CAS \ No newline at end of file diff --git a/pydcs_extensions/frenchpack/frenchpack.py b/pydcs_extensions/frenchpack/frenchpack.py new file mode 100644 index 00000000..12d51827 --- /dev/null +++ b/pydcs_extensions/frenchpack/frenchpack.py @@ -0,0 +1,288 @@ +# Requires French Pack mod : +# https://forums.eagle.ru/showthread.php?t=279974 +# +from dcs import unittype + +class AMX_10RCR(unittype.VehicleType): + id = "AMX10RCR" + name = "AMX-10RCR" + detection_range = 0 + threat_range = 4000 + air_weapon_dist = 4000 + + +class AMX_10RCR_SEPAR(unittype.VehicleType): + id = "SEPAR" + name = "AMX-10RCR SEPAR" + detection_range = 0 + threat_range = 4000 + air_weapon_dist = 4000 + + +class ERC_90(unittype.VehicleType): + id = "ERC" + name = "ERC-90" + detection_range = 0 + threat_range = 4000 + air_weapon_dist = 4000 + eprls = True + + +class VAB__50(unittype.VehicleType): + id = "VAB_50" + name = "VAB .50" + detection_range = 0 + threat_range = 1200 + air_weapon_dist = 1200 + eprls = True + + +class VAB_T20_13(unittype.VehicleType): + id = "VIB_VBR" + name = "VAB T20/13" + detection_range = 0 + threat_range = 2000 + air_weapon_dist = 2000 + eprls = True + + +class VAB_MEPHISTO(unittype.VehicleType): + id = "VAB_HOT" + name = "VAB MEPHISTO" + detection_range = 0 + threat_range = 4000 + air_weapon_dist = 4000 + eprls = True + + +class VBL__50(unittype.VehicleType): + id = "VBL50" + name = "VBL .50" + detection_range = 0 + threat_range = 1200 + air_weapon_dist = 1200 + eprls = True + + +class VBL_AANF1(unittype.VehicleType): + id = "VBLANF1" + name = "VBL AANF1" + detection_range = 0 + threat_range = 1000 + air_weapon_dist = 1000 + eprls = True + + +class VBAE_CRAB(unittype.VehicleType): + id = "VBAE" + name = "VBAE CRAB" + detection_range = 0 + threat_range = 3500 + air_weapon_dist = 3500 + eprls = True + + +class VBAE_CRAB_MMP(unittype.VehicleType): + id = "VBAE_MMP" + name = "VBAE CRAB MMP" + detection_range = 0 + threat_range = 3500 + air_weapon_dist = 3500 + eprls = True + + +class AMX_30B2(unittype.VehicleType): + id = "AMX-30B2" + name = "AMX-30B2" + detection_range = 0 + threat_range = 3500 + air_weapon_dist = 2500 + + +class Char_M551_Sheridan(unittype.VehicleType): + id = "SHERIDAN" + name = "Char M551 Sheridan" + detection_range = 0 + threat_range = 5000 + air_weapon_dist = 5000 + + +class Leclerc_Serie_XXI(unittype.VehicleType): + id = "Leclerc_XXI" + name = "Leclerc Série XXI" + detection_range = 0 + threat_range = 5000 + air_weapon_dist = 5000 + + +class DIM__TOYOTA_BLUE(unittype.VehicleType): + id = "Toyota_bleu" + name = "DIM' TOYOTA BLUE" + detection_range = 0 + threat_range = 1200 + air_weapon_dist = 1200 + eprls = True + + +class DIM__TOYOTA_GREEN(unittype.VehicleType): + id = "Toyota_vert" + name = "DIM' TOYOTA GREEN" + detection_range = 0 + threat_range = 1200 + air_weapon_dist = 1200 + eprls = True + + +class DIM__TOYOTA_DESERT(unittype.VehicleType): + id = "Toyota_desert" + name = "DIM' TOYOTA DESERT" + detection_range = 0 + threat_range = 1200 + air_weapon_dist = 1200 + eprls = True + + +class DIM__KAMIKAZE(unittype.VehicleType): + id = "Kamikaze" + name = "DIM' KAMIKAZE" + detection_range = 0 + threat_range = 50 + air_weapon_dist = 50 + eprls = True + +## FORTIFICATION + +class _FIELD_HIDE(unittype.VehicleType): + id = "FieldHL" + name = "*FIELD HIDE" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + +class _FIELD_HIDE_SMALL(unittype.VehicleType): + id = "HARRIERH" + name = "*FIELD HIDE SMALL" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + +class SmokeD1(unittype.VehicleType): + id = "SmokeD1" + name = "SmokeD1" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + +class SmokeD3(unittype.VehicleType): + id = "SmokeD3" + name = "SmokeD3" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + + +class TRM_2000(unittype.VehicleType): + id = "TRM2000" + name = "TRM-2000" + detection_range = 3500 + threat_range = 0 + air_weapon_dist = 0 + eprls = True + +class TRM_2000_Fuel(unittype.VehicleType): + id = "TRM2000_Citerne" + name = "TRM-2000 Fuel" + detection_range = 3500 + threat_range = 0 + air_weapon_dist = 0 + eprls = True + +class VAB_MEDICAL(unittype.VehicleType): + id = "VABH" + name = "VAB MEDICAL" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + eprls = True + +class VAB(unittype.VehicleType): + id = "VAB_RADIO" + name = "VAB" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + eprls = True + +class VBL(unittype.VehicleType): + id = "VBL-Radio" + name = "VBL" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + eprls = True + +class Tracma_TD_1500(unittype.VehicleType): + id = "Tracma" + name = "Tracma TD 1500" + detection_range = 0 + threat_range = 0 + air_weapon_dist = 0 + +## AIRDEFENCE + +class SMOKE_SAM_IR(unittype.VehicleType): + id = "SMOKESAM" + name = "SMOKE SAM IR" + detection_range = 20000 + threat_range = 20000 + air_weapon_dist = 20000 + eprls = True + +class _53T2(unittype.VehicleType): + id = "AA20" + name = "53T2" + detection_range = 5000 + threat_range = 2000 + air_weapon_dist = 2000 + +class TRM_2000_53T2(unittype.VehicleType): + id = "TRM2000_AA20" + name = "TRM-2000 53T2" + detection_range = 6000 + threat_range = 2000 + air_weapon_dist = 2000 + eprls = True + +class TRM_2000_PAMELA(unittype.VehicleType): + id = "TRMMISTRAL" + name = "TRM-2000 PAMELA" + detection_range = 8000 + threat_range = 10000 + air_weapon_dist = 10000 + eprls = True + +## INFANTRY + +class Infantry_Soldier_JTAC(unittype.VehicleType): + id = "JTACFP" + name = "Infantry Soldier JTAC" + detection_range = 0 + threat_range = 500 + air_weapon_dist = 500 + +## ARTILERY + +class MO_120_RT(unittype.VehicleType): + id = "M120" + name = "MO 120 RT" + detection_range = 0 + threat_range = 15000 + air_weapon_dist = 15000 + +class VAB_MORTIER(unittype.VehicleType): + id = "VAB_MORTIER" + name = "VAB MORTIER" + detection_range = 0 + threat_range = 15000 + air_weapon_dist = 15000 + eprls = True \ No newline at end of file diff --git a/pydcs_extensions/mb339/mb339.py b/pydcs_extensions/mb339/mb339.py new file mode 100644 index 00000000..39a63f76 --- /dev/null +++ b/pydcs_extensions/mb339/mb339.py @@ -0,0 +1,446 @@ +from enum import Enum + +from dcs import task +from dcs.planes import PlaneType +from dcs.weapons_data import Weapons + + +class MB_339PAN_Weapons: + ARF8M3_TP = {"clsid": "{ARF8M3_TP}", "name": "ARF8M3 TP", "weight": None} + BRD_4_250_4_MK_76_2_ARF_8M3TP_ = {"clsid": "{BRD-4-250}", "name": "BRD-4-250(4*MK.76+2*ARF-8M3TP)", "weight": 137.6} + Color_Oil_Tank = {"clsid": "{COLOR-TANK}", "name": "Color Oil Tank", "weight": 183} + Empty_Pylon = {"clsid": "{VOID-PYLON-MB339A}", "name": "Empty Pylon", "weight": 20} + Fuel_Tank_330lt = {"clsid": "{FUEL-SUBAL_TANK-330}", "name": "Fuel Tank 330lt", "weight": 315} + GunPod_AN_M3 = {"clsid": "{MB339-AN-M3_L}", "name": "GunPod AN/M3", "weight": 75} + GunPod_AN_M3_ = {"clsid": "{MB339-AN-M3_R}", "name": "GunPod AN/M3", "weight": 75} + GunPod_DEFA553 = {"clsid": "{MB339-DEFA553_L}", "name": "GunPod DEFA553", "weight": 190} + GunPod_DEFA553_ = {"clsid": "{MB339-DEFA553_R}", "name": "GunPod DEFA553", "weight": 190} + LAU_10___4_ZUNI_MK_71___ = {"clsid": "{LAU-10}", "name": "LAU-10 - 4 ZUNI MK 71", "weight": 308} + LR_25___25_ARF_8M3_API_ = {"clsid": "{LR-25API}", "name": "LR-25 - 25 ARF/8M3(API)", "weight": 141} + LR_25___25_ARF_8M3_HEI_ = {"clsid": "{LR-25HEI}", "name": "LR-25 - 25 ARF/8M3(HEI)", "weight": 161} + MAK79_2_MK_20 = {"clsid": "{MAK79_MK20 2L}", "name": "MAK79 2 MK-20", "weight": 464} + MAK79_2_MK_20_ = {"clsid": "{MAK79_MK20 2R}", "name": "MAK79 2 MK-20", "weight": 464} + MAK79_MK_20 = {"clsid": "{MAK79_MK20 1R}", "name": "MAK79 MK-20", "weight": 232} + MAK79_MK_20_ = {"clsid": "{MAK79_MK20 1L}", "name": "MAK79 MK-20", "weight": 232} + MB339_Black_Smoke = {"clsid": "{SMOKE-BLACK-MB339}", "name": "MB339 Black Smoke", "weight": 1} + MB339_Green_Smoke = {"clsid": "{SMOKE-GREEN-MB339}", "name": "MB339 Green Smoke", "weight": 1} + MB339_ORANGE_Smoke = {"clsid": "{SMOKE-ORANGE-MB339}", "name": "MB339 ORANGE Smoke", "weight": 1} + MB339_Red_Smoke = {"clsid": "{SMOKE-RED-MB339}", "name": "MB339 Red Smoke", "weight": 1} + MB339_White_Smoke = {"clsid": "{SMOKE-WHITE-MB339}", "name": "MB339 White Smoke", "weight": 1} + MB339_YELLOW_Smoke = {"clsid": "{SMOKE-YELLOW-MB339}", "name": "MB339 YELLOW Smoke", "weight": 1} + MK76 = {"clsid": "{MK76}", "name": "MK76", "weight": 11.3} + Tip_Fuel_Tank_500lt = {"clsid": "{FUEL-TIP-TANK-500-L}", "name": "Tip Fuel Tank 500lt", "weight": 471} + Tip_Fuel_Tank_500lt_ = {"clsid": "{FUEL-TIP-TANK-500-R}", "name": "Tip Fuel Tank 500lt", "weight": 471} + Tip_Fuel_Tank_Ellittici_320lt = {"clsid": "{FUEL-TIP-ELLITTIC-L}", "name": "Tip Fuel Tank Ellittici 320lt", "weight": 314.2} + Tip_Fuel_Tank_Ellittici_320lt_ = {"clsid": "{FUEL-TIP-ELLITTIC-R}", "name": "Tip Fuel Tank Ellittici 320lt", "weight": 314.2} + + +class MB_339PAN(PlaneType): + id = "MB-339PAN" + flyable = True + height = 4.77 + width = 10.5 + length = 12.13 + fuel_max = 626 + max_speed = 763.2 + category = "Interceptor" #{78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F} + radio_frequency = 124 + + panel_radio = { + 1: { + "channels": { + 1: 225, + 2: 258, + 4: 270, + 8: 257, + 16: 252, + 17: 268, + 9: 253, + 18: 269, + 5: 255, + 10: 263, + 20: 269, + 11: 267, + 3: 260, + 6: 259, + 12: 254, + 13: 264, + 7: 262, + 14: 266, + 19: 268, + 15: 265 + }, + }, + 2: { + "channels": { + 1: 225, + 2: 258, + 4: 270, + 8: 257, + 16: 252, + 17: 268, + 9: 253, + 18: 269, + 5: 255, + 10: 263, + 20: 269, + 30: 263, + 21: 225, + 11: 267, + 22: 258, + 3: 260, + 6: 259, + 12: 254, + 24: 270, + 19: 268, + 25: 255, + 13: 264, + 26: 259, + 27: 262, + 7: 262, + 14: 266, + 28: 257, + 23: 260, + 29: 253, + 15: 265 + }, + }, + } + + property_defaults = { + "SoloFlight": False, + "NetCrewControlPriority": 1, + } + + class Properties: + + class SoloFlight: + id = "SoloFlight" + + class NetCrewControlPriority: + id = "NetCrewControlPriority" + + class Values: + Pilot = 0 + Instructor = 1 + Ask_Always = -1 + Equally_Responsible = -2 + + class Liveries: + + class Georgia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Syria(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Finland(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Australia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Germany(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class SaudiArabia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Israel(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Croatia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class CzechRepublic(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Norway(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Romania(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Spain(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Ukraine(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Belgium(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Slovakia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Greece(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class UK(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Insurgents(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Hungary(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class France(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Abkhazia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Russia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Sweden(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Austria(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Switzerland(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Italy(Enum): + MB339PAN__Frecce_Tricolori = "MB339PAN 'Frecce Tricolori'" + MB339A__SVBIA____FACTORY = "MB339A 'SVBIA' - FACTORY" + MB339A__61BRIGATA____CAMO = "MB339A '61BRIGATA' - CAMO" + MB339A__61STORMO____CAMO = "MB339A '61STORMO' - CAMO" + MB339A__61STORMO____GREY = "MB339A '61STORMO' - GREY" + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class SouthOssetia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class SouthKorea(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Iran(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class China(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Pakistan(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Belarus(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class NorthKorea(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Iraq(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Kazakhstan(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Bulgaria(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Serbia(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class India(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class USAFAggressors(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class USA(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Denmark(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Egypt(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Canada(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class TheNetherlands(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Turkey(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Japan(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Poland(Enum): + MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa" + MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band" + MB339__Factory = "MB339 'Factory'" + + class Pylon1: + Tip_Fuel_Tank_500lt = (1, MB_339PAN_Weapons.Tip_Fuel_Tank_500lt) + Tip_Fuel_Tank_Ellittici_320lt = (1, MB_339PAN_Weapons.Tip_Fuel_Tank_Ellittici_320lt) + + class Pylon2: + Empty_Pylon = (2, MB_339PAN_Weapons.Empty_Pylon) + LR_25___25_ARF_8M3_HEI_ = (2, MB_339PAN_Weapons.LR_25___25_ARF_8M3_HEI_) + LR_25___25_ARF_8M3_API_ = (2, MB_339PAN_Weapons.LR_25___25_ARF_8M3_API_) + Mk_82 = (2, Weapons.Mk_82) + Matra_Type_155_Rocket_Pod = (2, Weapons.Matra_Type_155_Rocket_Pod) + + class Pylon3: + Fuel_Tank_330lt = (3, MB_339PAN_Weapons.Fuel_Tank_330lt) + Empty_Pylon = (3, MB_339PAN_Weapons.Empty_Pylon) + LR_25___25_ARF_8M3_HEI_ = (3, MB_339PAN_Weapons.LR_25___25_ARF_8M3_HEI_) + LR_25___25_ARF_8M3_API_ = (3, MB_339PAN_Weapons.LR_25___25_ARF_8M3_API_) + Mk_82 = (3, Weapons.Mk_82) + LAU_10___4_ZUNI_MK_71___ = (3, MB_339PAN_Weapons.LAU_10___4_ZUNI_MK_71___) + BRD_4_250_4_MK_76_2_ARF_8M3TP_ = (3, MB_339PAN_Weapons.BRD_4_250_4_MK_76_2_ARF_8M3TP_) + Matra_Type_155_Rocket_Pod = (3, Weapons.Matra_Type_155_Rocket_Pod) + + class Pylon4: + Color_Oil_Tank = (4, MB_339PAN_Weapons.Color_Oil_Tank) + Empty_Pylon = (4, MB_339PAN_Weapons.Empty_Pylon) + GunPod_AN_M3 = (4, MB_339PAN_Weapons.GunPod_AN_M3) + GunPod_DEFA553 = (4, MB_339PAN_Weapons.GunPod_DEFA553) + LR_25___25_ARF_8M3_HEI_ = (4, MB_339PAN_Weapons.LR_25___25_ARF_8M3_HEI_) + LR_25___25_ARF_8M3_API_ = (4, MB_339PAN_Weapons.LR_25___25_ARF_8M3_API_) + Mk_82 = (4, Weapons.Mk_82) + Matra_Type_155_Rocket_Pod = (4, Weapons.Matra_Type_155_Rocket_Pod) + + class Pylon5: + MB339_Red_Smoke = (5, MB_339PAN_Weapons.MB339_Red_Smoke) + MB339_Green_Smoke = (5, MB_339PAN_Weapons.MB339_Green_Smoke) + MB339_YELLOW_Smoke = (5, MB_339PAN_Weapons.MB339_YELLOW_Smoke) + MB339_ORANGE_Smoke = (5, MB_339PAN_Weapons.MB339_ORANGE_Smoke) + MB339_Black_Smoke = (5, MB_339PAN_Weapons.MB339_Black_Smoke) + + class Pylon6: + MB339_White_Smoke = (6, MB_339PAN_Weapons.MB339_White_Smoke) + + class Pylon7: + Color_Oil_Tank = (7, MB_339PAN_Weapons.Color_Oil_Tank) + Empty_Pylon = (7, MB_339PAN_Weapons.Empty_Pylon) + GunPod_AN_M3_ = (7, MB_339PAN_Weapons.GunPod_AN_M3_) + GunPod_DEFA553_ = (7, MB_339PAN_Weapons.GunPod_DEFA553_) + LR_25___25_ARF_8M3_HEI_ = (7, MB_339PAN_Weapons.LR_25___25_ARF_8M3_HEI_) + LR_25___25_ARF_8M3_API_ = (7, MB_339PAN_Weapons.LR_25___25_ARF_8M3_API_) + Mk_82 = (7, Weapons.Mk_82) + Matra_Type_155_Rocket_Pod = (7, Weapons.Matra_Type_155_Rocket_Pod) + + class Pylon8: + Fuel_Tank_330lt = (8, MB_339PAN_Weapons.Fuel_Tank_330lt) + Empty_Pylon = (8, MB_339PAN_Weapons.Empty_Pylon) + LR_25___25_ARF_8M3_HEI_ = (8, MB_339PAN_Weapons.LR_25___25_ARF_8M3_HEI_) + LR_25___25_ARF_8M3_API_ = (8, MB_339PAN_Weapons.LR_25___25_ARF_8M3_API_) + Mk_82 = (8, Weapons.Mk_82) + LAU_10___4_ZUNI_MK_71___ = (8, MB_339PAN_Weapons.LAU_10___4_ZUNI_MK_71___) + Matra_Type_155_Rocket_Pod = (8, Weapons.Matra_Type_155_Rocket_Pod) + BRD_4_250_4_MK_76_2_ARF_8M3TP_ = (8, MB_339PAN_Weapons.BRD_4_250_4_MK_76_2_ARF_8M3TP_) + + class Pylon9: + Empty_Pylon = (9, MB_339PAN_Weapons.Empty_Pylon) + LR_25___25_ARF_8M3_HEI_ = (9, MB_339PAN_Weapons.LR_25___25_ARF_8M3_HEI_) + LR_25___25_ARF_8M3_API_ = (9, MB_339PAN_Weapons.LR_25___25_ARF_8M3_API_) + Mk_82 = (9, Weapons.Mk_82) + Matra_Type_155_Rocket_Pod = (9, Weapons.Matra_Type_155_Rocket_Pod) + + class Pylon10: + Tip_Fuel_Tank_500lt_ = (10, MB_339PAN_Weapons.Tip_Fuel_Tank_500lt_) + Tip_Fuel_Tank_Ellittici_320lt_ = (10, MB_339PAN_Weapons.Tip_Fuel_Tank_Ellittici_320lt_) + + pylons = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + + tasks = [task.GroundAttack, task.RunwayAttack, task.CAS, task.AntishipStrike, task.Reconnaissance] + task_default = task.Nothing \ No newline at end of file diff --git a/pydcs_extensions/rafale/rafale.py b/pydcs_extensions/rafale/rafale.py new file mode 100644 index 00000000..880192a2 --- /dev/null +++ b/pydcs_extensions/rafale/rafale.py @@ -0,0 +1,1046 @@ +from enum import Enum + +from dcs import task +from dcs.planes import PlaneType +from dcs.weapons_data import Weapons + +class RafaleWeapons: + SCALP = {"clsid": "{SCALP}", "name": "SCALP", "weight": None} + AS_30L = {"clsid": "{AS_30L}", "name": "AS_30L", "weight": 292} + Exocet = {"clsid": "{Exocet}", "name": "Exocet", "weight": 640} + Thales_RBE2 = {"clsid": "{Thales_RBE2}", "name": "Thales_RBE2", "weight": 1.4789} + DAMOCLES = {"clsid": "{DAMOCLES}", "name": "DAMOCLES", "weight": 265} + DAMOCLES_ = {"clsid": "{DAMOCLES}", "name": "DAMOCLES", "weight": 265} + _2300_PTB_RAF = {"clsid": "{2300-PTB RAF}", "name": "2300-PTB RAF", "weight": 70} + _2300_PTB_RAF_ = {"clsid": "{2300-PTB RAF}", "name": "2300-PTB RAF", "weight": 70} + PTB_1500 = {"clsid": "{PTB-1500}", "name": "PTB-1500", "weight": 70} + + +class Rafale_A_S(PlaneType): + id = "Rafale_A_S" + flyable = False + height = 5.28 + width = 10.13 + length = 15.96 + fuel_max = 5000 + max_speed = 2001.996 + chaff = 48 + flare = 48 + charge_total = 96 + chaff_charge_size = 1 + flare_charge_size = 1 + category = "Interceptor" #{78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F} + radio_frequency = 127.5 + + class Liveries: + + class Georgia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Syria(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Finland(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Australia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Germany(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class SaudiArabia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Israel(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Croatia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class CzechRepublic(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Norway(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Romania(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Spain(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Ukraine(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Belgium(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Slovakia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Greece(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class UK(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Insurgents(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Hungary(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class France(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Abkhazia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Russia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Sweden(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Austria(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Switzerland(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Italy(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class SouthOssetia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class SouthKorea(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Iran(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class China(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Pakistan(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Belarus(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class NorthKorea(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Iraq(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Kazakhstan(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Bulgaria(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Serbia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class India(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class USAFAggressors(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class USA(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Denmark(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Egypt(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Canada(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class TheNetherlands(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Turkey(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Japan(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Poland(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Pylon1: + Smokewinder___red = (1, Weapons.Smokewinder___red) + Smokewinder___green = (1, Weapons.Smokewinder___green) + Smokewinder___blue = (1, Weapons.Smokewinder___blue) + Smokewinder___white = (1, Weapons.Smokewinder___white) + Smokewinder___yellow = (1, Weapons.Smokewinder___yellow) + Smokewinder___orange = (1, Weapons.Smokewinder___orange) + MICA_IR = (1, Weapons.MICA_IR) + AIM_9M_Sidewinder_IR_AAM = (1, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (1, Weapons.AIM_9P_Sidewinder_IR_AAM) +#ERRR {BRU-42_3*GBU-12} + + class Pylon2: + _2xGBU_12 = (2, Weapons._2xGBU_12) + MER_2_MK_82 = (2, Weapons.MER_2_MK_82) + _3_Mk_82 = (2, Weapons._3_Mk_82) + GBU_10 = (2, Weapons.GBU_10) + GBU_12 = (2, Weapons.GBU_12) + Mk_20 = (2, Weapons.Mk_20) + _3_Mk_20_Rockeye = (2, Weapons._3_Mk_20_Rockeye) + Mk_84 = (2, Weapons.Mk_84) + GBU_24 = (2, Weapons.GBU_24) + AGM_88C_ = (2, Weapons.AGM_88C_) + LAU_131___7_2_75__rockets_M151__HE_ = (2, Weapons.LAU_131___7_2_75__rockets_M151__HE_) + LAU3_HE151 = (2, Weapons.LAU3_HE151) + LAU3_WP156 = (2, Weapons.LAU3_WP156) + LAU3_HE5 = (2, Weapons.LAU3_HE5) + SCALP = (2, RafaleWeapons.SCALP) + AS_30L = (2, RafaleWeapons.AS_30L) + + class Pylon3: + GBU_10 = (3, Weapons.GBU_10) + GBU_24 = (3, Weapons.GBU_24) +#ERRR {BRU-42_3*GBU-12} + _2xGBU_12 = (3, Weapons._2xGBU_12) + GBU_12 = (3, Weapons.GBU_12) + MER_2_MK_82 = (3, Weapons.MER_2_MK_82) + _3_Mk_82 = (3, Weapons._3_Mk_82) + AGM_88C_ = (3, Weapons.AGM_88C_) + LAU3_HE151 = (3, Weapons.LAU3_HE151) + LAU3_WP156 = (3, Weapons.LAU3_WP156) + LAU_131x3_HYDRA_70_M151 = (3, Weapons.LAU_131x3_HYDRA_70_M151) + SCALP = (3, RafaleWeapons.SCALP) + AS_30L = (3, RafaleWeapons.AS_30L) + PTB_1500 = (3, RafaleWeapons.PTB_1500) + _2300_PTB_RAF_ = (3, RafaleWeapons._2300_PTB_RAF) + + class Pylon4: + AIM_9M_Sidewinder_IR_AAM = (4, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (4, Weapons.AIM_9P_Sidewinder_IR_AAM) + MICA_IR = (4, Weapons.MICA_IR) + LAU3_WP156 = (4, Weapons.LAU3_WP156) + + class Pylon5: + Mk_84 = (5, Weapons.Mk_84) + PTB_1500 = (5, RafaleWeapons.PTB_1500) + _2300_PTB_RAF_ = (5, RafaleWeapons._2300_PTB_RAF) + Mercury_LLTV_Pod = (5, Weapons.Mercury_LLTV_Pod) + Exocet = (5, RafaleWeapons.Exocet) + + class Pylon6: + AIM_9M_Sidewinder_IR_AAM = (6, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (6, Weapons.AIM_9P_Sidewinder_IR_AAM) + MICA_IR = (6, Weapons.MICA_IR) + LAU3_WP156 = (6, Weapons.LAU3_WP156) + + class Pylon7: + AN_AAQ_28_LITENING = (7, Weapons.AN_AAQ_28_LITENING) + DAMOCLES_ = (7, RafaleWeapons.DAMOCLES_) + Thales_RBE2 = (7, RafaleWeapons.Thales_RBE2) + + class Pylon8: + GBU_10 = (8, Weapons.GBU_10) + GBU_24 = (8, Weapons.GBU_24) +#ERRR {BRU-42_3*GBU-12} + _2xGBU_12 = (8, Weapons._2xGBU_12) + GBU_12 = (8, Weapons.GBU_12) + MER_2_MK_82 = (8, Weapons.MER_2_MK_82) + _3_Mk_20_Rockeye = (8, Weapons._3_Mk_20_Rockeye) + _3_Mk_82 = (8, Weapons._3_Mk_82) + AGM_88C_ = (8, Weapons.AGM_88C_) + LAU3_HE151 = (8, Weapons.LAU3_HE151) + LAU3_WP156 = (8, Weapons.LAU3_WP156) + LAU_131x3_HYDRA_70_M151 = (8, Weapons.LAU_131x3_HYDRA_70_M151) + SCALP = (8, RafaleWeapons.SCALP) + AS_30L = (8, RafaleWeapons.AS_30L) + PTB_1500 = (8, RafaleWeapons.PTB_1500) + _2300_PTB_RAF_ = (8, RafaleWeapons._2300_PTB_RAF) + + class Pylon9: + GBU_24 = (9, Weapons.GBU_24) +#ERRR {BRU-42_3*GBU-12} + MER_2_MK_82 = (9, Weapons.MER_2_MK_82) + _2xGBU_12 = (9, Weapons._2xGBU_12) + GBU_10 = (9, Weapons.GBU_10) + GBU_12 = (9, Weapons.GBU_12) + Mk_20 = (9, Weapons.Mk_20) + _3_Mk_20_Rockeye = (9, Weapons._3_Mk_20_Rockeye) + Mk_84 = (9, Weapons.Mk_84) + _3_Mk_82 = (9, Weapons._3_Mk_82) + AGM_88C_ = (9, Weapons.AGM_88C_) + LAU_131___7_2_75__rockets_M151__HE_ = (9, Weapons.LAU_131___7_2_75__rockets_M151__HE_) + LAU3_HE151 = (9, Weapons.LAU3_HE151) + LAU3_WP156 = (9, Weapons.LAU3_WP156) + LAU3_HE5 = (9, Weapons.LAU3_HE5) + SCALP = (9, RafaleWeapons.SCALP) + AS_30L = (9, RafaleWeapons.AS_30L) + + class Pylon10: + AIM_9M_Sidewinder_IR_AAM = (10, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (10, Weapons.AIM_9P_Sidewinder_IR_AAM) + MICA_IR = (10, Weapons.MICA_IR) + Smokewinder___red = (10, Weapons.Smokewinder___red) + Smokewinder___green = (10, Weapons.Smokewinder___green) + Smokewinder___blue = (10, Weapons.Smokewinder___blue) + Smokewinder___white = (10, Weapons.Smokewinder___white) + Smokewinder___yellow = (10, Weapons.Smokewinder___yellow) + Smokewinder___orange = (10, Weapons.Smokewinder___orange) + + pylons = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + + tasks = [task.CAP, task.Escort, task.FighterSweep, task.GroundAttack, task.CAS, task.AFAC, task.RunwayAttack, task.AntishipStrike] + task_default = task.CAP + + +class Rafale_M(PlaneType): + id = "Rafale_M" + flyable = False + height = 5.28 + width = 10.13 + length = 15.96 + fuel_max = 5000 + max_speed = 2001.996 + chaff = 48 + flare = 48 + charge_total = 96 + chaff_charge_size = 1 + flare_charge_size = 1 + category = "Interceptor" #{78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F} + radio_frequency = 127.5 + + class Liveries: + + class Georgia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Syria(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Finland(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Australia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Germany(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class SaudiArabia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Israel(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Croatia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class CzechRepublic(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Norway(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Romania(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Spain(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Ukraine(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Belgium(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Slovakia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Greece(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class UK(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Insurgents(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Hungary(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class France(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Abkhazia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Russia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Sweden(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Austria(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Switzerland(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Italy(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class SouthOssetia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class SouthKorea(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Iran(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class China(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Pakistan(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Belarus(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class NorthKorea(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Iraq(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Kazakhstan(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Bulgaria(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Serbia(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class India(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class USAFAggressors(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class USA(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Denmark(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Egypt(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Canada(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class TheNetherlands(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Turkey(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Japan(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Poland(Enum): + _01_MARINE_12_F = "01 MARINE 12 F" + _02_MARINE_MAT_17F = "02 MARINE MAT 17F" + _03_BLACK_DERIVE_11F = "03 BLACK DERIVE 11F" + _04_MARINE_OLD = "04 MARINE OLD" + _05_BRAZIL = "05 BRAZIL" + _06_NEUTRE = "06 NEUTRE" + + class Pylon1: + Smokewinder___red = (1, Weapons.Smokewinder___red) + Smokewinder___green = (1, Weapons.Smokewinder___green) + Smokewinder___blue = (1, Weapons.Smokewinder___blue) + Smokewinder___white = (1, Weapons.Smokewinder___white) + Smokewinder___yellow = (1, Weapons.Smokewinder___yellow) + Smokewinder___orange = (1, Weapons.Smokewinder___orange) + MICA_IR = (1, Weapons.MICA_IR) + AIM_9M_Sidewinder_IR_AAM = (1, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (1, Weapons.AIM_9P_Sidewinder_IR_AAM) + + class Pylon2: + Mk_84 = (2, Weapons.Mk_84) + MER_2_MK_83 = (2, Weapons.MER_2_MK_83) + MER_2_MK_82 = (2, Weapons.MER_2_MK_82) + _3_Mk_82 = (2, Weapons._3_Mk_82) + LAU_131___7_2_75__rockets_M151__HE_ = (2, Weapons.LAU_131___7_2_75__rockets_M151__HE_) + LAU3_HE151 = (2, Weapons.LAU3_HE151) + LAU3_WP156 = (2, Weapons.LAU3_WP156) + LAU3_HE5 = (2, Weapons.LAU3_HE5) + MICA_IR = (2, Weapons.MICA_IR) + AIM_7M = (2, Weapons.AIM_7M) + AIM_120B = (2, Weapons.AIM_120B) + AIM_120C = (2, Weapons.AIM_120C) + LAU_115_2_LAU_127_AIM_120C = (2, Weapons.LAU_115_2_LAU_127_AIM_120C) + Super_530D = (2, Weapons.Super_530D) + + class Pylon3: + Mk_84 = (3, Weapons.Mk_84) + MER_2_MK_83 = (3, Weapons.MER_2_MK_83) + MER_2_MK_82 = (3, Weapons.MER_2_MK_82) + _3_Mk_82 = (3, Weapons._3_Mk_82) + LAU3_HE151 = (3, Weapons.LAU3_HE151) + LAU3_WP156 = (3, Weapons.LAU3_WP156) + LAU_131x3_HYDRA_70_M151 = (3, Weapons.LAU_131x3_HYDRA_70_M151) + MICA_IR = (3, Weapons.MICA_IR) + AIM_7M = (3, Weapons.AIM_7M) + AIM_120B = (3, Weapons.AIM_120B) + AIM_120C = (3, Weapons.AIM_120C) + Super_530D = (3, Weapons.Super_530D) + PTB_1500 = (3, RafaleWeapons.PTB_1500) + _2300_PTB_RAF_ = (3, RafaleWeapons._2300_PTB_RAF) + + class Pylon4: + MICA_IR = (4, Weapons.MICA_IR) + AIM_9M_Sidewinder_IR_AAM = (4, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (4, Weapons.AIM_9P_Sidewinder_IR_AAM) + LAU3_WP156 = (4, Weapons.LAU3_WP156) + + class Pylon5: + PTB_1500 = (5, RafaleWeapons.PTB_1500) + _2300_PTB_RAF_ = (5, RafaleWeapons._2300_PTB_RAF) + MICA_IR = (5, Weapons.MICA_IR) + AIM_7M = (5, Weapons.AIM_7M) + AIM_120B = (5, Weapons.AIM_120B) + AIM_120C = (5, Weapons.AIM_120C) + Super_530D = (5, Weapons.Super_530D) + + class Pylon6: + MICA_IR = (6, Weapons.MICA_IR) + AIM_9M_Sidewinder_IR_AAM = (6, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (6, Weapons.AIM_9P_Sidewinder_IR_AAM) + LAU3_WP156 = (6, Weapons.LAU3_WP156) + + class Pylon7: + AN_AAQ_28_LITENING = (7, Weapons.AN_AAQ_28_LITENING) + DAMOCLES_ = (7, RafaleWeapons.DAMOCLES_) + + class Pylon8: + Mk_84 = (8, Weapons.Mk_84) + MER_2_MK_83 = (8, Weapons.MER_2_MK_83) + MER_2_MK_82 = (8, Weapons.MER_2_MK_82) + _3_Mk_82 = (8, Weapons._3_Mk_82) + LAU3_HE151 = (8, Weapons.LAU3_HE151) + LAU3_WP156 = (8, Weapons.LAU3_WP156) + LAU_131x3_HYDRA_70_M151 = (8, Weapons.LAU_131x3_HYDRA_70_M151) + MICA_IR = (8, Weapons.MICA_IR) + AIM_7M = (8, Weapons.AIM_7M) + AIM_120B = (8, Weapons.AIM_120B) + AIM_120C = (8, Weapons.AIM_120C) + Super_530D = (8, Weapons.Super_530D) + PTB_1500 = (8, RafaleWeapons.PTB_1500) + _2300_PTB_RAF_ = (8, RafaleWeapons._2300_PTB_RAF) + + class Pylon9: + Mk_84 = (9, Weapons.Mk_84) + MER_2_MK_83 = (9, Weapons.MER_2_MK_83) + MER_2_MK_82 = (9, Weapons.MER_2_MK_82) + _3_Mk_82 = (9, Weapons._3_Mk_82) + LAU_131___7_2_75__rockets_M151__HE_ = (9, Weapons.LAU_131___7_2_75__rockets_M151__HE_) + LAU3_HE151 = (9, Weapons.LAU3_HE151) + LAU3_WP156 = (9, Weapons.LAU3_WP156) + LAU3_HE5 = (9, Weapons.LAU3_HE5) + MICA_IR = (9, Weapons.MICA_IR) + AIM_7M = (9, Weapons.AIM_7M) + AIM_120B = (9, Weapons.AIM_120B) + AIM_120C = (9, Weapons.AIM_120C) + LAU_115_2_LAU_127_AIM_120C = (9, Weapons.LAU_115_2_LAU_127_AIM_120C) + Super_530D = (9, Weapons.Super_530D) + + class Pylon10: + AIM_9M_Sidewinder_IR_AAM = (10, Weapons.AIM_9M_Sidewinder_IR_AAM) + AIM_9P_Sidewinder_IR_AAM = (10, Weapons.AIM_9P_Sidewinder_IR_AAM) + MICA_IR = (10, Weapons.MICA_IR) + Smokewinder___red = (10, Weapons.Smokewinder___red) + Smokewinder___green = (10, Weapons.Smokewinder___green) + Smokewinder___blue = (10, Weapons.Smokewinder___blue) + Smokewinder___white = (10, Weapons.Smokewinder___white) + Smokewinder___yellow = (10, Weapons.Smokewinder___yellow) + Smokewinder___orange = (10, Weapons.Smokewinder___orange) + + pylons = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + + tasks = [task.CAP, task.Escort, task.FighterSweep, task.GroundAttack, task.CAS, task.AFAC, task.RunwayAttack, task.AntishipStrike, task.Reconnaissance, task.Intercept] + task_default = task.CAP diff --git a/qt_ui/main.py b/qt_ui/main.py index 55262ab9..5b075cdf 100644 --- a/qt_ui/main.py +++ b/qt_ui/main.py @@ -1,7 +1,7 @@ from userdata import logging_config # Logging setup -VERSION_STRING = "2.0RC9" +VERSION_STRING = "2.0.10" logging_config.init_logging(VERSION_STRING) import logging @@ -17,19 +17,19 @@ from qt_ui import uiconstants from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from qt_ui.windows.QLiberationWindow import QLiberationWindow from qt_ui.windows.preferences.QLiberationFirstStartWindow import QLiberationFirstStartWindow -from userdata import liberation_install, persistency +from userdata import liberation_install, persistency, liberation_theme if __name__ == "__main__": + os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # Potential fix for 4K screens app = QApplication(sys.argv) + # init the theme and load the stylesheet based on the theme index + liberation_theme.init() css = "" - with open("./resources/stylesheets/style.css") as stylesheet: + with open("./resources/stylesheets/"+liberation_theme.get_theme_css_file()) as stylesheet: app.setStyleSheet(stylesheet.read()) - - - # Inject custom payload in pydcs framework custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads") if os.path.exists(custom_payloads): @@ -84,6 +84,5 @@ if __name__ == "__main__": logging.info("Attempt to restore original mission scripting file") liberation_install.restore_original_mission_scripting() logging.info("QT process exited with code : " + str(qt_execution_code)) - sys.exit(0) diff --git a/qt_ui/uiconstants.py b/qt_ui/uiconstants.py index be107c02..c0f13eac 100644 --- a/qt_ui/uiconstants.py +++ b/qt_ui/uiconstants.py @@ -6,11 +6,10 @@ from PySide2.QtGui import QColor, QFont, QPixmap from game.event import UnitsDeliveryEvent, FrontlineAttackEvent from theater.theatergroundobject import CATEGORY_MAP +from userdata.liberation_theme import get_theme_icons URLS : Dict[str, str] = { "Manual": "https://github.com/khopa/dcs_liberation/wiki", - "Troubleshooting": "https://github.com/shdwp/dcs_liberation/wiki/Troubleshooting", - "Modding": "https://github.com/shdwp/dcs_liberation/wiki/Modding-tutorial", "Repository": "https://github.com/khopa/dcs_liberation", "ForumThread": "https://forums.eagle.ru/showthread.php?t=214834", "Issues": "https://github.com/khopa/dcs_liberation/issues" @@ -19,26 +18,58 @@ URLS : Dict[str, str] = { LABELS_OPTIONS = ["Full", "Abbreviated", "Dot Only", "Off"] SKILL_OPTIONS = ["Average", "Good", "High", "Excellent"] -COLORS: Dict[str, QColor] = { - "dark_red": QColor(140, 20, 20), - "red": QColor(200, 80, 80), - "bright_red": QColor(150, 80, 80), - "super_red": QColor(200, 120, 120), - "blue": QColor(164, 164, 255), - "dark_blue": QColor(45, 62, 80), - "white": QColor(255, 255, 255), - "green": QColor(128, 186, 128), - "bright_green": QColor(64, 200, 64), - "black": QColor(0, 0, 0), - "black_transparent": QColor(0, 0, 0, 64), - "blue_transparent": QColor(164, 164, 255, 32), - "red_transparent": QColor(255, 125, 125, 32) +FONT_SIZE = 8 +FONT_NAME = "Arial" +# FONT = QFont("Arial", 12, weight=5, italic=True) +FONT_PRIMARY = QFont(FONT_NAME, FONT_SIZE, weight=5, italic=False) +FONT_PRIMARY_I = QFont(FONT_NAME, FONT_SIZE, weight=5, italic=True) +FONT_PRIMARY_B = QFont(FONT_NAME, FONT_SIZE, weight=75, italic=False) +FONT_MAP = QFont(FONT_NAME, 10, weight=75, italic=False) + +# new themes can be added here +THEMES: Dict[int, Dict[str, str]] = { + 0: {'themeName': 'Vanilla', + 'themeFile': 'windows-style.css', + 'themeIcons': 'medium', + }, + + 1: {'themeName': 'DCS World', + 'themeFile': 'style-dcs.css', + 'themeIcons': 'light', + }, + } +COLORS: Dict[str, QColor] = { + "white": QColor(255, 255, 255), + "white_transparent": QColor(255, 255, 255, 35), + "grey_transparent": QColor(150, 150, 150, 30), -CP_SIZE = 25 -FONT = QFont("Arial", 12, weight=5, italic=True) + "red": QColor(200, 80, 80), + "dark_red": QColor(140, 20, 20), + "red_transparent": QColor(227, 32, 0, 20), + "blue": QColor(0, 132, 255), + "dark_blue": QColor(45, 62, 80), + "blue_transparent": QColor(0, 132, 255, 20), + + "bright_red": QColor(150, 80, 80), + "super_red": QColor(227, 32, 0), + + "green": QColor(128, 186, 128), + "bright_green": QColor(64, 200, 64), + + "black": QColor(0, 0, 0), + "black_transparent": QColor(0, 0, 0, 5), + + "orange": QColor(254, 125, 10), + + "night_overlay": QColor(12, 20, 69), + "dawn_dust_overlay": QColor(46, 38, 85), + +} + +CP_SIZE = 24 AIRCRAFT_ICONS: Dict[str, QPixmap] = {} VEHICLES_ICONS: Dict[str, QPixmap] = {} @@ -46,9 +77,9 @@ ICONS: Dict[str, QPixmap] = {} def load_icons(): - ICONS["New"] = QPixmap("./resources/ui/misc/new.png") - ICONS["Open"] = QPixmap("./resources/ui/misc/open.png") - ICONS["Save"] = QPixmap("./resources/ui/misc/save.png") + ICONS["New"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/new.png") + ICONS["Open"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/open.png") + ICONS["Save"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/save.png") ICONS["Terrain_Caucasus"] = QPixmap("./resources/ui/terrain_caucasus.gif") ICONS["Terrain_Persian_Gulf"] = QPixmap("./resources/ui/terrain_pg.gif") @@ -61,12 +92,12 @@ def load_icons(): ICONS["Dusk"] = QPixmap("./resources/ui/daytime/dusk.png") ICONS["Night"] = QPixmap("./resources/ui/daytime/night.png") - ICONS["Money"] = QPixmap("./resources/ui/misc/money_icon.png") - ICONS["PassTurn"] = QPixmap("./resources/ui/misc/hourglass.png") - ICONS["Proceed"] = QPixmap("./resources/ui/misc/proceed.png") - ICONS["Settings"] = QPixmap("./resources/ui/misc/settings.png") - ICONS["Statistics"] = QPixmap("./resources/ui/misc/statistics.png") - ICONS["Ordnance"] = QPixmap("./resources/ui/misc/ordnance_icon.png") + ICONS["Money"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/money_icon.png") + ICONS["PassTurn"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/hourglass.png") + ICONS["Proceed"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/proceed.png") + ICONS["Settings"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/settings.png") + ICONS["Statistics"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/statistics.png") + ICONS["Ordnance"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/ordnance_icon.png") ICONS["target"] = QPixmap("./resources/ui/ground_assets/target.png") ICONS["cleared"] = QPixmap("./resources/ui/ground_assets/cleared.png") @@ -77,9 +108,9 @@ def load_icons(): ICONS["ship"] = QPixmap("./resources/ui/ground_assets/ship.png") ICONS["ship_blue"] = QPixmap("./resources/ui/ground_assets/ship_blue.png") - ICONS["Generator"] = QPixmap("./resources/ui/misc/generator.png") - ICONS["Missile"] = QPixmap("./resources/ui/misc/missile.png") - ICONS["Cheat"] = QPixmap("./resources/ui/misc/cheat.png") + ICONS["Generator"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/generator.png") + ICONS["Missile"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/missile.png") + ICONS["Cheat"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/cheat.png") ICONS["TaskCAS"] = QPixmap("./resources/ui/tasks/cas.png") ICONS["TaskCAP"] = QPixmap("./resources/ui/tasks/cap.png") diff --git a/qt_ui/widgets/QTopPanel.py b/qt_ui/widgets/QTopPanel.py index 901bef6d..2a77cb23 100644 --- a/qt_ui/widgets/QTopPanel.py +++ b/qt_ui/widgets/QTopPanel.py @@ -34,7 +34,7 @@ class QTopPanel(QFrame): self.proceedButton = QPushButton("Mission Planning") self.proceedButton.setIcon(CONST.ICONS["Proceed"]) - self.proceedButton.setProperty("style", "btn-primary") + self.proceedButton.setProperty("style", "btn-success") self.proceedButton.clicked.connect(self.proceed) if self.game and self.game.turn == 0: self.proceedButton.setEnabled(False) diff --git a/qt_ui/widgets/map/QLiberationMap.py b/qt_ui/widgets/map/QLiberationMap.py index 1f18d11e..80cce076 100644 --- a/qt_ui/widgets/map/QLiberationMap.py +++ b/qt_ui/widgets/map/QLiberationMap.py @@ -71,7 +71,6 @@ class QLiberationMap(QGraphicsView): """ Uncomment to set up theather reference points - def keyPressEvent(self, event): #super(QLiberationMap, self).keyPressEvent(event) @@ -85,34 +84,36 @@ class QLiberationMap(QGraphicsView): i = i + 1 if event.key() == QtCore.Qt.Key_Down: - self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0] + 100, self.game.theater.reference_points[point_0][1] + self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0] + 10, self.game.theater.reference_points[point_0][1] if event.key() == QtCore.Qt.Key_Up: - self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0] - 100, self.game.theater.reference_points[point_0][1] + self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0] - 10, self.game.theater.reference_points[point_0][1] if event.key() == QtCore.Qt.Key_Left: - self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0], self.game.theater.reference_points[point_0][1] + 100 + self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0], self.game.theater.reference_points[point_0][1] + 10 if event.key() == QtCore.Qt.Key_Right: - self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0], self.game.theater.reference_points[point_0][1] - 100 + self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0], self.game.theater.reference_points[point_0][1] - 10 if event.key() == QtCore.Qt.Key_2 and numpad_mod: - self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0] + 100, self.game.theater.reference_points[point_1][1] + self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0] + 10, self.game.theater.reference_points[point_1][1] if event.key() == QtCore.Qt.Key_8 and numpad_mod: - self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0] - 100, self.game.theater.reference_points[point_1][1] + self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0] - 10, self.game.theater.reference_points[point_1][1] if event.key() == QtCore.Qt.Key_4 and numpad_mod: - self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0], self.game.theater.reference_points[point_1][1] + 100 + self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0], self.game.theater.reference_points[point_1][1] + 10 if event.key() == QtCore.Qt.Key_6 and numpad_mod: - self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0], self.game.theater.reference_points[point_1][1] - 100 + self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0], self.game.theater.reference_points[point_1][1] - 10 print(self.game.theater.reference_points) self.reload_scene() """ - def reload_scene(self): scene = self.scene() scene.clear() + playerColor = self.game.get_player_color() + enemyColor = self.game.get_enemy_color() + self.addBackground() # Uncomment below to help set up theater reference points @@ -128,11 +129,11 @@ class QLiberationMap(QGraphicsView): CONST.CP_SIZE, cp, self.game)) if cp.captured: - pen = QPen(brush=CONST.COLORS["blue"]) - brush = CONST.COLORS["blue_transparent"] + pen = QPen(brush=CONST.COLORS[playerColor]) + brush = CONST.COLORS[playerColor+"_transparent"] else: - pen = QPen(brush=CONST.COLORS["red"]) - brush = CONST.COLORS["red_transparent"] + pen = QPen(brush=CONST.COLORS[enemyColor]) + brush = CONST.COLORS[enemyColor+"_transparent"] added_objects = [] for ground_object in cp.ground_objects: @@ -157,34 +158,35 @@ class QLiberationMap(QGraphicsView): if unit.threat_range > max_range: max_range = unit.threat_range if has_radar: - scene.addEllipse(go_pos[0] - max_range/300.0 + 8, go_pos[1] - max_range/300.0 + 8, max_range/150.0, max_range/150.0, pen, brush) + scene.addEllipse(go_pos[0] - max_range/300.0 + 8, go_pos[1] - max_range/300.0 + 8, max_range/150.0, max_range/150.0, CONST.COLORS["white_transparent"], CONST.COLORS["grey_transparent"]) added_objects.append(ground_object.obj_name) for cp in self.game.theater.enemy_points(): if self.get_display_rule("lines"): - self.scene_create_lines_for_cp(cp) + self.scene_create_lines_for_cp(cp, playerColor, enemyColor) + for cp in self.game.theater.player_points(): if self.get_display_rule("lines"): - self.scene_create_lines_for_cp(cp) + self.scene_create_lines_for_cp(cp, playerColor, enemyColor) for cp in self.game.theater.controlpoints: if cp.captured: - pen = QPen(brush=CONST.COLORS["blue"]) - brush = CONST.COLORS["blue_transparent"] + pen = QPen(brush=CONST.COLORS[playerColor]) + brush = CONST.COLORS[playerColor+"_transparent"] + + flight_path_pen = QPen(brush=CONST.COLORS[playerColor]) + flight_path_pen.setColor(CONST.COLORS[playerColor]) - flight_path_pen = QPen(brush=CONST.COLORS["blue"]) - flight_path_pen.setColor(CONST.COLORS["blue"]) - flight_path_pen.setWidth(1) - flight_path_pen.setStyle(Qt.DashDotLine) else: - pen = QPen(brush=CONST.COLORS["red"]) - brush = CONST.COLORS["red_transparent"] + pen = QPen(brush=CONST.COLORS[enemyColor]) + brush = CONST.COLORS[enemyColor+"_transparent"] - flight_path_pen = QPen(brush=CONST.COLORS["bright_red"]) - flight_path_pen.setColor(CONST.COLORS["bright_red"]) - flight_path_pen.setWidth(1) - flight_path_pen.setStyle(Qt.DashDotLine) + flight_path_pen = QPen(brush=CONST.COLORS[enemyColor]) + flight_path_pen.setColor(CONST.COLORS[enemyColor]) + + flight_path_pen.setWidth(1) + flight_path_pen.setStyle(Qt.DashDotLine) pos = self._transform_point(cp.position) if self.get_display_rule("flight_paths"): @@ -202,27 +204,27 @@ class QLiberationMap(QGraphicsView): for cp in self.game.theater.controlpoints: pos = self._transform_point(cp.position) - text = scene.addText(cp.name, font=QFont("Trebuchet MS", 10, weight=5, italic=False)) + text = scene.addText(cp.name, font=CONST.FONT_MAP) text.setPos(pos[0] + CONST.CP_SIZE, pos[1] - CONST.CP_SIZE / 2) - text = scene.addText(cp.name, font=QFont("Trebuchet MS", 10, weight=5, italic=False)) + text = scene.addText(cp.name, font=CONST.FONT_MAP) text.setDefaultTextColor(Qt.white) text.setPos(pos[0] + CONST.CP_SIZE + 1, pos[1] - CONST.CP_SIZE / 2 + 1) - def scene_create_lines_for_cp(self, cp: ControlPoint): + def scene_create_lines_for_cp(self, cp: ControlPoint, playerColor, enemyColor): scene = self.scene() pos = self._transform_point(cp.position) for connected_cp in cp.connected_points: pos2 = self._transform_point(connected_cp.position) if not cp.captured: - color = CONST.COLORS["red"] + color = CONST.COLORS["dark_"+enemyColor] elif cp.captured: - color = CONST.COLORS["blue"] + color = CONST.COLORS["dark_"+playerColor] else: - color = CONST.COLORS["red"] + color = CONST.COLORS["dark_"+enemyColor] pen = QPen(brush=color) pen.setColor(color) - pen.setWidth(16) + pen.setWidth(6) if cp.captured and not connected_cp.captured and Conflict.has_frontline_between(cp, connected_cp): if not cp.captured: scene.addLine(pos[0], pos[1], pos2[0], pos2[1], pen=pen) @@ -234,8 +236,8 @@ class QLiberationMap(QGraphicsView): p1 = point_from_heading(pos2[0], pos2[1], h+180, 25) p2 = point_from_heading(pos2[0], pos2[1], h, 25) frontline_pen = QPen(brush=CONST.COLORS["bright_red"]) - frontline_pen.setColor(CONST.COLORS["bright_red"]) - frontline_pen.setWidth(18) + frontline_pen.setColor(CONST.COLORS["orange"]) + frontline_pen.setWidth(8) scene.addLine(p1[0], p1[1], p2[0], p2[1], pen=frontline_pen) else: @@ -318,14 +320,14 @@ class QLiberationMap(QGraphicsView): pass elif self.game.current_turn_daytime == "night": ov = QPixmap(bg.width(), bg.height()) - ov.fill(QColor(40, 40, 150)) + ov.fill(CONST.COLORS["night_overlay"]) overlay = scene.addPixmap(ov) effect = QGraphicsOpacityEffect() effect.setOpacity(0.7) overlay.setGraphicsEffect(effect) else: ov = QPixmap(bg.width(), bg.height()) - ov.fill(QColor(165, 100, 100)) + ov.fill(CONST.COLORS["dawn_dust_overlay"]) overlay = scene.addPixmap(ov) effect = QGraphicsOpacityEffect() effect.setOpacity(0.3) diff --git a/qt_ui/widgets/map/QLiberationScene.py b/qt_ui/widgets/map/QLiberationScene.py index c13ac0fe..30f0b56a 100644 --- a/qt_ui/widgets/map/QLiberationScene.py +++ b/qt_ui/widgets/map/QLiberationScene.py @@ -1,13 +1,13 @@ from PySide2.QtGui import QFont from PySide2.QtWidgets import QGraphicsScene -from qt_ui.uiconstants import COLORS +import qt_ui.uiconstants as CONST class QLiberationScene(QGraphicsScene): def __init__(self, parent): super().__init__(parent) - item = self.addText("No save file found. Go to \"File/New Game\" to setup a new campaign.", - QFont("Arial", 14, weight=5)) - item.setDefaultTextColor(COLORS["white"]) + item = self.addText("Go to \"File/New Game\" to setup a new campaign or go to \"File/Open\" to load an existing save game.", + CONST.FONT_PRIMARY) + item.setDefaultTextColor(CONST.COLORS["white"]) diff --git a/qt_ui/widgets/map/QMapControlPoint.py b/qt_ui/widgets/map/QMapControlPoint.py index 774d1d77..09061e16 100644 --- a/qt_ui/widgets/map/QMapControlPoint.py +++ b/qt_ui/widgets/map/QMapControlPoint.py @@ -5,7 +5,6 @@ from PySide2.QtWidgets import QGraphicsRectItem, QGraphicsSceneHoverEvent, QGrap import qt_ui.uiconstants as CONST from game import Game -from qt_ui.windows.basemenu.QBaseMenu import QBaseMenu from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2 from theater import ControlPoint, db @@ -71,7 +70,8 @@ class QMapControlPoint(QGraphicsRectItem): self.update() def mousePressEvent(self, event:QGraphicsSceneMouseEvent): - self.contextMenuEvent(event) + self.openBaseMenu() + #self.contextMenuEvent(event) def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent): @@ -89,17 +89,11 @@ class QMapControlPoint(QGraphicsRectItem): @property def brush_color(self)->QColor: - if self.parent.game.player_country in db.BLUEFOR_FACTIONS: - return self.model.captured and CONST.COLORS["blue"] or CONST.COLORS["super_red"] - else: - return self.model.captured and CONST.COLORS["super_red"] or CONST.COLORS["blue"] + return self.model.captured and CONST.COLORS["blue"] or CONST.COLORS["super_red"] @property def pen_color(self) -> QColor: - if self.parent.game.player_country in db.BLUEFOR_FACTIONS: - return self.model.captured and CONST.COLORS["dark_blue"] or CONST.COLORS["bright_red"] - else: - return self.model.captured and CONST.COLORS["bright_red"] or CONST.COLORS["dark_blue"] + return self.model.captured and CONST.COLORS["white"] or CONST.COLORS["white"] def openBaseMenu(self): self.baseMenu = QBaseMenu2(self.window(), self.model, self.game) diff --git a/qt_ui/widgets/map/QMapEvent.py b/qt_ui/widgets/map/QMapEvent.py index 13570bdf..5e24f35e 100644 --- a/qt_ui/widgets/map/QMapEvent.py +++ b/qt_ui/widgets/map/QMapEvent.py @@ -17,17 +17,22 @@ class QMapEvent(QGraphicsRectItem): self.setToolTip(str(self.gameEvent)) self.playable = not isinstance(self.gameEvent, UnitsDeliveryEvent) + + def paint(self, painter, option, widget=None): + playerColor = self.game.get_player_color() + enemyColor = self.game.get_enemy_color() + if self.parent.get_display_rule("events"): painter.save() if self.gameEvent.is_player_attacking: - painter.setPen(QPen(brush=CONST.COLORS["blue"])) - painter.setBrush(CONST.COLORS["blue"]) + painter.setPen(QPen(brush=CONST.COLORS[playerColor])) + painter.setBrush(CONST.COLORS[playerColor]) else: - painter.setPen(QPen(brush=CONST.COLORS["red"])) - painter.setBrush(CONST.COLORS["red"]) + painter.setPen(QPen(brush=CONST.COLORS[enemyColor])) + painter.setBrush(CONST.COLORS[enemyColor]) if self.isUnderMouse() and self.playable: painter.setBrush(CONST.COLORS["white"]) diff --git a/qt_ui/widgets/map/QMapGroundObject.py b/qt_ui/widgets/map/QMapGroundObject.py index b28f2ea6..dbbf4d79 100644 --- a/qt_ui/widgets/map/QMapGroundObject.py +++ b/qt_ui/widgets/map/QMapGroundObject.py @@ -42,6 +42,10 @@ class QMapGroundObject(QGraphicsRectItem): def paint(self, painter, option, widget=None): #super(QMapControlPoint, self).paint(painter, option, widget) + + playerIcons = "_blue" + enemyIcons = "" + if self.parent.get_display_rule("go"): painter.save() @@ -50,9 +54,9 @@ class QMapGroundObject(QGraphicsRectItem): cat = "ship" if not self.model.is_dead and not self.cp.captured: - painter.drawPixmap(option.rect, CONST.ICONS[cat]) + painter.drawPixmap(option.rect, CONST.ICONS[cat + enemyIcons]) elif not self.model.is_dead: - painter.drawPixmap(option.rect, CONST.ICONS[cat + "_blue"]) + painter.drawPixmap(option.rect, CONST.ICONS[cat + playerIcons]) else: painter.drawPixmap(option.rect, CONST.ICONS["destroyed"]) painter.restore() diff --git a/qt_ui/windows/QDebriefingWindow.py b/qt_ui/windows/QDebriefingWindow.py index c5e45d0d..752d19d5 100644 --- a/qt_ui/windows/QDebriefingWindow.py +++ b/qt_ui/windows/QDebriefingWindow.py @@ -1,4 +1,4 @@ -from PySide2.QtGui import QIcon +from PySide2.QtGui import QIcon, QPixmap from PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout, QGroupBox, QGridLayout, QPushButton from game.game import Event, db, Game @@ -25,14 +25,21 @@ class QDebriefingWindow(QDialog): self.layout = QVBoxLayout() - # Result + header = QLabel(self) + header.setGeometry(0, 0, 655, 106) + pixmap = QPixmap("./resources/ui/debriefing.png") + header.setPixmap(pixmap) + self.layout.addWidget(header) + self.layout.addStretch() - if self.gameEvent.is_successfull(self.debriefing): - title = QLabel("Operation Succesfull !") - title.setProperty("style", "title-success") - else: - title = QLabel("Operation failed !") - title.setProperty("style", "title-danger") + # Result + #if self.gameEvent.is_successfull(self.debriefing): + # title = QLabel("Operation end !") + # title.setProperty("style", "title-success") + #else: + # title = QLabel("Operation end !") + # title.setProperty("style", "title-danger") + title = QLabel("Casualty report") self.layout.addWidget(title) # Player lost units diff --git a/qt_ui/windows/QLiberationWindow.py b/qt_ui/windows/QLiberationWindow.py index 8128d910..9e3cd242 100644 --- a/qt_ui/windows/QLiberationWindow.py +++ b/qt_ui/windows/QLiberationWindow.py @@ -5,7 +5,7 @@ import webbrowser from PySide2.QtCore import Qt from PySide2.QtGui import QIcon from PySide2.QtWidgets import QWidget, QVBoxLayout, QMainWindow, QAction, QMessageBox, QDesktopWidget, \ - QSplitter + QSplitter, QFileDialog import qt_ui.uiconstants as CONST from game import Game @@ -54,6 +54,7 @@ class QLiberationWindow(QMainWindow): hbox = QSplitter(Qt.Horizontal) hbox.addWidget(self.info_panel) hbox.addWidget(self.liberation_map) + hbox.setSizes([2, 8]) vbox = QVBoxLayout() vbox.setMargin(0) @@ -73,10 +74,18 @@ class QLiberationWindow(QMainWindow): self.newGameAction.setIcon(QIcon(CONST.ICONS["New"])) self.newGameAction.triggered.connect(self.newGame) + self.openAction = QAction("Open", self) + self.openAction.setIcon(QIcon(CONST.ICONS["Open"])) + self.openAction.triggered.connect(self.openFile) + self.saveGameAction = QAction("Save", self) self.saveGameAction.setIcon(QIcon(CONST.ICONS["Save"])) self.saveGameAction.triggered.connect(self.saveGame) + self.saveAsAction = QAction("Save As", self) + self.saveAsAction.setIcon(QIcon(CONST.ICONS["Save"])) + self.saveAsAction.triggered.connect(self.saveGameAs) + self.showAboutDialogAction = QAction("About DCS Liberation", self) self.showAboutDialogAction.setIcon(QIcon.fromTheme("help-about")) self.showAboutDialogAction.triggered.connect(self.showAboutDialog) @@ -88,7 +97,7 @@ class QLiberationWindow(QMainWindow): def initToolbar(self): self.tool_bar = self.addToolBar("File") self.tool_bar.addAction(self.newGameAction) - #self.tool_bar.addAction(QIcon(CONST.ICONS["Open"]), "Open") + self.tool_bar.addAction(self.openAction) self.tool_bar.addAction(self.saveGameAction) def initMenuBar(self): @@ -96,25 +105,23 @@ class QLiberationWindow(QMainWindow): file_menu = self.menu.addMenu("File") file_menu.addAction(self.newGameAction) - #file_menu.addAction(QIcon(CONST.ICONS["Open"]), "Open") # TODO : implement + file_menu.addAction(self.openAction) file_menu.addAction(self.saveGameAction) + file_menu.addAction(self.saveAsAction) file_menu.addSeparator() file_menu.addAction(self.showLiberationPrefDialogAction) file_menu.addSeparator() - #file_menu.addAction("Save As") # TODO : implement #file_menu.addAction("Close Current Game", lambda: self.closeGame()) # Not working file_menu.addAction("Exit" , lambda: self.exit()) - help_menu = self.menu.addMenu("Help") + help_menu.addAction("Discord Server", lambda: webbrowser.open_new_tab("https://" + "discord.gg" + "/" + "bKrt" + "rkJ")) + help_menu.addAction("Github Repository", lambda: webbrowser.open_new_tab("https://github.com/khopa/dcs_liberation")) + help_menu.addAction("Releases", lambda: webbrowser.open_new_tab("https://github.com/Khopa/dcs_liberation/releases")) help_menu.addAction("Online Manual", lambda: webbrowser.open_new_tab(URLS["Manual"])) - help_menu.addAction("Discord", lambda: webbrowser.open_new_tab("https://" + "discord.gg" + "/" + "bKrt" + "rkJ")) - #help_menu.addAction("Troubleshooting Guide", lambda: webbrowser.open_new_tab(URLS["Troubleshooting"])) - #help_menu.addAction("Modding Guide", lambda: webbrowser.open_new_tab(URLS["Modding"])) - #help_menu.addSeparator() ----> Note from Khopa : I disable these links since it's not up to date for this branch - #help_menu.addAction("Contribute", lambda: webbrowser.open_new_tab(URLS["Repository"])) - help_menu.addAction("Forum Thread", lambda: webbrowser.open_new_tab(URLS["ForumThread"])) + help_menu.addAction("ED Forum Thread", lambda: webbrowser.open_new_tab(URLS["ForumThread"])) help_menu.addAction("Report an issue", lambda: webbrowser.open_new_tab(URLS["Issues"])) + help_menu.addSeparator() help_menu.addAction(self.showAboutDialogAction) @@ -163,10 +170,29 @@ class QLiberationWindow(QMainWindow): wizard.show() wizard.accepted.connect(lambda: self.onGameGenerated(wizard.generatedGame)) + def openFile(self): + file = QFileDialog.getOpenFileName(self, "Select game file to open", + dir=persistency._dcs_saved_game_folder, + filter="*.liberation") + if file is not None: + game = persistency.load_game(file[0]) + self.setGame(game) + GameUpdateSignal.get_instance().updateGame(self.game) + def saveGame(self): logging.info("Saving game") - persistency.save_game(self.game) - GameUpdateSignal.get_instance().updateGame(self.game) + + if self.game.savepath: + persistency.save_game(self.game) + GameUpdateSignal.get_instance().updateGame(self.game) + else: + self.saveGameAs() + + def saveGameAs(self): + file = QFileDialog.getSaveFileName(self, "Save As", dir=persistency._dcs_saved_game_folder, filter="*.liberation") + if file is not None: + self.game.savepath = file[0] + persistency.save_game(self.game) def onGameGenerated(self, game: Game): logging.info("On Game generated") @@ -187,13 +213,15 @@ class QLiberationWindow(QMainWindow): def showAboutDialog(self): text = "

DCS Liberation

" + \ - "

Repository

" + \ - "Source code : https://github.com/shdwp/dcs_liberation
" + \ - "

Authors/Contributors


" + \ - "shdwp, Khopa, Wrycu, calvinmorrow, JohanAberg
" + \ + "Source code : https://github.com/khopa/dcs_liberation" + \ + "

Authors

" + \ + "

DCS Liberation was originally developed by shdwp, DCS Liberation 2.0 is a partial rewrite based on this work by Khopa." \ + "

Contributors

" + \ + "shdwp, Khopa, Wrycu, calvinmorrow, JohanAberg, Deus" + \ "

Special Thanks :

" \ "rp- for the pydcs framework
"\ - "Grimes (mrSkortch) & Speed for the MIST framework
" + "Grimes (mrSkortch) & Speed for the MIST framework
"\ + "Ciribob for the JTACAutoLase.lua script
" about = QMessageBox() about.setWindowTitle("About DCS Liberation") diff --git a/qt_ui/windows/QNewGameWizard.py b/qt_ui/windows/QNewGameWizard.py index 3fd56fb3..e74f5e06 100644 --- a/qt_ui/windows/QNewGameWizard.py +++ b/qt_ui/windows/QNewGameWizard.py @@ -3,10 +3,12 @@ from __future__ import unicode_literals import datetime from PySide2 import QtGui, QtWidgets +from PySide2.QtWidgets import QHBoxLayout, QVBoxLayout from dcs.task import CAP, CAS import qt_ui.uiconstants as CONST from game import db, Game +from game.settings import Settings from gen import namegen from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy, thechannel @@ -30,13 +32,12 @@ class NewGameWizard(QtWidgets.QWizard): def accept(self): - blueFaction = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "blue"][self.field("blueFaction")] - redFaction = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "red"][self.field("redFaction")] - playerIsBlue = self.field("playerIsBlue") + blueFaction = [c for c in db.FACTIONS][self.field("blueFaction")] + redFaction = [c for c in db.FACTIONS][self.field("redFaction")] isTerrainPg = self.field("isTerrainPg") isTerrainNttr = self.field("isTerrainNttr") isTerrainCaucasusSmall = self.field("isTerrainCaucasusSmall") - isTerrainCaucasusSmallInverted = self.field("isTerrainCaucasusSmallInverted") + isTerrainRussia = self.field("isTerrainRussia") isTerrainCaucasusNorth= self.field("isTerrainCaucasusNorth") isIranianCampaignTheater = self.field("isIranianCampaignTheater") isTerrainNormandy = self.field("isTerrainNormandy") @@ -47,9 +48,15 @@ class NewGameWizard(QtWidgets.QWizard): timePeriod = db.TIME_PERIODS[list(db.TIME_PERIODS.keys())[self.field("timePeriod")]] midGame = self.field("midGame") multiplier = self.field("multiplier") + no_carrier = self.field("no_carrier") + no_lha = self.field("no_lha") + supercarrier = self.field("supercarrier") + no_player_navy = self.field("no_player_navy") + no_enemy_navy = self.field("no_enemy_navy") + invertMap = self.field("invertMap") - player_name = playerIsBlue and blueFaction or redFaction - enemy_name = playerIsBlue and redFaction or blueFaction + player_name = blueFaction + enemy_name = redFaction if isTerrainPg: conflicttheater = persiangulf.PersianGulfTheater() @@ -57,8 +64,8 @@ class NewGameWizard(QtWidgets.QWizard): conflicttheater = nevada.NevadaTheater() elif isTerrainCaucasusSmall: conflicttheater = caucasus.WesternGeorgia() - elif isTerrainCaucasusSmallInverted: - conflicttheater = caucasus.WesternGeorgiaInverted() + elif isTerrainRussia: + conflicttheater = caucasus.RussiaSmall() elif isTerrainCaucasusNorth: conflicttheater = caucasus.NorthCaucasus() elif isIranianCampaignTheater: @@ -76,20 +83,25 @@ class NewGameWizard(QtWidgets.QWizard): else: conflicttheater = caucasus.CaucasusTheater() + settings = Settings() + settings.inverted = invertMap + settings.supercarrier = supercarrier + settings.do_not_generate_carrier = no_carrier + settings.do_not_generate_lha = no_lha + settings.do_not_generate_player_navy = no_player_navy + settings.do_not_generate_enemy_navy = no_enemy_navy + self.generatedGame = self.start_new_game(player_name, enemy_name, conflicttheater, midGame, multiplier, - timePeriod) + timePeriod, settings) super(NewGameWizard, self).accept() def start_new_game(self, player_name: str, enemy_name: str, conflicttheater: ConflictTheater, - midgame: bool, multiplier: float, period: datetime): - - if midgame: - for i in range(0, int(len(conflicttheater.controlpoints) / 2)): - conflicttheater.controlpoints[i].captured = True + midgame: bool, multiplier: float, period: datetime, settings:Settings): # Reset name generator namegen.reset() + start_generator.prepare_theater(conflicttheater, settings, midgame) print("-- Starting New Game Generator") print("Enemy name : " + enemy_name) @@ -101,14 +113,15 @@ class NewGameWizard(QtWidgets.QWizard): game = Game(player_name=player_name, enemy_name=enemy_name, theater=conflicttheater, - start_date=period) + start_date=period, + settings=settings) print("-- Game Object generated") start_generator.generate_groundobjects(conflicttheater, game) game.budget = int(game.budget * multiplier) game.settings.multiplier = multiplier game.settings.sams = True - game.settings.version = "2.0RC9" + game.settings.version = "2.0.10" if midgame: game.budget = game.budget * 4 * len(list(conflicttheater.conflicts())) @@ -140,59 +153,59 @@ class FactionSelection(QtWidgets.QWizardPage): self.setTitle("Faction selection") self.setSubTitle("\nChoose the two opposing factions and select the player side.") self.setPixmap(QtWidgets.QWizard.LogoPixmap, - QtGui.QPixmap('./resources/ui/wizard/logo1.png')) + QtGui.QPixmap('./resources/ui/misc/generator.png')) self.setMinimumHeight(250) - blues = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "blue"] - reds = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "red"] + # Factions selection + self.factionsGroup = QtWidgets.QGroupBox("Factions") + self.factionsGroupLayout = QtWidgets.QGridLayout() - # Create form - blueFaction = QtWidgets.QLabel("Blue Faction :") + blueFaction = QtWidgets.QLabel("Player Faction :") self.blueFactionSelect = QtWidgets.QComboBox() - for f in blues: + for f in db.FACTIONS: self.blueFactionSelect.addItem(f) blueFaction.setBuddy(self.blueFactionSelect) - redFaction = QtWidgets.QLabel("Red Faction :") + redFaction = QtWidgets.QLabel("Enemy Faction :") self.redFactionSelect = QtWidgets.QComboBox() - for r in reds: + for i, r in enumerate(db.FACTIONS): self.redFactionSelect.addItem(r) + if r == "Russia 1990": # Default ennemy + self.redFactionSelect.setCurrentIndex(i) redFaction.setBuddy(self.redFactionSelect) - sideGroup = QtWidgets.QGroupBox("Player Side") - blueforRadioButton = QtWidgets.QRadioButton("BLUEFOR") - redforRadioButton = QtWidgets.QRadioButton("REDFOR") - blueforRadioButton.setChecked(True) - - # Unit Preview self.blueSideRecap = QtWidgets.QLabel("") - self.blueSideRecap.setFont(QtGui.QFont("Arial", italic=True)) + self.blueSideRecap.setFont(CONST.FONT_PRIMARY_I) self.blueSideRecap.setWordWrap(True) + self.redSideRecap = QtWidgets.QLabel("") - self.redSideRecap.setFont(QtGui.QFont("Arial", italic=True)) + self.redSideRecap.setFont(CONST.FONT_PRIMARY_I) self.redSideRecap.setWordWrap(True) + self.factionsGroupLayout.addWidget(blueFaction, 0, 0) + self.factionsGroupLayout.addWidget(self.blueFactionSelect, 0, 1) + self.factionsGroupLayout.addWidget(self.blueSideRecap, 1, 0, 1, 2) + self.factionsGroupLayout.addWidget(redFaction, 2, 0) + self.factionsGroupLayout.addWidget(self.redFactionSelect, 2, 1) + self.factionsGroupLayout.addWidget(self.redSideRecap, 3, 0, 1, 2) + self.factionsGroup.setLayout(self.factionsGroupLayout) + + # Create required mod layout + self.requiredModsGroup = QtWidgets.QGroupBox("Required Mods") + self.requiredModsGroupLayout = QtWidgets.QHBoxLayout() + self.requiredMods = QtWidgets.QLabel("
  • None
") + self.requiredModsGroupLayout.addWidget(self.requiredMods) + self.requiredModsGroup.setLayout(self.requiredModsGroupLayout) + # Link form fields self.registerField('blueFaction', self.blueFactionSelect) self.registerField('redFaction', self.redFactionSelect) - self.registerField('playerIsBlue', blueforRadioButton) - self.registerField('playerIsRed', redforRadioButton) # Build layout - sideGroupLayout = QtWidgets.QVBoxLayout() - sideGroupLayout.addWidget(blueforRadioButton) - sideGroupLayout.addWidget(redforRadioButton) - sideGroup.setLayout(sideGroupLayout) - - layout = QtWidgets.QGridLayout() - layout.addWidget(blueFaction, 0, 0) - layout.addWidget(self.blueFactionSelect, 0, 1) - layout.addWidget(self.blueSideRecap, 1, 0, 1, 2) - layout.addWidget(redFaction, 2, 0) - layout.addWidget(self.redFactionSelect, 2, 1) - layout.addWidget(self.redSideRecap, 3, 0, 1, 2) - layout.addWidget(sideGroup, 4, 0, 1, 2) + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.factionsGroup) + layout.addWidget(self.requiredModsGroup) self.setLayout(layout) self.updateUnitRecap() @@ -200,8 +213,14 @@ class FactionSelection(QtWidgets.QWizardPage): self.redFactionSelect.activated.connect(self.updateUnitRecap) def updateUnitRecap(self): - red_units = db.FACTIONS[self.redFactionSelect.currentText()]["units"] - blue_units = db.FACTIONS[self.blueFactionSelect.currentText()]["units"] + + self.requiredMods.setText("
    ") + + red_faction = db.FACTIONS[self.redFactionSelect.currentText()] + blue_faction = db.FACTIONS[self.blueFactionSelect.currentText()] + + red_units = red_faction["units"] + blue_units = blue_faction["units"] blue_txt = "" for u in blue_units: @@ -217,6 +236,23 @@ class FactionSelection(QtWidgets.QWizardPage): red_txt = red_txt + "\n" self.redSideRecap.setText(red_txt) + has_mod = False + if "requirements" in red_faction.keys(): + has_mod = True + for mod in red_faction["requirements"].keys(): + self.requiredMods.setText(self.requiredMods.text() + "\n
  • " + mod + ": " + red_faction["requirements"][mod] + "
  • ") + + if "requirements" in blue_faction.keys(): + has_mod = True + for mod in blue_faction["requirements"].keys(): + if not "requirements" in red_faction.keys() or mod not in red_faction["requirements"].keys(): + self.requiredMods.setText(self.requiredMods.text() + "\n
  • " + mod + ": " + blue_faction["requirements"][mod] + "
  • ") + + if has_mod: + self.requiredMods.setText(self.requiredMods.text() + "
\n\n") + else: + self.requiredMods.setText(self.requiredMods.text() + "
  • None
  • \n") + class TheaterConfiguration(QtWidgets.QWizardPage): def __init__(self, parent=None): @@ -227,24 +263,27 @@ class TheaterConfiguration(QtWidgets.QWizardPage): self.setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap('./resources/ui/wizard/logo1.png')) + self.setPixmap(QtWidgets.QWizard.WatermarkPixmap, + QtGui.QPixmap('./resources/ui/wizard/watermark3.png')) + # Terrain selection terrainGroup = QtWidgets.QGroupBox("Terrain") - terrainCaucasusSmall = QtWidgets.QRadioButton("Caucasus - Western Georgia [RECOMMENDED - Early Cold War Era]") + terrainCaucasusSmall = QtWidgets.QRadioButton("Caucasus - Western Georgia") terrainCaucasusSmall.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"])) - terrainCaucasusSmallInverted = QtWidgets.QRadioButton("Caucasus - Western Georgia Inverted [RECOMMENDED - Early Cold War Era]") - terrainCaucasusSmallInverted.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"])) - terrainCaucasus = QtWidgets.QRadioButton("Caucasus - Full map [NOT TESTED]") + terrainRussia = QtWidgets.QRadioButton("Caucasus - Russia Small") + terrainRussia.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"])) + terrainCaucasus = QtWidgets.QRadioButton("Caucasus - Full map [NOT RECOMMENDED]") terrainCaucasus.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"])) - terrainCaucasusNorth = QtWidgets.QRadioButton("Caucasus - North - [RECOMMENDED - Modern Era]") + terrainCaucasusNorth = QtWidgets.QRadioButton("Caucasus - North") terrainCaucasusNorth.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"])) - terrainPg = QtWidgets.QRadioButton("Persian Gulf - Full Map [NOT TESTED]") + terrainPg = QtWidgets.QRadioButton("Persian Gulf - Full Map [NOT RECOMMENDED]") terrainPg.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Persian_Gulf"])) - terrainIran = QtWidgets.QRadioButton("Persian Gulf - Invasion of Iran [RECOMMENDED]") + terrainIran = QtWidgets.QRadioButton("Persian Gulf - Invasion of Iran") terrainIran.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Persian_Gulf"])) - terrainEmirates = QtWidgets.QRadioButton("Persian Gulf - Emirates [RECOMMENDED]") + terrainEmirates = QtWidgets.QRadioButton("Persian Gulf - Emirates") terrainEmirates.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Persian_Gulf"])) - terrainNttr = QtWidgets.QRadioButton("Nevada - North Nevada [RECOMMENDED]") + terrainNttr = QtWidgets.QRadioButton("Nevada - North Nevada") terrainNttr.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Nevada"])) terrainNormandy = QtWidgets.QRadioButton("Normandy") terrainNormandy.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Normandy"])) @@ -256,6 +295,15 @@ class TheaterConfiguration(QtWidgets.QWizardPage): terrainChannelComplete.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Channel"])) terrainCaucasusSmall.setChecked(True) + # Campaign settings + mapSettingsGroup = QtWidgets.QGroupBox("Map Settings") + invertMap = QtWidgets.QCheckBox() + self.registerField('invertMap', invertMap) + mapSettingsLayout = QtWidgets.QGridLayout() + mapSettingsLayout.addWidget(QtWidgets.QLabel("Invert Map"), 1, 0) + mapSettingsLayout.addWidget(invertMap, 1, 1) + mapSettingsGroup.setLayout(mapSettingsLayout) + # Time Period timeGroup = QtWidgets.QGroupBox("Time Period") timePeriod = QtWidgets.QLabel("Start date :") @@ -268,7 +316,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage): # Register fields self.registerField('isTerrainCaucasus', terrainCaucasus) self.registerField('isTerrainCaucasusSmall', terrainCaucasusSmall) - self.registerField('isTerrainCaucasusSmallInverted', terrainCaucasusSmallInverted) + self.registerField('isTerrainRussia', terrainRussia) self.registerField('isTerrainCaucasusNorth', terrainCaucasusNorth) self.registerField('isTerrainPg', terrainPg) self.registerField('isIranianCampaignTheater', terrainIran) @@ -283,7 +331,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage): # Build layout terrainGroupLayout = QtWidgets.QVBoxLayout() terrainGroupLayout.addWidget(terrainCaucasusSmall) - terrainGroupLayout.addWidget(terrainCaucasusSmallInverted) + terrainGroupLayout.addWidget(terrainRussia) terrainGroupLayout.addWidget(terrainCaucasusNorth) terrainGroupLayout.addWidget(terrainCaucasus) terrainGroupLayout.addWidget(terrainIran) @@ -303,8 +351,9 @@ class TheaterConfiguration(QtWidgets.QWizardPage): layout = QtWidgets.QGridLayout() layout.setColumnMinimumWidth(0, 20) - layout.addWidget(terrainGroup) - layout.addWidget(timeGroup) + layout.addWidget(terrainGroup, 0, 0, 3, 1) + layout.addWidget(mapSettingsGroup, 0, 1, 1, 1) + layout.addWidget(timeGroup, 1, 1, 1, 1) self.setLayout(layout) @@ -323,15 +372,47 @@ class MiscOptions(QtWidgets.QWizardPage): multiplier.setMinimum(1) multiplier.setMaximum(5) + miscSettingsGroup = QtWidgets.QGroupBox("Misc Settings") self.registerField('midGame', midGame) self.registerField('multiplier', multiplier) + # Campaign settings + generatorSettingsGroup = QtWidgets.QGroupBox("Generator Settings") + no_carrier = QtWidgets.QCheckBox() + self.registerField('no_carrier', no_carrier) + no_lha = QtWidgets.QCheckBox() + self.registerField('no_lha', no_lha) + supercarrier = QtWidgets.QCheckBox() + self.registerField('supercarrier', supercarrier) + no_player_navy= QtWidgets.QCheckBox() + self.registerField('no_player_navy', no_player_navy) + no_enemy_navy = QtWidgets.QCheckBox() + self.registerField('no_enemy_navy', no_enemy_navy) + + generatorLayout = QtWidgets.QGridLayout() + generatorLayout.addWidget(QtWidgets.QLabel("No Aircraft Carriers"), 1, 0) + generatorLayout.addWidget(no_carrier, 1, 1) + generatorLayout.addWidget(QtWidgets.QLabel("No LHA"), 2, 0) + generatorLayout.addWidget(no_lha, 2, 1) + generatorLayout.addWidget(QtWidgets.QLabel("Use Supercarrier module"), 3, 0) + generatorLayout.addWidget(supercarrier, 3, 1) + generatorLayout.addWidget(QtWidgets.QLabel("No Player Navy"), 4, 0) + generatorLayout.addWidget(no_player_navy, 4, 1) + generatorLayout.addWidget(QtWidgets.QLabel("No Enemy Navy"), 5, 0) + generatorLayout.addWidget(no_enemy_navy, 5, 1) + generatorSettingsGroup.setLayout(generatorLayout) + layout = QtWidgets.QGridLayout() layout.addWidget(QtWidgets.QLabel("Start at mid game"), 1, 0) layout.addWidget(midGame, 1, 1) layout.addWidget(QtWidgets.QLabel("Ennemy forces multiplier [Disabled for Now]"), 2, 0) layout.addWidget(multiplier, 2, 1) - self.setLayout(layout) + miscSettingsGroup.setLayout(layout) + + mlayout = QVBoxLayout() + mlayout.addWidget(miscSettingsGroup) + mlayout.addWidget(generatorSettingsGroup) + self.setLayout(mlayout) class ConclusionPage(QtWidgets.QWizardPage): diff --git a/qt_ui/windows/QWaitingForMissionResultWindow.py b/qt_ui/windows/QWaitingForMissionResultWindow.py index bd880262..22fdc152 100644 --- a/qt_ui/windows/QWaitingForMissionResultWindow.py +++ b/qt_ui/windows/QWaitingForMissionResultWindow.py @@ -1,15 +1,18 @@ +import json import os from PySide2 import QtCore -from PySide2.QtCore import QObject, Signal -from PySide2.QtGui import QMovie, QIcon -from PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout, QGroupBox, QGridLayout, QPushButton +from PySide2.QtCore import QObject, Signal, Qt +from PySide2.QtGui import QMovie, QIcon, QPixmap +from PySide2.QtWidgets import QLabel, QDialog, QGroupBox, QGridLayout, QPushButton, QFileDialog, QMessageBox, QTextEdit, \ + QHBoxLayout -from game.game import Event, Game +from game.game import Event, Game, logging from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from userdata.debriefing import wait_for_debriefing, Debriefing from userdata.persistency import base_path + class DebriefingFileWrittenSignal(QObject): instance = None @@ -36,48 +39,87 @@ class QWaitingForMissionResultWindow(QDialog): self.gameEvent = gameEvent self.game = game self.setWindowTitle("Waiting for mission completion.") - self.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, False) self.setWindowIcon(QIcon("./resources/icon.png")) + self.setMinimumHeight(570) self.initUi() DebriefingFileWrittenSignal.get_instance().debriefingReceived.connect(self.updateLayout) - wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game) + self.wait_thread = wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game) def initUi(self): self.layout = QGridLayout() + + header = QLabel(self) + header.setGeometry(0, 0, 655, 106) + pixmap = QPixmap("./resources/ui/conflict.png") + header.setPixmap(pixmap) + self.layout.addWidget(header, 0, 0) + self.gridLayout = QGridLayout() - self.gridLayout.addWidget(QLabel("You are clear for takeoff"), 1, 0) - self.gridLayout.addWidget(QLabel(""), 2, 0) - self.gridLayout.addWidget(QLabel("

    For Singleplayer :

    "), 3, 0) - self.gridLayout.addWidget(QLabel("In DCS, open the Mission Editor, and load the file : "), 4, 0) - self.gridLayout.addWidget(QLabel("liberation_nextturn"), 5, 0) - self.gridLayout.addWidget(QLabel("Then once the mission is loaded in ME, in menu \"Flight\", click on FLY Mission to launch"), 6, 0) - self.gridLayout.addWidget(QLabel(""), 7, 0) - self.gridLayout.addWidget(QLabel("

    For Multiplayer :

    "), 8, 0) - self.gridLayout.addWidget(QLabel("In DCS, open the Mission Editor, and load the file : "), 9, 0) - self.gridLayout.addWidget(QLabel("liberation_nextturn"), 10, 0) - self.gridLayout.addWidget(QLabel("Click on File/Save. Then exit the mission editor, and go to Multiplayer."), 11, 0) - self.gridLayout.addWidget(QLabel("Then host a server with the mission, and tell your friends to join !"), 12, 0) - self.gridLayout.addWidget(QLabel("(The step in the mission editor is important, and fix a game breaking bug.)"), 13, 0) - self.gridLayout.addWidget(QLabel(""), 14, 0) + TEXT = "" + \ + "You are clear for takeoff" + \ + "" + \ + "

    For Singleplayer :

    \n" + \ + "In DCS, open the Mission Editor, and load the file : \n" + \ + "liberation_nextturn\n" + \ + "

    Then once the mission is loaded in ME, in menu \"Flight\",\n" + \ + "click on FLY Mission to launch.

    \n" + \ + "" + \ + "

    For Multiplayer :

    " + \ + "In DCS, open the Mission Editor, and load the file : " + \ + "liberation_nextturn" + \ + "

    Click on File/Save. Then exit the mission editor, and go to Multiplayer.

    " + \ + "

    Then host a server with the mission, and tell your friends to join !

    " + \ + "(The step in the mission editor is important, and fix a game breaking bug.)" + \ + "

    Finishing

    " + \ + "

    Once you have played the mission, click on the \"Accept Results\" button.

    " + \ + "

    If DCS Liberation does not detect mission end, use the manually submit button, and choose the state.json file.

    " + + self.instructions_text = QTextEdit(TEXT) + self.instructions_text.setReadOnly(True) + self.gridLayout.addWidget(self.instructions_text, 1, 0) progress = QLabel("") progress.setAlignment(QtCore.Qt.AlignCenter) - progressBar = QMovie("./resources/ui/loader.gif") - progress.setMovie(progressBar) - self.gridLayout.addWidget(progress, 15, 0) - self.gridLayout.addWidget(QLabel(""), 16, 0) - self.gridLayout.addWidget(QLabel("Once you have played the mission, this window will dissapear."), 17, 0) - self.gridLayout.addWidget(QLabel("You will have to click on \"Accept Results\" to proceed"), 18, 0) + progress_bar = QMovie("./resources/ui/loader.gif") + progress.setMovie(progress_bar) - progressBar.start() - self.layout.addLayout(self.gridLayout,0,0) + self.actions = QGroupBox("Actions :") + self.actions_layout = QHBoxLayout() + self.actions.setLayout(self.actions_layout) + + self.manually_submit = QPushButton("Manually Submit [Advanced users]") + self.manually_submit.clicked.connect(self.submit_manually) + self.actions_layout.addWidget(self.manually_submit) + self.cancel = QPushButton("Abort mission") + self.cancel.clicked.connect(self.close) + self.actions_layout.addWidget(self.cancel) + self.gridLayout.addWidget(self.actions, 2, 0) + + + self.actions2 = QGroupBox("Actions :") + self.actions2_layout = QHBoxLayout() + self.actions2.setLayout(self.actions2_layout) + self.manually_submit2 = QPushButton("Manually Submit [Advanced users]") + self.manually_submit2.clicked.connect(self.submit_manually) + self.actions2_layout.addWidget(self.manually_submit2) + self.cancel2 = QPushButton("Abort mission") + self.cancel2.clicked.connect(self.close) + self.actions2_layout.addWidget(self.cancel2) + self.proceed = QPushButton("Accept results") + self.proceed.setProperty("style", "btn-success") + self.proceed.clicked.connect(self.process_debriefing) + self.actions2_layout.addWidget(self.proceed) + + progress_bar.start() + self.layout.addLayout(self.gridLayout, 1, 0) self.setLayout(self.layout) def updateLayout(self, debriefing): updateBox = QGroupBox("Mission status") updateLayout = QGridLayout() updateBox.setLayout(updateLayout) + self.debriefing = debriefing updateLayout.addWidget(QLabel("Aircrafts destroyed"), 0, 0) updateLayout.addWidget(QLabel(str(len(debriefing.killed_aircrafts))), 0, 1) @@ -85,40 +127,72 @@ class QWaitingForMissionResultWindow(QDialog): updateLayout.addWidget(QLabel("Ground units destroyed"), 1, 0) updateLayout.addWidget(QLabel(str(len(debriefing.killed_ground_units))), 1, 1) - updateLayout.addWidget(QLabel("Weapons fired"), 2, 0) - updateLayout.addWidget(QLabel(str(len(debriefing.weapons_fired))), 2, 1) + #updateLayout.addWidget(QLabel("Weapons fired"), 2, 0) + #updateLayout.addWidget(QLabel(str(len(debriefing.weapons_fired))), 2, 1) - updateLayout.addWidget(QLabel("Base Capture Events"), 3, 0) - updateLayout.addWidget(QLabel(str(len(debriefing.base_capture_events))), 3, 1) + updateLayout.addWidget(QLabel("Base Capture Events"), 2, 0) + updateLayout.addWidget(QLabel(str(len(debriefing.base_capture_events))), 2, 1) # Clear previous content of the window for i in reversed(range(self.gridLayout.count())): - self.gridLayout.itemAt(i).widget().setParent(None) + try: + self.gridLayout.itemAt(i).widget().setParent(None) + except: + pass # Set new window content self.gridLayout.addWidget(updateBox, 0, 0) if not debriefing.mission_ended: self.gridLayout.addWidget(QLabel("Mission is being played"), 1, 0) + self.gridLayout.addWidget(self.actions, 2, 0) else: - #self.gridLayout.addWidget(QLabel("Mission is over !"), 1, 0) - proceed = QPushButton("Accept results") - proceed.setProperty("style", "btn-primary") - proceed.clicked.connect(lambda: self.process_debriefing(debriefing)) - self.gridLayout.addWidget(proceed, 1, 0) + self.gridLayout.addWidget(QLabel("Mission is over"), 1, 0) + self.gridLayout.addWidget(self.actions2, 2, 0) + def on_debriefing_udpate(self, debriefing): - print("On Debriefing update") - print(debriefing) - DebriefingFileWrittenSignal.get_instance().sendDebriefing(debriefing) - wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game) + try: + logging.info("On Debriefing update") + print(debriefing) + DebriefingFileWrittenSignal.get_instance().sendDebriefing(debriefing) + except Exception as e: + logging.error("Got an error while sending debriefing") + logging.error(e) + self.wait_thread = wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game) - def process_debriefing(self, debriefing: Debriefing): - self.game.finish_event(event=self.gameEvent, debriefing=debriefing) + def process_debriefing(self): + self.game.finish_event(event=self.gameEvent, debriefing=self.debriefing) self.game.pass_turn(ignored_cps=[self.gameEvent.to_cp, ]) - GameUpdateSignal.get_instance().sendDebriefing(self.game, self.gameEvent, debriefing) + GameUpdateSignal.get_instance().sendDebriefing(self.game, self.gameEvent, self.debriefing) self.close() def debriefing_directory_location(self) -> str: return os.path.join(base_path(), "liberation_debriefings") + + def closeEvent(self, evt): + super(QWaitingForMissionResultWindow, self).closeEvent(evt) + if self.wait_thread is not None: + self.wait_thread.stop() + + def submit_manually(self): + file = QFileDialog.getOpenFileName(self, "Select game file to open", filter="json(*.json)", dir=".") + print(file) + try: + with open(file[0], "r") as json_file: + json_data = json.load(json_file) + json_data["mission_ended"] = True + debriefing = Debriefing(json_data, self.game) + self.on_debriefing_udpate(debriefing) + except Exception as e: + logging.error(e) + msg = QMessageBox() + msg.setIcon(QMessageBox.Information) + msg.setText("Invalid file : " + file[0]) + msg.setWindowTitle("Invalid file.") + msg.setStandardButtons(QMessageBox.Ok) + msg.setWindowFlags(Qt.WindowStaysOnTopHint) + msg.exec_() + return + diff --git a/qt_ui/windows/basemenu/QBaseMenu.py b/qt_ui/windows/basemenu/QBaseMenu.py deleted file mode 100644 index b033a2d0..00000000 --- a/qt_ui/windows/basemenu/QBaseMenu.py +++ /dev/null @@ -1,246 +0,0 @@ -import traceback - -from PySide2.QtCore import Qt -from PySide2.QtGui import QCloseEvent -from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QDialog, QVBoxLayout, QGridLayout, QPushButton, \ - QGroupBox, QSizePolicy, QSpacerItem -from dcs.unittype import UnitType - -from game.event import UnitsDeliveryEvent, ControlPointType -from qt_ui.widgets.QBudgetBox import QBudgetBox -from qt_ui.widgets.base.QAirportInformation import QAirportInformation -from qt_ui.windows.basemenu.base_defenses.QBaseInformation import QBaseInformation -from qt_ui.windows.mission.QPlannedFlightsView import QPlannedFlightsView -from qt_ui.windows.GameUpdateSignal import GameUpdateSignal -from theater import ControlPoint, CAP, Embarking, CAS, PinpointStrike, db -from game import Game - - -class QBaseMenu(QDialog): - - def __init__(self, parent, controlPoint: ControlPoint, game: Game): - super(QBaseMenu, self).__init__(parent) - - self.cp = controlPoint - self.game = game - self.is_carrier = self.cp.cptype in [ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP] - - try: - self.airport = game.theater.terrain.airport_by_id(self.cp.id) - except: - self.airport = None - - if self.cp.captured: - self.deliveryEvent = None - for event in self.game.events: - print(event.__class__) - print(UnitsDeliveryEvent.__class__) - if event.__class__ == UnitsDeliveryEvent and event.from_cp == self.cp: - self.deliveryEvent = event - break - if not self.deliveryEvent: - print("Rebuild event") - self.deliveryEvent = self.game.units_delivery_event(self.cp) - - self.setWindowFlags(Qt.WindowStaysOnTopHint) - self.setMinimumSize(300, 200) - self.setModal(True) - self.initUi() - - def initUi(self): - - self.setWindowTitle(self.cp.name) - - self.topLayoutWidget = QWidget() - self.topLayout = QHBoxLayout() - - title = QLabel("" + self.cp.name + "") - title.setAlignment(Qt.AlignLeft | Qt.AlignTop) - title.setProperty("style", "base-title") - unitsPower = QLabel("{} / {} / Runway : {}".format(self.cp.base.total_planes, self.cp.base.total_armor, - "Available" if self.cp.has_runway() else "Unavailable")) - - self.topLayout.addWidget(title) - self.topLayout.addWidget(unitsPower) - self.topLayout.setAlignment(Qt.AlignTop) - self.topLayoutWidget.setProperty("style", "baseMenuHeader") - self.topLayoutWidget.setLayout(self.topLayout) - - if self.cp.captured: - units = { - CAP: db.find_unittype(CAP, self.game.player_name), - Embarking: db.find_unittype(Embarking, self.game.player_name), - CAS: db.find_unittype(CAS, self.game.player_name), - PinpointStrike: db.find_unittype(PinpointStrike, self.game.player_name), - } - else: - units = { - CAP: db.find_unittype(CAP, self.game.enemy_name), - Embarking: db.find_unittype(Embarking, self.game.enemy_name), - CAS: db.find_unittype(CAS, self.game.enemy_name), - PinpointStrike: db.find_unittype(PinpointStrike, self.game.enemy_name), - } - - self.mainLayout = QGridLayout() - self.leftLayout = QVBoxLayout() - self.unitLayout = QVBoxLayout() - self.bought_amount_labels = {} - self.existing_units_labels = {} - - row = 0 - - if self.cp.captured: - - self.recruitment = QGroupBox("Recruitment") - self.recruitmentLayout = QVBoxLayout() - self.budget = QBudgetBox() - self.budget.setBudget(self.game.budget, self.game.budget_reward_amount) - self.recruitmentLayout.addWidget(self.budget) - - for task_type in units.keys(): - - if task_type == PinpointStrike and self.is_carrier: - continue - - units_column = list(set(units[task_type])) - if len(units_column) == 0: continue - units_column.sort(key=lambda x: db.PRICES[x]) - - task_box = QGroupBox("{}".format(db.task_name(task_type))) - task_box_layout = QGridLayout() - task_box.setLayout(task_box_layout) - row = 0 - for unit_type in units_column: - if self.is_carrier and not unit_type in db.CARRIER_CAPABLE: - continue - row = self.add_purchase_row(unit_type, task_box_layout, row) - - stretch = QVBoxLayout() - stretch.addStretch() - task_box_layout.addLayout(stretch, row, 0) - - self.recruitmentLayout.addWidget(task_box) - self.recruitmentLayout.addStretch() - - self.recruitment.setLayout(self.recruitmentLayout) - self.leftLayout.addWidget(self.recruitment) - self.leftLayout.addStretch() - else: - intel = QGroupBox("Intel") - intelLayout = QVBoxLayout() - - for task_type in units.keys(): - units_column = list(set(units[task_type])) - - if sum([self.cp.base.total_units_of_type(u) for u in units_column]) > 0: - - group = QGroupBox(db.task_name(task_type)) - groupLayout = QGridLayout() - group.setLayout(groupLayout) - - row = 0 - for unit_type in units_column: - existing_units = self.cp.base.total_units_of_type(unit_type) - if existing_units == 0: - continue - groupLayout.addWidget(QLabel("" + db.unit_type_name(unit_type) + ""), row, 0) - groupLayout.addWidget(QLabel(str(existing_units)), row, 1) - row += 1 - - intelLayout.addWidget(group) - intelLayout.addStretch() - intel.setLayout(intelLayout) - self.leftLayout.addWidget(intel) - - self.mainLayout.addWidget(self.topLayoutWidget, 0, 0) - self.mainLayout.addLayout(self.leftLayout, 1, 0) - self.mainLayout.addWidget(QBaseInformation(self.cp, self.airport), 1, 1) - - self.rightLayout = QVBoxLayout() - try: - self.rightLayout.addWidget(QPlannedFlightsView(self.game.planners[self.cp.id])) - except Exception: - traceback.print_exc() - - if self.airport: - self.rightLayout.addWidget(QAirportInformation(self.cp, self.airport)) - self.mainLayout.addLayout(self.rightLayout, 1, 2) - - self.setLayout(self.mainLayout) - - def add_purchase_row(self, unit_type, layout, row): - - existing_units = self.cp.base.total_units_of_type(unit_type) - scheduled_units = self.deliveryEvent.units.get(unit_type, 0) - - unitName = QLabel("" + db.unit_type_name(unit_type) + "") - unitName.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) - - existing_units = QLabel(str(existing_units)) - existing_units.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - - amount_bought = QLabel("[{}]".format(str(scheduled_units))) - amount_bought.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - - self.existing_units_labels[unit_type] = existing_units - self.bought_amount_labels[unit_type] = amount_bought - - price = QLabel("{}m".format(db.PRICES[unit_type])) - price.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - - buy = QPushButton("+") - buy.setProperty("style", "btn-success") - buy.setMinimumSize(24, 24) - buy.clicked.connect(lambda: self.buy(unit_type)) - buy.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - - sell = QPushButton("-") - sell.setProperty("style", "btn-danger") - sell.setMinimumSize(24, 24) - sell.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - sell.clicked.connect(lambda: self.sell(unit_type)) - - layout.addWidget(unitName, row, 0) - layout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum), row, 1) - layout.addWidget(existing_units, row, 2) - layout.addWidget(amount_bought, row, 3) - layout.addWidget(price, row, 4) - layout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum), row, 5) - layout.addWidget(buy, row, 6) - layout.addWidget(sell, row, 7) - - return row + 1 - - def _update_count_label(self, unit_type: UnitType): - self.bought_amount_labels[unit_type].setText("[{}]".format( - unit_type in self.deliveryEvent.units and "{}".format(self.deliveryEvent.units[unit_type]) or "0" - )) - - self.existing_units_labels[unit_type].setText("{}".format( - self.cp.base.total_units_of_type(unit_type) - )) - - def buy(self, unit_type): - price = db.PRICES[unit_type] - if self.game.budget >= price: - self.deliveryEvent.deliver({unit_type: 1}) - self.game.budget -= price - self.budget.setBudget(self.game.budget, self.game.budget_reward_amount) - self._update_count_label(unit_type) - - def sell(self, unit_type): - if self.deliveryEvent.units.get(unit_type, 0) > 0: - price = db.PRICES[unit_type] - self.game.budget += price - self.deliveryEvent.units[unit_type] = self.deliveryEvent.units[unit_type] - 1 - if self.deliveryEvent.units[unit_type] == 0: - del self.deliveryEvent.units[unit_type] - elif self.cp.base.total_units_of_type(unit_type) > 0: - price = db.PRICES[unit_type] - self.game.budget += price - self.cp.base.commit_losses({unit_type: 1}) - - self._update_count_label(unit_type) - - def closeEvent(self, closeEvent:QCloseEvent): - GameUpdateSignal.get_instance().updateGame(self.game) \ No newline at end of file diff --git a/qt_ui/windows/basemenu/QBaseMenu2.py b/qt_ui/windows/basemenu/QBaseMenu2.py index 1c4ffcd6..d74a72b8 100644 --- a/qt_ui/windows/basemenu/QBaseMenu2.py +++ b/qt_ui/windows/basemenu/QBaseMenu2.py @@ -1,5 +1,5 @@ from PySide2.QtCore import Qt -from PySide2.QtGui import QCloseEvent +from PySide2.QtGui import QCloseEvent, QPixmap from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QDialog, QGridLayout from game import Game @@ -35,6 +35,8 @@ class QBaseMenu2(QDialog): self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setMinimumSize(300, 200) + self.setMinimumWidth(800) + self.setMaximumWidth(800) self.setModal(True) self.initUi() @@ -46,6 +48,11 @@ class QBaseMenu2(QDialog): self.topLayoutWidget = QWidget() self.topLayout = QHBoxLayout() + header = QLabel(self) + header.setGeometry(0, 0, 655, 106) + pixmap = QPixmap(self.get_base_image()) + header.setPixmap(pixmap) + title = QLabel("" + self.cp.name + "") title.setAlignment(Qt.AlignLeft | Qt.AlignTop) title.setProperty("style", "base-title") @@ -59,10 +66,19 @@ class QBaseMenu2(QDialog): self.topLayoutWidget.setLayout(self.topLayout) self.mainLayout = QGridLayout() - self.mainLayout.addWidget(self.topLayoutWidget, 0, 0) - self.mainLayout.addWidget(self.qbase_menu_tab, 1, 0) + self.mainLayout.addWidget(header, 0, 0) + self.mainLayout.addWidget(self.topLayoutWidget, 1, 0) + self.mainLayout.addWidget(self.qbase_menu_tab, 2, 0) self.setLayout(self.mainLayout) def closeEvent(self, closeEvent:QCloseEvent): - GameUpdateSignal.get_instance().updateGame(self.game) \ No newline at end of file + GameUpdateSignal.get_instance().updateGame(self.game) + + def get_base_image(self): + if self.cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP: + return "./resources/ui/carrier.png" + elif self.cp.cptype == ControlPointType.LHA_GROUP: + return "./resources/ui/lha.png" + else: + return "./resources/ui/airbase.png" \ No newline at end of file diff --git a/qt_ui/windows/basemenu/QRecruitBehaviour.py b/qt_ui/windows/basemenu/QRecruitBehaviour.py index 096caeff..86844e65 100644 --- a/qt_ui/windows/basemenu/QRecruitBehaviour.py +++ b/qt_ui/windows/basemenu/QRecruitBehaviour.py @@ -1,5 +1,5 @@ from PySide2.QtWidgets import QLabel, QPushButton, \ - QSizePolicy, QSpacerItem + QSizePolicy, QSpacerItem, QGroupBox, QHBoxLayout from dcs.unittype import UnitType from theater import db @@ -19,54 +19,75 @@ class QRecruitBehaviour: def add_purchase_row(self, unit_type, layout, row): + exist = QGroupBox() + exist.setProperty("style", "buy-box") + exist.setMaximumHeight(36) + exist.setMinimumHeight(36) + existLayout = QHBoxLayout() + exist.setLayout(existLayout) + existing_units = self.cp.base.total_units_of_type(unit_type) scheduled_units = self.deliveryEvent.units.get(unit_type, 0) - unitName = QLabel("" + db.unit_type_name(unit_type) + "") + unitName = QLabel("" + db.unit_type_name_2(unit_type) + "") unitName.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) existing_units = QLabel(str(existing_units)) existing_units.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - amount_bought = QLabel("[{}]".format(str(scheduled_units))) + amount_bought = QLabel("{}".format(str(scheduled_units))) amount_bought.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.existing_units_labels[unit_type] = existing_units self.bought_amount_labels[unit_type] = amount_bought - price = QLabel("{}m".format(db.PRICES[unit_type])) + price = QLabel("$ {:02d} m".format(db.PRICES[unit_type])) price.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) + buysell = QGroupBox() + buysell.setProperty("style", "buy-box") + buysell.setMaximumHeight(36) + buysell.setMinimumHeight(36) + buysellayout = QHBoxLayout() + buysell.setLayout(buysellayout) + buy = QPushButton("+") - buy.setProperty("style", "btn-success") - buy.setMinimumSize(24, 24) + buy.setProperty("style", "btn-buy") + buy.setMinimumSize(16, 16) + buy.setMaximumSize(16, 16) buy.clicked.connect(lambda: self.buy(unit_type)) buy.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) sell = QPushButton("-") - sell.setProperty("style", "btn-danger") - sell.setMinimumSize(24, 24) + sell.setProperty("style", "btn-sell") + sell.setMinimumSize(16, 16) + sell.setMaximumSize(16, 16) sell.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) sell.clicked.connect(lambda: self.sell(unit_type)) - layout.addWidget(unitName, row, 0) - layout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum), row, 1) - layout.addWidget(existing_units, row, 2) - layout.addWidget(amount_bought, row, 3) - layout.addWidget(price, row, 4) - layout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum), row, 5) - layout.addWidget(buy, row, 6) - layout.addWidget(sell, row, 7) + + existLayout.addWidget(unitName) + existLayout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum)) + existLayout.addWidget(existing_units) + existLayout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum)) + existLayout.addWidget(price) + + buysellayout.addWidget(sell) + buysellayout.addWidget(amount_bought) + buysellayout.addWidget(buy) + + layout.addWidget(exist, row, 1) + layout.addWidget(buysell, row, 2) return row + 1 def _update_count_label(self, unit_type: UnitType): - self.bought_amount_labels[unit_type].setText("[{}]".format( + self.bought_amount_labels[unit_type].setText("{}".format( unit_type in self.deliveryEvent.units and "{}".format(self.deliveryEvent.units[unit_type]) or "0" )) - self.existing_units_labels[unit_type].setText("{}".format( + self.existing_units_labels[unit_type].setText("{}".format( self.cp.base.total_units_of_type(unit_type) )) diff --git a/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py b/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py index c9245e84..2d4621d6 100644 --- a/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py +++ b/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py @@ -1,4 +1,5 @@ -from PySide2.QtWidgets import QVBoxLayout, QGridLayout, QGroupBox +from PySide2.QtCore import Qt +from PySide2.QtWidgets import QVBoxLayout, QGridLayout, QGroupBox, QScrollArea, QFrame, QWidget from game.event import UnitsDeliveryEvent from qt_ui.windows.basemenu.QRecruitBehaviour import QRecruitBehaviour @@ -6,10 +7,10 @@ from theater import ControlPoint, CAP, CAS, db from game import Game -class QAircraftRecruitmentMenu(QGroupBox, QRecruitBehaviour): +class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour): def __init__(self, cp:ControlPoint, game:Game): - QGroupBox.__init__(self, "Recruitment") + QFrame.__init__(self) self.cp = cp self.game = game @@ -25,13 +26,14 @@ class QAircraftRecruitmentMenu(QGroupBox, QRecruitBehaviour): self.init_ui() def init_ui(self): - layout = QVBoxLayout() + main_layout = QVBoxLayout() units = { CAP: db.find_unittype(CAP, self.game.player_name), CAS: db.find_unittype(CAS, self.game.player_name), } + scroll_content = QWidget() task_box_layout = QGridLayout() row = 0 @@ -49,6 +51,11 @@ class QAircraftRecruitmentMenu(QGroupBox, QRecruitBehaviour): stretch.addStretch() task_box_layout.addLayout(stretch, row, 0) - layout.addLayout(task_box_layout) - layout.addStretch() - self.setLayout(layout) + scroll_content.setLayout(task_box_layout) + scroll = QScrollArea() + scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) + scroll.setWidgetResizable(True) + scroll.setWidget(scroll_content) + main_layout.addWidget(scroll) + self.setLayout(main_layout) diff --git a/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py b/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py index 24e834d4..e260d64c 100644 --- a/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py +++ b/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py @@ -1,4 +1,5 @@ -from PySide2.QtWidgets import QVBoxLayout, QGridLayout, QGroupBox +from PySide2.QtCore import Qt +from PySide2.QtWidgets import QVBoxLayout, QGridLayout, QGroupBox, QFrame, QWidget, QScrollArea from game import Game from game.event import UnitsDeliveryEvent @@ -6,10 +7,10 @@ from qt_ui.windows.basemenu.QRecruitBehaviour import QRecruitBehaviour from theater import ControlPoint, PinpointStrike, db -class QArmorRecruitmentMenu(QGroupBox, QRecruitBehaviour): +class QArmorRecruitmentMenu(QFrame, QRecruitBehaviour): def __init__(self, cp:ControlPoint, game:Game): - QGroupBox.__init__(self, "Recruitment") + QFrame.__init__(self) self.cp = cp self.game = game @@ -25,13 +26,15 @@ class QArmorRecruitmentMenu(QGroupBox, QRecruitBehaviour): self.init_ui() def init_ui(self): - layout = QVBoxLayout() + main_layout = QVBoxLayout() units = { PinpointStrike: db.find_unittype(PinpointStrike, self.game.player_name), } + scroll_content = QWidget() task_box_layout = QGridLayout() + scroll_content.setLayout(task_box_layout) row = 0 for task_type in units.keys(): @@ -44,6 +47,11 @@ class QArmorRecruitmentMenu(QGroupBox, QRecruitBehaviour): stretch.addStretch() task_box_layout.addLayout(stretch, row, 0) - layout.addLayout(task_box_layout) - layout.addStretch() - self.setLayout(layout) + scroll_content.setLayout(task_box_layout) + scroll = QScrollArea() + scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) + scroll.setWidgetResizable(True) + scroll.setWidget(scroll_content) + main_layout.addWidget(scroll) + self.setLayout(main_layout) \ No newline at end of file diff --git a/qt_ui/windows/infos/QInfoPanel.py b/qt_ui/windows/infos/QInfoPanel.py index a7a81d56..6b31afa3 100644 --- a/qt_ui/windows/infos/QInfoPanel.py +++ b/qt_ui/windows/infos/QInfoPanel.py @@ -22,7 +22,7 @@ class QInfoPanel(QGroupBox): layout = QVBoxLayout() layout.addWidget(self.informations_list) layout.setSpacing(0) - layout.setContentsMargins(0, 0, 0, 0) + layout.setContentsMargins(0, 20, 0, 0) self.setLayout(layout) diff --git a/qt_ui/windows/mission/QMissionPlanning.py b/qt_ui/windows/mission/QMissionPlanning.py index 858df43a..431ce00b 100644 --- a/qt_ui/windows/mission/QMissionPlanning.py +++ b/qt_ui/windows/mission/QMissionPlanning.py @@ -16,7 +16,7 @@ class QMissionPlanning(QDialog): super(QMissionPlanning, self).__init__() self.game = game self.setWindowFlags(Qt.WindowStaysOnTopHint) - self.setMinimumSize(1000, 420) + self.setMinimumSize(1000, 440) self.setModal(True) self.setWindowTitle("Mission Preparation") self.setWindowIcon(EVENT_ICONS["strike"]) @@ -33,10 +33,12 @@ class QMissionPlanning(QDialog): self.select_airbase = QChooseAirbase(self.game) self.select_airbase.selected_airbase_changed.connect(self.on_departure_cp_changed) self.planned_flight_view = QPlannedFlightsView(None) + self.available_aircraft_at_selected_location = {} if self.captured_cp[0].id in self.game.planners.keys(): self.planner = self.game.planners[self.captured_cp[0].id] self.planned_flight_view.set_flight_planner(self.planner) self.selected_cp = self.captured_cp[0] + self.available_aircraft_at_selected_location = self.planner.get_available_aircraft() self.planned_flight_view.selectionModel().setCurrentIndex(self.planned_flight_view.indexAt(QPoint(1, 1)), QItemSelectionModel.Rows) self.planned_flight_view.selectionModel().selectionChanged.connect(self.on_flight_selection_change) @@ -51,12 +53,13 @@ class QMissionPlanning(QDialog): self.add_flight_button = QPushButton("Add Flight") self.add_flight_button.clicked.connect(self.on_add_flight) self.delete_flight_button = QPushButton("Delete Selected") + self.delete_flight_button.setProperty("style", "btn-danger") self.delete_flight_button.clicked.connect(self.on_delete_flight) self.button_layout = QHBoxLayout() self.button_layout.addStretch() - self.button_layout.addWidget(self.add_flight_button) self.button_layout.addWidget(self.delete_flight_button) + self.button_layout.addWidget(self.add_flight_button) self.mission_start_button = QPushButton("Take Off") self.mission_start_button.setProperty("style", "start-button") @@ -81,8 +84,10 @@ class QMissionPlanning(QDialog): if len(cps) == 1: self.selected_cp = cps[0] self.planner = self.game.planners[cps[0].id] + self.available_aircraft_at_selected_location = self.planner.get_available_aircraft() self.planned_flight_view.set_flight_planner(self.planner) else: + self.available_aircraft_at_selected_location = {} self.planned_flight_view.set_flight_planner(None) def on_flight_selection_change(self): diff --git a/qt_ui/windows/mission/flight/QFlightCreator.py b/qt_ui/windows/mission/flight/QFlightCreator.py index 2ee1c9d7..293ba75f 100644 --- a/qt_ui/windows/mission/flight/QFlightCreator.py +++ b/qt_ui/windows/mission/flight/QFlightCreator.py @@ -40,7 +40,8 @@ class QFlightCreator(QDialog): for aircraft_type in self.planner.get_available_aircraft().keys(): print(aircraft_type) print(aircraft_type.name) - self.select_type_aircraft.addItem(aircraft_type.id, userData=aircraft_type) + if self.available[aircraft_type] > 0: + self.select_type_aircraft.addItem(aircraft_type.id, userData=aircraft_type) self.select_type_aircraft.setCurrentIndex(0) self.select_flight_type = QComboBox() @@ -61,6 +62,11 @@ class QFlightCreator(QDialog): self.select_count_of_aircraft.setMaximum(4) self.select_count_of_aircraft.setValue(2) + aircraft_type = self.select_type_aircraft.currentData() + if aircraft_type is not None: + self.select_count_of_aircraft.setValue(min(self.available[aircraft_type], 2)) + self.select_count_of_aircraft.setMaximum(min(self.available[aircraft_type], 4)) + self.add_button = QPushButton("Add") self.add_button.clicked.connect(self.create_flight) diff --git a/qt_ui/windows/mission/flight/generator/QSTRIKEMissionGenerator.py b/qt_ui/windows/mission/flight/generator/QSTRIKEMissionGenerator.py index 1c07d735..6da88e0b 100644 --- a/qt_ui/windows/mission/flight/generator/QSTRIKEMissionGenerator.py +++ b/qt_ui/windows/mission/flight/generator/QSTRIKEMissionGenerator.py @@ -12,7 +12,7 @@ from qt_ui.windows.mission.flight.generator.QAbstractMissionGenerator import QAb class QSTRIKEMissionGenerator(QAbstractMissionGenerator): def __init__(self, game: Game, flight: Flight, flight_waypoint_list): - super(QSTRIKEMissionGenerator, self).__init__(game, flight, flight_waypoint_list, "SEAD/DEAD Generator") + super(QSTRIKEMissionGenerator, self).__init__(game, flight, flight_waypoint_list, "Strike Generator") self.tgt_selection_box = QStrikeTargetSelectionComboBox(self.game) self.tgt_selection_box.setMinimumWidth(200) @@ -33,7 +33,7 @@ class QSTRIKEMissionGenerator(QAbstractMissionGenerator): layout = QVBoxLayout() wpt_layout = QHBoxLayout() - wpt_layout.addWidget(QLabel("SEAD/DEAD target : ")) + wpt_layout.addWidget(QLabel("Target : ")) wpt_layout.addStretch() wpt_layout.addWidget(self.tgt_selection_box, alignment=Qt.AlignRight) diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py index bc740a34..8deefbc7 100644 --- a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py @@ -38,9 +38,13 @@ class QFlightWaypointList(QTableView): takeoff.description = "Take Off" takeoff.name = takeoff.pretty_name = "Take Off from " + self.flight.from_cp.name self.model.appendRow(QWaypointItem(takeoff, 0)) - self.model.setItem(0, 1, QStandardItem("0 ft AGL")) + item = QStandardItem("0 feet AGL") + item.setEditable(False) + self.model.setItem(0, 1, item) for i, point in enumerate(self.flight.points): self.model.insertRow(self.model.rowCount()) self.model.setItem(self.model.rowCount()-1, 0, QWaypointItem(point, i + 1)) - self.model.setItem(self.model.rowCount()-1, 1, QStandardItem(str(meter_to_feet(point.alt)) + " ft " + str(["AGL" if point.alt_type == "RADIO" else "MSL"][0]))) + item = QStandardItem(str(meter_to_feet(point.alt)) + " ft " + str(["AGL" if point.alt_type == "RADIO" else "MSL"][0])) + item.setEditable(False) + self.model.setItem(self.model.rowCount()-1, 1, item) self.selectionModel().setCurrentIndex(self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select) \ No newline at end of file diff --git a/qt_ui/windows/preferences/QLiberationPreferences.py b/qt_ui/windows/preferences/QLiberationPreferences.py index eba000fe..074c1c17 100644 --- a/qt_ui/windows/preferences/QLiberationPreferences.py +++ b/qt_ui/windows/preferences/QLiberationPreferences.py @@ -1,11 +1,16 @@ import os from PySide2 import QtWidgets +from PySide2.QtCore import QFile from PySide2.QtGui import Qt from PySide2.QtWidgets import QFrame, QLineEdit, QGridLayout, QVBoxLayout, QLabel, QPushButton, \ - QFileDialog, QMessageBox, QDialog + QFileDialog, QMessageBox, QDialog, QComboBox, QApplication +import qt_ui.uiconstants as CONST +import sys -from userdata import liberation_install +import userdata +from userdata import liberation_install, liberation_theme +from userdata.liberation_theme import get_theme_index, set_theme_index class QLiberationPreferences(QFrame): @@ -28,6 +33,8 @@ class QLiberationPreferences(QFrame): self.browse_saved_game.clicked.connect(self.on_browse_saved_games) self.browse_install_dir = QPushButton("Browse...") self.browse_install_dir.clicked.connect(self.on_browse_installation_dir) + self.themeSelect = QComboBox() + [self.themeSelect.addItem(y['themeName']) for x, y in CONST.THEMES.items()] self.initUi() @@ -40,6 +47,9 @@ class QLiberationPreferences(QFrame): layout.addWidget(QLabel("DCS installation directory:"), 2, 0, alignment=Qt.AlignLeft) layout.addWidget(self.edit_dcs_install_dir, 3, 0, alignment=Qt.AlignRight) layout.addWidget(self.browse_install_dir, 3, 1, alignment=Qt.AlignRight) + layout.addWidget(QLabel("Theme (Requires Restart)"), 4, 0) + layout.addWidget(self.themeSelect, 4, 1, alignment=Qt.AlignRight) + self.themeSelect.setCurrentIndex(get_theme_index()) main_layout.addLayout(layout) main_layout.addStretch() @@ -63,6 +73,7 @@ class QLiberationPreferences(QFrame): print("Applying changes") self.saved_game_dir = self.edit_saved_game_dir.text() self.dcs_install_dir = self.edit_dcs_install_dir.text() + set_theme_index(self.themeSelect.currentIndex()) if not os.path.isdir(self.saved_game_dir): error_dialog = QMessageBox.critical(self, "Wrong DCS Saved Games directory.", @@ -78,7 +89,8 @@ class QLiberationPreferences(QFrame): error_dialog.exec_() return False - if not os.path.isdir(os.path.join(self.dcs_install_dir, "Scripts")) and os.path.isfile(os.path.join(self.dcs_install_dir, "bin", "DCS.exe")): + if not os.path.isdir(os.path.join(self.dcs_install_dir, "Scripts")) and os.path.isfile( + os.path.join(self.dcs_install_dir, "bin", "DCS.exe")): error_dialog = QMessageBox.critical(self, "Wrong DCS installation directory.", self.dcs_install_dir + " is not a valid DCS installation directory", QMessageBox.StandardButton.Ok) @@ -87,7 +99,5 @@ class QLiberationPreferences(QFrame): liberation_install.setup(self.saved_game_dir, self.dcs_install_dir) liberation_install.save_config() + liberation_theme.save_theme_config() return True - - - diff --git a/qt_ui/windows/settings/QSettingsWindow.py b/qt_ui/windows/settings/QSettingsWindow.py index ea87fd2b..e6ba069a 100644 --- a/qt_ui/windows/settings/QSettingsWindow.py +++ b/qt_ui/windows/settings/QSettingsWindow.py @@ -166,13 +166,23 @@ class QSettingsWindow(QDialog): self.generate_marks.setChecked(self.game.settings.generate_marks) self.generate_marks.toggled.connect(self.applySettings) + + if not hasattr(self.game.settings, "include_jtac_if_available"): + self.game.settings.include_jtac_if_available = True + + self.include_jtac_if_available = QCheckBox() + self.include_jtac_if_available.setChecked(self.game.settings.include_jtac_if_available) + self.include_jtac_if_available.toggled.connect(self.applySettings) + self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0) self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight) self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0) self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight) + self.gameplayLayout.addWidget(QLabel("Include JTAC (If available)"), 2, 0) + self.gameplayLayout.addWidget(self.include_jtac_if_available, 2, 1, Qt.AlignRight) self.performance = QGroupBox("Performance") - self.performanceLayout = QGridLayout(); + self.performanceLayout = QGridLayout() self.performanceLayout.setAlignment(Qt.AlignTop) self.performance.setLayout(self.performanceLayout) @@ -200,6 +210,10 @@ class QSettingsWindow(QDialog): self.ai_parking_start.setChecked(self.game.settings.perf_ai_parking_start) self.ai_parking_start.toggled.connect(self.applySettings) + self.destroyed_units = QCheckBox() + self.destroyed_units.setChecked(self.game.settings.perf_destroyed_units) + self.destroyed_units.toggled.connect(self.applySettings) + self.culling = QCheckBox() self.culling.setChecked(self.game.settings.perf_culling) self.culling.toggled.connect(self.applySettings) @@ -222,12 +236,14 @@ class QSettingsWindow(QDialog): self.performanceLayout.addWidget(self.infantry, 4, 1, alignment=Qt.AlignRight) self.performanceLayout.addWidget(QLabel("AI planes parking start (AI starts in flight if disabled)"), 5, 0) self.performanceLayout.addWidget(self.ai_parking_start, 5, 1, alignment=Qt.AlignRight) + self.performanceLayout.addWidget(QLabel("Include destroyed units carcass"), 6, 0) + self.performanceLayout.addWidget(self.destroyed_units, 6, 1, alignment=Qt.AlignRight) - self.performanceLayout.addWidget(QHorizontalSeparationLine(), 6, 0, 1, 2) - self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 7, 0) - self.performanceLayout.addWidget(self.culling, 7, 1, alignment=Qt.AlignRight) - self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 8, 0) - self.performanceLayout.addWidget(self.culling_distance, 8, 1, alignment=Qt.AlignRight) + self.performanceLayout.addWidget(QHorizontalSeparationLine(), 7, 0, 1, 2) + self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 8, 0) + self.performanceLayout.addWidget(self.culling, 8, 1, alignment=Qt.AlignRight) + self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 9, 0) + self.performanceLayout.addWidget(self.culling_distance, 9, 1, alignment=Qt.AlignRight) self.generatorLayout.addWidget(self.gameplay) self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience.")) @@ -282,6 +298,7 @@ class QSettingsWindow(QDialog): self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData() self.game.settings.external_views_allowed = self.ext_views.isChecked() self.game.settings.generate_marks = self.generate_marks.isChecked() + self.game.settings.include_jtac_if_available = self.include_jtac_if_available.isChecked() print(self.game.settings.map_coalition_visibility) @@ -293,6 +310,7 @@ class QSettingsWindow(QDialog): self.game.settings.perf_moving_units = self.moving_units.isChecked() self.game.settings.perf_infantry = self.infantry.isChecked() self.game.settings.perf_ai_parking_start = self.ai_parking_start.isChecked() + self.game.settings.perf_destroyed_units = self.destroyed_units.isChecked() self.game.settings.perf_culling = self.culling.isChecked() self.game.settings.perf_culling_distance = int(self.culling_distance.value()) diff --git a/requirements.txt b/requirements.txt index bd681225..3346b044 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -pydcs>=0.9.4 +pydcs>=0.9.9 Pyside2>=5.13.0 pyinstaller==3.6 pyproj==2.6.1.post1 diff --git a/resources/caulandmap.p b/resources/caulandmap.p index a13651d1..a9fe3cbe 100644 Binary files a/resources/caulandmap.p and b/resources/caulandmap.p differ diff --git a/resources/caumap.gif b/resources/caumap.gif index 7c2d9ea2..53a4a774 100644 Binary files a/resources/caumap.gif and b/resources/caumap.gif differ diff --git a/resources/channellandmap.p b/resources/channellandmap.p index e91ad179..c0fe728e 100644 Binary files a/resources/channellandmap.p and b/resources/channellandmap.p differ diff --git a/resources/customized_payloads/A-20G.lua b/resources/customized_payloads/A-20G.lua new file mode 100644 index 00000000..f627bf4f --- /dev/null +++ b/resources/customized_payloads/A-20G.lua @@ -0,0 +1,72 @@ +local unitPayloads = { + ["name"] = "A-20G", + ["payloads"] = { + [1] = { + ["name"] = "ANTISHIP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{4xAN-M64_on_InvCountedAttachmentPoints}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [2] = { + ["name"] = "STRIKE", + ["pylons"] = { + [1] = { + ["CLSID"] = "{4xAN-M64_on_InvCountedAttachmentPoints}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [3] = { + ["name"] = "CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{4xAN-M64_on_InvCountedAttachmentPoints}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [4] = { + ["name"] = "CAP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{4xAN-M64_on_InvCountedAttachmentPoints}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [5] = { + ["name"] = "SEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{4xAN-M64_on_InvCountedAttachmentPoints}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + }, + ["tasks"] = { + [1] = 32, + [2] = 30, + [3] = 17, + }, + ["unitType"] = "A-20G", +} +return unitPayloads diff --git a/resources/customized_payloads/A-4E-C.lua b/resources/customized_payloads/A-4E-C.lua new file mode 100644 index 00000000..d1cdcf0c --- /dev/null +++ b/resources/customized_payloads/A-4E-C.lua @@ -0,0 +1,141 @@ +local unitPayloads = { + ["name"] = "A-4E-C", + ["payloads"] = { + [1] = { + ["name"] = "CAP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{GAR-8}", + ["num"] = 4, + }, + [2] = { + ["CLSID"] = "{GAR-8}", + ["num"] = 2, + }, + [3] = { + ["CLSID"] = "{DFT-150gal}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [2] = { + ["name"] = "CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{F3EFE0AB-E91A-42D8-9CA2-B63C91ED570A}", + ["num"] = 5, + }, + [2] = { + ["CLSID"] = "{F3EFE0AB-E91A-42D8-9CA2-B63C91ED570A}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{DFT-150gal}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [3] = { + ["name"] = "STRIKE", + ["pylons"] = { + [1] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 5, + }, + [2] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [4] = { + ["name"] = "SEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 4, + }, + [2] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 5, + }, + [3] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 1, + }, + [5] = { + ["CLSID"] = "{DFT-150gal}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [5] = { + ["name"] = "ANTISHIP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 5, + }, + [2] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 4, + }, + [3] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{AGM_45A}", + ["num"] = 1, + }, + [5] = { + ["CLSID"] = "{DFT-150gal}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + }, + ["tasks"] = { + }, + ["unitType"] = "A-4E-C", +} +return unitPayloads diff --git a/resources/customized_payloads/AV8BNA.lua b/resources/customized_payloads/AV8BNA.lua index 3015c576..d2ba669a 100644 --- a/resources/customized_payloads/AV8BNA.lua +++ b/resources/customized_payloads/AV8BNA.lua @@ -2,46 +2,6 @@ local unitPayloads = { ["name"] = "AV8BNA", ["payloads"] = { [1] = { - ["name"] = "Anti Armor", - ["pylons"] = { - [1] = { - ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", - ["num"] = 8, - }, - [2] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 7, - }, - [3] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 6, - }, - [4] = { - ["CLSID"] = "{GAU_12_Equalizer}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 3, - }, - [6] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 2, - }, - [7] = { - ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", - ["num"] = 1, - }, - [8] = { - ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}", - ["num"] = 5, - }, - }, - ["tasks"] = { - [1] = 33, - }, - }, - [2] = { ["name"] = "CAP", ["pylons"] = { [1] = { @@ -61,18 +21,15 @@ local unitPayloads = { ["num"] = 7, }, [5] = { - ["CLSID"] = "{ALQ_164_RF_Jammer}", - ["num"] = 5, - }, - [6] = { ["CLSID"] = "{GAU_12_Equalizer}", ["num"] = 4, }, }, ["tasks"] = { + [1] = 31, }, }, - [3] = { + [2] = { ["name"] = "CAS", ["pylons"] = { [1] = { @@ -80,79 +37,51 @@ local unitPayloads = { ["num"] = 8, }, [2] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 7, - }, - [3] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 6, - }, - [4] = { - ["CLSID"] = "{GAU_12_Equalizer}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 3, - }, - [6] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 2, - }, - [7] = { ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 1, }, - [8] = { + [3] = { + ["CLSID"] = "LAU_117_AGM_65G", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "LAU_117_AGM_65G", + ["num"] = 7, + }, + [5] = { + ["CLSID"] = "{GAU_12_Equalizer}", + ["num"] = 4, + }, + [6] = { ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}", ["num"] = 5, }, }, ["tasks"] = { - [1] = 33, + [1] = 31, }, }, - [4] = { + [3] = { ["name"] = "STRIKE", ["pylons"] = { [1] = { - ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", - ["num"] = 8, + ["CLSID"] = "{BRU-42_2*GBU-38_LEFT}", + ["num"] = 2, }, [2] = { - ["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}", + ["CLSID"] = "{BRU-42_2*GBU-38_RIGHT}", ["num"] = 7, }, [3] = { - ["CLSID"] = "{BRU-42_2*Mk-83_RIGHT}", - ["num"] = 6, - }, - [4] = { - ["CLSID"] = "{ALQ_164_RF_Jammer}", + ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}", ["num"] = 5, }, - [5] = { - ["CLSID"] = "{BRU-42_2*Mk-83_LEFT}", - ["num"] = 3, - }, - [6] = { - ["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}", - ["num"] = 2, - }, - [7] = { - ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", - ["num"] = 1, - }, - [8] = { - ["CLSID"] = "{GAU_12_Equalizer}", - ["num"] = 4, - }, }, ["tasks"] = { - [1] = 32, + [1] = 31, }, }, - [5] = { + [4] = { ["name"] = "ANTISHIP", ["pylons"] = { [1] = { @@ -160,36 +89,52 @@ local unitPayloads = { ["num"] = 8, }, [2] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 7, - }, - [3] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 6, - }, - [4] = { - ["CLSID"] = "{GAU_12_Equalizer}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 3, - }, - [6] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 2, - }, - [7] = { ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 1, }, - [8] = { + [3] = { + ["CLSID"] = "LAU_117_AGM_65G", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "LAU_117_AGM_65G", + ["num"] = 7, + }, + [5] = { ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}", ["num"] = 5, }, }, ["tasks"] = { - [1] = 33, + [1] = 31, + }, + }, + [5] = { + ["name"] = "INTERCEPT", + ["pylons"] = { + [1] = { + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", + ["num"] = 8, + }, + [2] = { + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{AIM-9M-ON-ADAPTER}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{AIM-9M-ON-ADAPTER}", + ["num"] = 7, + }, + [5] = { + ["CLSID"] = "{GAU_12_Equalizer}", + ["num"] = 4, + }, + }, + ["tasks"] = { + [1] = 31, }, }, [6] = { @@ -212,23 +157,20 @@ local unitPayloads = { ["num"] = 7, }, [5] = { - ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}", + ["CLSID"] = "{ALQ_164_RF_Jammer}", ["num"] = 5, }, [6] = { - ["CLSID"] = "{GAU_12_Equalizer}", - ["num"] = 4, + ["CLSID"] = "LAU_117_AGM_65G", + ["num"] = 6, }, [7] = { ["CLSID"] = "LAU_117_AGM_65G", ["num"] = 3, }, - [8] = { - ["CLSID"] = "LAU_117_AGM_65G", - ["num"] = 6, - }, }, ["tasks"] = { + [1] = 31, }, }, }, diff --git a/resources/customized_payloads/F-15C.lua b/resources/customized_payloads/F-15C.lua index f66928dd..3362ccf5 100644 --- a/resources/customized_payloads/F-15C.lua +++ b/resources/customized_payloads/F-15C.lua @@ -2,10 +2,10 @@ local unitPayloads = { ["name"] = "F-15C", ["payloads"] = { [1] = { - ["name"] = "CAP", + ["name"] = "CAS", ["pylons"] = { [1] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 1, }, [2] = { @@ -17,11 +17,11 @@ local unitPayloads = { ["num"] = 3, }, [4] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 4, }, [5] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 5, }, [6] = { @@ -29,11 +29,11 @@ local unitPayloads = { ["num"] = 6, }, [7] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 7, }, [8] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 8, }, [9] = { @@ -45,7 +45,7 @@ local unitPayloads = { ["num"] = 10, }, [11] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 11, }, }, @@ -56,10 +56,10 @@ local unitPayloads = { }, }, [2] = { - ["name"] = "CAS", + ["name"] = "STRIKE", ["pylons"] = { [1] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 1, }, [2] = { @@ -71,11 +71,11 @@ local unitPayloads = { ["num"] = 3, }, [4] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 4, }, [5] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 5, }, [6] = { @@ -83,11 +83,11 @@ local unitPayloads = { ["num"] = 6, }, [7] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 7, }, [8] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 8, }, [9] = { @@ -99,7 +99,7 @@ local unitPayloads = { ["num"] = 10, }, [11] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 11, }, }, @@ -110,10 +110,10 @@ local unitPayloads = { }, }, [3] = { - ["name"] = "STRIKE", + ["name"] = "CAP", ["pylons"] = { [1] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 1, }, [2] = { @@ -125,11 +125,11 @@ local unitPayloads = { ["num"] = 3, }, [4] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 4, }, [5] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 5, }, [6] = { @@ -137,11 +137,11 @@ local unitPayloads = { ["num"] = 6, }, [7] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 7, }, [8] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 8, }, [9] = { @@ -153,7 +153,7 @@ local unitPayloads = { ["num"] = 10, }, [11] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 11, }, }, @@ -167,7 +167,7 @@ local unitPayloads = { ["name"] = "ANTISHIP", ["pylons"] = { [1] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 1, }, [2] = { @@ -179,11 +179,11 @@ local unitPayloads = { ["num"] = 3, }, [4] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 4, }, [5] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 5, }, [6] = { @@ -191,11 +191,11 @@ local unitPayloads = { ["num"] = 6, }, [7] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 7, }, [8] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 8, }, [9] = { @@ -207,7 +207,7 @@ local unitPayloads = { ["num"] = 10, }, [11] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 11, }, }, @@ -221,7 +221,7 @@ local unitPayloads = { ["name"] = "SEAD", ["pylons"] = { [1] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 1, }, [2] = { @@ -233,11 +233,11 @@ local unitPayloads = { ["num"] = 3, }, [4] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 4, }, [5] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 5, }, [6] = { @@ -245,11 +245,11 @@ local unitPayloads = { ["num"] = 6, }, [7] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 7, }, [8] = { - ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", ["num"] = 8, }, [9] = { @@ -261,7 +261,7 @@ local unitPayloads = { ["num"] = 10, }, [11] = { - ["CLSID"] = "{AIM-9P5}", + ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["num"] = 11, }, }, diff --git a/resources/customized_payloads/FW-190A8.lua b/resources/customized_payloads/FW-190A8.lua index cf9b0bce..765a7491 100644 --- a/resources/customized_payloads/FW-190A8.lua +++ b/resources/customized_payloads/FW-190A8.lua @@ -34,10 +34,10 @@ local unitPayloads = { }, }, [3] = { - ["name"] = "ANTISHIP", + ["name"] = "CAP", ["pylons"] = { [1] = { - ["CLSID"] = "{SD_500_A}", + ["CLSID"] = "", ["num"] = 1, }, }, @@ -46,8 +46,20 @@ local unitPayloads = { }, }, [4] = { - ["name"] = "CAP", + ["name"] = "ANTISHIP", ["pylons"] = { + [1] = { + ["CLSID"] = "{SD_500_A}", + ["num"] = 1, + }, + [2] = { + ["CLSID"] = "{WGr21}", + ["num"] = 2, + }, + [3] = { + ["CLSID"] = "{WGr21}", + ["num"] = 3, + }, }, ["tasks"] = { [1] = 31, diff --git a/resources/customized_payloads/MB-339PAN.lua b/resources/customized_payloads/MB-339PAN.lua new file mode 100644 index 00000000..c3d04b5f --- /dev/null +++ b/resources/customized_payloads/MB-339PAN.lua @@ -0,0 +1,164 @@ +local unitPayloads = { + ["name"] = "MB-339PAN", + ["payloads"] = { + [1] = { + ["name"] = "CAP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{MB339-DEFA553_R}", + ["num"] = 7, + }, + [2] = { + ["CLSID"] = "{MB339-DEFA553_L}", + ["num"] = 4, + }, + [3] = { + ["CLSID"] = "{FUEL-TIP-ELLITTIC-L}", + ["num"] = 1, + }, + [4] = { + ["CLSID"] = "{FUEL-TIP-ELLITTIC-R}", + ["num"] = 10, + }, + }, + ["tasks"] = { + }, + }, + [2] = { + ["name"] = "CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-R}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-L}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{LAU-10}", + ["num"] = 3, + }, + [4] = { + ["CLSID"] = "{LAU-10}", + ["num"] = 8, + }, + [5] = { + ["CLSID"] = "{MB339-DEFA553_L}", + ["num"] = 4, + }, + [6] = { + ["CLSID"] = "{MB339-DEFA553_R}", + ["num"] = 7, + }, + }, + ["tasks"] = { + }, + }, + [3] = { + ["name"] = "ANTISHIP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-R}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-L}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{LAU-10}", + ["num"] = 3, + }, + [4] = { + ["CLSID"] = "{LAU-10}", + ["num"] = 8, + }, + [5] = { + ["CLSID"] = "{MB339-DEFA553_L}", + ["num"] = 4, + }, + [6] = { + ["CLSID"] = "{MB339-DEFA553_R}", + ["num"] = 7, + }, + }, + ["tasks"] = { + }, + }, + [4] = { + ["name"] = "STRIKE", + ["pylons"] = { + [1] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-R}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-L}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 3, + }, + [4] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 8, + }, + [5] = { + ["CLSID"] = "{MB339-AN-M3_L}", + ["num"] = 4, + }, + [6] = { + ["CLSID"] = "{MB339-AN-M3_R}", + ["num"] = 7, + }, + [7] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 9, + }, + [8] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 2, + }, + }, + ["tasks"] = { + }, + }, + [5] = { + ["name"] = "SEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-R}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{FUEL-TIP-TANK-500-L}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{LAU-10}", + ["num"] = 3, + }, + [4] = { + ["CLSID"] = "{LAU-10}", + ["num"] = 8, + }, + [5] = { + ["CLSID"] = "{MB339-AN-M3_L}", + ["num"] = 4, + }, + [6] = { + ["CLSID"] = "{MB339-AN-M3_R}", + ["num"] = 7, + }, + }, + ["tasks"] = { + }, + }, + }, + ["tasks"] = { + }, + ["unitType"] = "MB-339PAN", +} +return unitPayloads diff --git a/resources/customized_payloads/OH-58D.lua b/resources/customized_payloads/OH-58D.lua new file mode 100644 index 00000000..abcf1359 --- /dev/null +++ b/resources/customized_payloads/OH-58D.lua @@ -0,0 +1,87 @@ +local unitPayloads = { + ["name"] = "OH-58D", + ["payloads"] = { + [1] = { + ["name"] = "CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "oh-58-brauning", + ["num"] = 1, + }, + [2] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 16, + }, + }, + [2] = { + ["name"] = "STRIKE", + ["pylons"] = { + [1] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 1, + }, + [2] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 16, + }, + }, + [3] = { + ["name"] = "CAP", + ["pylons"] = { + [1] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 1, + }, + [2] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 16, + }, + }, + [4] = { + ["name"] = "ANTISHIP", + ["pylons"] = { + [1] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 1, + }, + [2] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 16, + }, + }, + [5] = { + ["name"] = "SEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 1, + }, + [2] = { + ["CLSID"] = "AGM114x2_OH_58", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 16, + }, + }, + }, + ["unitType"] = "OH-58D", +} +return unitPayloads diff --git a/resources/customized_payloads/Rafale_A_S.lua b/resources/customized_payloads/Rafale_A_S.lua new file mode 100644 index 00000000..40c61645 --- /dev/null +++ b/resources/customized_payloads/Rafale_A_S.lua @@ -0,0 +1,225 @@ +local unitPayloads = { + ["name"] = "Rafale_A_S", + ["payloads"] = { + [1] = { + ["name"] = "CAP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [4] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 4, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [2] = { + ["name"] = "CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [4] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{AS_30L}", + ["num"] = 9, + }, + [6] = { + ["CLSID"] = "{AS_30L}", + ["num"] = 8, + }, + [7] = { + ["CLSID"] = "{AS_30L}", + ["num"] = 3, + }, + [8] = { + ["CLSID"] = "{AS_30L}", + ["num"] = 2, + }, + [9] = { + ["CLSID"] = "{DAMOCLES}", + ["num"] = 7, + }, + [10] = { + ["CLSID"] = "{PTB-1500}", + ["num"] = 5, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [3] = { + ["name"] = "ANTISHIP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [4] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 9, + }, + [6] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 8, + }, + [7] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 3, + }, + [8] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 2, + }, + [9] = { + ["CLSID"] = "{Thales_RBE2}", + ["num"] = 7, + }, + [10] = { + ["CLSID"] = "{Exocet}", + ["num"] = 5, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [4] = { + ["name"] = "SEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [4] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 9, + }, + [6] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 8, + }, + [7] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 3, + }, + [8] = { + ["CLSID"] = "{B06DD79A-F21E-4EB9-BD9D-AB3844618C93}", + ["num"] = 2, + }, + [9] = { + ["CLSID"] = "{DAMOCLES}", + ["num"] = 7, + }, + [10] = { + ["CLSID"] = "{PTB-1500}", + ["num"] = 5, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [5] = { + ["name"] = "STRIKE", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [4] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{SCALP}", + ["num"] = 9, + }, + [6] = { + ["CLSID"] = "{SCALP}", + ["num"] = 8, + }, + [7] = { + ["CLSID"] = "{SCALP}", + ["num"] = 3, + }, + [8] = { + ["CLSID"] = "{SCALP}", + ["num"] = 2, + }, + [9] = { + ["CLSID"] = "{DAMOCLES}", + ["num"] = 7, + }, + [10] = { + ["CLSID"] = "{PTB-1500}", + ["num"] = 5, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + }, + ["tasks"] = { + }, + ["unitType"] = "Rafale_A_S", +} +return unitPayloads diff --git a/resources/customized_payloads/Rafale_M.lua b/resources/customized_payloads/Rafale_M.lua new file mode 100644 index 00000000..ca564585 --- /dev/null +++ b/resources/customized_payloads/Rafale_M.lua @@ -0,0 +1,209 @@ +local unitPayloads = { + ["name"] = "Rafale_M", + ["payloads"] = { + [1] = { + ["name"] = "CAP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "LAU-115_2*LAU-127_AIM-120C", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "LAU-115_2*LAU-127_AIM-120C", + ["num"] = 9, + }, + [5] = { + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", + ["num"] = 8, + }, + [6] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [7] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 5, + }, + [8] = { + ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [2] = { + ["name"] = "CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "LAU3_HE5", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "LAU3_HE5", + ["num"] = 9, + }, + [5] = { + ["CLSID"] = "LAU3_WP156", + ["num"] = 8, + }, + [6] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [7] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 5, + }, + [8] = { + ["CLSID"] = "LAU3_WP156", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [3] = { + ["name"] = "STRIKE", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", + ["num"] = 9, + }, + [5] = { + ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", + ["num"] = 8, + }, + [6] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [7] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 5, + }, + [8] = { + ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [4] = { + ["name"] = "SEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{D5D51E24-348C-4702-96AF-97A714E72697}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{D5D51E24-348C-4702-96AF-97A714E72697}", + ["num"] = 9, + }, + [5] = { + ["CLSID"] = "{D5D51E24-348C-4702-96AF-97A714E72697}", + ["num"] = 8, + }, + [6] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [7] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 5, + }, + [8] = { + ["CLSID"] = "{D5D51E24-348C-4702-96AF-97A714E72697}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + [5] = { + ["name"] = "ANTISHIP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 10, + }, + [2] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{18617C93-78E7-4359-A8CE-D754103EDF63}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{18617C93-78E7-4359-A8CE-D754103EDF63}", + ["num"] = 9, + }, + [5] = { + ["CLSID"] = "{18617C93-78E7-4359-A8CE-D754103EDF63}", + ["num"] = 8, + }, + [6] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 6, + }, + [7] = { + ["CLSID"] = "{0DA03783-61E4-40B2-8FAE-6AEE0A5C5AAE}", + ["num"] = 5, + }, + [8] = { + ["CLSID"] = "{18617C93-78E7-4359-A8CE-D754103EDF63}", + ["num"] = 3, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + }, + ["tasks"] = { + }, + ["unitType"] = "Rafale_M", +} +return unitPayloads diff --git a/resources/gulflandmap.p b/resources/gulflandmap.p index 539db733..e0447fbd 100644 Binary files a/resources/gulflandmap.p and b/resources/gulflandmap.p differ diff --git a/resources/nevada.gif b/resources/nevada.gif index d57b199e..e2cf1136 100644 Binary files a/resources/nevada.gif and b/resources/nevada.gif differ diff --git a/resources/nevlandmap.p b/resources/nevlandmap.p index 5ac9c213..111c24d4 100644 Binary files a/resources/nevlandmap.p and b/resources/nevlandmap.p differ diff --git a/resources/normandy.gif b/resources/normandy.gif index b170b795..39b9e6a0 100644 Binary files a/resources/normandy.gif and b/resources/normandy.gif differ diff --git a/resources/normandylandmap.p b/resources/normandylandmap.p index e7858cde..0f41f8ea 100644 Binary files a/resources/normandylandmap.p and b/resources/normandylandmap.p differ diff --git a/resources/persiangulf.gif b/resources/persiangulf.gif index c7940924..0bf94807 100644 Binary files a/resources/persiangulf.gif and b/resources/persiangulf.gif differ diff --git a/resources/scripts/JTACAutoLase.lua b/resources/scripts/JTACAutoLase.lua new file mode 100644 index 00000000..f0af3ecb --- /dev/null +++ b/resources/scripts/JTACAutoLase.lua @@ -0,0 +1,729 @@ +--[[ +JTAC Automatic Targeting and Laser Script + +Allows a JTAC to mark and hold an IR and Laser point on a target allowing TGP's to lock onto the lase and ease +of target location using NV Goggles + +The JTAC will automatically switch targets when a target is destroyed or goes out of Line of Sight + +NOTE: LOS doesn't include buildings or tree's... Sorry! + +The script can also be useful in daylight by enabling the JTAC to mark enemy positions with Smoke. +The JTAC will only move the smoke to the target every 5 minutes (to stop a huge trail of smoke markers) unless the target +is destroyed, in which case the new target will be marked straight away with smoke. + +You can also enable an F10 menu option for coalition units allowing the JTAC(s) to report their current status. + +If a JTAC is down it won't report in. + +USAGE: + +Place JTAC units on the map with the mission editor putting each JTAC in it's own group containing only itself and no +other units. Name the group something easy to remember e.g. JTAC1 and make sure the JTAC units have a unique name which must +not be the same as the group name. The editor should do this for you but be careful if you copy and paste. + +Load the script at the start of the mission with a Trigger Once or as the init script of the mission + +Run the code below as a DO SCRIPT at the start of the mission, or after a delay if you prefer + +JTACAutoLase('JTAC1', 1688) + +OR + +JTACAutoLase('JTAC1', 1688, false,"all") - means no smoke marks for this jtac and it will target all ground troops + +OR + +JTACAutoLase('JTAC1', 1688, true,"vehicle") - means smoke marks for this jtac and it will target ONLY ground vehicles + +OR + +JTACAutoLase('JTAC1', 1688, true,"troop") - means smoke marks for this jtac and it will target ONLY ground troops + +OR + +JTACAutoLase('JTAC1', 1688, true,"all", 4) - means BLUE smoke marks for this jtac and it will target all ground troops + +Where JTAC1 is the Group name of the JTAC Group with one and only one JTAC unit. + +The script doesn't care if the unit isn't activated when run, as it'll automatically activate when the JTAC is activated in +the mission but there can be a delay of up to 30 seconds after activation for the JTAC to start searching for targets. + +You can also run the code at any time if a JTAC is dynamically added to the map as long as you know the Group name of the JTAC. + +Last Edit: 21/04/2015 + +Change log: + Added new config of JTAC smoke colour globally or per JTAC + Added new config of JTAC targetting to either target only troops or vehicles or all + Added new induvidual config of JTAC smoke and location which will override global setting + Added Lat / Lon + MGRS to JTAC Target position + Changed Lasing method to update laser marker rather than create and destroy + - This gives much better tracking behaviour! + Fixed JTAC lasing through terrain. + Fixed Lase staying on when JTAC Dies + Fixed Lase staying on when target dies and there are no other targets + Added Radio noise when message is shown + Stop multiple JTACS targeting the same target + + +Parts of MIST used. Source is https://github.com/mrSkortch/MissionScriptingTools/blob/master/mist.lua + +]] + +-- CONFIG +JTAC_maxDistance = 50000 -- How far a JTAC can "see" in meters (with LOS) + +JTAC_smokeOn = true -- enables marking of target with smoke, can be overriden by the JTACAutoLase in editor + +JTAC_smokeColour = 1 -- Green = 0 , Red = 1, White = 2, Orange = 3, Blue = 4 + +JTAC_jtacStatusF10 = true -- enables F10 JTAC Status menu + +JTAC_location = true -- shows location in JTAC message, can be overriden by the JTACAutoLase in editor + +JTAC_lock = "all" -- "vehicle" OR "troop" OR "all" forces JTAC to only lock vehicles or troops or all ground units + +-- END CONFIG + +-- BE CAREFUL MODIFYING BELOW HERE + +GLOBAL_JTAC_LASE = {} +GLOBAL_JTAC_IR = {} +GLOBAL_JTAC_SMOKE = {} +GLOBAL_JTAC_UNITS = {} -- list of JTAC units for f10 command +GLOBAL_JTAC_CURRENT_TARGETS = {} +GLOBAL_JTAC_RADIO_ADDED = {} --keeps track of who's had the radio command added +GLOBAL_JTAC_LASER_CODES = {} -- keeps track of laser codes for jtac + + +function JTACAutoLase(jtacGroupName, laserCode,smoke,lock,colour) + + if smoke == nil then + + smoke = JTAC_smokeOn + end + + if lock == nil then + + lock = JTAC_lock + end + + if colour == nil then + colour = JTAC_smokeColour + end + + GLOBAL_JTAC_LASER_CODES[jtacGroupName] = laserCode + + local jtacGroup = getGroup(jtacGroupName) + local jtacUnit + + if jtacGroup == nil or #jtacGroup == 0 then + + notify("JTAC Group " .. jtacGroupName .. " KIA!", 10) + + --remove from list + GLOBAL_JTAC_UNITS[jtacGroupName] = nil + + cleanupJTAC(jtacGroupName) + + return + else + + jtacUnit = jtacGroup[1] + --add to list + GLOBAL_JTAC_UNITS[jtacGroupName] = jtacUnit:getName() + + + end + + + -- search for current unit + + if jtacUnit:isActive() == false then + + cleanupJTAC(jtacGroupName) + + env.info(jtacGroupName .. ' Not Active - Waiting 30 seconds') + timer.scheduleFunction(timerJTACAutoLase, { jtacGroupName, laserCode,smoke,lock,colour}, timer.getTime() + 30) + + return + end + + local enemyUnit = getCurrentUnit(jtacUnit, jtacGroupName) + + if enemyUnit == nil and GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] ~= nil then + + local tempUnitInfo = GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] + + -- env.info("TEMP UNIT INFO: " .. tempUnitInfo.name .. " " .. tempUnitInfo.unitType) + + local tempUnit = Unit.getByName(tempUnitInfo.name) + + if tempUnit ~= nil and tempUnit:getLife() > 0 and tempUnit:isActive() == true then + notify(jtacGroupName .. " target " .. tempUnitInfo.unitType .. " lost. Scanning for Targets. ", 10) + else + notify(jtacGroupName .. " target " .. tempUnitInfo.unitType .. " KIA. Good Job! Scanning for Targets. ", 10) + end + + --remove from smoke list + GLOBAL_JTAC_SMOKE[tempUnitInfo.name] = nil + + -- remove from target list + GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] = nil + + --stop lasing + cancelLase(jtacGroupName) + + end + + + if enemyUnit == nil then + enemyUnit = findNearestVisibleEnemy(jtacUnit,lock) + + if enemyUnit ~= nil then + + -- store current target for easy lookup + GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] = { name = enemyUnit:getName(), unitType = enemyUnit:getTypeName(), unitId = enemyUnit:getID() } + + notify(jtacGroupName .. " lasing new target " .. enemyUnit:getTypeName() .. '. CODE: ' .. laserCode ..getPositionString(enemyUnit) , 10) + + -- create smoke + if smoke == true then + + --create first smoke + createSmokeMarker(enemyUnit,colour) + end + end + end + + if enemyUnit ~= nil then + + laseUnit(enemyUnit, jtacUnit, jtacGroupName, laserCode) + + -- env.info('Timer timerSparkleLase '..jtacGroupName.." "..laserCode.." "..enemyUnit:getName()) + timer.scheduleFunction(timerJTACAutoLase, { jtacGroupName, laserCode, smoke,lock,colour }, timer.getTime() + 1) + + + if smoke == true then + local nextSmokeTime = GLOBAL_JTAC_SMOKE[enemyUnit:getName()] + + --recreate smoke marker after 5 mins + if nextSmokeTime ~= nil and nextSmokeTime < timer.getTime() then + + createSmokeMarker(enemyUnit, colour) + end + end + + else + -- env.info('LASE: No Enemies Nearby') + + -- stop lazing the old spot + cancelLase(jtacGroupName) + -- env.info('Timer Slow timerSparkleLase '..jtacGroupName.." "..laserCode.." "..enemyUnit:getName()) + + timer.scheduleFunction(timerJTACAutoLase, { jtacGroupName, laserCode, smoke,lock,colour }, timer.getTime() + 5) + end +end + + +-- used by the timer function +function timerJTACAutoLase(args) + + JTACAutoLase(args[1], args[2], args[3],args[4]) +end + +function cleanupJTAC(jtacGroupName) + -- clear laser - just in case + cancelLase(jtacGroupName) + + -- Cleanup + GLOBAL_JTAC_UNITS[jtacGroupName] = nil + + GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] = nil +end + + +function notify(message, displayFor) + + + trigger.action.outTextForCoalition(coalition.side.BLUE, message, displayFor) + trigger.action.outSoundForCoalition(coalition.side.BLUE, "radiobeep.ogg") +end + +function createSmokeMarker(enemyUnit,colour) + + --recreate in 5 mins + GLOBAL_JTAC_SMOKE[enemyUnit:getName()] = timer.getTime() + 300.0 + + -- move smoke 2 meters above target for ease + local enemyPoint = enemyUnit:getPoint() + trigger.action.smoke({ x = enemyPoint.x, y = enemyPoint.y + 2.0, z = enemyPoint.z }, colour) +end + +function cancelLase(jtacGroupName) + + --local index = "JTAC_"..jtacUnit:getID() + + local tempLase = GLOBAL_JTAC_LASE[jtacGroupName] + + if tempLase ~= nil then + Spot.destroy(tempLase) + GLOBAL_JTAC_LASE[jtacGroupName] = nil + + -- env.info('Destroy laze '..index) + + tempLase = nil + end + + local tempIR = GLOBAL_JTAC_IR[jtacGroupName] + + if tempIR ~= nil then + Spot.destroy(tempIR) + GLOBAL_JTAC_IR[jtacGroupName] = nil + + -- env.info('Destroy laze '..index) + + tempIR = nil + end +end + +function laseUnit(enemyUnit, jtacUnit, jtacGroupName, laserCode) + + --cancelLase(jtacGroupName) + + local spots = {} + + local enemyVector = enemyUnit:getPoint() + local enemyVectorUpdated = { x = enemyVector.x, y = enemyVector.y + 2.0, z = enemyVector.z } + + local oldLase = GLOBAL_JTAC_LASE[jtacGroupName] + local oldIR = GLOBAL_JTAC_IR[jtacGroupName] + + if oldLase == nil or oldIR == nil then + + -- create lase + + local status, result = pcall(function() + spots['irPoint'] = Spot.createInfraRed(jtacUnit, { x = 0, y = 2.0, z = 0 }, enemyVectorUpdated) + spots['laserPoint'] = Spot.createLaser(jtacUnit, { x = 0, y = 2.0, z = 0 }, enemyVectorUpdated, laserCode) + return spots + end) + + if not status then + env.error('ERROR: ' .. assert(result), false) + else + if result.irPoint then + + -- env.info(jtacUnit:getName() .. ' placed IR Pointer on '..enemyUnit:getName()) + + GLOBAL_JTAC_IR[jtacGroupName] = result.irPoint --store so we can remove after + + end + if result.laserPoint then + + -- env.info(jtacUnit:getName() .. ' is Lasing '..enemyUnit:getName()..'. CODE:'..laserCode) + + GLOBAL_JTAC_LASE[jtacGroupName] = result.laserPoint + end + end + + else + + -- update lase + + if oldLase~=nil then + oldLase:setPoint(enemyVectorUpdated) + end + + if oldIR ~= nil then + oldIR:setPoint(enemyVectorUpdated) + end + + end + +end + +-- get currently selected unit and check they're still in range +function getCurrentUnit(jtacUnit, jtacGroupName) + + + local unit = nil + + if GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] ~= nil then + unit = Unit.getByName(GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName].name) + end + + local tempPoint = nil + local tempDist = nil + local tempPosition = nil + + local jtacPosition = jtacUnit:getPosition() + local jtacPoint = jtacUnit:getPoint() + + if unit ~= nil and unit:getLife() > 0 and unit:isActive() == true then + + -- calc distance + tempPoint = unit:getPoint() + -- tempPosition = unit:getPosition() + + tempDist = getDistance(tempPoint.x, tempPoint.z, jtacPoint.x, jtacPoint.z) + if tempDist < JTAC_maxDistance then + -- calc visible + + -- check slightly above the target as rounding errors can cause issues, plus the unit has some height anyways + local offsetEnemyPos = { x = tempPoint.x, y = tempPoint.y + 2.0, z = tempPoint.z } + local offsetJTACPos = { x = jtacPoint.x, y = jtacPoint.y + 2.0, z = jtacPoint.z } + + if land.isVisible(offsetEnemyPos, offsetJTACPos) then + return unit + end + end + end + return nil +end + + +-- Find nearest enemy to JTAC that isn't blocked by terrain +function findNearestVisibleEnemy(jtacUnit, targetType) + + local x = 1 + local i = 1 + + local units = nil + local groupName = nil + + local nearestUnit = nil + local nearestDistance = JTAC_maxDistance + + local redGroups = coalition.getGroups(1, Group.Category.GROUND) + + local jtacPoint = jtacUnit:getPoint() + local jtacPosition = jtacUnit:getPosition() + + local tempPoint = nil + local tempPosition = nil + + local tempDist = nil + + -- finish this function + for i = 1, #redGroups do + if redGroups[i] ~= nil then + groupName = redGroups[i]:getName() + units = getGroup(groupName) + if #units > 0 then + + for x = 1, #units do + + --check to see if a JTAC has already targeted this unit + local targeted = alreadyTarget(jtacUnit,units[x]) + local allowedTarget = true + + if targetType == "vehicle" then + + allowedTarget = isVehicle(units[x]) + + elseif targetType == "troop" then + + allowedTarget = isInfantry(units[x]) + + end + + + if units[x]:isActive() == true and targeted == false and allowedTarget == true then + + -- calc distance + tempPoint = units[x]:getPoint() + -- tempPosition = units[x]:getPosition() + + tempDist = getDistance(tempPoint.x, tempPoint.z, jtacPoint.x, jtacPoint.z) + + -- env.info("tempDist" ..tempDist) + -- env.info("JTAC_maxDistance" ..JTAC_maxDistance) + + if tempDist < JTAC_maxDistance and tempDist < nearestDistance then + + local offsetEnemyPos = { x = tempPoint.x, y = tempPoint.y + 2.0, z = tempPoint.z } + local offsetJTACPos = { x = jtacPoint.x, y = jtacPoint.y + 2.0, z = jtacPoint.z } + + + -- calc visible + if land.isVisible(offsetEnemyPos, offsetJTACPos) then + + nearestDistance = tempDist + nearestUnit = units[x] + end + + end + end + end + end + end + end + + + if nearestUnit == nil then + return nil + end + + + return nearestUnit +end +-- tests whether the unit is targeted by another JTAC +function alreadyTarget(jtacUnit, enemyUnit) + + for y , jtacTarget in pairs(GLOBAL_JTAC_CURRENT_TARGETS) do + + if jtacTarget.unitId == enemyUnit:getID() then + -- env.info("ALREADY TARGET") + return true + end + + end + + return false + +end + + +-- Returns only alive units from group but the group / unit may not be active + +function getGroup(groupName) + + local groupUnits = Group.getByName(groupName) + + local filteredUnits = {} --contains alive units + local x = 1 + + if groupUnits ~= nil then + + groupUnits = groupUnits:getUnits() + + if groupUnits ~= nil and #groupUnits > 0 then + for x = 1, #groupUnits do + if groupUnits[x]:getLife() > 0 then + table.insert(filteredUnits, groupUnits[x]) + end + end + end + end + + return filteredUnits +end + +-- Distance measurement between two positions, assume flat world + +function getDistance(xUnit, yUnit, xZone, yZone) + local xDiff = xUnit - xZone + local yDiff = yUnit - yZone + + return math.sqrt(xDiff * xDiff + yDiff * yDiff) +end + +-- gets the JTAC status and displays to coalition units +function getJTACStatus() + + --returns the status of all JTAC units + + local jtacGroupName = nil + local jtacUnit = nil + local jtacUnitName = nil + + local message = "JTAC STATUS: \n\n" + + for jtacGroupName, jtacUnitName in pairs(GLOBAL_JTAC_UNITS) do + + --look up units + jtacUnit = Unit.getByName(jtacUnitName) + + if jtacUnit ~= nil and jtacUnit:getLife() > 0 and jtacUnit:isActive() == true then + + local enemyUnit = getCurrentUnit(jtacUnit, jtacGroupName) + + local laserCode = GLOBAL_JTAC_LASER_CODES[jtacGroupName] + + if laserCode == nil then + laserCode = "UNKNOWN" + end + + if enemyUnit ~= nil and enemyUnit:getLife() > 0 and enemyUnit:isActive() == true then + message = message .. "" .. jtacGroupName .. " targeting " .. enemyUnit:getTypeName().. " CODE: ".. laserCode .. getPositionString(enemyUnit) .. "\n" + else + message = message .. "" .. jtacGroupName .. " searching for targets" .. getPositionString(jtacUnit) .."\n" + end + end + end + + notify(message, 10) +end + + +-- Radio command for players (F10 Menu) + +function addRadioCommands() + + --looop over all players and add command + -- missionCommands.addCommandForCoalition( coalition.side.BLUE, "JTAC Status" ,nil, getJTACStatus ,nil) + + timer.scheduleFunction(addRadioCommands, nil, timer.getTime() + 10) + + local blueGroups = coalition.getGroups(coalition.side.BLUE) + local x = 1 + + if blueGroups ~= nil then + for x, tmpGroup in pairs(blueGroups) do + + + local index = "GROUP_" .. Group.getID(tmpGroup) + -- env.info("adding command for "..index) + if GLOBAL_JTAC_RADIO_ADDED[index] == nil then + -- env.info("about command for "..index) + missionCommands.addCommandForGroup(Group.getID(tmpGroup), "JTAC Status", nil, getJTACStatus, nil) + GLOBAL_JTAC_RADIO_ADDED[index] = true + -- env.info("Added command for " .. index) + end + end + end +end + +function isInfantry(unit) + + local typeName = unit:getTypeName() + + --type coerce tostring + typeName = string.lower(typeName.."") + + local soldierType = { "infantry","paratrooper","stinger","manpad"} + + for key,value in pairs(soldierType) do + if string.match(typeName, value) then + return true + end + end + + return false + +end + +-- assume anything that isnt soldier is vehicle +function isVehicle(unit) + + if isInfantry(unit) then + return false + end + + return true + +end + + +function getPositionString(unit) + + if JTAC_location == false then + return "" + end + + local latLngStr = latLngString(unit,3) + + local mgrsString = MGRSString(coord.LLtoMGRS(coord.LOtoLL(unit:getPosition().p)),5) + + return " @ " .. latLngStr .. " - MGRS "..mgrsString + +end + +-- source of Function MIST - https://github.com/mrSkortch/MissionScriptingTools/blob/master/mist.lua +function latLngString(unit, acc) + + local lat, lon = coord.LOtoLL(unit:getPosition().p) + + local latHemi, lonHemi + if lat > 0 then + latHemi = 'N' + else + latHemi = 'S' + end + + if lon > 0 then + lonHemi = 'E' + else + lonHemi = 'W' + end + + lat = math.abs(lat) + lon = math.abs(lon) + + local latDeg = math.floor(lat) + local latMin = (lat - latDeg)*60 + + local lonDeg = math.floor(lon) + local lonMin = (lon - lonDeg)*60 + + -- degrees, decimal minutes. + latMin = roundNumber(latMin, acc) + lonMin = roundNumber(lonMin, acc) + + if latMin == 60 then + latMin = 0 + latDeg = latDeg + 1 + end + + if lonMin == 60 then + lonMin = 0 + lonDeg = lonDeg + 1 + end + + local minFrmtStr -- create the formatting string for the minutes place + if acc <= 0 then -- no decimal place. + minFrmtStr = '%02d' + else + local width = 3 + acc -- 01.310 - that's a width of 6, for example. + minFrmtStr = '%0' .. width .. '.' .. acc .. 'f' + end + + return string.format('%02d', latDeg) .. ' ' .. string.format(minFrmtStr, latMin) .. '\'' .. latHemi .. ' ' + .. string.format('%02d', lonDeg) .. ' ' .. string.format(minFrmtStr, lonMin) .. '\'' .. lonHemi + +end + +-- source of Function MIST - https://github.com/mrSkortch/MissionScriptingTools/blob/master/mist.lua + function MGRSString(MGRS, acc) + if acc == 0 then + return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph + else + return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph .. ' ' .. string.format('%0' .. acc .. 'd', roundNumber(MGRS.Easting/(10^(5-acc)), 0)) + .. ' ' .. string.format('%0' .. acc .. 'd', roundNumber(MGRS.Northing/(10^(5-acc)), 0)) + end +end +-- From http://lua-users.org/wiki/SimpleRound + function roundNumber(num, idp) + local mult = 10^(idp or 0) + return math.floor(num * mult + 0.5) / mult +end + +-- add the radio commands +if JTAC_jtacStatusF10 == true then + timer.scheduleFunction(addRadioCommands, nil, timer.getTime() + 1) +end + + + +--DEBUG FUNCTIONS - IGNORE +--function print_functions(o) +-- +-- for key,value in pairs(getmetatable(o)) do +-- env.info(tostring(key) .." ".. tostring(value)) +-- end +--end +-- +--function dump_table(o) +-- if type(o) == 'table' then +-- local s = '{ ' +-- for k,v in pairs(o) do +-- if type(k) ~= 'number' then k = '"'..k..'"' end +-- s = s .. '['..k..'] = ' .. dump_table(v) .. ',' +-- end +-- return s .. '} ' +-- else +-- return tostring(o) +-- end +--end \ No newline at end of file diff --git a/resources/scripts/MissionScripting.original.lua b/resources/scripts/MissionScripting.original.lua new file mode 100644 index 00000000..86f9cda2 --- /dev/null +++ b/resources/scripts/MissionScripting.original.lua @@ -0,0 +1,21 @@ +--Initialization script for the Mission lua Environment (SSE) + +dofile('Scripts/ScriptingSystem.lua') + +--Sanitize Mission Scripting environment +--This makes unavailable some unsecure functions. +--Mission downloaded from server to client may contain potentialy harmful lua code that may use these functions. +--You can remove the code below and make availble these functions at your own risk. + +local function sanitizeModule(name) + _G[name] = nil + package.loaded[name] = nil +end + +do + sanitizeModule('os') + sanitizeModule('io') + sanitizeModule('lfs') + require = nil + loadlib = nil +end \ No newline at end of file diff --git a/resources/scripts/dcs_liberation.lua b/resources/scripts/dcs_liberation.lua index 2b1782cf..a9476fa4 100644 --- a/resources/scripts/dcs_liberation.lua +++ b/resources/scripts/dcs_liberation.lua @@ -9,6 +9,7 @@ killed_aircrafts = {} killed_ground_units = {} weapons_fired = {} base_capture_events = {} +destroyed_objects_positions = {} mission_ended = false local function messageAll(message) @@ -21,6 +22,7 @@ end write_state = function() --messageAll("Writing DCS Liberation State...") + --logger.info("Writing DCS LIBERATION state") local fp = io.open(debriefing_file_location, 'w') local game_state = { ["killed_aircrafts"] = killed_aircrafts, @@ -28,9 +30,11 @@ write_state = function() ["weapons_fired"] = weapons_fired, ["base_capture_events"] = base_capture_events, ["mission_ended"] = mission_ended, + ["destroyed_objects_positions"] = destroyed_objects_positions, } fp:write(json:encode(game_state)) fp:close() + --logger.info("Done writing DCS Liberation state") --messageAll("Done writing DCS Liberation state.") end @@ -45,11 +49,19 @@ local function onEvent(event) if event.id == world.event.S_EVENT_DEAD and event.initiator then killed_ground_units[#killed_ground_units + 1] = event.initiator.getName(event.initiator) + local position = event.initiator.getPosition(event.initiator) + local destruction = {} + destruction.x = position.p.x + destruction.y = position.p.y + destruction.z = position.p.z + destruction.type = event.initiator:getTypeName() + destruction.orientation = mist.getHeading(event.initiator) * 57.3 + destroyed_objects_positions[#destroyed_objects_positions + 1] = destruction end - if event.id == world.event.S_EVENT_SHOT and event.weapon then - weapons_fired[#weapons_fired + 1] = event.weapon.getTypeName(event.weapon) - end + --if event.id == world.event.S_EVENT_SHOT and event.weapon then + -- weapons_fired[#weapons_fired + 1] = event.weapon.getTypeName(event.weapon) + --end if event.id == world.event.S_EVENT_BASE_CAPTURED and event.place then --messageAll("Base captured :" .. event.place.getName(event.place)) diff --git a/resources/stylesheets/check-hover.png b/resources/stylesheets/check-hover.png new file mode 100644 index 00000000..71fd2ad5 Binary files /dev/null and b/resources/stylesheets/check-hover.png differ diff --git a/resources/stylesheets/check.png b/resources/stylesheets/check.png new file mode 100644 index 00000000..e1b612b3 Binary files /dev/null and b/resources/stylesheets/check.png differ diff --git a/resources/stylesheets/chevron-down.png b/resources/stylesheets/chevron-down.png new file mode 100644 index 00000000..186aa21e Binary files /dev/null and b/resources/stylesheets/chevron-down.png differ diff --git a/resources/stylesheets/chevron-up.png b/resources/stylesheets/chevron-up.png new file mode 100644 index 00000000..8eb856b3 Binary files /dev/null and b/resources/stylesheets/chevron-up.png differ diff --git a/resources/stylesheets/style-dcs.css b/resources/stylesheets/style-dcs.css new file mode 100644 index 00000000..fb41fa21 --- /dev/null +++ b/resources/stylesheets/style-dcs.css @@ -0,0 +1,493 @@ +/*ui theme based on dcs*/ + + +/* +colors + +Backgrounds +blue ------------------------ #2D3E50 +dark blue ------------------- #1D2731 +med/grey/blue --------------- #435466 +dark grey ------------------- #4E5760 +button blue/grey gradient --- qlineargradient(x1:0, y1:0, x2:1, y2:1,stop:0 #A4B3B9, stop:1 #85989D); +button green gradient --- qlineargradient(x1:0, y1:0, x2:1, y2:1,stop:0 #82A466, stop:1 #5C863F); + +Text +white text ------------------- #ffffff +blue text -------------------- #3592C4 +grey text -------------------- #B7C0C6 + +*/ + +/*QMenuBar*/ +QMenuBar { + spacing: 2px; /* spacing between menu bar items */ + border-bottom:none; +} + +QMenuBar::item { + padding: 4px 10px; + background: transparent; + border-radius: 2px; + margin: 4px 0; +} + +QMenuBar::item:selected { /* when selected using mouse or keyboard */ + background: #1D2731; +} + +QMenuBar::item:pressed { + background: #1D2731; +} + +QMenu::item:selected { + background: #435466; +} + +QScrollBar:horizontal { + background: #435466; +} +QScrollBar:vertical { + background: #435466; +} + +QLabel{ +font-weight:normal; +text-align:right; +} + + +/*QWidget*/ +QWidget { + background-color: #2D3E50; + color:white; +} + + +/*QLiberationWindow*/ +QLiberationWindow{ + background-color: #2D3E50; + color:white; +} + +/*QTopPanel*/ +QTopPanel, +QTopPanel * { + background-color: #1D2731; + color: #B7C0C6; + font-size: 12px; + font-weight: bold; +} + +/*QPushButton*/ +QPushButton { + background: qlineargradient(x1:0, y1:0, x2:1, y2:1,stop:0 #A4B3B9, stop:1 #85989D); + border: 1px solid #97A9A9; + color:#fff; + padding: 6px 10px; + cursor: pointer; + border-radius:2px; +} + +QPushButton:hover { + background: #6c7b7f; + cursor:pointer; +} + +/*btn-primary*/ +QPushButton[style="btn-primary"]{ + background: qlineargradient(x1:0, y1:0, x2:1, y2:1,stop:0 #A4B3B9, stop:1 #85989D); + border: 1px solid #97A9A9; + color:#fff; + padding: 6px; + border-radius:2px; + cursor: pointer; + font-weight:bold; + text-transform:uppercase; +} +QPushButton[style="btn-primary"]:hover{ + background: #6c7b7f; +} + + +/*highlighted buttons*/ +QPushButton[style="btn-success"] , QPushButton[style="start-button"]{ + background-color:#82A466; + color: white; + cursor:pointer; + border-radius:2px; + font-weight:bold; + text-transform:uppercase; +} + +QPushButton[style="start-button"]{ + padding: 8px 30px; +} + +QPushButton[style="btn-success"]:hover , QPushButton[style="start-button"]:hover{ + background:#5C863F; +} + + + +/* Buy button */ +QPushButton[style="btn-buy"]{ + background-color:#82A466; + color: white; + cursor:pointer; + border-radius:2px; + font-weight:bold; + text-transform:uppercase; + margin: 0px; + padding: 2px; +} + +QPushButton[style="btn-buy"]:hover{ + cursor:pointer; + background:#5C863F; +} + +/* Sell button */ +QPushButton[style="btn-sell"]{ + background-color:#9E3232; + color: white; + cursor:pointer; + border-radius:2px; + font-weight:bold; + text-transform:uppercase; + margin: 0px; + padding: 2px; +} + +QPushButton[style="btn-sell"]:hover{ + cursor:pointer; + background:#D84545; +} + + + +QPushButton[style="btn-danger"]{ + background-color:#9E3232; + color: white; + cursor:pointer; + padding: 6px; + border-radius:2px; + border: 1px solid #9E3232; +} + +QPushButton[style="btn-danger"]:hover{ + background-color:#D84545; +} + +QPushButton:disabled{ + + background:#d6d6d6; +} + +/*QLabel*/ +QLabel{ + border: none; +} + +QLabel[style="base-title"]{ + font-size: 24px; + font-color: #ccc; +} + +QLabel[style="icon-plane"]{ + background-color:#48719D; + min-height:24px; + max-width: 84px; + border: 1px solid black; + text-align:center; + color:white; +} + +QLabel[style="BARCAP"]{ + border: 1px solid black; + background-color: #445299; + color:white; + padding:2px 6px; +} + +QLabel[style="TARCAP"]{ + border: 1px solid black; + background-color: #445299; + color:white; + padding:2px 6px; +} + +QLabel[style="CAP"]{ + border: 1px solid black; + background-color: #445299; + color:white; + padding:2px 6px; +} + +QLabel[style="INTERCEPTION"]{ + border: 1px solid black; + background-color: #7752bc; + color:white; + padding:2px 6px; +} + +QLabel[style="CAS"]{ + border: 1px solid black; + background-color: #ab2244; + color:white; + padding:2px 6px; +} + +QLabel[style="BAI"]{ + border: 1px solid black; + background-color: #ab2244; + color:white; + padding:2px 6px; +} + +QLabel[style="ANTISHIP"]{ + border: 1px solid black; + background-color: #ab2244; + color:white; + padding:2px 6px; +} + +QLabel[style="STRIKE"]{ + border: 1px solid black; + background-color: #ab2244; + color:white; + padding:2px 6px; +} + +QLabel[style="DEAD"]{ + border: 1px solid black; + background-color: #cc8844; + color:white; + padding:2px 6px; +} + +QLabel[style="SEAD"]{ + border: 1px solid black; + background-color: #aa7744; + color:white; + padding:2px 6px; +} + +/*QGroupBox these are the sections that look like fieldsets*/ +QGroupBox { + margin-top: 1ex; /* leave space at the top for the title */ + border:1px solid #435466; + padding:5px; + margin:5px; +} + +QGroupBox[style="buy-box"]{ + padding: 0px; + margin: 0px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; /* position at the top left */ + padding: 5px; + color: #B7C0C6; + font-weight: 800; +} + + +/*checkboxes*/ +QGroupBox::indicator , QCheckBox::indicator { + width: 14px; + height: 14px; + border: 1px solid #435466; + +} + +QGroupBox::indicator:hover , QCheckBox::indicator:hover { + border-color: #fff; + image: url(resources/stylesheets/check-hover.png); +} + +QGroupBox::indicator:unchecked , QCheckBox::indicator:unchecked { + +} + +QGroupBox::indicator:checked , QCheckBox::indicator:checked { +image: url(resources/stylesheets/check.png); +} + + +/*QDialog*/ +QDialog{ + +} + +QListView { + border: 1px solid #14202B; + background-color: #14202B; +} + +/*QTabWidget*/ +QTabWidget::pane { /* The tab widget frame */ + border: 1px solid #1D2731; +} + +QTabWidget::tab-bar { + border: 1px solid #14202B; +} + +QTabBar::tab { + color:#5B626B; + background: #202C3A; + border-right: 1px solid #14202B; + border-left: 1px solid #14202B; + border-top: 1px solid #14202B; + min-width: 8ex; + padding: 6px 10px; +} + +QTabBar::tab:hover { + background: #1D2731; + color:#fff; +} + +QTabBar::tab:selected { + color:#3592C4; + background:#2C3E4C; +} + + + +/*QComboBox*/ +QComboBox { + border:1px solid #3B4656; + color: #fff; + padding: 4px 10px; + background: #1D2731; +} + +QComboBox::editable { + border:4px solid red; +} + +QComboBox:hover{ + border-color: #3592C4; +} + +QComboBox:disabled, QComboBox::drop-down:disabled{ + color: #B7C0C6; + background: #435466; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + padding: 2px; + border:none; + color: #fff; + height: 20px; +} + +QComboBox::down-arrow { + image: url(resources/stylesheets/chevron-down.png); +} + +QComboBox QAbstractItemView { + padding: 4px; + border:1px solid #3B4656; + background: #465C74; + + } + + +/*QSpinBox number input with up down arrows*/ +QSpinBox{ + border:1px solid #3B4656; + color: #fff; + padding: 4px 10px; + background: #1D2731; + min-width:40px; +} + +QSpinBox:hover{ + border-color: #3592C4; +} + +QSpinBox::up-button , QSpinBox::down-button{ + border:none; +} + +QSpinBox::up-button{ + image: url(resources/stylesheets/chevron-up.png); +} + +QSpinBox::down-button{ + image: url(resources/stylesheets/chevron-down.png); +} + + + +QLineEdit{ + padding: 4px 10px; + border:1px solid #3B4656; + background: #465C74; + color: #fff; + margin-bottom:10px; +} + + +/*table view*/ +QHeaderView{ + background: #4B5B74; +} +QHeaderView::section { + background: #4B5B74; + padding: 4px; + border-style: none; + border-bottom: 1px solid #1D2731; +} + +QHeaderView::section:horizontal +{ + /*border: none;*/ + text-align:left; + background: #4B5B74; +} + +QHeaderView::section:vertical +{ + /*border: none;*/ + text-align:left; + background: #4B5B74; +} + +QTableWidget { + gridline-color: red; + background: #4B5B74; +} + +QTableView QTableCornerButton::section { + background: #4B5B74; +} + +/*helper modifiers*/ +*[style="no-border"] { + border:none; +} + +*[style="bordered"]{ + border: 1px solid #1D2731; +} + + +/* +QBaseMenu{ + background-color:#699245; + color:white; +} + +QWidget[style="baseMenuHeader"]{ + font-size: 24px; + font-weight: bold; + color:white; +}*/ diff --git a/resources/stylesheets/style.css b/resources/stylesheets/style.css index 1d387adb..7a6f74cf 100644 --- a/resources/stylesheets/style.css +++ b/resources/stylesheets/style.css @@ -42,7 +42,7 @@ QPushButton[style="start-button"]{ background-color:#699245; color: white; cursor:pointer; - padding: 15px 15px 15px 15px; + padding: 5px 5px 5px 5px; border-radius:5px; } @@ -53,6 +53,40 @@ QPushButton[style="start-button"]:hover{ cursor: pointer; } +/* Buy button */ +QPushButton[style="btn-buy"]{ + background-color:#82A466; + color: white; + cursor:pointer; + border-radius:2px; + font-weight:bold; + text-transform:uppercase; + margin: 0px; + padding: 2px; +} + +QPushButton[style="btn-buy"]:hover{ + cursor:pointer; + background:#5C863F; +} + +/* Sell button */ +QPushButton[style="btn-sell"]{ + background-color:#9E3232; + color: white; + cursor:pointer; + border-radius:2px; + font-weight:bold; + text-transform:uppercase; + margin: 0px; + padding: 2px; +} + +QPushButton[style="btn-sell"]:hover{ + cursor:pointer; + background:#D84545; +} + QPushButton[style="btn-danger"]{ background-color:#9E3232; color: white; diff --git a/resources/stylesheets/windows-style.css b/resources/stylesheets/windows-style.css new file mode 100644 index 00000000..cbf5010f --- /dev/null +++ b/resources/stylesheets/windows-style.css @@ -0,0 +1,3 @@ +/* +windows basis styles +*/ diff --git a/resources/thechannel.gif b/resources/thechannel.gif index 15005ed7..d917143e 100644 Binary files a/resources/thechannel.gif and b/resources/thechannel.gif differ diff --git a/resources/tools/cau_terrain.miz b/resources/tools/cau_terrain.miz index dc94b0d5..e0542b89 100644 Binary files a/resources/tools/cau_terrain.miz and b/resources/tools/cau_terrain.miz differ diff --git a/resources/tools/channel_terrain.miz b/resources/tools/channel_terrain.miz index 5fe3f780..53afc022 100644 Binary files a/resources/tools/channel_terrain.miz and b/resources/tools/channel_terrain.miz differ diff --git a/resources/tools/generate_landmap.py b/resources/tools/generate_landmap.py index f4124ba5..816747c5 100644 --- a/resources/tools/generate_landmap.py +++ b/resources/tools/generate_landmap.py @@ -3,7 +3,7 @@ import pickle from dcs.mission import Mission from dcs.planes import A_10C -for terrain in ["cau", "gulf", "nev", "channel"]: +for terrain in ["cau"]: print("Terrain " + terrain) m = Mission() m.load_file("./{}_terrain.miz".format(terrain)) diff --git a/resources/tools/gulf_terrain.miz b/resources/tools/gulf_terrain.miz index 6b5d6de7..52ca6d05 100644 Binary files a/resources/tools/gulf_terrain.miz and b/resources/tools/gulf_terrain.miz differ diff --git a/resources/tools/nev_terrain.miz b/resources/tools/nev_terrain.miz index ce6ad669..4621f1f5 100644 Binary files a/resources/tools/nev_terrain.miz and b/resources/tools/nev_terrain.miz differ diff --git a/resources/tools/normandy_terrain.miz b/resources/tools/normandy_terrain.miz index 77c3e206..cb42c13c 100644 Binary files a/resources/tools/normandy_terrain.miz and b/resources/tools/normandy_terrain.miz differ diff --git a/resources/ui/airbase.png b/resources/ui/airbase.png new file mode 100644 index 00000000..9fe36945 Binary files /dev/null and b/resources/ui/airbase.png differ diff --git a/resources/ui/carrier.png b/resources/ui/carrier.png new file mode 100644 index 00000000..4ae09dd6 Binary files /dev/null and b/resources/ui/carrier.png differ diff --git a/resources/ui/conflict.png b/resources/ui/conflict.png new file mode 100644 index 00000000..ee233637 Binary files /dev/null and b/resources/ui/conflict.png differ diff --git a/resources/ui/debriefing.png b/resources/ui/debriefing.png new file mode 100644 index 00000000..ceda551f Binary files /dev/null and b/resources/ui/debriefing.png differ diff --git a/resources/ui/ground_assets/aa.png b/resources/ui/ground_assets/aa.png index 171b5e4c..87d8a6ef 100644 Binary files a/resources/ui/ground_assets/aa.png and b/resources/ui/ground_assets/aa.png differ diff --git a/resources/ui/ground_assets/allycamp.png b/resources/ui/ground_assets/allycamp.png index 92b731af..a57564bc 100644 Binary files a/resources/ui/ground_assets/allycamp.png and b/resources/ui/ground_assets/allycamp.png differ diff --git a/resources/ui/ground_assets/ammo.png b/resources/ui/ground_assets/ammo.png index d28d296b..5f6a5a6a 100644 Binary files a/resources/ui/ground_assets/ammo.png and b/resources/ui/ground_assets/ammo.png differ diff --git a/resources/ui/ground_assets/comms.png b/resources/ui/ground_assets/comms.png index 9c0815dd..fc75eafc 100644 Binary files a/resources/ui/ground_assets/comms.png and b/resources/ui/ground_assets/comms.png differ diff --git a/resources/ui/ground_assets/derrick.png b/resources/ui/ground_assets/derrick.png index 5f2597bb..4317ff30 100644 Binary files a/resources/ui/ground_assets/derrick.png and b/resources/ui/ground_assets/derrick.png differ diff --git a/resources/ui/ground_assets/factory.png b/resources/ui/ground_assets/factory.png index 13d2b70e..427f0c61 100644 Binary files a/resources/ui/ground_assets/factory.png and b/resources/ui/ground_assets/factory.png differ diff --git a/resources/ui/ground_assets/farp.png b/resources/ui/ground_assets/farp.png index 359371c5..93614760 100644 Binary files a/resources/ui/ground_assets/farp.png and b/resources/ui/ground_assets/farp.png differ diff --git a/resources/ui/ground_assets/fob.png b/resources/ui/ground_assets/fob.png index 5fef4e8d..b651d7d7 100644 Binary files a/resources/ui/ground_assets/fob.png and b/resources/ui/ground_assets/fob.png differ diff --git a/resources/ui/ground_assets/fuel.png b/resources/ui/ground_assets/fuel.png index 89d20cfd..0210b9c3 100644 Binary files a/resources/ui/ground_assets/fuel.png and b/resources/ui/ground_assets/fuel.png differ diff --git a/resources/ui/ground_assets/oil.png b/resources/ui/ground_assets/oil.png index 6288bdfe..ea59b953 100644 Binary files a/resources/ui/ground_assets/oil.png and b/resources/ui/ground_assets/oil.png differ diff --git a/resources/ui/ground_assets/power.png b/resources/ui/ground_assets/power.png index 835f4512..203fcf76 100644 Binary files a/resources/ui/ground_assets/power.png and b/resources/ui/ground_assets/power.png differ diff --git a/resources/ui/ground_assets/ship.png b/resources/ui/ground_assets/ship.png index 534a99a4..097d01dc 100644 Binary files a/resources/ui/ground_assets/ship.png and b/resources/ui/ground_assets/ship.png differ diff --git a/resources/ui/ground_assets/target.png b/resources/ui/ground_assets/target.png index 251bafd4..91913868 100644 Binary files a/resources/ui/ground_assets/target.png and b/resources/ui/ground_assets/target.png differ diff --git a/resources/ui/ground_assets/village.png b/resources/ui/ground_assets/village.png index 0dcdb63b..599e532c 100644 Binary files a/resources/ui/ground_assets/village.png and b/resources/ui/ground_assets/village.png differ diff --git a/resources/ui/ground_assets/ware.png b/resources/ui/ground_assets/ware.png index 50ee2af3..eec7b0a0 100644 Binary files a/resources/ui/ground_assets/ware.png and b/resources/ui/ground_assets/ware.png differ diff --git a/resources/ui/ground_assets/ww2bunker.png b/resources/ui/ground_assets/ww2bunker.png index 5d029ae8..ced23ea0 100644 Binary files a/resources/ui/ground_assets/ww2bunker.png and b/resources/ui/ground_assets/ww2bunker.png differ diff --git a/resources/ui/lha.png b/resources/ui/lha.png new file mode 100644 index 00000000..7f2a68e9 Binary files /dev/null and b/resources/ui/lha.png differ diff --git a/resources/ui/loader.gif b/resources/ui/loader.gif index 47adbf03..1a29732d 100644 Binary files a/resources/ui/loader.gif and b/resources/ui/loader.gif differ diff --git a/resources/ui/misc/cheat.png b/resources/ui/misc/cheat.png index 9001790c..af0270cb 100644 Binary files a/resources/ui/misc/cheat.png and b/resources/ui/misc/cheat.png differ diff --git a/resources/ui/misc/icons-dark/cheat.png b/resources/ui/misc/dark/cheat.png similarity index 100% rename from resources/ui/misc/icons-dark/cheat.png rename to resources/ui/misc/dark/cheat.png diff --git a/resources/ui/misc/icons-dark/generator.png b/resources/ui/misc/dark/generator.png similarity index 100% rename from resources/ui/misc/icons-dark/generator.png rename to resources/ui/misc/dark/generator.png diff --git a/resources/ui/misc/icons-dark/hourglass.png b/resources/ui/misc/dark/hourglass.png similarity index 100% rename from resources/ui/misc/icons-dark/hourglass.png rename to resources/ui/misc/dark/hourglass.png diff --git a/resources/ui/misc/icons-dark/missile.png b/resources/ui/misc/dark/missile.png similarity index 100% rename from resources/ui/misc/icons-dark/missile.png rename to resources/ui/misc/dark/missile.png diff --git a/resources/ui/misc/icons-dark/money_icon.png b/resources/ui/misc/dark/money_icon.png similarity index 100% rename from resources/ui/misc/icons-dark/money_icon.png rename to resources/ui/misc/dark/money_icon.png diff --git a/resources/ui/misc/icons-dark/new.png b/resources/ui/misc/dark/new.png similarity index 100% rename from resources/ui/misc/icons-dark/new.png rename to resources/ui/misc/dark/new.png diff --git a/resources/ui/misc/icons-dark/open.png b/resources/ui/misc/dark/open.png similarity index 100% rename from resources/ui/misc/icons-dark/open.png rename to resources/ui/misc/dark/open.png diff --git a/resources/ui/misc/icons-dark/ordnance_icon.png b/resources/ui/misc/dark/ordnance_icon.png similarity index 100% rename from resources/ui/misc/icons-dark/ordnance_icon.png rename to resources/ui/misc/dark/ordnance_icon.png diff --git a/resources/ui/misc/icons-dark/proceed.png b/resources/ui/misc/dark/proceed.png similarity index 100% rename from resources/ui/misc/icons-dark/proceed.png rename to resources/ui/misc/dark/proceed.png diff --git a/resources/ui/misc/icons-dark/save.png b/resources/ui/misc/dark/save.png similarity index 100% rename from resources/ui/misc/icons-dark/save.png rename to resources/ui/misc/dark/save.png diff --git a/resources/ui/misc/icons-dark/settings.png b/resources/ui/misc/dark/settings.png similarity index 100% rename from resources/ui/misc/icons-dark/settings.png rename to resources/ui/misc/dark/settings.png diff --git a/resources/ui/misc/icons-dark/statistics.png b/resources/ui/misc/dark/statistics.png similarity index 100% rename from resources/ui/misc/icons-dark/statistics.png rename to resources/ui/misc/dark/statistics.png diff --git a/resources/ui/misc/generator.png b/resources/ui/misc/generator.png index 3a2971a9..d5ad0721 100644 Binary files a/resources/ui/misc/generator.png and b/resources/ui/misc/generator.png differ diff --git a/resources/ui/misc/hourglass.png b/resources/ui/misc/hourglass.png index d42e65b6..73745fc5 100644 Binary files a/resources/ui/misc/hourglass.png and b/resources/ui/misc/hourglass.png differ diff --git a/resources/ui/misc/icons-light/cheat.png b/resources/ui/misc/light/cheat.png similarity index 100% rename from resources/ui/misc/icons-light/cheat.png rename to resources/ui/misc/light/cheat.png diff --git a/resources/ui/misc/icons-light/generator.png b/resources/ui/misc/light/generator.png similarity index 100% rename from resources/ui/misc/icons-light/generator.png rename to resources/ui/misc/light/generator.png diff --git a/resources/ui/misc/icons-light/hourglass.png b/resources/ui/misc/light/hourglass.png similarity index 100% rename from resources/ui/misc/icons-light/hourglass.png rename to resources/ui/misc/light/hourglass.png diff --git a/resources/ui/misc/icons-light/missile.png b/resources/ui/misc/light/missile.png similarity index 100% rename from resources/ui/misc/icons-light/missile.png rename to resources/ui/misc/light/missile.png diff --git a/resources/ui/misc/icons-light/money_icon.png b/resources/ui/misc/light/money_icon.png similarity index 100% rename from resources/ui/misc/icons-light/money_icon.png rename to resources/ui/misc/light/money_icon.png diff --git a/resources/ui/misc/icons-light/new.png b/resources/ui/misc/light/new.png similarity index 100% rename from resources/ui/misc/icons-light/new.png rename to resources/ui/misc/light/new.png diff --git a/resources/ui/misc/icons-light/open.png b/resources/ui/misc/light/open.png similarity index 100% rename from resources/ui/misc/icons-light/open.png rename to resources/ui/misc/light/open.png diff --git a/resources/ui/misc/icons-light/ordnance_icon.png b/resources/ui/misc/light/ordnance_icon.png similarity index 100% rename from resources/ui/misc/icons-light/ordnance_icon.png rename to resources/ui/misc/light/ordnance_icon.png diff --git a/resources/ui/misc/icons-light/proceed.png b/resources/ui/misc/light/proceed.png similarity index 100% rename from resources/ui/misc/icons-light/proceed.png rename to resources/ui/misc/light/proceed.png diff --git a/resources/ui/misc/icons-light/save.png b/resources/ui/misc/light/save.png similarity index 100% rename from resources/ui/misc/icons-light/save.png rename to resources/ui/misc/light/save.png diff --git a/resources/ui/misc/icons-light/settings.png b/resources/ui/misc/light/settings.png similarity index 100% rename from resources/ui/misc/icons-light/settings.png rename to resources/ui/misc/light/settings.png diff --git a/resources/ui/misc/icons-light/statistics.png b/resources/ui/misc/light/statistics.png similarity index 100% rename from resources/ui/misc/icons-light/statistics.png rename to resources/ui/misc/light/statistics.png diff --git a/resources/ui/misc/icons-medium/cheat.png b/resources/ui/misc/medium/cheat.png similarity index 100% rename from resources/ui/misc/icons-medium/cheat.png rename to resources/ui/misc/medium/cheat.png diff --git a/resources/ui/misc/icons-medium/generator.png b/resources/ui/misc/medium/generator.png similarity index 100% rename from resources/ui/misc/icons-medium/generator.png rename to resources/ui/misc/medium/generator.png diff --git a/resources/ui/misc/icons-medium/hourglass.png b/resources/ui/misc/medium/hourglass.png similarity index 100% rename from resources/ui/misc/icons-medium/hourglass.png rename to resources/ui/misc/medium/hourglass.png diff --git a/resources/ui/misc/icons-medium/missile.png b/resources/ui/misc/medium/missile.png similarity index 100% rename from resources/ui/misc/icons-medium/missile.png rename to resources/ui/misc/medium/missile.png diff --git a/resources/ui/misc/icons-medium/money_icon.png b/resources/ui/misc/medium/money_icon.png similarity index 100% rename from resources/ui/misc/icons-medium/money_icon.png rename to resources/ui/misc/medium/money_icon.png diff --git a/resources/ui/misc/icons-medium/new.png b/resources/ui/misc/medium/new.png similarity index 100% rename from resources/ui/misc/icons-medium/new.png rename to resources/ui/misc/medium/new.png diff --git a/resources/ui/misc/icons-medium/open.png b/resources/ui/misc/medium/open.png similarity index 100% rename from resources/ui/misc/icons-medium/open.png rename to resources/ui/misc/medium/open.png diff --git a/resources/ui/misc/icons-medium/ordnance_icon.png b/resources/ui/misc/medium/ordnance_icon.png similarity index 100% rename from resources/ui/misc/icons-medium/ordnance_icon.png rename to resources/ui/misc/medium/ordnance_icon.png diff --git a/resources/ui/misc/icons-medium/proceed.png b/resources/ui/misc/medium/proceed.png similarity index 100% rename from resources/ui/misc/icons-medium/proceed.png rename to resources/ui/misc/medium/proceed.png diff --git a/resources/ui/misc/icons-medium/save.png b/resources/ui/misc/medium/save.png similarity index 100% rename from resources/ui/misc/icons-medium/save.png rename to resources/ui/misc/medium/save.png diff --git a/resources/ui/misc/icons-medium/settings.png b/resources/ui/misc/medium/settings.png similarity index 100% rename from resources/ui/misc/icons-medium/settings.png rename to resources/ui/misc/medium/settings.png diff --git a/resources/ui/misc/icons-medium/statistics.png b/resources/ui/misc/medium/statistics.png similarity index 100% rename from resources/ui/misc/icons-medium/statistics.png rename to resources/ui/misc/medium/statistics.png diff --git a/resources/ui/misc/missile.png b/resources/ui/misc/missile.png index 5fb0c691..086a43e7 100644 Binary files a/resources/ui/misc/missile.png and b/resources/ui/misc/missile.png differ diff --git a/resources/ui/misc/money_icon.png b/resources/ui/misc/money_icon.png index 0f81d4d2..dc626090 100644 Binary files a/resources/ui/misc/money_icon.png and b/resources/ui/misc/money_icon.png differ diff --git a/resources/ui/misc/new.png b/resources/ui/misc/new.png index 363509e2..3ff8a26c 100644 Binary files a/resources/ui/misc/new.png and b/resources/ui/misc/new.png differ diff --git a/resources/ui/misc/open.png b/resources/ui/misc/open.png index 5908bd44..97e15fdd 100644 Binary files a/resources/ui/misc/open.png and b/resources/ui/misc/open.png differ diff --git a/resources/ui/misc/ordnance_icon.png b/resources/ui/misc/ordnance_icon.png index ef40da1d..d9794c2c 100644 Binary files a/resources/ui/misc/ordnance_icon.png and b/resources/ui/misc/ordnance_icon.png differ diff --git a/resources/ui/misc/proceed.png b/resources/ui/misc/proceed.png index 3158786b..22c9b89d 100644 Binary files a/resources/ui/misc/proceed.png and b/resources/ui/misc/proceed.png differ diff --git a/resources/ui/misc/save.png b/resources/ui/misc/save.png index f6d4b63f..550b4963 100644 Binary files a/resources/ui/misc/save.png and b/resources/ui/misc/save.png differ diff --git a/resources/ui/misc/settings.png b/resources/ui/misc/settings.png index 7aa676ee..058808b8 100644 Binary files a/resources/ui/misc/settings.png and b/resources/ui/misc/settings.png differ diff --git a/resources/ui/misc/statistics.png b/resources/ui/misc/statistics.png index dba4e84c..731c69c7 100644 Binary files a/resources/ui/misc/statistics.png and b/resources/ui/misc/statistics.png differ diff --git a/resources/ui/splash_screen.png b/resources/ui/splash_screen.png index 68ff04ee..2b9e23c6 100644 Binary files a/resources/ui/splash_screen.png and b/resources/ui/splash_screen.png differ diff --git a/resources/ui/units/aircrafts/A-4E-C_24.jpg b/resources/ui/units/aircrafts/A-4E-C_24.jpg new file mode 100644 index 00000000..4a00e383 Binary files /dev/null and b/resources/ui/units/aircrafts/A-4E-C_24.jpg differ diff --git a/resources/ui/units/aircrafts/C-101EB CC_24.jpg b/resources/ui/units/aircrafts/C-101CC_24.jpg similarity index 100% rename from resources/ui/units/aircrafts/C-101EB CC_24.jpg rename to resources/ui/units/aircrafts/C-101CC_24.jpg diff --git a/resources/ui/units/aircrafts/MB-339PAN_24.jpg b/resources/ui/units/aircrafts/MB-339PAN_24.jpg new file mode 100644 index 00000000..c4dfd709 Binary files /dev/null and b/resources/ui/units/aircrafts/MB-339PAN_24.jpg differ diff --git a/resources/ui/units/aircrafts/Rafale_A_S_24.jpg b/resources/ui/units/aircrafts/Rafale_A_S_24.jpg new file mode 100644 index 00000000..293afa73 Binary files /dev/null and b/resources/ui/units/aircrafts/Rafale_A_S_24.jpg differ diff --git a/resources/ui/units/aircrafts/Rafale_M_24.jpg b/resources/ui/units/aircrafts/Rafale_M_24.jpg new file mode 100644 index 00000000..293afa73 Binary files /dev/null and b/resources/ui/units/aircrafts/Rafale_M_24.jpg differ diff --git a/resources/ui/wizard/logo1.png b/resources/ui/wizard/logo1.png index 765e00bb..7aa676ee 100644 Binary files a/resources/ui/wizard/logo1.png and b/resources/ui/wizard/logo1.png differ diff --git a/resources/ui/wizard/original/logo1.png b/resources/ui/wizard/original/logo1.png new file mode 100644 index 00000000..765e00bb Binary files /dev/null and b/resources/ui/wizard/original/logo1.png differ diff --git a/resources/ui/wizard/watermark1.png b/resources/ui/wizard/watermark1.png index 95ef2e4a..13dcfebb 100644 Binary files a/resources/ui/wizard/watermark1.png and b/resources/ui/wizard/watermark1.png differ diff --git a/resources/ui/wizard/watermark2.png b/resources/ui/wizard/watermark2.png index 136d6666..d7c308d3 100644 Binary files a/resources/ui/wizard/watermark2.png and b/resources/ui/wizard/watermark2.png differ diff --git a/resources/ui/wizard/watermark3.png b/resources/ui/wizard/watermark3.png new file mode 100644 index 00000000..c30444f1 Binary files /dev/null and b/resources/ui/wizard/watermark3.png differ diff --git a/theater/caucasus.py b/theater/caucasus.py index 3fadd1d7..1ebad24d 100644 --- a/theater/caucasus.py +++ b/theater/caucasus.py @@ -1,11 +1,8 @@ -import re - -from dcs.terrain import caucasus from dcs import mapping +from dcs.terrain import caucasus -from .landmap import * from .conflicttheater import * -from .base import * +from .landmap import * class CaucasusTheater(ConflictTheater): @@ -22,7 +19,7 @@ class CaucasusTheater(ConflictTheater): "night": (0, 5), } - carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-305810.6875, 406399.1875)) + def __init__(self, load_ground_objects=True): super(CaucasusTheater, self).__init__() @@ -45,6 +42,9 @@ class CaucasusTheater(ConflictTheater): self.mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, LAND, SIZE_BIG, 1.3) self.mozdok = ControlPoint.from_airport(caucasus.Mozdok, LAND, SIZE_BIG, 1.1) + self.carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-305810.6875, 406399.1875), 1001) + self.lha = ControlPoint.lha("Tarawa", mapping.Point(-326050.6875, 519452.1875), 1002) + self.vaziani.frontline_offset = 0.5 self.vaziani.base.strength = 1 @@ -63,15 +63,21 @@ class CaucasusTheater(ConflictTheater): self.add_controlpoint(self.gudauta, connected_to=[self.sochi, self.sukhumi]) self.add_controlpoint(self.sochi, connected_to=[self.gudauta, self.gelendzhik]) - self.add_controlpoint(self.gelendzhik, connected_to=[self.sochi, ]) - self.add_controlpoint(self.krymsk, connected_to=[self.anapa, self.krasnodar]) + self.add_controlpoint(self.gelendzhik, connected_to=[self.sochi, self.krymsk]) + self.add_controlpoint(self.krymsk, connected_to=[self.anapa, self.krasnodar, self.gelendzhik]) self.add_controlpoint(self.anapa, connected_to=[self.krymsk]) self.add_controlpoint(self.krasnodar, connected_to=[self.krymsk, self.maykop]) self.add_controlpoint(self.carrier_1) + self.add_controlpoint(self.lha) self.carrier_1.captured = True + self.carrier_1.captured_invert = True + self.lha.captured = True + self.lha.captured_invert = True + self.batumi.captured = True + self.anapa.captured_invert = True """ @@ -102,7 +108,8 @@ class WesternGeorgia(ConflictTheater): self.sukhumi = ControlPoint.from_airport(caucasus.Sukhumi_Babushara, COAST_DR_E, SIZE_REGULAR, 1.2) self.gudauta = ControlPoint.from_airport(caucasus.Gudauta, COAST_DR_E, SIZE_REGULAR, 1.2) self.sochi = ControlPoint.from_airport(caucasus.Sochi_Adler, COAST_DR_E, SIZE_BIG, IMPORTANCE_HIGH) - self.carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-285810.6875, 496399.1875)) + self.carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-285810.6875, 496399.1875), 1001) + self.lha = ControlPoint.lha("Tarawa", mapping.Point(-326050.6875, 519452.1875), 1002) self.add_controlpoint(self.kutaisi, connected_to=[self.senaki]) self.add_controlpoint(self.senaki, connected_to=[self.kobuleti, self.sukhumi, self.kutaisi]) @@ -111,21 +118,26 @@ class WesternGeorgia(ConflictTheater): self.add_controlpoint(self.gudauta, connected_to=[self.sochi, self.sukhumi]) self.add_controlpoint(self.sochi, connected_to=[self.gudauta]) self.add_controlpoint(self.carrier_1) + self.add_controlpoint(self.lha) self.carrier_1.captured = True + self.carrier_1.captured_invert = True + self.lha.captured = True + self.lha.captured_invert = True self.kobuleti.captured = True + self.sochi.captured_invert = True """ Georgian Theather [inverted starting position] Ideal for smaller scale campaign """ -class WesternGeorgiaInverted(ConflictTheater): - +class RussiaSmall(ConflictTheater): terrain = caucasus.Caucasus() overview_image = "caumap.gif" reference_points = {(-317948.32727306, 635639.37385346): (278.5 * 4, 319 * 4), (-355692.3067714, 617269.96285781): (263 * 4, 352 * 4), } + landmap = load_landmap("resources\\caulandmap.p") daytime_map = { "dawn": (6, 9), @@ -134,30 +146,19 @@ class WesternGeorgiaInverted(ConflictTheater): "night": (0, 5), } - def __init__(self, load_ground_objects=True): - super(WesternGeorgiaInverted, self).__init__() + super(RussiaSmall, self).__init__() - self.kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, LAND, SIZE_SMALL, IMPORTANCE_LOW) - self.senaki = ControlPoint.from_airport(caucasus.Senaki_Kolkhi, LAND, SIZE_REGULAR, IMPORTANCE_LOW) - self.kobuleti = ControlPoint.from_airport(caucasus.Kobuleti, COAST_A_E, SIZE_SMALL, 1.1) - self.sukhumi = ControlPoint.from_airport(caucasus.Sukhumi_Babushara, COAST_DR_E, SIZE_REGULAR, 1.2) - self.gudauta = ControlPoint.from_airport(caucasus.Gudauta, COAST_DR_E, SIZE_REGULAR, 1.2) - self.sochi = ControlPoint.from_airport(caucasus.Sochi_Adler, COAST_DR_E, SIZE_BIG, IMPORTANCE_HIGH) - self.carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-285810.6875, 496399.1875)) - - self.add_controlpoint(self.kutaisi, connected_to=[self.senaki]) - self.add_controlpoint(self.senaki, connected_to=[self.kobuleti, self.sukhumi, self.kutaisi]) - self.add_controlpoint(self.kobuleti, connected_to=[self.senaki]) - self.add_controlpoint(self.sukhumi, connected_to=[self.gudauta, self.senaki]) - self.add_controlpoint(self.gudauta, connected_to=[self.sochi, self.sukhumi]) - self.add_controlpoint(self.sochi, connected_to=[self.gudauta]) - self.add_controlpoint(self.carrier_1) - - self.carrier_1.captured = True - self.sochi.captured = True + self.maykop = ControlPoint.from_airport(caucasus.Maykop_Khanskaya, LAND, SIZE_LARGE, IMPORTANCE_HIGH) + self.mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, LAND, SIZE_BIG, 1.3) + self.mozdok = ControlPoint.from_airport(caucasus.Mozdok, LAND, SIZE_BIG, 1.1) + self.add_controlpoint(self.mozdok, connected_to=[self.mineralnye]) + self.add_controlpoint(self.mineralnye, connected_to=[self.mozdok, self.maykop]) + self.add_controlpoint(self.maykop, connected_to=[self.mineralnye]) + self.mozdok.captured = True + self.maykop.captured_invert = True class NorthCaucasus(ConflictTheater): @@ -174,8 +175,6 @@ class NorthCaucasus(ConflictTheater): "night": (0, 5), } - carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-305810.6875, 406399.1875)) - def __init__(self, load_ground_objects=True): super(NorthCaucasus, self).__init__() @@ -186,7 +185,8 @@ class NorthCaucasus(ConflictTheater): self.nalchik = ControlPoint.from_airport(caucasus.Nalchik, LAND, SIZE_REGULAR, 1.1) self.mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, LAND, SIZE_BIG, 1.3) self.mozdok = ControlPoint.from_airport(caucasus.Mozdok, LAND, SIZE_BIG, 1.1) - self.carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-285810.6875, 496399.1875)) + self.carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-285810.6875, 496399.1875), 1001) + self.lha = ControlPoint.lha("Tarawa", mapping.Point(-326050.6875, 519452.1875), 1002) self.vaziani.frontline_offset = 0.5 self.vaziani.base.strength = 1 @@ -199,7 +199,14 @@ class NorthCaucasus(ConflictTheater): self.add_controlpoint(self.mineralnye, connected_to=[self.nalchik, self.mozdok, self.maykop]) self.add_controlpoint(self.maykop, connected_to=[self.mineralnye]) self.add_controlpoint(self.carrier_1, connected_to=[]) + self.add_controlpoint(self.lha, connected_to=[]) self.carrier_1.captured = True self.vaziani.captured = True self.kutaisi.captured = True + + self.carrier_1.captured_invert = True + self.maykop.captured_invert = True + self.lha.captured = True + self.lha.captured_invert = True + self.mineralnye.captured_invert = True diff --git a/theater/controlpoint.py b/theater/controlpoint.py index 0cf09872..49da85b4 100644 --- a/theater/controlpoint.py +++ b/theater/controlpoint.py @@ -4,7 +4,7 @@ from enum import Enum from dcs.mapping import * from dcs.terrain import Airport -from dcs.ships import CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov +from dcs.ships import CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov, Type_071_Amphibious_Transport_Dock from game import db from gen.ground_forces.combat_stance import CombatStance @@ -12,7 +12,7 @@ from .theatergroundobject import TheaterGroundObject class ControlPointType(Enum): - AIRBASE = 0 # An airbase with slot for everything + AIRBASE = 0 # An airbase with slots for everything AIRCRAFT_CARRIER_GROUP = 1 # A group with a Stennis type carrier (F/A-18, F-14 compatible) LHA_GROUP = 2 # A group with a Tarawa carrier (Helicopters & Harrier) FARP = 4 # A FARP, with slots for helicopters @@ -55,6 +55,7 @@ class ControlPoint: self.size = size self.importance = importance self.captured = False + self.captured_invert = False self.has_frontline = has_frontline self.radials = radials self.connected_points = [] @@ -75,7 +76,7 @@ class ControlPoint: return obj @classmethod - def carrier(cls, name: str, at: Point, id: int = 1001): + def carrier(cls, name: str, at: Point, id: int): import theater.conflicttheater cp = cls(id, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1, has_frontline=False, cptype=ControlPointType.AIRCRAFT_CARRIER_GROUP) @@ -87,7 +88,7 @@ class ControlPoint: return cp @classmethod - def lha(cls, name: str, at: Point, id: int = 1002): + def lha(cls, name: str, at: Point, id: int): import theater.conflicttheater cp = cls(id, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1, has_frontline=False, cptype=ControlPointType.LHA_GROUP) @@ -148,7 +149,7 @@ class ControlPoint: if g.dcs_identifier in ["CARRIER", "LHA"]: for group in g.groups: for u in group.units: - if db.unit_type_from_name(u.type) in [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov]: + if db.unit_type_from_name(u.type) in [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov, Type_071_Amphibious_Transport_Dock]: return True return False elif self.cptype in [ControlPointType.AIRBASE, ControlPointType.FARP]: diff --git a/theater/nevada.py b/theater/nevada.py index cfc440ad..a7b7d030 100644 --- a/theater/nevada.py +++ b/theater/nevada.py @@ -22,28 +22,21 @@ class NevadaTheater(ConflictTheater): def __init__(self): super(NevadaTheater, self).__init__() - self.tonopah = ControlPoint.from_airport(nevada.Tonopah_Airport, LAND, SIZE_SMALL, IMPORTANCE_LOW) self.tonopah_test_range = ControlPoint.from_airport(nevada.Tonopah_Test_Range_Airfield, LAND, SIZE_SMALL,IMPORTANCE_LOW) self.lincoln_conty = ControlPoint.from_airport(nevada.Lincoln_County, LAND, SIZE_SMALL, 1.2) - self.pahute_mesa = ControlPoint.from_airport(nevada.Pahute_Mesa_Airstrip, LAND, SIZE_SMALL, 1.1) self.groom_lake = ControlPoint.from_airport(nevada.Groom_Lake_AFB, LAND, SIZE_REGULAR, IMPORTANCE_HIGH) self.mesquite = ControlPoint.from_airport(nevada.Mesquite, LAND, SIZE_REGULAR, 1.3) - self.beatty = ControlPoint.from_airport(nevada.Beatty_Airport, LAND, SIZE_REGULAR, 1.1) self.creech = ControlPoint.from_airport(nevada.Creech_AFB, LAND, SIZE_BIG, IMPORTANCE_HIGH) - #self.las_vegas = ControlPoint.from_airport(nevada.North_Las_Vegas, LAND, SIZE_LARGE, IMPORTANCE_HIGH) - #self.jean = ControlPoint.from_airport(nevada.Jean_Airport, LAND, SIZE_REGULAR, 1.2) - #self.laughlin = ControlPoint.from_airport(nevada.Laughlin_Airport, LAND, SIZE_LARGE, IMPORTANCE_HIGH) + self.nellis = ControlPoint.from_airport(nevada.Nellis_AFB, LAND, SIZE_BIG, IMPORTANCE_HIGH) - self.add_controlpoint(self.tonopah, connected_to=[self.tonopah_test_range]) + self.add_controlpoint(self.tonopah_test_range, connected_to=[self.lincoln_conty, self.groom_lake]) + self.add_controlpoint(self.lincoln_conty, connected_to=[self.tonopah_test_range, self.mesquite]) + self.add_controlpoint(self.groom_lake, connected_to=[self.mesquite, self.creech, self.tonopah_test_range]) - self.add_controlpoint(self.tonopah_test_range, connected_to=[self.tonopah, self.lincoln_conty, self.pahute_mesa]) - self.add_controlpoint(self.lincoln_conty, connected_to=[self.tonopah_test_range, self.mesquite, self.groom_lake]) - self.add_controlpoint(self.pahute_mesa, connected_to=[self.groom_lake, self.tonopah_test_range, self.beatty, self.creech]) - self.add_controlpoint(self.groom_lake, connected_to=[self.pahute_mesa, self.lincoln_conty, self.mesquite]) + self.add_controlpoint(self.creech, connected_to=[self.groom_lake, self.nellis]) + self.add_controlpoint(self.mesquite, connected_to=[self.lincoln_conty, self.groom_lake]) + self.add_controlpoint(self.nellis, connected_to=[self.creech]) - self.add_controlpoint(self.beatty, connected_to=[self.pahute_mesa]) - self.add_controlpoint(self.creech, connected_to=[self.mesquite, self.pahute_mesa]) - self.add_controlpoint(self.mesquite, connected_to=[self.lincoln_conty, self.groom_lake, self.creech]) - - self.tonopah.captured = True + self.nellis.captured = True + self.tonopah_test_range.captured_invert = True diff --git a/theater/normandy.py b/theater/normandy.py index 5364db4b..dd67e9a6 100644 --- a/theater/normandy.py +++ b/theater/normandy.py @@ -44,6 +44,8 @@ class NormandyTheater(ConflictTheater): self.chailey.captured = True self.needOarPoint.captured = True + self.evreux.captured_invert = True + class NormandySmall(ConflictTheater): terrain = dcs.terrain.Normandy() @@ -77,3 +79,5 @@ class NormandySmall(ConflictTheater): self.deuxjumeaux.captured = True self.needOarPoint.captured = True + + self.evreux.captured_invert = True diff --git a/theater/persiangulf.py b/theater/persiangulf.py index f7465d7d..6826369b 100644 --- a/theater/persiangulf.py +++ b/theater/persiangulf.py @@ -10,8 +10,8 @@ class PersianGulfTheater(ConflictTheater): terrain = dcs.terrain.PersianGulf() overview_image = "persiangulf.gif" reference_points = { - (persiangulf.Sir_Abu_Nuayr.position.x, persiangulf.Sir_Abu_Nuayr.position.y): (423 * 4, 150 * 4), - (persiangulf.Sirri_Island.position.x, persiangulf.Sirri_Island.position.y): (447 * 4, 82 * 4), } + (persiangulf.Shiraz_International_Airport.position.x, persiangulf.Shiraz_International_Airport.position.y): (772, -1970), + (persiangulf.Liwa_Airbase.position.x, persiangulf.Liwa_Airbase.position.y): (1188, 78), } landmap = load_landmap("resources\\gulflandmap.p") daytime_map = { "dawn": (6, 8), @@ -48,8 +48,8 @@ class PersianGulfTheater(ConflictTheater): self.liwa = ControlPoint.from_airport(persiangulf.Liwa_Airbase, LAND, SIZE_BIG, IMPORTANCE_HIGH) self.jiroft = ControlPoint.from_airport(persiangulf.Jiroft_Airport, LAND, SIZE_BIG, IMPORTANCE_HIGH) self.bandar_e_jask = ControlPoint.from_airport(persiangulf.Bandar_e_Jask_airfield, LAND, SIZE_TINY,IMPORTANCE_LOW) - self.west_carrier = ControlPoint.carrier("West carrier", Point(-69043.813952358, -159916.65947136)) - self.east_carrier = ControlPoint.carrier("East carrier", Point(59514.324335475, 28165.517980635)) + self.west_carrier = ControlPoint.carrier("West carrier", Point(-69043.813952358, -159916.65947136), 1001) + self.east_carrier = ControlPoint.carrier("East carrier", Point(59514.324335475, 28165.517980635), 1002) self.add_controlpoint(self.liwa, connected_to=[self.al_dhafra]) self.add_controlpoint(self.al_dhafra, connected_to=[self.liwa, self.al_maktoum, self.al_ain]) @@ -84,13 +84,19 @@ class PersianGulfTheater(ConflictTheater): self.east_carrier.captured = True self.liwa.captured = True + self.west_carrier.captured_invert = True + self.east_carrier.captured_invert = True + self.shiraz.captured_invert = True + class IranianCampaign(ConflictTheater): terrain = dcs.terrain.PersianGulf() overview_image = "persiangulf.gif" - reference_points = {(persiangulf.Sir_Abu_Nuayr.position.x, persiangulf.Sir_Abu_Nuayr.position.y): (423*4, 150*4), - (persiangulf.Sirri_Island.position.x, persiangulf.Sirri_Island.position.y): (447*4, 82*4), } + reference_points = { + (persiangulf.Shiraz_International_Airport.position.x, persiangulf.Shiraz_International_Airport.position.y): ( + 772, -1970), + (persiangulf.Liwa_Airbase.position.x, persiangulf.Liwa_Airbase.position.y): (1188, 78), } landmap = load_landmap("resources\\gulflandmap.p") daytime_map = { "dawn": (6, 8), @@ -152,13 +158,16 @@ class IranianCampaign(ConflictTheater): self.havadarya.captured = True self.bandar_abbas.captured = True + self.shiraz.captured_invert = True + class Emirates(ConflictTheater): terrain = dcs.terrain.PersianGulf() overview_image = "persiangulf.gif" reference_points = { - (persiangulf.Sir_Abu_Nuayr.position.x, persiangulf.Sir_Abu_Nuayr.position.y): (423 * 4, 150 * 4), - (persiangulf.Sirri_Island.position.x, persiangulf.Sirri_Island.position.y): (447 * 4, 82 * 4), } + (persiangulf.Shiraz_International_Airport.position.x, persiangulf.Shiraz_International_Airport.position.y): ( + 772, -1970), + (persiangulf.Liwa_Airbase.position.x, persiangulf.Liwa_Airbase.position.y): (1188, 78), } landmap = load_landmap("resources\\gulflandmap.p") daytime_map = { "dawn": (6, 8), @@ -196,3 +205,7 @@ class Emirates(ConflictTheater): self.tarawa_carrier.captured = True self.east_carrier.captured = True self.fujairah.captured = True + + self.tarawa_carrier.captured_invert = True + self.east_carrier.captured_invert = True + self.fujairah.captured_invert = True diff --git a/theater/start_generator.py b/theater/start_generator.py index 634ee22a..26820755 100644 --- a/theater/start_generator.py +++ b/theater/start_generator.py @@ -5,6 +5,7 @@ import typing import logging from game.data.building_data import DEFAULT_AVAILABLE_BUILDINGS +from game.settings import Settings from gen import namegen, TheaterGroundObject from gen.defenses.armor_group_generator import generate_armor_group from gen.fleet.ship_group_generator import generate_carrier_group, generate_lha_group, generate_ship_group @@ -64,6 +65,7 @@ def generate_groundobjects(theater: ConflictTheater, game): tpls = pickle.load(f) group_id = 0 + cp_to_remove = [] for cp in theater.controlpoints: group_id = generate_cp_ground_points(cp, theater, game, group_id, tpls) @@ -75,7 +77,7 @@ def generate_groundobjects(theater: ConflictTheater, game): if cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP: # Create ground object group - group_id = group_id + 1 + group_id = game.next_group_id() g = TheaterGroundObject("CARRIER") g.group_id = group_id g.object_id = 0 @@ -94,9 +96,11 @@ def generate_groundobjects(theater: ConflictTheater, game): # Set new name : if "carrier_names" in db.FACTIONS[faction_name]: cp.name = random.choice(db.FACTIONS[faction_name]["carrier_names"]) + else: + cp_to_remove.append(cp) elif cp.cptype == ControlPointType.LHA_GROUP: # Create ground object group - group_id = group_id + 1 + group_id = game.next_group_id() g = TheaterGroundObject("LHA") g.group_id = group_id g.object_id = 0 @@ -115,19 +119,21 @@ def generate_groundobjects(theater: ConflictTheater, game): # Set new name : if "lhanames" in db.FACTIONS[faction_name]: cp.name = random.choice(db.FACTIONS[faction_name]["lhanames"]) + else: + cp_to_remove.append(cp) else: - for i in range(random.randint(3,6)): + for i in range(random.randint(3, 6)): logging.info("GENERATE BASE DEFENSE") - point = find_location(True, cp.position, theater, 1000, 2800, [], True) + point = find_location(True, cp.position, theater, 800, 3200, [], True) logging.info(point) if point is None: logging.info("Couldn't find point for {} base defense".format(cp)) continue - group_id = group_id + 1 + group_id = game.next_group_id() g = TheaterGroundObject("aa") g.group_id = group_id @@ -148,8 +154,15 @@ def generate_groundobjects(theater: ConflictTheater, game): for ground_object in cp.ground_objects: logging.info(ground_object.groups) + # Generate navy groups if "boat" in db.FACTIONS[faction_name].keys(): + if cp.captured and game.settings.do_not_generate_player_navy: + continue + + if not cp.captured and game.settings.do_not_generate_enemy_navy: + continue + boat_count = 1 if "boat_count" in db.FACTIONS[faction_name].keys(): boat_count = int(db.FACTIONS[faction_name]["boat_count"]) @@ -162,7 +175,7 @@ def generate_groundobjects(theater: ConflictTheater, game): logging.info("Couldn't find point for {} ships".format(cp)) continue - group_id = group_id + 1 + group_id = game.next_group_id() g = TheaterGroundObject("aa") g.group_id = group_id @@ -181,6 +194,8 @@ def generate_groundobjects(theater: ConflictTheater, game): g.groups.append(group) cp.ground_objects.append(g) + + if "missiles" in db.FACTIONS[faction_name].keys(): missiles_count = 1 @@ -195,7 +210,7 @@ def generate_groundobjects(theater: ConflictTheater, game): logging.info("Couldn't find point for {} missiles".format(cp)) continue - group_id = group_id + 1 + group_id = game.next_group_id() g = TheaterGroundObject("aa") g.group_id = group_id @@ -214,6 +229,9 @@ def generate_groundobjects(theater: ConflictTheater, game): g.groups.append(group) cp.ground_objects.append(g) + for cp in cp_to_remove: + theater.controlpoints.remove(cp) + def generate_airbase_defense_group(airbase_defense_group_id, ground_obj:TheaterGroundObject, faction, game, cp): @@ -341,7 +359,7 @@ def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templat continue object_id = 0 - group_id = group_id + 1 + group_id = game.next_group_id() logging.info("generated {} for {}".format(tpl_category, cp)) @@ -368,3 +386,37 @@ def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templat cp.ground_objects.append(g) return group_id + + +def prepare_theater(theater: ConflictTheater, settings:Settings, midgame): + + to_remove = [] + + # autocapture half the base if midgame + if midgame: + for i in range(0, int(len(theater.controlpoints) / 2)): + theater.controlpoints[i].captured = True + + # Remove carrier and lha, invert situation if needed + for cp in theater.controlpoints: + if cp.cptype is ControlPointType.AIRCRAFT_CARRIER_GROUP and settings.do_not_generate_carrier: + to_remove.append(cp) + elif cp.cptype is ControlPointType.LHA_GROUP and settings.do_not_generate_lha: + to_remove.append(cp) + + if settings.inverted: + cp.captured = cp.captured_invert + + # do remove + for cp in to_remove: + theater.controlpoints.remove(cp) + + # reapply midgame inverted if needed + if midgame and settings.inverted: + for i, cp in enumerate(reversed(theater.controlpoints)): + if i > len(theater.controlpoints): + break + else: + cp.captured = True + + diff --git a/theater/theatergroundobject.py b/theater/theatergroundobject.py index f7441663..42fc69f1 100644 --- a/theater/theatergroundobject.py +++ b/theater/theatergroundobject.py @@ -1,4 +1,5 @@ from dcs.mapping import Point +import uuid NAME_BY_CATEGORY = { "power": "Power plant", @@ -70,6 +71,7 @@ class TheaterGroundObject: groups = [] obj_name = "" sea_object = False + uuid = uuid.uuid1() def __init__(self, category: str): self.category = category diff --git a/theater/thechannel.py b/theater/thechannel.py index 97132d20..18b1a617 100644 --- a/theater/thechannel.py +++ b/theater/thechannel.py @@ -50,6 +50,12 @@ class ChannelTheater(ConflictTheater): self.lympne.captured = True self.manston.captured = True + self.manston.captured_invert = True + self.dunkirk.captured_invert = True + self.stomer.captured_invert = True + self.merville.captured_invert = True + self.abeville.captured_invert = True + class ChannelTheaterComplete(ConflictTheater): terrain = dcs.terrain.TheChannel() @@ -95,4 +101,9 @@ class ChannelTheaterComplete(ConflictTheater): #self.dunkirk.captured = True self.highhalden.captured = True self.lympne.captured = True - self.manston.captured = True \ No newline at end of file + self.manston.captured = True + + self.dunkirk.captured_invert = True + self.stomer.captured_invert = True + self.merville.captured_invert = True + self.abeville.captured_invert = True diff --git a/userdata/debriefing.py b/userdata/debriefing.py index 77364f5b..5886270e 100644 --- a/userdata/debriefing.py +++ b/userdata/debriefing.py @@ -1,17 +1,11 @@ import json import logging import os -import re import threading import time import typing -from dcs.lua import parse -from dcs.mission import Mission -from dcs.unit import UnitType - from game import db -from .persistency import base_path DEBRIEFING_LOG_EXTENSION = "log" @@ -35,7 +29,9 @@ class Debriefing: self.killed_ground_units = state_data["killed_ground_units"] self.weapons_fired = state_data["weapons_fired"] self.mission_ended = state_data["mission_ended"] + self.destroyed_units = state_data["destroyed_objects_positions"] + self.__destroyed_units = [] logging.info("--------------------------------") logging.info("Starting Debriefing preprocessing") logging.info("--------------------------------") @@ -44,6 +40,7 @@ class Debriefing: logging.info(self.killed_ground_units) logging.info(self.weapons_fired) logging.info(self.mission_ended) + logging.info(self.destroyed_units) logging.info("--------------------------------") self.player_country_id = db.country_id_from_name(game.player_country) @@ -166,20 +163,39 @@ class Debriefing: logging.info(self.enemy_dead_buildings_dict) -def _poll_new_debriefing_log(callback: typing.Callable, game): - if os.path.isfile("state.json"): - last_modified = os.path.getmtime("state.json") - else: - last_modified = 0 - while True: - if os.path.isfile("state.json") and os.path.getmtime("state.json") > last_modified: - with open("state.json", "r") as json_file: - json_data = json.load(json_file) #Debriefing.parse(os.path.join(debriefing_directory_location(), file)) - debriefing = Debriefing(json_data, game) - callback(debriefing) - break - time.sleep(5) +class PollDebriefingFileThread(threading.Thread): + """Thread class with a stop() method. The thread itself has to check + regularly for the stopped() condition.""" -def wait_for_debriefing(callback: typing.Callable, game): - threading.Thread(target=_poll_new_debriefing_log, args=[callback, game]).start() + def __init__(self, callback: typing.Callable, game): + super(PollDebriefingFileThread, self).__init__() + self._stop_event = threading.Event() + self.callback = callback + self.game = game + + def stop(self): + self._stop_event.set() + + def stopped(self): + return self._stop_event.is_set() + + def run(self): + if os.path.isfile("state.json"): + last_modified = os.path.getmtime("state.json") + else: + last_modified = 0 + while not self.stopped(): + if os.path.isfile("state.json") and os.path.getmtime("state.json") > last_modified: + with open("state.json", "r") as json_file: + json_data = json.load(json_file) + debriefing = Debriefing(json_data, self.game) + self.callback(debriefing) + break + time.sleep(5) + + +def wait_for_debriefing(callback: typing.Callable, game)->PollDebriefingFileThread: + thread = PollDebriefingFileThread(callback, game) + thread.start() + return thread diff --git a/userdata/liberation_theme.py b/userdata/liberation_theme.py new file mode 100644 index 00000000..703d15ee --- /dev/null +++ b/userdata/liberation_theme.py @@ -0,0 +1,74 @@ +import json +import os + +import qt_ui.uiconstants as CONST + +global __theme_index + +THEME_PREFERENCES_FILE_PATH = "liberation_theme.json" + +DEFAULT_THEME_INDEX = 1 + + +def init(): + global __theme_index + + __theme_index = DEFAULT_THEME_INDEX + print("init setting theme index to " + str(__theme_index)) + + if os.path.isfile(THEME_PREFERENCES_FILE_PATH): + try: + with(open(THEME_PREFERENCES_FILE_PATH)) as prefs: + pref_data = json.loads(prefs.read()) + __theme_index = pref_data["theme_index"] + print(__theme_index) + set_theme_index(__theme_index) + save_theme_config() + print("file setting theme index to " + str(__theme_index)) + except: + # is this necessary? + set_theme_index(DEFAULT_THEME_INDEX) + print("except setting theme index to " + str(__theme_index)) + else: + # is this necessary? + set_theme_index(DEFAULT_THEME_INDEX) + print("else setting theme index to " + str(__theme_index)) + + +# set theme index then use save_theme_config to save to file +def set_theme_index(x): + global __theme_index + __theme_index = x + + +# get theme index to reference other theme properties(themeName, themeFile, themeIcons) +def get_theme_index(): + global __theme_index + return __theme_index + + +# get theme name based on current index +def get_theme_name(): + theme_name = CONST.THEMES[get_theme_index()]['themeName'] + return theme_name + + +# get theme icon sub-folder name based on current index +def get_theme_icons(): + theme_icons = CONST.THEMES[get_theme_index()]['themeIcons'] + return str(theme_icons) + + +# get theme stylesheet css based on current index +def get_theme_css_file(): + theme_file = CONST.THEMES[get_theme_index()]['themeFile'] + return str(theme_file) + + +# save current theme index to json file +def save_theme_config(): + pref_data = { + "theme_index": get_theme_index() + } + with(open(THEME_PREFERENCES_FILE_PATH, "w")) as prefs: + prefs.write(json.dumps(pref_data)) diff --git a/userdata/persistency.py b/userdata/persistency.py index 27af4677..9e55dda0 100644 --- a/userdata/persistency.py +++ b/userdata/persistency.py @@ -4,31 +4,30 @@ import pickle import shutil _dcs_saved_game_folder = None # type: str - +_file_abs_path = None def setup(user_folder: str): global _dcs_saved_game_folder _dcs_saved_game_folder = user_folder - + _file_abs_path = os.path.join(base_path(), "default.liberation") def base_path() -> str: global _dcs_saved_game_folder assert _dcs_saved_game_folder return _dcs_saved_game_folder - def _save_file() -> str: - return os.path.join(base_path(), "liberation_save") - + return os.path.join(base_path(), "default.liberation") def _temporary_save_file() -> str: - return os.path.join(base_path(), "liberation_save_tmp") + return os.path.join(base_path(), "tmpsave.liberation") +def _autosave_path() -> str: + return os.path.join(base_path(), "autosave.liberation") def _save_file_exists() -> bool: return os.path.exists(_save_file()) - def mission_path_for(name: str) -> str: return os.path.join(base_path(), "Missions", "{}".format(name)) @@ -45,13 +44,37 @@ def restore_game(): logging.error("Invalid Save game") return None +def load_game(path): + with open(path, "rb") as f: + try: + save = pickle.load(f) + save.savepath = path + return save + except: + logging.error("Invalid Save game") + return None def save_game(game) -> bool: try: with open(_temporary_save_file(), "wb") as f: pickle.dump(game, f) - shutil.copy(_temporary_save_file(), _save_file()) + shutil.copy(_temporary_save_file(), game.savepath) return True except Exception as e: logging.error(e) return False + +def autosave(game) -> bool: + """ + Autosave to the autosave location + :param game: Game to save + :return: True if saved succesfully + """ + try: + with open(_autosave_path(), "wb") as f: + pickle.dump(game, f) + return True + except Exception as e: + logging.error(e) + return False +