Merge pull request #46 from Khopa/develop

Merge develop 2.0.10
This commit is contained in:
C. Perreau 2020-08-13 00:02:21 +02:00 committed by GitHub
commit db8e7f0474
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
220 changed files with 7391 additions and 1103 deletions

View File

@ -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 # 2.0 RC 9
## Features/Improvements : ## Features/Improvements :

View File

@ -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,
]

View File

@ -49,6 +49,5 @@ UNITS_WITH_RADAR = [
LHA_1_Tarawa, LHA_1_Tarawa,
Type_052B_Destroyer, Type_052B_Destroyer,
Type_054A_Frigate, Type_054A_Frigate,
Type_052C_Destroyer, Type_052C_Destroyer
Type_093,
] ]

View File

@ -13,20 +13,29 @@ from dcs.unit import *
from dcs.unittype import * from dcs.unittype import *
from dcs.unitgroup import * from dcs.unitgroup import *
from game.factions.australia_2005 import Australia_2005
from game.factions.bluefor_coldwar import BLUEFOR_COLDWAR 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_1995 import France_1995
from game.factions.france_2005 import France_2005 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_1944_easy import Germany_1944_Easy
from game.factions.germany_1990 import Germany_1990 from game.factions.germany_1990 import Germany_1990
from game.factions.insurgent import Insurgent 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.iran_2015 import Iran_2015
from game.factions.israel_2000 import Israel_2000 from game.factions.israel_2000 import Israel_2000
from game.factions.italy_1990 import Italy_1990 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.libya_2011 import Lybia_2011
from game.factions.netherlands_1990 import Netherlands_1990 from game.factions.netherlands_1990 import Netherlands_1990
from game.factions.north_korea_2000 import NorthKorea_2000 from game.factions.north_korea_2000 import NorthKorea_2000
from game.factions.pakistan_2015 import Pakistan_2015 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.russia_1975 import Russia_1975
from game.factions.germany_1944 import Germany_1944 from game.factions.germany_1944 import Germany_1944
from game.factions.india_2010 import India_2010 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.sweden_1990 import Sweden_1990
from game.factions.turkey_2005 import Turkey_2005 from game.factions.turkey_2005 import Turkey_2005
from game.factions.uae_2005 import UAE_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.uk_1990 import UnitedKingdom_1990
from game.factions.ukraine_2010 import Ukraine_2010 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_1955 import USA_1955
from game.factions.usa_1960 import USA_1960 from game.factions.usa_1960 import USA_1960
from game.factions.usa_1965 import USA_1965 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.usa_2005 import USA_2005
from game.factions.bluefor_modern import BLUEFOR_MODERN 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 ---------- BEGINNING OF CONFIGURATION SECTION
""" """
@ -103,6 +161,8 @@ PRICES = {
F_4E: 10, F_4E: 10,
AJS37: 12, AJS37: 12,
C_101CC: 6, C_101CC: 6,
A_4E_C: 8,
MB_339PAN: 6,
AV8BNA: 14, AV8BNA: 14,
M_2000C: 16, M_2000C: 16,
@ -131,13 +191,15 @@ PRICES = {
Ka_50: 13, Ka_50: 13,
SA342M: 8, SA342M: 8,
SA342L: 5, SA342L: 5,
SA342Minigun: 4,
SA342Mistral: 8,
UH_1H: 4, UH_1H: 4,
Mi_8MT: 5, Mi_8MT: 5,
Mi_24V: 12, Mi_24V: 18,
Mi_28N: 16, Mi_28N: 24,
AH_1W: 10, AH_1W: 20,
AH_64A: 12, AH_64A: 24,
AH_64D: 16, AH_64D: 30,
OH_58D: 6, OH_58D: 6,
# Bombers # Bombers
@ -164,6 +226,10 @@ PRICES = {
P_47D_30: 18, P_47D_30: 18,
B_17G: 30, B_17G: 30,
# Modded
Rafale_M: 26,
Rafale_A_S: 26,
# armor # armor
Armor.APC_MTLB: 4, Armor.APC_MTLB: 4,
Armor.FDDM_Grad: 5, Armor.FDDM_Grad: 5,
@ -171,15 +237,15 @@ PRICES = {
Armor.ARV_BTR_RD: 8, Armor.ARV_BTR_RD: 8,
Armor.APC_BTR_80: 8, Armor.APC_BTR_80: 8,
Armor.MBT_T_55: 18, Armor.MBT_T_55: 18,
Armor.MBT_T_72B: 25, Armor.MBT_T_72B: 22,
Armor.MBT_T_80U: 30, Armor.MBT_T_80U: 25,
Armor.MBT_T_90: 35, Armor.MBT_T_90: 30,
Armor.IFV_BMD_1: 8, Armor.IFV_BMD_1: 8,
Armor.IFV_BMP_1: 14, Armor.IFV_BMP_1: 14,
Armor.IFV_BMP_2: 16, Armor.IFV_BMP_2: 16,
Armor.IFV_BMP_3: 18, Armor.IFV_BMP_3: 18,
Armor.ZBD_04A: 12, Armor.ZBD_04A: 12,
Armor.ZTZ_96B: 35, Armor.ZTZ_96B: 30,
Armor.APC_Cobra: 4, Armor.APC_Cobra: 4,
Armor.APC_M113: 6, Armor.APC_M113: 6,
@ -188,14 +254,14 @@ PRICES = {
Armor.IFV_M2A2_Bradley: 12, Armor.IFV_M2A2_Bradley: 12,
Armor.APC_M1126_Stryker_ICV: 10, Armor.APC_M1126_Stryker_ICV: 10,
Armor.ATGM_M1134_Stryker: 12, Armor.ATGM_M1134_Stryker: 12,
Armor.MBT_M60A3_Patton: 18, Armor.MBT_M60A3_Patton: 16,
Armor.MBT_M1A2_Abrams: 35, Armor.MBT_M1A2_Abrams: 25,
Armor.MBT_Leclerc: 35, Armor.MBT_Leclerc: 25,
Armor.MBT_Leopard_1A3: 24, Armor.MBT_Leopard_1A3: 20,
Armor.MBT_Leopard_2: 35, Armor.MBT_Leopard_2: 25,
Armor.MBT_Merkava_Mk__4: 35, Armor.MBT_Merkava_Mk__4: 25,
Armor.TPz_Fuchs: 5, Armor.TPz_Fuchs: 5,
Armor.MBT_Challenger_II: 30, Armor.MBT_Challenger_II: 25,
Armor.IFV_Marder: 10, Armor.IFV_Marder: 10,
Armor.IFV_MCV_80: 10, Armor.IFV_MCV_80: 10,
Armor.IFV_LAV_25: 7, Armor.IFV_LAV_25: 7,
@ -208,7 +274,7 @@ PRICES = {
Artillery.SPH_2S3_Akatsia: 24, Artillery.SPH_2S3_Akatsia: 24,
Artillery.SPH_2S19_Msta: 30, Artillery.SPH_2S19_Msta: 30,
Artillery.MLRS_BM_21_Grad: 15, 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, Artillery.MLRS_9A52_Smerch: 40,
Unarmed.Transport_UAZ_469: 3, Unarmed.Transport_UAZ_469: 3,
@ -270,6 +336,38 @@ PRICES = {
Armed_speedboat: 10, Armed_speedboat: 10,
Dry_cargo_ship_Ivanov: 10, Dry_cargo_ship_Ivanov: 10,
Tanker_Elnya_160: 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, FW_190A8,
SpitfireLFMkIXCW, SpitfireLFMkIXCW,
SpitfireLFMkIX, SpitfireLFMkIX,
A_4E_C,
Rafale_M,
SA342Mistral
], ],
CAS: [ CAS: [
F_86F_Sabre, F_86F_Sabre,
@ -333,6 +434,7 @@ UNIT_BY_TASK = {
Ka_50, Ka_50,
SA342M, SA342M,
SA342L, SA342L,
SA342Minigun,
Su_24M, Su_24M,
Su_24MR, Su_24MR,
AH_64A, AH_64A,
@ -350,7 +452,9 @@ UNIT_BY_TASK = {
A_20G, A_20G,
P_47D_30, P_47D_30,
Ju_88A4, Ju_88A4,
B_17G B_17G,
MB_339PAN,
Rafale_A_S
], ],
Transport: [ Transport: [
IL_76MD, IL_76MD,
@ -513,6 +617,29 @@ UNIT_BY_TASK = {
Artillery.M12_GMC, Artillery.M12_GMC,
Artillery.Sturmpanzer_IV_Brummbär, 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: [ AirDefence: [
@ -602,46 +729,83 @@ Units separated by country.
country : DCS Country name country : DCS Country name
""" """
FACTIONS = { 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 1955": Russia_1955,
"Russia 1965": Russia_1965, "Russia 1965": Russia_1965,
"Russia 1975": Russia_1975, "Russia 1975": Russia_1975,
"Russia 1990": Russia_1990, "Russia 1990": Russia_1990,
"Russia 2010": Russia_2010, "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, "Lybia 2011": Lybia_2011,
"China 2000": China_2000,
"Pakistan 2015": Pakistan_2015,
"Iran 2015": Iran_2015,
"North Korea 2000": NorthKorea_2000, "North Korea 2000": NorthKorea_2000,
"Insurgent": Insurgent, "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 (WW2 Pack)": Germany_1944,
"Germany 1944 Easy (WW2 Pack)": Germany_1944_Easy, "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 = { CARRIER_TYPE_BY_PLANE = {
@ -749,6 +913,12 @@ PLANE_PAYLOAD_OVERRIDES = {
Bf_109K_4: COMMON_OVERRIDE, Bf_109K_4: COMMON_OVERRIDE,
SpitfireLFMkIXCW: COMMON_OVERRIDE, SpitfireLFMkIXCW: COMMON_OVERRIDE,
SpitfireLFMkIX: 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:{ AH_64D:{
CAS: "AGM-114K*16" CAS: "AGM-114K*16"
@ -825,12 +995,14 @@ CARRIER_CAPABLE = [
F_14B, F_14B,
AV8BNA, AV8BNA,
Su_33, Su_33,
A_4E_C,
UH_1H, UH_1H,
Mi_8MT, Mi_8MT,
Ka_50, Ka_50,
AH_1W, AH_1W,
OH_58D, OH_58D,
UH_60A,
SA342L, SA342L,
SA342M, SA342M,
@ -846,6 +1018,7 @@ LHA_CAPABLE = [
Ka_50, Ka_50,
AH_1W, AH_1W,
OH_58D, OH_58D,
UH_60A,
SA342L, SA342L,
SA342M, SA342M,
@ -919,6 +1092,8 @@ def find_infantry(country_name: str) -> typing.List[UnitType]:
def unit_type_name(unit_type) -> str: def unit_type_name(unit_type) -> str:
return unit_type.id and unit_type.id or unit_type.name 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: def unit_type_from_name(name: str) -> UnitType:
if name in vehicle_map: if name in vehicle_map:

View File

@ -206,10 +206,10 @@ class Event:
# ------------------------------ # ------------------------------
# Captured bases # Captured bases
if self.game.player_country in db.BLUEFOR_FACTIONS: #if self.game.player_country in db.BLUEFOR_FACTIONS:
coalition = 2 # Value in DCS mission event for BLUE coalition = 2 # Value in DCS mission event for BLUE
else: #else:
coalition = 1 # Value in DCS mission event for RED # coalition = 1 # Value in DCS mission event for RED
for captured in debriefing.base_capture_events: for captured in debriefing.base_capture_events:
try: try:
@ -253,6 +253,12 @@ class Event:
except Exception as e: except Exception as e:
print(e) print(e)
# Destroyed units carcass
# -------------------------
for destroyed_unit in debriefing.destroyed_units:
self.game.add_destroyed_units(destroyed_unit)
# ----------------------------------- # -----------------------------------
# Compute damage to bases # Compute damage to bases
for cp in self.game.theater.player_points(): for cp in self.game.theater.player_points():

View File

@ -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
}

View File

@ -42,10 +42,6 @@ BLUEFOR_COLDWAR = {
CVN_74_John_C__Stennis, CVN_74_John_C__Stennis,
], "helicopter_carrier": [ ], "helicopter_carrier": [
LHA_1_Tarawa, LHA_1_Tarawa,
], "destroyer": [
Oliver_Hazzard_Perry_class,
], "cruiser": [
Ticonderoga_class,
], "carrier_names": [ ], "carrier_names": [
"CVN-71 Theodore Roosevelt", "CVN-71 Theodore Roosevelt",
"CVN-72 Abraham Lincoln", "CVN-72 Abraham Lincoln",
@ -58,6 +54,5 @@ BLUEFOR_COLDWAR = {
"LHA-4 Nassau", "LHA-4 Nassau",
"LHA-5 Peleliu" "LHA-5 Peleliu"
], "boat": [ ], "boat": [
"OliverHazardPerryGroupGenerator" ], "has_jtac": True
]
} }

View File

@ -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
}

View File

@ -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
}

View File

@ -78,5 +78,5 @@ BLUEFOR_MODERN = {
"LHA-5 Peleliu" "LHA-5 Peleliu"
], "boat":[ ], "boat":[
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -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
}

View File

@ -3,7 +3,7 @@ from dcs.planes import *
from dcs.ships import * from dcs.ships import *
from dcs.vehicles import * from dcs.vehicles import *
China_2000 = { China_2010 = {
"country": "China", "country": "China",
"side": "red", "side": "red",
"units": [ "units": [
@ -37,7 +37,9 @@ China_2000 = {
Unarmed.Transport_Ural_375, Unarmed.Transport_Ural_375,
Unarmed.Transport_UAZ_469, Unarmed.Transport_UAZ_469,
Infantry.Soldier_AK,
Infantry.Paratrooper_AKS,
Infantry.Infantry_Soldier_Rus,
Infantry.Paratrooper_RPG_16, Infantry.Paratrooper_RPG_16,
CV_1143_5_Admiral_Kuznetsov, CV_1143_5_Admiral_Kuznetsov,
@ -56,10 +58,20 @@ China_2000 = {
Type_052C_Destroyer Type_052C_Destroyer
], "cruiser": [ ], "cruiser": [
Type_054A_Frigate, 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": [ ], "carrier_names": [
"001 Liaoning", "001 Liaoning",
"002 Shandong", "002 Shandong",
], "boat":[ ], "boat":[
"ChineseNavyGroupGenerator", "Type54GroupGenerator" "Type54GroupGenerator"
] ], "has_jtac": True
} }

View File

@ -17,6 +17,7 @@ France_1995 = {
SA342M, SA342M,
SA342L, SA342L,
SA342Mistral,
Armor.MBT_Leclerc, Armor.MBT_Leclerc,
Armor.TPz_Fuchs, # Standing as VAB Armor.TPz_Fuchs, # Standing as VAB
@ -42,5 +43,5 @@ France_1995 = {
AirDefence.SAM_Roland_ADS AirDefence.SAM_Roland_ADS
], "boat":[ ], "boat":[
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -18,6 +18,7 @@ France_2005 = {
SA342M, SA342M,
SA342L, SA342L,
SA342Mistral,
Armor.MBT_Leclerc, Armor.MBT_Leclerc,
Armor.TPz_Fuchs, # Standing as VAB Armor.TPz_Fuchs, # Standing as VAB
@ -50,12 +51,12 @@ France_2005 = {
], "cruiser": [ ], "cruiser": [
Ticonderoga_class, Ticonderoga_class,
], "carrier_names": [ ], "carrier_names": [
"R91 Charles de Gaulle", "PA Charles de Gaulle",
], "lhanames": [ ], "lhanames": [
"L9013 Mistral", "L9013 Mistral",
"L9014 Tonerre", "L9014 Tonerre",
"L9015 Dixmude" "L9015 Dixmude"
], "boat":[ ], "boat":[
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -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
}

View File

@ -39,7 +39,7 @@ Germany_1944 = {
"objects": WW2_GERMANY_BUILDINGS, "objects": WW2_GERMANY_BUILDINGS,
"doctrine": WWII_DOCTRINE, "doctrine": WWII_DOCTRINE,
"boat": ["UBoatGroupGenerator", "SchnellbootGroupGenerator"], "boat": ["UBoatGroupGenerator", "SchnellbootGroupGenerator"],
"boat_count": 4, "boat_count": 2,
"missiles": ["V1GroupGenerator"], "missiles": ["V1GroupGenerator"],
"missiles_count": 1 "missiles_count": 1
} }

View File

@ -32,7 +32,7 @@ Germany_1944_Easy = {
"objects": WW2_GERMANY_BUILDINGS, "objects": WW2_GERMANY_BUILDINGS,
"doctrine": WWII_DOCTRINE, "doctrine": WWII_DOCTRINE,
"boat": ["UBoatGroupGenerator", "SchnellbootGroupGenerator"], "boat": ["UBoatGroupGenerator", "SchnellbootGroupGenerator"],
"boat_count": 4, "boat_count": 1,
"missiles": ["V1GroupGenerator"], "missiles": ["V1GroupGenerator"],
"missiles_count": 1 "missiles_count": 1
} }

View File

@ -51,5 +51,5 @@ India_2010 = {
"INS Vikramaditya" "INS Vikramaditya"
], "boat":[ ], "boat":[
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator", "MolniyaGroupGenerator" "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator", "MolniyaGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -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",
}
}

View File

@ -35,5 +35,5 @@ Israel_2000 = {
AirDefence.SAM_Avenger_M1097 AirDefence.SAM_Avenger_M1097
], "boat": [ ], "boat": [
"ArleighBurkeGroupGenerator" "ArleighBurkeGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -39,10 +39,10 @@ Italy_1990 = {
Oliver_Hazzard_Perry_class, Oliver_Hazzard_Perry_class,
], "cruiser": [ ], "cruiser": [
Ticonderoga_class, Ticonderoga_class,
], "lha_names": [ ], "lhanames": [
"Giuseppe Garibaldi", "Giuseppe Garibaldi",
"Cavour", "Cavour",
], "boat":[ ], "boat":[
"OliverHazardPerryGroupGenerator" "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -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
}

View File

@ -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
}

View File

@ -3,7 +3,7 @@ from dcs.planes import *
from dcs.vehicles import * from dcs.vehicles import *
Lybia_2011 = { Lybia_2011 = {
"country": "Russia", "country": "Lybia",
"side": "red", "side": "red",
"units": [ "units": [

View File

@ -34,5 +34,5 @@ Netherlands_1990 = {
AirDefence.SAM_Avenger_M1097 AirDefence.SAM_Avenger_M1097
], "boat": [ ], "boat": [
"OliverHazardPerryGroupGenerator" "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -36,5 +36,5 @@ Pakistan_2015 = {
AirDefence.AAA_ZU_23_Closed AirDefence.AAA_ZU_23_Closed
], "boat": [ ], "boat": [
"Type54GroupGenerator", "OliverHazardPerryGroupGenerator" "Type54GroupGenerator", "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -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
}

View File

@ -58,6 +58,9 @@ Russia_1990 = {
AirDefence.SAM_SA_9_Strela_1_9P31, AirDefence.SAM_SA_9_Strela_1_9P31,
AirDefence.SAM_SA_13_Strela_10M3_9A35M3, AirDefence.SAM_SA_13_Strela_10M3_9A35M3,
AirDefence.SPAAA_ZSU_23_4_Shilka AirDefence.SPAAA_ZSU_23_4_Shilka
], "carrier_names": [
"Admiral Kuznetov",
"Admiral Gorshkov"
], "aircraft_carrier": [ ], "aircraft_carrier": [
CV_1143_5_Admiral_Kuznetsov, CV_1143_5_Admiral_Kuznetsov,
], "destroyer": [ ], "destroyer": [

View File

@ -7,7 +7,6 @@ Russia_2010 = {
"country": "Russia", "country": "Russia",
"side": "red", "side": "red",
"units": [ "units": [
AJS37,
MiG_23MLD, MiG_23MLD,
Su_25, Su_25,
Su_27, Su_27,
@ -37,6 +36,9 @@ Russia_2010 = {
Armor.MBT_T_90, Armor.MBT_T_90,
Armor.MBT_T_80U, Armor.MBT_T_80U,
Armor.MBT_T_72B, Armor.MBT_T_72B,
Armor.IFV_BMP_1,
Armor.IFV_BMP_2,
Armor.IFV_BMP_3,
Artillery.MLRS_9K57_Uragan_BM_27, Artillery.MLRS_9K57_Uragan_BM_27,
Artillery.SPH_2S19_Msta, Artillery.SPH_2S19_Msta,
@ -59,6 +61,8 @@ Russia_2010 = {
AirDefence.SAM_SA_13_Strela_10M3_9A35M3 AirDefence.SAM_SA_13_Strela_10M3_9A35M3
], "aircraft_carrier": [ ], "aircraft_carrier": [
CV_1143_5_Admiral_Kuznetsov, CV_1143_5_Admiral_Kuznetsov,
], "carrier_names": [
"Admiral Kuznetov"
], "destroyer": [ ], "destroyer": [
FF_1135M_Rezky, FF_1135M_Rezky,
], "cruiser": [ ], "cruiser": [

View File

@ -46,5 +46,5 @@ Spain_1990 = {
"Juan Carlos I", "Juan Carlos I",
], "boat":[ ], "boat":[
"OliverHazardPerryGroupGenerator" "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -27,5 +27,5 @@ Sweden_1990 = {
], ],
"shorad": [ "shorad": [
AirDefence.SAM_Avenger_M1097 AirDefence.SAM_Avenger_M1097
] ], "has_jtac": True
} }

View File

@ -38,5 +38,5 @@ Turkey_2005 = {
AirDefence.SPAAA_ZSU_23_4_Shilka AirDefence.SPAAA_ZSU_23_4_Shilka
], "boat":[ ], "boat":[
"OliverHazardPerryGroupGenerator" "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -32,5 +32,5 @@ UAE_2005 = {
Armed_speedboat, Armed_speedboat,
], "boat":[ ], "boat":[
"OliverHazardPerryGroupGenerator" "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

42
game/factions/uk_1944.py Normal file
View File

@ -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
}

View File

@ -16,7 +16,7 @@ UnitedKingdom_1990 = {
C_130, C_130,
E_3A, E_3A,
SA342L, SA342M,
AH_64A, AH_64A,
Armor.MBT_Challenger_II, Armor.MBT_Challenger_II,
@ -42,11 +42,11 @@ UnitedKingdom_1990 = {
Oliver_Hazzard_Perry_class, Oliver_Hazzard_Perry_class,
], "cruiser": [ ], "cruiser": [
Ticonderoga_class, Ticonderoga_class,
], "lha_names": [ ], "lhanames": [
"HMS Invincible", "HMS Invincible",
"HMS Illustrious", "HMS Illustrious",
"HMS Ark Royal", "HMS Ark Royal",
], "boat":[ ], "boat":[
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -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"
]
}

View File

@ -6,6 +6,40 @@ from game.data.building_data import WW2_ALLIES_BUILDINGS
from game.data.doctrine import WWII_DOCTRINE from game.data.doctrine import WWII_DOCTRINE
USA_1944 = { 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", "country": "USA",
"side": "blue", "side": "blue",
"units": [ "units": [

View File

@ -37,6 +37,5 @@ USA_1965 = {
AirDefence.AAA_Vulcan_M163, AirDefence.AAA_Vulcan_M163,
AirDefence.SAM_Chaparral_M48 AirDefence.SAM_Chaparral_M48
], "boat":[ ], "boat":[
"OliverHazardPerryGroupGenerator"
] ]
} }

View File

@ -61,5 +61,5 @@ USA_1990 = {
"LHA-5 Peleliu" "LHA-5 Peleliu"
], "boat":[ ], "boat":[
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator" "ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -11,7 +11,6 @@ USA_2005 = {
F_14B, F_14B,
FA_18C_hornet, FA_18C_hornet,
F_16C_50, F_16C_50,
JF_17,
A_10C, A_10C,
AV8BNA, AV8BNA,
@ -67,5 +66,5 @@ USA_2005 = {
"LHA-5 Peleliu" "LHA-5 Peleliu"
], "boat":[ ], "boat":[
"ArleighBurkeGroupGenerator" "ArleighBurkeGroupGenerator"
] ], "has_jtac": True
} }

View File

@ -1,7 +1,7 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from game.db import REWARDS, PLAYER_BUDGET_BASE, sys 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.flights.ai_flight_planner import FlightPlanner
from gen.ground_forces.ai_ground_planner import GroundPlanner from gen.ground_forces.ai_ground_planner import GroundPlanner
from .event import * from .event import *
@ -56,8 +56,8 @@ class Game:
current_unit_id = 0 current_unit_id = 0
current_group_id = 0 current_group_id = 0
def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater, start_date: datetime): def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater, start_date: datetime, settings):
self.settings = Settings() self.settings = settings
self.events = [] self.events = []
self.theater = theater self.theater = theater
self.player_name = player_name self.player_name = player_name
@ -73,7 +73,26 @@ class Game:
self.informations = [] self.informations = []
self.informations.append(Information("Game Start", "-" * 40, 0)) self.informations.append(Information("Game Start", "-" * 40, 0))
self.__culling_points = self.compute_conflicts_position() 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 @property
def player_faction(self): def player_faction(self):
@ -175,18 +194,6 @@ class Game:
else: else:
return event.name == self.player_name 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): def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint] = None):
logging.info("Pass turn") logging.info("Pass turn")
@ -237,6 +244,9 @@ class Game:
gplanner.plan_groundwar() gplanner.plan_groundwar()
self.ground_planners[cp.id] = gplanner self.ground_planners[cp.id] = gplanner
# Autosave progress
persistency.autosave(self)
def _enemy_reinforcement(self): def _enemy_reinforcement(self):
""" """
Compute and commision reinforcement for enemy bases Compute and commision reinforcement for enemy bases
@ -340,6 +350,8 @@ class Game:
# By default, use the existing frontline conflict position # By default, use the existing frontline conflict position
for conflict in self.theater.conflicts(): for conflict in self.theater.conflicts():
points.append(Conflict.frontline_position(self.theater, conflict[0], conflict[1])[0]) 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 there is no conflict take the center point between the two nearest opposing bases
if len(points) == 0: if len(points) == 0:
@ -351,6 +363,11 @@ class Game:
if d < min_distance: if d < min_distance:
min_distance = d min_distance = d
cpoint = Point((cp.position.x + cp2.position.x) / 2, (cp.position.y + cp2.position.y) / 2) 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: if cpoint is not None:
points.append(cpoint) points.append(cpoint)
@ -361,6 +378,12 @@ class Game:
return points 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): def position_culled(self, pos):
""" """
Check if unit can be generated at given position depending on culling performance settings Check if unit can be generated at given position depending on culling performance settings
@ -375,3 +398,21 @@ class Game:
return False return False
return True 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"

View File

@ -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

View File

@ -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 = []

View File

@ -47,29 +47,6 @@ class FrontlineAttackOperation(Operation):
conflict=conflict) conflict=conflict)
def generate(self): 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.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.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") self.briefinggen.append_waypoint("CAS AREA IP")

View File

@ -18,7 +18,6 @@ class Operation:
conflict = None # type: Conflict conflict = None # type: Conflict
armorgen = None # type: ArmorConflictGenerator armorgen = None # type: ArmorConflictGenerator
airgen = None # type: AircraftConflictGenerator airgen = None # type: AircraftConflictGenerator
shipgen = None # type: ShipGenerator
triggersgen = None # type: TriggersGenerator triggersgen = None # type: TriggersGenerator
airsupportgen = None # type: AirSupportConflictGenerator airsupportgen = None # type: AirSupportConflictGenerator
visualgen = None # type: VisualGenerator visualgen = None # type: VisualGenerator
@ -65,7 +64,6 @@ class Operation:
self.current_mission = mission self.current_mission = mission
self.conflict = conflict self.conflict = conflict
self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings, self.game) self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings, self.game)
self.shipgen = ShipGenerator(mission, conflict)
self.airsupportgen = AirSupportConflictGenerator(mission, conflict, self.game) self.airsupportgen = AirSupportConflictGenerator(mission, conflict, self.game)
self.triggersgen = TriggersGenerator(mission, conflict, self.game) self.triggersgen = TriggersGenerator(mission, conflict, self.game)
self.visualgen = VisualGenerator(mission, conflict, self.game) self.visualgen = VisualGenerator(mission, conflict, self.game)
@ -90,12 +88,12 @@ class Operation:
# Setup coalition : # Setup coalition :
self.current_mission.coalition["blue"] = Coalition("blue") self.current_mission.coalition["blue"] = Coalition("blue")
self.current_mission.coalition["red"] = Coalition("red") 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)]()) p_country = self.game.player_country
self.current_mission.coalition["red"].add_country(country_dict[db.country_id_from_name(self.game.enemy_country)]()) e_country = self.game.enemy_country
else: self.current_mission.coalition["blue"].add_country(country_dict[db.country_id_from_name(p_country)]())
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(e_country)]())
self.current_mission.coalition["red"].add_country(country_dict[db.country_id_from_name(self.game.player_country)]())
print([c for c in self.current_mission.coalition["blue"].countries.keys()]) print([c for c in self.current_mission.coalition["blue"].countries.keys()])
print([c for c in self.current_mission.coalition["red"].countries.keys()]) print([c for c in self.current_mission.coalition["red"].countries.keys()])
@ -125,6 +123,26 @@ class Operation:
# Generate ground object first # Generate ground object first
self.groundobjectgen.generate() 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) # Air Support (Tanker & Awacs)
self.airsupportgen.generate(self.is_awacs_enabled) self.airsupportgen.generate(self.is_awacs_enabled)
@ -139,6 +157,7 @@ class Operation:
self.airgen.generate_flights(cp, country, self.game.planners[cp.id]) self.airgen.generate_flights(cp, country, self.game.planners[cp.id])
# Generate ground units on frontline everywhere # Generate ground units on frontline everywhere
self.game.jtacs = []
for player_cp, enemy_cp in self.game.theater.conflicts(True): for player_cp, enemy_cp in self.game.theater.conflicts(True):
conflict = Conflict.frontline_cas_conflict(self.attacker_name, self.defender_name, conflict = Conflict.frontline_cas_conflict(self.attacker_name, self.defender_name,
self.current_mission.country(self.attacker_country), self.current_mission.country(self.attacker_country),
@ -157,14 +176,14 @@ class Operation:
else: else:
self.current_mission.groundControl.red_tactical_commander = self.ca_slots self.current_mission.groundControl.red_tactical_commander = self.ca_slots
# triggers # Triggers
if self.game.is_player_attack(self.conflict.attackers_country): if self.game.is_player_attack(self.conflict.attackers_country):
cp = self.conflict.from_cp cp = self.conflict.from_cp
else: else:
cp = self.conflict.to_cp cp = self.conflict.to_cp
self.triggersgen.generate() self.triggersgen.generate()
# options # Options
self.forcedoptionsgen.generate() self.forcedoptionsgen.generate()
# Generate Visuals Smoke Effects # Generate Visuals Smoke Effects
@ -177,6 +196,18 @@ class Operation:
load_mist.add_action(DoScript(String(f.read()))) load_mist.add_action(DoScript(String(f.read())))
self.current_mission.triggerrules.triggers.append(load_mist) 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") load_dcs_libe = TriggerStart(comment="Load DCS Liberation Script")
with open("./resources/scripts/dcs_liberation.lua") as f: with open("./resources/scripts/dcs_liberation.lua") as f:
script = f.read() script = f.read()
@ -189,10 +220,10 @@ class Operation:
# Briefing Generation # Briefing Generation
for i, tanker_type in enumerate(self.airsupportgen.generated_tankers): 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: 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") self.briefinggen.append_frequency("Flight", "251 MHz AM")

View File

@ -1,32 +1,42 @@
class Settings: class Settings:
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
# Difficulty settings # Difficulty settings
player_skill = "Good" self.player_skill = "Good"
enemy_skill = "Average" self.enemy_skill = "Average"
enemy_vehicle_skill = "Average" self.enemy_vehicle_skill = "Average"
map_coalition_visibility = "All Units" self.map_coalition_visibility = "All Units"
labels = "Full" self.labels = "Full"
only_player_takeoff = True # Legacy parameter do not use self.only_player_takeoff = True # Legacy parameter do not use
night_disabled = False self.night_disabled = False
external_views_allowed = True self.external_views_allowed = True
supercarrier = False self.supercarrier = False
multiplier = 1 self.multiplier = 1
generate_marks = True self.generate_marks = True
sams = True # Legacy parameter do not use self.sams = True # Legacy parameter do not use
cold_start = False # Legacy parameter do not use self.cold_start = False # Legacy parameter do not use
version = None self.version = None
self.include_jtac_if_available = True
# Performance oriented # Performance oriented
perf_red_alert_state = True self.perf_red_alert_state = True
perf_smoke_gen = True self.perf_smoke_gen = True
perf_artillery = True self.perf_artillery = True
perf_moving_units = True self.perf_moving_units = True
perf_infantry = True self.perf_infantry = True
perf_ai_parking_start = True self.perf_ai_parking_start = True
self.perf_destroyed_units = True
# Performance culling # Performance culling
perf_culling = False self.perf_culling = False
perf_culling_distance = 100 self.perf_culling_distance = 100

View File

@ -3,7 +3,6 @@ from .aircraft import *
from .armor import * from .armor import *
from .airsupportgen import * from .airsupportgen import *
from .conflictgen import * from .conflictgen import *
from .shipgen import *
from .visualgen import * from .visualgen import *
from .triggergen import * from .triggergen import *
from .environmentgen import * from .environmentgen import *

View File

@ -1,10 +1,12 @@
from dcs.action import ActivateGroup, AITaskPush from dcs.action import ActivateGroup, AITaskPush, MessageToCoalition, MessageToAll
from dcs.condition import TimeAfter, CoalitionHasAirdrome from dcs.condition import TimeAfter, CoalitionHasAirdrome, PartOfCoalitionInZone
from dcs.helicopters import UH_1H from dcs.helicopters import UH_1H
from dcs.terrain.terrain import NoParkingSlotError from dcs.terrain.terrain import NoParkingSlotError
from dcs.triggers import TriggerOnce, Event from dcs.triggers import TriggerOnce, Event
from game.data.cap_capabilities_db import GUNFIGHTERS
from game.settings import Settings from game.settings import Settings
from game.utils import nm_to_meter
from gen.flights.ai_flight_planner import FlightPlanner from gen.flights.ai_flight_planner import FlightPlanner
from gen.flights.flight import Flight, FlightType, FlightWaypointType from gen.flights.flight import Flight, FlightType, FlightWaypointType
from .conflictgen import * from .conflictgen import *
@ -36,7 +38,7 @@ class AircraftConflictGenerator:
return self.settings.cold_start and StartType.Cold or StartType.Warm 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 did_load_loadout = False
unit_type = group.units[0].unit_type unit_type = group.units[0].unit_type
@ -70,8 +72,8 @@ class AircraftConflictGenerator:
for unit_instance in group.units: for unit_instance in group.units:
unit_instance.livery_id = db.PLANE_LIVERY_OVERRIDES[unit_type] unit_instance.livery_id = db.PLANE_LIVERY_OVERRIDES[unit_type]
single_client = client_count == 1 single_client = flight.client_count == 1
for idx in range(0, min(len(group.units), client_count)): for idx in range(0, min(len(group.units), flight.client_count)):
if single_client: if single_client:
group.units[idx].set_player() group.units[idx].set_player()
else: else:
@ -85,17 +87,33 @@ class AircraftConflictGenerator:
if unit_type is F_14B: if unit_type is F_14B:
group.units[idx].set_property(F_14B.Properties.INSAlignmentStored.id, True) group.units[idx].set_property(F_14B.Properties.INSAlignmentStored.id, True)
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) 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]: if unit_type in helicopters.helicopter_map.values() and unit_type not in [UH_1H]:
group.set_frequency(127.5) group.set_frequency(127.5)
else: 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) group.set_frequency(251.0)
else: else:
# WW2 # WW2
if unit_type in [FW_190A8, FW_190D9, Bf_109K_4, Ju_88A4]:
group.set_frequency(40)
else:
group.set_frequency(124.0) 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: 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 assert count > 0
assert unit is not None assert unit is not None
@ -108,7 +126,7 @@ class AircraftConflictGenerator:
country=side, country=side,
name=name, name=name,
aircraft_type=unit_type, aircraft_type=unit_type,
airport=self.m.terrain.airport_by_id(airport.id), airport=airport,
maintask=None, maintask=None,
start_type=start_type, start_type=start_type,
group_size=count, group_size=count,
@ -143,10 +161,13 @@ class AircraftConflictGenerator:
group.points[0].alt_type = "RADIO" group.points[0].alt_type = "RADIO"
return group 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 count > 0
assert unit is not None 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)) logging.info("airgen: {} for {} at unit {}".format(unit_type, side.id, at))
return self.m.flight_group_from_unit( return self.m.flight_group_from_unit(
country=side, country=side,
@ -154,7 +175,7 @@ class AircraftConflictGenerator:
aircraft_type=unit_type, aircraft_type=unit_type,
pad_group=at, pad_group=at,
maintask=None, maintask=None,
start_type=self._start_type(), start_type=start_type,
group_size=count) group_size=count)
def _generate_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: db.StartingPosition): 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): 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: for flight in flight_planner.flights:
if flight.client_count == 0 and self.game.position_culled(flight.from_cp.position): if flight.client_count == 0 and self.game.position_culled(flight.from_cp.position):
@ -240,10 +266,6 @@ class AircraftConflictGenerator:
continue continue
group = self.generate_planned_flight(cp, country, flight) 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) self.setup_group_activation_trigger(flight, group)
@ -255,7 +277,7 @@ class AircraftConflictGenerator:
group.late_activation = False group.late_activation = False
group.uncontrolled = True 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)) activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in * 60))
if (flight.from_cp.cptype == ControlPointType.AIRBASE): if (flight.from_cp.cptype == ControlPointType.AIRBASE):
if flight.from_cp.captured: if flight.from_cp.captured:
@ -265,12 +287,16 @@ class AircraftConflictGenerator:
activation_trigger.add_condition( activation_trigger.add_condition(
CoalitionHasAirdrome(self.game.get_enemy_coalition_id(), flight.from_cp.id)) 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()) group.add_trigger_action(StartCommand())
activation_trigger.add_action(AITaskPush(group.id, len(group.tasks))) activation_trigger.add_action(AITaskPush(group.id, len(group.tasks)))
self.m.triggerrules.triggers.append(activation_trigger) self.m.triggerrules.triggers.append(activation_trigger)
else: else:
group.late_activation = True 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)) activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in*60))
if(flight.from_cp.cptype == ControlPointType.AIRBASE): if(flight.from_cp.cptype == ControlPointType.AIRBASE):
@ -279,9 +305,22 @@ class AircraftConflictGenerator:
else: else:
activation_trigger.add_condition(CoalitionHasAirdrome(self.game.get_enemy_coalition_id(), flight.from_cp.id)) 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)) activation_trigger.add_action(ActivateGroup(group.id))
self.m.triggerrules.triggers.append(activation_trigger) 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): def generate_planned_flight(self, cp, country, flight:Flight):
try: try:
if flight.client_count == 0 and self.game.settings.perf_ai_parking_start: if flight.client_count == 0 and self.game.settings.perf_ai_parking_start:
@ -310,7 +349,8 @@ class AircraftConflictGenerator:
unit_type=flight.unit_type, unit_type=flight.unit_type,
count=flight.count, count=flight.count,
client_count=0, client_count=0,
at=self.m.find_group(group_name),) at=self.m.find_group(group_name),
start_type=st)
else: else:
group = self._generate_at_airport( group = self._generate_at_airport(
name=namegen.next_unit_name(country, cp.id, flight.unit_type), name=namegen.next_unit_name(country, cp.id, flight.unit_type),
@ -318,7 +358,7 @@ class AircraftConflictGenerator:
unit_type=flight.unit_type, unit_type=flight.unit_type,
count=flight.count, count=flight.count,
client_count=0, client_count=0,
airport=self.m.terrain.airport_by_id(cp.at.id), airport=cp.airport,
start_type=st) start_type=st)
except Exception: except Exception:
# Generated when there is no place on Runway or on Parking Slots # Generated when there is no place on Runway or on Parking Slots
@ -332,56 +372,70 @@ class AircraftConflictGenerator:
at=cp.position) at=cp.position)
group.points[0].alt = 1500 group.points[0].alt = 1500
flight.group = group
return group return group
def setup_group_as_intercept_flight(self, group, flight): def setup_group_as_intercept_flight(self, group, flight):
group.points[0].ETA = 0 group.points[0].ETA = 0
group.late_activation = True group.late_activation = True
self._setup_group(group, Intercept, flight.client_count) self._setup_group(group, Intercept, flight)
for point in flight.points: for point in flight.points:
group.add_waypoint(Point(point.x,point.y), point.alt) group.add_waypoint(Point(point.x,point.y), point.alt)
def setup_flight_group(self, group, flight, flight_type): 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 group.task = CAP.name
self._setup_group(group, CAP, flight.client_count) self._setup_group(group, CAP, flight)
# group.points[0].tasks.clear() # group.points[0].tasks.clear()
# group.tasks.clear() group.points[0].tasks.clear()
# group.tasks.append(EngageTargets(max_distance=40, targets=[Targets.All.Air])) 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])) # 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]: elif flight_type in [FlightType.CAS, FlightType.BAI]:
group.task = CAS.name 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.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(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFireWeaponFree)) 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]: elif flight_type in [FlightType.SEAD, FlightType.DEAD]:
group.task = SEAD.name 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.clear()
group.points[0].tasks.append(NoTask()) group.points[0].tasks.append(NoTask())
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire))
group.points[0].tasks.append(OptRestrictJettison(True)) group.points[0].tasks.append(OptRestrictJettison(True))
group.points[0].tasks.append(OptRTBOnOutOfAmmo(OptRTBOnOutOfAmmo.Values.ASM))
elif flight_type in [FlightType.STRIKE]: elif flight_type in [FlightType.STRIKE]:
group.task = PinpointStrike.name 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.clear()
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire))
group.points[0].tasks.append(OptRestrictJettison(True)) group.points[0].tasks.append(OptRestrictJettison(True))
elif flight_type in [FlightType.ANTISHIP]: elif flight_type in [FlightType.ANTISHIP]:
group.task = AntishipStrike.name 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.clear()
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire))
group.points[0].tasks.append(OptRestrictJettison(True)) 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): for i, point in enumerate(flight.points):
if not point.only_for_player or (point.only_for_player and flight.client_count > 0): 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) 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)) group.add_nav_target_point(t.position, "PP" + str(j + 1))
if group.units[0].unit_type == F_14B and j == 0: if group.units[0].unit_type == F_14B and j == 0:
group.add_nav_target_point(t.position, "ST") 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: elif point.waypoint_type == FlightWaypointType.INGRESS_SEAD:
tgroup = self.m.find_group(point.targetGroup.group_identifier) 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)) group.add_nav_target_point(t.position, "PP" + str(j + 1))
if group.units[0].unit_type == F_14B and j == 0: if group.units[0].unit_type == F_14B and j == 0:
group.add_nav_target_point(t.position, "ST") 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: if pt is not None:
pt.alt_type = point.alt_type pt.alt_type = point.alt_type
@ -448,7 +506,7 @@ class AircraftConflictGenerator:
def setup_group_as_antiship_flight(self, group, flight): def setup_group_as_antiship_flight(self, group, flight):
group.task = AntishipStrike.name 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.clear()
group.points[0].tasks.append(AntishipStrikeTaskAction()) group.points[0].tasks.append(AntishipStrikeTaskAction())

View File

@ -32,6 +32,7 @@ class AirSupportConflictGenerator:
def generate(self, is_awacs_enabled): def generate(self, is_awacs_enabled):
player_cp = self.conflict.from_cp if self.conflict.from_cp.captured else self.conflict.to_cp 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)): 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)) 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 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, plane_type=tanker_unit_type,
position=tanker_position, position=tanker_position,
altitude=TANKER_ALT, altitude=TANKER_ALT,
race_distance=58000,
frequency=130 + i, frequency=130 + i,
start_type=StartType.Warm, 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(SetInvisibleCommand(True))
tanker_group.points[0].tasks.append(SetImmortalCommand(True)) tanker_group.points[0].tasks.append(SetImmortalCommand(True))
@ -62,7 +68,7 @@ class AirSupportConflictGenerator:
altitude=AWACS_ALT, altitude=AWACS_ALT,
airport=None, airport=None,
position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE), position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE),
frequency=133, frequency=233,
start_type=StartType.Warm, start_type=StartType.Warm,
) )
awacs_flight.points[0].tasks.append(SetInvisibleCommand(True)) awacs_flight.points[0].tasks.append(SetInvisibleCommand(True))

View File

@ -1,4 +1,7 @@
from dcs.action import AITaskPush, AITaskSet
from dcs.condition import TimeAfter, UnitDamaged, Or, GroupLifeLess
from dcs.task import * from dcs.task import *
from dcs.triggers import TriggerOnce, Event
from gen import namegen from gen import namegen
from gen.ground_forces.ai_ground_planner import CombatGroupRole, DISTANCE_FROM_FRONTLINE from gen.ground_forces.ai_ground_planner import CombatGroupRole, DISTANCE_FROM_FRONTLINE
@ -17,10 +20,12 @@ AGGRESIVE_MOVE_DISTANCE = 16000
FIGHT_DISTANCE = 3500 FIGHT_DISTANCE = 3500
RANDOM_OFFSET_ATTACK = 250
class GroundConflictGenerator: class GroundConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict, game, player_planned_combat_groups, enemy_planned_combat_groups, player_stance): 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.conflict = conflict
self.enemy_planned_combat_groups = enemy_planned_combat_groups self.enemy_planned_combat_groups = enemy_planned_combat_groups
self.player_planned_combat_groups = player_planned_combat_groups self.player_planned_combat_groups = player_planned_combat_groups
@ -58,7 +63,7 @@ class GroundConflictGenerator:
if final_position is not None: if final_position is not None:
g = self._generate_group( g = self._generate_group(
side=self.m.country(self.game.player_country), side=self.mission.country(self.game.player_country),
unit=group.units[0], unit=group.units[0],
heading=self.conflict.heading+90, heading=self.conflict.heading+90,
count=len(group.units), count=len(group.units),
@ -66,7 +71,7 @@ class GroundConflictGenerator:
g.set_skill(self.game.settings.player_skill) g.set_skill(self.game.settings.player_skill)
player_groups.append((g,group)) 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 # Create enemy groups at random position
for group in self.enemy_planned_combat_groups: for group in self.enemy_planned_combat_groups:
@ -78,7 +83,7 @@ class GroundConflictGenerator:
if final_position is not None: if final_position is not None:
g = self._generate_group( g = self._generate_group(
side=self.m.country(self.game.enemy_country), side=self.mission.country(self.game.enemy_country),
unit=group.units[0], unit=group.units[0],
heading=self.conflict.heading - 90, heading=self.conflict.heading - 90,
count=len(group.units), count=len(group.units),
@ -86,14 +91,26 @@ class GroundConflictGenerator:
g.set_skill(self.game.settings.enemy_vehicle_skill) g.set_skill(self.game.settings.enemy_vehicle_skill)
enemy_groups.append((g, group)) 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 # 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.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) 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): def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading):
@ -118,7 +135,7 @@ class GroundConflictGenerator:
return return
u = random.choice(possible_infantry_units) u = random.choice(possible_infantry_units)
self.m.vehicle_group( self.mission.vehicle_group(
side, side,
namegen.next_infantry_name(side, cp, u), u, namegen.next_infantry_name(side, cp, u), u,
position=infantry_position, position=infantry_position,
@ -129,7 +146,7 @@ class GroundConflictGenerator:
for i in range(randint(3, 10)): for i in range(randint(3, 10)):
u = random.choice(possible_infantry_units) u = random.choice(possible_infantry_units)
position = infantry_position.random_point_within(55, 5) position = infantry_position.random_point_within(55, 5)
self.m.vehicle_group( self.mission.vehicle_group(
side, side,
namegen.next_infantry_name(side, cp, u), u, namegen.next_infantry_name(side, cp, u), u,
position=position, position=position,
@ -149,14 +166,63 @@ class GroundConflictGenerator:
if self.game.settings.perf_artillery: if self.game.settings.perf_artillery:
target = self.get_artillery_target_in_range(dcs_group, group, enemy_groups) target = self.get_artillery_target_in_range(dcs_group, group, enemy_groups)
if target is not None: 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]: elif group.role in [CombatGroupRole.TANK, CombatGroupRole.IFV]:
if stance == CombatStance.AGGRESIVE: if stance == CombatStance.AGGRESIVE:
# Attack nearest enemy if any # Attack nearest enemy if any
# Then move forward OR Attack enemy base if it is not too far away # Then move forward OR Attack enemy base if it is not too far away
target = self.find_nearest_enemy_group(dcs_group, enemy_groups) target = self.find_nearest_enemy_group(dcs_group, enemy_groups)
if target is not None: 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.add_waypoint(target.points[0].position + rand_offset, PointAction.OffRoad)
dcs_group.points[1].tasks.append(AttackGroup(target.id)) 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) targets = self.find_n_nearest_enemy_groups(dcs_group, enemy_groups, 3)
i = 1 i = 1
for target in targets: for target in targets:
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.add_waypoint(target.points[0].position+rand_offset, PointAction.OffRoad)
dcs_group.points[i].tasks.append(AttackGroup(target.id)) dcs_group.points[i].tasks.append(AttackGroup(target.id))
i = i + 1 i = i + 1
if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE: 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) attack_point = to_cp.position.random_point_within(500, 0)
dcs_group.add_waypoint(attack_point) 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]: elif group.role in [CombatGroupRole.APC, CombatGroupRole.ATGM]:
if stance in [CombatStance.AGGRESIVE, CombatStance.BREAKTHROUGH, CombatStance.ELIMINATION]: 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) attack_point = self.find_offensive_point(dcs_group, forward_heading, AGGRESIVE_MOVE_DISTANCE)
dcs_group.add_waypoint(attack_point, PointAction.OnRoad) dcs_group.add_waypoint(attack_point, PointAction.OnRoad)
if stance != CombatStance.RETREAT:
self.add_morale_trigger(dcs_group, forward_heading)
if stance == CombatStance.RETREAT: if stance == CombatStance.RETREAT:
# In retreat mode, the units will fall back # In retreat mode, the units will fall back
# If the ally base is close enough, the units will even regroup there # 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) 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 Find a point to retreat to
:param dcs_group: DCS mission group we are searching a retreat point for :param dcs_group: DCS mission group we are searching a retreat point for
:param frontline_heading: Heading of the frontline :param frontline_heading: Heading of the frontline
:return: dcs.mapping.Point object with the desired position :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): def find_offensive_point(self, dcs_group, frontline_heading, distance):
""" """
@ -310,7 +420,7 @@ class GroundConflictGenerator:
cp = self.conflict.to_cp cp = self.conflict.to_cp
logging.info("armorgen: {} for {}".format(unit, side.id)) logging.info("armorgen: {} for {}".format(unit, side.id))
group = self.m.vehicle_group( group = self.mission.vehicle_group(
side, side,
namegen.next_unit_name(side, cp.id, unit), unit, namegen.next_unit_name(side, cp.id, unit), unit,
position=self._group_point(at), position=self._group_point(at),

View File

@ -24,6 +24,8 @@ class BriefingGenerator:
self.targets = [] self.targets = []
self.waypoints = [] self.waypoints = []
self.jtacs = []
def append_frequency(self, name: str, frequency: str): def append_frequency(self, name: str, frequency: str):
self.freqs.append((name, frequency)) self.freqs.append((name, frequency))
@ -45,8 +47,13 @@ class BriefingGenerator:
self.description += "#0 -- TAKEOFF : Take off from " + flight.from_cp.name + "\n" self.description += "#0 -- TAKEOFF : Take off from " + flight.from_cp.name + "\n"
for i, wpt in enumerate(flight.points): for i, wpt in enumerate(flight.points):
self.description += "#" + str(1+i) + " -- " + wpt.name + " : " + wpt.description + "\n" 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" self.description += "-" * 50 + "\n"
def add_ally_flight_description(self, flight): def add_ally_flight_description(self, flight):
@ -54,7 +61,6 @@ class BriefingGenerator:
flight_unit_name = db.unit_type_name(flight.unit_type) 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" self.description += flight.flight_type.name + " " + flight_unit_name + " x " + str(flight.count) + ", departing in " + str(flight.scheduled_in) + " minutes \n"
def generate(self): def generate(self):
self.description = "" self.description = ""
@ -62,8 +68,7 @@ class BriefingGenerator:
self.description += "DCS Liberation turn #" + str(self.game.turn) + "\n" self.description += "DCS Liberation turn #" + str(self.game.turn) + "\n"
self.description += "=" * 15 + "\n\n" self.description += "=" * 15 + "\n\n"
self.description += "Current situation:\n" self.generate_ongoing_war_text()
self.description += "=" * 15 + "\n\n"
self.description += "\n"*2 self.description += "\n"*2
self.description += "Your flights:" + "\n" self.description += "Your flights:" + "\n"
@ -89,11 +94,12 @@ class BriefingGenerator:
for name, freq in self.freqs: for name, freq in self.freqs:
self.description += "{}: {}\n".format(name, freq) self.description += "{}: {}\n".format(name, freq)
self.description += ("-" * 50) + "\n" self.description += ("-" * 50) + "\n"
for cp in self.game.theater.controlpoints: for cp in self.game.theater.controlpoints:
if cp.captured and cp.cptype in [ControlPointType.LHA_GROUP, ControlPointType.AIRCRAFT_CARRIER_GROUP]: if cp.captured and cp.cptype in [ControlPointType.LHA_GROUP, ControlPointType.AIRCRAFT_CARRIER_GROUP]:
self.description += cp.name + "\n" self.description += cp.name + "\n"
self.description += "RADIO : 127.5 Mhz AM\n"
self.description += "TACAN : " self.description += "TACAN : "
self.description += str(cp.tacanN) self.description += str(cp.tacanN)
if cp.tacanY: if cp.tacanY:
self.description += "Y" self.description += "Y"
@ -105,6 +111,80 @@ class BriefingGenerator:
self.description += "ICLS Channel : " + str(cp.icls) + "\n" self.description += "ICLS Channel : " + str(cp.icls) + "\n"
self.description += "-" * 50 + "\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.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)

View File

@ -23,11 +23,12 @@ class CarrierGroupGenerator(GroupGenerator):
return return
# Add destroyers escort # Add destroyers escort
if "destroyer" in self.faction.keys():
dd_type = random.choice(self.faction["destroyer"]) 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, "DD1", self.position.x + 2500, self.position.y + 4500, self.heading)
self.add_unit(dd_type, "DD2", self.position.x + 250, self.position.y - 450, 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, "DD3", self.position.x + 4500, self.position.y + 8500, self.heading)
self.add_unit(dd_type, "DD4", self.position.x + 450, self.position.y - 850, 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 self.get_generated_group().points[0].speed = 20

View File

@ -31,7 +31,7 @@ class ChineseNavyGroupGenerator(GroupGenerator):
self.add_unit(dd_type, "FF2", self.position.x + 2400, self.position.y - 900, self.heading) self.add_unit(dd_type, "FF2", self.position.x + 2400, self.position.y - 900, self.heading)
if include_cc: 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.add_unit(cc_type, "CC1", self.position.x, self.position.y, self.heading)
self.get_generated_group().points[0].speed = 20 self.get_generated_group().points[0].speed = 20

View File

@ -19,7 +19,7 @@ class LHAGroupGenerator(GroupGenerator):
# Add destroyers escort # Add destroyers escort
if "destroyer" in self.faction.keys(): if "destroyer" in self.faction.keys():
dd_type = random.choice(self.faction["destroyer"]) 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, "DD1", self.position.x + 1250, self.position.y + 1450, self.heading)
self.add_unit(dd_type, "DD2", self.position.x + 250, self.position.y - 450, 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 self.get_generated_group().points[0].speed = 20

View File

@ -106,6 +106,7 @@ class FlightPlanner:
break break
inventory[unit] = inventory[unit] - 2 inventory[unit] = inventory[unit] - 2
flight = Flight(unit, 2, self.from_cp, FlightType.INTERCEPTION) flight = Flight(unit, 2, self.from_cp, FlightType.INTERCEPTION)
flight.scheduled_in = 1
flight.points = [] flight.points = []
self.interceptor_flights.append(flight) self.interceptor_flights.append(flight)

View File

@ -3,13 +3,22 @@ from dcs.helicopters import *
# Interceptor are the aircraft prioritized for interception tasks # Interceptor are the aircraft prioritized for interception tasks
# If none is available, the AI will use regular CAP-capable aircraft instead # 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 = [ INTERCEPT_CAPABLE = [
MiG_21Bis, MiG_21Bis,
MiG_25PD, MiG_25PD,
MiG_31, MiG_31,
MiG_29S,
MiG_29A,
MiG_29G,
MiG_29K,
M_2000C, M_2000C,
Mirage_2000_5, Mirage_2000_5,
Rafale_M,
F_14B, F_14B,
F_15C, F_15C,
@ -56,6 +65,9 @@ CAP_CAPABLE = [
Bf_109K_4, Bf_109K_4,
FW_190D9, FW_190D9,
FW_190A8, FW_190A8,
A_4E_C,
Rafale_M,
] ]
# USed for CAS (Close air support) and BAI (Battlefield Interdiction) # USed for CAS (Close air support) and BAI (Battlefield Interdiction)
@ -89,6 +101,7 @@ CAS_CAPABLE = [
FA_18C_hornet, FA_18C_hornet,
C_101CC, C_101CC,
MB_339PAN,
L_39ZA, L_39ZA,
AJS37, AJS37,
@ -116,6 +129,9 @@ CAS_CAPABLE = [
Bf_109K_4, Bf_109K_4,
FW_190D9, FW_190D9,
FW_190A8, FW_190A8,
A_4E_C,
Rafale_A_S
] ]
# Aircraft used for SEAD / DEAD tasks # Aircraft used for SEAD / DEAD tasks
@ -133,14 +149,16 @@ SEAD_CAPABLE = [
Su_30, Su_30,
Su_34, Su_34,
MiG_27K, MiG_27K,
A_4E_C,
Rafale_A_S
] ]
# Aircraft used for Strike mission # Aircraft used for Strike mission
STRIKE_CAPABLE = [ STRIKE_CAPABLE = [
MiG_15bis, MiG_15bis,
MiG_29A,
MiG_27K, MiG_27K,
MiG_29S, MB_339PAN,
Su_17M4, Su_17M4,
Su_24M, Su_24M,
@ -180,6 +198,9 @@ STRIKE_CAPABLE = [
FW_190D9, FW_190D9,
FW_190A8, FW_190A8,
A_4E_C,
Rafale_A_S
] ]
ANTISHIP_CAPABLE = [ ANTISHIP_CAPABLE = [
@ -193,4 +214,5 @@ ANTISHIP_CAPABLE = [
A_10A, A_10A,
Ju_88A4, Ju_88A4,
Rafale_A_S
] ]

View File

@ -91,6 +91,7 @@ class Flight:
loadout = {} loadout = {}
preset_loadout_name = "" preset_loadout_name = ""
start_type = "Runway" start_type = "Runway"
group = False # Contains DCS Mission group data after mission has been generated
# How long before this flight should take off # How long before this flight should take off
scheduled_in = 0 scheduled_in = 0

View File

@ -7,6 +7,8 @@ from gen import Conflict
from gen.ground_forces.combat_stance import CombatStance from gen.ground_forces.combat_stance import CombatStance
from theater import ControlPoint from theater import ControlPoint
import pydcs_extensions.frenchpack.frenchpack as frenchpack
TYPE_TANKS = [ TYPE_TANKS = [
Armor.MBT_T_55, Armor.MBT_T_55,
Armor.MBT_T_72B, Armor.MBT_T_72B,
@ -32,6 +34,18 @@ TYPE_TANKS = [
Armor.ST_Centaur_IV, Armor.ST_Centaur_IV,
Armor.CT_Cromwell_IV, Armor.CT_Cromwell_IV,
Armor.HIT_Churchill_VII, 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 = [ TYPE_ATGM = [
@ -44,6 +58,12 @@ TYPE_ATGM = [
Armor.TD_Jagdpanzer_IV, Armor.TD_Jagdpanzer_IV,
Armor.TD_Jagdpanther_G1, Armor.TD_Jagdpanther_G1,
Armor.TD_M10_GMC, Armor.TD_M10_GMC,
# Mods
frenchpack.VBAE_CRAB_MMP,
frenchpack.VAB_MEPHISTO,
frenchpack.TRM_2000_PAMELA,
] ]
TYPE_IFV = [ TYPE_IFV = [
@ -61,6 +81,12 @@ TYPE_IFV = [
# WW2 # WW2
Armor.IFV_Sd_Kfz_234_2_Puma, Armor.IFV_Sd_Kfz_234_2_Puma,
Armor.LAC_M8_Greyhound, Armor.LAC_M8_Greyhound,
# Mods
frenchpack.ERC_90,
frenchpack.VBAE_CRAB,
frenchpack.VAB_T20_13
] ]
TYPE_APC = [ TYPE_APC = [
@ -81,6 +107,12 @@ TYPE_APC = [
# WW2 # WW2
Armor.APC_M2A1, Armor.APC_M2A1,
Armor.APC_Sd_Kfz_251, Armor.APC_Sd_Kfz_251,
# Mods
frenchpack.VAB__50,
frenchpack.VBL__50,
frenchpack.VBL_AANF1,
] ]
TYPE_ARTILLERY = [ TYPE_ARTILLERY = [
@ -117,6 +149,11 @@ TYPE_LOGI = [
Unarmed.Willys_MB, Unarmed.Willys_MB,
Unarmed.Land_Rover_109_S3, Unarmed.Land_Rover_109_S3,
Unarmed.Land_Rover_101_FC, Unarmed.Land_Rover_101_FC,
# Mods
frenchpack.VBL,
frenchpack.VAB,
] ]
TYPE_INFANTRY = [ TYPE_INFANTRY = [
@ -148,14 +185,14 @@ class CombatGroupRole(Enum):
DISTANCE_FROM_FRONTLINE = { DISTANCE_FROM_FRONTLINE = {
CombatGroupRole.TANK:2800, CombatGroupRole.TANK:3200,
CombatGroupRole.APC:7000, CombatGroupRole.APC:8000,
CombatGroupRole.IFV:3000, CombatGroupRole.IFV:3700,
CombatGroupRole.ARTILLERY:14000, CombatGroupRole.ARTILLERY:18000,
CombatGroupRole.SHORAD:12000, CombatGroupRole.SHORAD:13000,
CombatGroupRole.LOGI:18000, CombatGroupRole.LOGI:20000,
CombatGroupRole.INFANTRY:2800, CombatGroupRole.INFANTRY:3000,
CombatGroupRole.ATGM:5500 CombatGroupRole.ATGM:6200
} }
GROUP_SIZES_BY_COMBAT_STANCE = { GROUP_SIZES_BY_COMBAT_STANCE = {

View File

@ -45,12 +45,6 @@ class GroundObjectsGenerator:
def generate(self): 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: for cp in self.game.theater.controlpoints:
if cp.captured: if cp.captured:
@ -78,6 +72,7 @@ class GroundObjectsGenerator:
vehicle.position.x = u.position.x vehicle.position.x = u.position.x
vehicle.position.y = u.position.y vehicle.position.y = u.position.y
vehicle.heading = u.heading vehicle.heading = u.heading
vehicle.player_can_drive = True
vg.add_unit(vehicle) vg.add_unit(vehicle)
else: else:
vg = self.m.ship_group(side, g.name, utype, position=g.position, vg = self.m.ship_group(side, g.name, utype, position=g.position,
@ -121,7 +116,7 @@ class GroundObjectsGenerator:
found_carrier_destination = False found_carrier_destination = False
attempt = 0 attempt = 0
while not found_carrier_destination and attempt < 5: 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): if self.game.theater.is_in_sea(point):
found_carrier_destination = True found_carrier_destination = True
sg.add_waypoint(point) sg.add_waypoint(point)

View File

@ -20,6 +20,12 @@ class SA10Generator(GroupGenerator):
# Search radar for missiles (optionnal) # 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) 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) # 2 different launcher type (C & D)
num_launchers = random.randint(6, 8) num_launchers = random.randint(6, 8)
positions = self.get_circular_position(num_launchers, launcher_distance=120, coverage=360) 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) num_launchers = random.randint(6, 8)
positions = self.get_circular_position(num_launchers, launcher_distance=350, coverage=360) positions = self.get_circular_position(num_launchers, launcher_distance=350, coverage=360)
for i, position in enumerate(positions): 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])

View File

@ -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

View File

@ -95,8 +95,8 @@ class TriggersGenerator:
self.mission.triggerrules.triggers.append(mark_trigger) self.mission.triggerrules.triggers.append(mark_trigger)
def generate(self): def generate(self):
player_coalition = self.game.player_country in db.BLUEFOR_FACTIONS and "blue" or "red" player_coalition = "blue"
enemy_coalition = player_coalition == "blue" and "red" or "blue" enemy_coalition = "red"
self.mission.coalition["blue"].bullseye = {"x": self.conflict.position.x, self.mission.coalition["blue"].bullseye = {"x": self.conflict.position.x,
"y": self.conflict.position.y} "y": self.conflict.position.y}

1
liberation_theme.json Normal file
View File

@ -0,0 +1 @@
{"theme_index": 1}

View File

@ -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 <CLEAN>
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 <CLEAN>
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 <CLEAN>
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 <CLEAN>
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 <CLEAN>
pylons = {1, 2, 3, 4, 5}
tasks = [task.CAP, task.CAS, task.SEAD, task.GroundAttack, task.AFAC, task.Refueling]
task_default = task.CAS

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
from userdata import logging_config from userdata import logging_config
# Logging setup # Logging setup
VERSION_STRING = "2.0RC9" VERSION_STRING = "2.0.10"
logging_config.init_logging(VERSION_STRING) logging_config.init_logging(VERSION_STRING)
import logging import logging
@ -17,19 +17,19 @@ from qt_ui import uiconstants
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.QLiberationWindow import QLiberationWindow from qt_ui.windows.QLiberationWindow import QLiberationWindow
from qt_ui.windows.preferences.QLiberationFirstStartWindow import QLiberationFirstStartWindow 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__": if __name__ == "__main__":
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # Potential fix for 4K screens
app = QApplication(sys.argv) app = QApplication(sys.argv)
# init the theme and load the stylesheet based on the theme index
liberation_theme.init()
css = "" 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()) app.setStyleSheet(stylesheet.read())
# Inject custom payload in pydcs framework # Inject custom payload in pydcs framework
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads") custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads")
if os.path.exists(custom_payloads): if os.path.exists(custom_payloads):
@ -84,6 +84,5 @@ if __name__ == "__main__":
logging.info("Attempt to restore original mission scripting file") logging.info("Attempt to restore original mission scripting file")
liberation_install.restore_original_mission_scripting() liberation_install.restore_original_mission_scripting()
logging.info("QT process exited with code : " + str(qt_execution_code)) logging.info("QT process exited with code : " + str(qt_execution_code))
sys.exit(0)

View File

@ -6,11 +6,10 @@ from PySide2.QtGui import QColor, QFont, QPixmap
from game.event import UnitsDeliveryEvent, FrontlineAttackEvent from game.event import UnitsDeliveryEvent, FrontlineAttackEvent
from theater.theatergroundobject import CATEGORY_MAP from theater.theatergroundobject import CATEGORY_MAP
from userdata.liberation_theme import get_theme_icons
URLS : Dict[str, str] = { URLS : Dict[str, str] = {
"Manual": "https://github.com/khopa/dcs_liberation/wiki", "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", "Repository": "https://github.com/khopa/dcs_liberation",
"ForumThread": "https://forums.eagle.ru/showthread.php?t=214834", "ForumThread": "https://forums.eagle.ru/showthread.php?t=214834",
"Issues": "https://github.com/khopa/dcs_liberation/issues" "Issues": "https://github.com/khopa/dcs_liberation/issues"
@ -19,26 +18,58 @@ URLS : Dict[str, str] = {
LABELS_OPTIONS = ["Full", "Abbreviated", "Dot Only", "Off"] LABELS_OPTIONS = ["Full", "Abbreviated", "Dot Only", "Off"]
SKILL_OPTIONS = ["Average", "Good", "High", "Excellent"] SKILL_OPTIONS = ["Average", "Good", "High", "Excellent"]
COLORS: Dict[str, QColor] = { FONT_SIZE = 8
"dark_red": QColor(140, 20, 20), FONT_NAME = "Arial"
"red": QColor(200, 80, 80), # FONT = QFont("Arial", 12, weight=5, italic=True)
"bright_red": QColor(150, 80, 80), FONT_PRIMARY = QFont(FONT_NAME, FONT_SIZE, weight=5, italic=False)
"super_red": QColor(200, 120, 120), FONT_PRIMARY_I = QFont(FONT_NAME, FONT_SIZE, weight=5, italic=True)
"blue": QColor(164, 164, 255), FONT_PRIMARY_B = QFont(FONT_NAME, FONT_SIZE, weight=75, italic=False)
"dark_blue": QColor(45, 62, 80), FONT_MAP = QFont(FONT_NAME, 10, weight=75, italic=False)
"white": QColor(255, 255, 255),
"green": QColor(128, 186, 128), # new themes can be added here
"bright_green": QColor(64, 200, 64), THEMES: Dict[int, Dict[str, str]] = {
"black": QColor(0, 0, 0), 0: {'themeName': 'Vanilla',
"black_transparent": QColor(0, 0, 0, 64), 'themeFile': 'windows-style.css',
"blue_transparent": QColor(164, 164, 255, 32), 'themeIcons': 'medium',
"red_transparent": QColor(255, 125, 125, 32) },
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 "red": QColor(200, 80, 80),
FONT = QFont("Arial", 12, weight=5, italic=True) "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] = {} AIRCRAFT_ICONS: Dict[str, QPixmap] = {}
VEHICLES_ICONS: Dict[str, QPixmap] = {} VEHICLES_ICONS: Dict[str, QPixmap] = {}
@ -46,9 +77,9 @@ ICONS: Dict[str, QPixmap] = {}
def load_icons(): def load_icons():
ICONS["New"] = QPixmap("./resources/ui/misc/new.png") ICONS["New"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/new.png")
ICONS["Open"] = QPixmap("./resources/ui/misc/open.png") ICONS["Open"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/open.png")
ICONS["Save"] = QPixmap("./resources/ui/misc/save.png") ICONS["Save"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/save.png")
ICONS["Terrain_Caucasus"] = QPixmap("./resources/ui/terrain_caucasus.gif") ICONS["Terrain_Caucasus"] = QPixmap("./resources/ui/terrain_caucasus.gif")
ICONS["Terrain_Persian_Gulf"] = QPixmap("./resources/ui/terrain_pg.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["Dusk"] = QPixmap("./resources/ui/daytime/dusk.png")
ICONS["Night"] = QPixmap("./resources/ui/daytime/night.png") ICONS["Night"] = QPixmap("./resources/ui/daytime/night.png")
ICONS["Money"] = QPixmap("./resources/ui/misc/money_icon.png") ICONS["Money"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/money_icon.png")
ICONS["PassTurn"] = QPixmap("./resources/ui/misc/hourglass.png") ICONS["PassTurn"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/hourglass.png")
ICONS["Proceed"] = QPixmap("./resources/ui/misc/proceed.png") ICONS["Proceed"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/proceed.png")
ICONS["Settings"] = QPixmap("./resources/ui/misc/settings.png") ICONS["Settings"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/settings.png")
ICONS["Statistics"] = QPixmap("./resources/ui/misc/statistics.png") ICONS["Statistics"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/statistics.png")
ICONS["Ordnance"] = QPixmap("./resources/ui/misc/ordnance_icon.png") ICONS["Ordnance"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/ordnance_icon.png")
ICONS["target"] = QPixmap("./resources/ui/ground_assets/target.png") ICONS["target"] = QPixmap("./resources/ui/ground_assets/target.png")
ICONS["cleared"] = QPixmap("./resources/ui/ground_assets/cleared.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"] = QPixmap("./resources/ui/ground_assets/ship.png")
ICONS["ship_blue"] = QPixmap("./resources/ui/ground_assets/ship_blue.png") ICONS["ship_blue"] = QPixmap("./resources/ui/ground_assets/ship_blue.png")
ICONS["Generator"] = QPixmap("./resources/ui/misc/generator.png") ICONS["Generator"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/generator.png")
ICONS["Missile"] = QPixmap("./resources/ui/misc/missile.png") ICONS["Missile"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/missile.png")
ICONS["Cheat"] = QPixmap("./resources/ui/misc/cheat.png") ICONS["Cheat"] = QPixmap("./resources/ui/misc/"+get_theme_icons()+"/cheat.png")
ICONS["TaskCAS"] = QPixmap("./resources/ui/tasks/cas.png") ICONS["TaskCAS"] = QPixmap("./resources/ui/tasks/cas.png")
ICONS["TaskCAP"] = QPixmap("./resources/ui/tasks/cap.png") ICONS["TaskCAP"] = QPixmap("./resources/ui/tasks/cap.png")

View File

@ -34,7 +34,7 @@ class QTopPanel(QFrame):
self.proceedButton = QPushButton("Mission Planning") self.proceedButton = QPushButton("Mission Planning")
self.proceedButton.setIcon(CONST.ICONS["Proceed"]) self.proceedButton.setIcon(CONST.ICONS["Proceed"])
self.proceedButton.setProperty("style", "btn-primary") self.proceedButton.setProperty("style", "btn-success")
self.proceedButton.clicked.connect(self.proceed) self.proceedButton.clicked.connect(self.proceed)
if self.game and self.game.turn == 0: if self.game and self.game.turn == 0:
self.proceedButton.setEnabled(False) self.proceedButton.setEnabled(False)

View File

@ -71,7 +71,6 @@ class QLiberationMap(QGraphicsView):
""" """
Uncomment to set up theather reference points Uncomment to set up theather reference points
def keyPressEvent(self, event): def keyPressEvent(self, event):
#super(QLiberationMap, self).keyPressEvent(event) #super(QLiberationMap, self).keyPressEvent(event)
@ -85,34 +84,36 @@ class QLiberationMap(QGraphicsView):
i = i + 1 i = i + 1
if event.key() == QtCore.Qt.Key_Down: 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: 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: 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: 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: 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: 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: 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: 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) print(self.game.theater.reference_points)
self.reload_scene() self.reload_scene()
""" """
def reload_scene(self): def reload_scene(self):
scene = self.scene() scene = self.scene()
scene.clear() scene.clear()
playerColor = self.game.get_player_color()
enemyColor = self.game.get_enemy_color()
self.addBackground() self.addBackground()
# Uncomment below to help set up theater reference points # Uncomment below to help set up theater reference points
@ -128,11 +129,11 @@ class QLiberationMap(QGraphicsView):
CONST.CP_SIZE, cp, self.game)) CONST.CP_SIZE, cp, self.game))
if cp.captured: if cp.captured:
pen = QPen(brush=CONST.COLORS["blue"]) pen = QPen(brush=CONST.COLORS[playerColor])
brush = CONST.COLORS["blue_transparent"] brush = CONST.COLORS[playerColor+"_transparent"]
else: else:
pen = QPen(brush=CONST.COLORS["red"]) pen = QPen(brush=CONST.COLORS[enemyColor])
brush = CONST.COLORS["red_transparent"] brush = CONST.COLORS[enemyColor+"_transparent"]
added_objects = [] added_objects = []
for ground_object in cp.ground_objects: for ground_object in cp.ground_objects:
@ -157,32 +158,33 @@ class QLiberationMap(QGraphicsView):
if unit.threat_range > max_range: if unit.threat_range > max_range:
max_range = unit.threat_range max_range = unit.threat_range
if has_radar: 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) added_objects.append(ground_object.obj_name)
for cp in self.game.theater.enemy_points(): for cp in self.game.theater.enemy_points():
if self.get_display_rule("lines"): 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(): for cp in self.game.theater.player_points():
if self.get_display_rule("lines"): 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: for cp in self.game.theater.controlpoints:
if cp.captured: if cp.captured:
pen = QPen(brush=CONST.COLORS["blue"]) pen = QPen(brush=CONST.COLORS[playerColor])
brush = CONST.COLORS["blue_transparent"] 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: else:
pen = QPen(brush=CONST.COLORS["red"]) pen = QPen(brush=CONST.COLORS[enemyColor])
brush = CONST.COLORS["red_transparent"] brush = CONST.COLORS[enemyColor+"_transparent"]
flight_path_pen = QPen(brush=CONST.COLORS[enemyColor])
flight_path_pen.setColor(CONST.COLORS[enemyColor])
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.setWidth(1)
flight_path_pen.setStyle(Qt.DashDotLine) flight_path_pen.setStyle(Qt.DashDotLine)
@ -202,27 +204,27 @@ class QLiberationMap(QGraphicsView):
for cp in self.game.theater.controlpoints: for cp in self.game.theater.controlpoints:
pos = self._transform_point(cp.position) 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.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.setDefaultTextColor(Qt.white)
text.setPos(pos[0] + CONST.CP_SIZE + 1, pos[1] - CONST.CP_SIZE / 2 + 1) 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() scene = self.scene()
pos = self._transform_point(cp.position) pos = self._transform_point(cp.position)
for connected_cp in cp.connected_points: for connected_cp in cp.connected_points:
pos2 = self._transform_point(connected_cp.position) pos2 = self._transform_point(connected_cp.position)
if not cp.captured: if not cp.captured:
color = CONST.COLORS["red"] color = CONST.COLORS["dark_"+enemyColor]
elif cp.captured: elif cp.captured:
color = CONST.COLORS["blue"] color = CONST.COLORS["dark_"+playerColor]
else: else:
color = CONST.COLORS["red"] color = CONST.COLORS["dark_"+enemyColor]
pen = QPen(brush=color) pen = QPen(brush=color)
pen.setColor(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 cp.captured and not connected_cp.captured and Conflict.has_frontline_between(cp, connected_cp):
if not cp.captured: if not cp.captured:
scene.addLine(pos[0], pos[1], pos2[0], pos2[1], pen=pen) 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) p1 = point_from_heading(pos2[0], pos2[1], h+180, 25)
p2 = point_from_heading(pos2[0], pos2[1], h, 25) p2 = point_from_heading(pos2[0], pos2[1], h, 25)
frontline_pen = QPen(brush=CONST.COLORS["bright_red"]) frontline_pen = QPen(brush=CONST.COLORS["bright_red"])
frontline_pen.setColor(CONST.COLORS["bright_red"]) frontline_pen.setColor(CONST.COLORS["orange"])
frontline_pen.setWidth(18) frontline_pen.setWidth(8)
scene.addLine(p1[0], p1[1], p2[0], p2[1], pen=frontline_pen) scene.addLine(p1[0], p1[1], p2[0], p2[1], pen=frontline_pen)
else: else:
@ -318,14 +320,14 @@ class QLiberationMap(QGraphicsView):
pass pass
elif self.game.current_turn_daytime == "night": elif self.game.current_turn_daytime == "night":
ov = QPixmap(bg.width(), bg.height()) ov = QPixmap(bg.width(), bg.height())
ov.fill(QColor(40, 40, 150)) ov.fill(CONST.COLORS["night_overlay"])
overlay = scene.addPixmap(ov) overlay = scene.addPixmap(ov)
effect = QGraphicsOpacityEffect() effect = QGraphicsOpacityEffect()
effect.setOpacity(0.7) effect.setOpacity(0.7)
overlay.setGraphicsEffect(effect) overlay.setGraphicsEffect(effect)
else: else:
ov = QPixmap(bg.width(), bg.height()) ov = QPixmap(bg.width(), bg.height())
ov.fill(QColor(165, 100, 100)) ov.fill(CONST.COLORS["dawn_dust_overlay"])
overlay = scene.addPixmap(ov) overlay = scene.addPixmap(ov)
effect = QGraphicsOpacityEffect() effect = QGraphicsOpacityEffect()
effect.setOpacity(0.3) effect.setOpacity(0.3)

View File

@ -1,13 +1,13 @@
from PySide2.QtGui import QFont from PySide2.QtGui import QFont
from PySide2.QtWidgets import QGraphicsScene from PySide2.QtWidgets import QGraphicsScene
from qt_ui.uiconstants import COLORS import qt_ui.uiconstants as CONST
class QLiberationScene(QGraphicsScene): class QLiberationScene(QGraphicsScene):
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent) super().__init__(parent)
item = self.addText("No save file found. Go to \"File/New Game\" to setup a new campaign.", item = self.addText("Go to \"File/New Game\" to setup a new campaign or go to \"File/Open\" to load an existing save game.",
QFont("Arial", 14, weight=5)) CONST.FONT_PRIMARY)
item.setDefaultTextColor(COLORS["white"]) item.setDefaultTextColor(CONST.COLORS["white"])

View File

@ -5,7 +5,6 @@ from PySide2.QtWidgets import QGraphicsRectItem, QGraphicsSceneHoverEvent, QGrap
import qt_ui.uiconstants as CONST import qt_ui.uiconstants as CONST
from game import Game from game import Game
from qt_ui.windows.basemenu.QBaseMenu import QBaseMenu
from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2 from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2
from theater import ControlPoint, db from theater import ControlPoint, db
@ -71,7 +70,8 @@ class QMapControlPoint(QGraphicsRectItem):
self.update() self.update()
def mousePressEvent(self, event:QGraphicsSceneMouseEvent): def mousePressEvent(self, event:QGraphicsSceneMouseEvent):
self.contextMenuEvent(event) self.openBaseMenu()
#self.contextMenuEvent(event)
def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent): def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent):
@ -89,17 +89,11 @@ class QMapControlPoint(QGraphicsRectItem):
@property @property
def brush_color(self)->QColor: 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"] 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"]
@property @property
def pen_color(self) -> QColor: def pen_color(self) -> QColor:
if self.parent.game.player_country in db.BLUEFOR_FACTIONS: return self.model.captured and CONST.COLORS["white"] or CONST.COLORS["white"]
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"]
def openBaseMenu(self): def openBaseMenu(self):
self.baseMenu = QBaseMenu2(self.window(), self.model, self.game) self.baseMenu = QBaseMenu2(self.window(), self.model, self.game)

View File

@ -17,17 +17,22 @@ class QMapEvent(QGraphicsRectItem):
self.setToolTip(str(self.gameEvent)) self.setToolTip(str(self.gameEvent))
self.playable = not isinstance(self.gameEvent, UnitsDeliveryEvent) self.playable = not isinstance(self.gameEvent, UnitsDeliveryEvent)
def paint(self, painter, option, widget=None): 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"): if self.parent.get_display_rule("events"):
painter.save() painter.save()
if self.gameEvent.is_player_attacking: if self.gameEvent.is_player_attacking:
painter.setPen(QPen(brush=CONST.COLORS["blue"])) painter.setPen(QPen(brush=CONST.COLORS[playerColor]))
painter.setBrush(CONST.COLORS["blue"]) painter.setBrush(CONST.COLORS[playerColor])
else: else:
painter.setPen(QPen(brush=CONST.COLORS["red"])) painter.setPen(QPen(brush=CONST.COLORS[enemyColor]))
painter.setBrush(CONST.COLORS["red"]) painter.setBrush(CONST.COLORS[enemyColor])
if self.isUnderMouse() and self.playable: if self.isUnderMouse() and self.playable:
painter.setBrush(CONST.COLORS["white"]) painter.setBrush(CONST.COLORS["white"])

View File

@ -42,6 +42,10 @@ class QMapGroundObject(QGraphicsRectItem):
def paint(self, painter, option, widget=None): def paint(self, painter, option, widget=None):
#super(QMapControlPoint, self).paint(painter, option, widget) #super(QMapControlPoint, self).paint(painter, option, widget)
playerIcons = "_blue"
enemyIcons = ""
if self.parent.get_display_rule("go"): if self.parent.get_display_rule("go"):
painter.save() painter.save()
@ -50,9 +54,9 @@ class QMapGroundObject(QGraphicsRectItem):
cat = "ship" cat = "ship"
if not self.model.is_dead and not self.cp.captured: 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: elif not self.model.is_dead:
painter.drawPixmap(option.rect, CONST.ICONS[cat + "_blue"]) painter.drawPixmap(option.rect, CONST.ICONS[cat + playerIcons])
else: else:
painter.drawPixmap(option.rect, CONST.ICONS["destroyed"]) painter.drawPixmap(option.rect, CONST.ICONS["destroyed"])
painter.restore() painter.restore()

View File

@ -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 PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout, QGroupBox, QGridLayout, QPushButton
from game.game import Event, db, Game from game.game import Event, db, Game
@ -25,14 +25,21 @@ class QDebriefingWindow(QDialog):
self.layout = QVBoxLayout() 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): # Result
title = QLabel("<b>Operation Succesfull !</b>") #if self.gameEvent.is_successfull(self.debriefing):
title.setProperty("style", "title-success") # title = QLabel("<b>Operation end !</b>")
else: # title.setProperty("style", "title-success")
title = QLabel("<b>Operation failed !</b>") #else:
title.setProperty("style", "title-danger") # title = QLabel("<b>Operation end !</b>")
# title.setProperty("style", "title-danger")
title = QLabel("<b>Casualty report</b>")
self.layout.addWidget(title) self.layout.addWidget(title)
# Player lost units # Player lost units

View File

@ -5,7 +5,7 @@ import webbrowser
from PySide2.QtCore import Qt from PySide2.QtCore import Qt
from PySide2.QtGui import QIcon from PySide2.QtGui import QIcon
from PySide2.QtWidgets import QWidget, QVBoxLayout, QMainWindow, QAction, QMessageBox, QDesktopWidget, \ from PySide2.QtWidgets import QWidget, QVBoxLayout, QMainWindow, QAction, QMessageBox, QDesktopWidget, \
QSplitter QSplitter, QFileDialog
import qt_ui.uiconstants as CONST import qt_ui.uiconstants as CONST
from game import Game from game import Game
@ -54,6 +54,7 @@ class QLiberationWindow(QMainWindow):
hbox = QSplitter(Qt.Horizontal) hbox = QSplitter(Qt.Horizontal)
hbox.addWidget(self.info_panel) hbox.addWidget(self.info_panel)
hbox.addWidget(self.liberation_map) hbox.addWidget(self.liberation_map)
hbox.setSizes([2, 8])
vbox = QVBoxLayout() vbox = QVBoxLayout()
vbox.setMargin(0) vbox.setMargin(0)
@ -73,10 +74,18 @@ class QLiberationWindow(QMainWindow):
self.newGameAction.setIcon(QIcon(CONST.ICONS["New"])) self.newGameAction.setIcon(QIcon(CONST.ICONS["New"]))
self.newGameAction.triggered.connect(self.newGame) 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 = QAction("Save", self)
self.saveGameAction.setIcon(QIcon(CONST.ICONS["Save"])) self.saveGameAction.setIcon(QIcon(CONST.ICONS["Save"]))
self.saveGameAction.triggered.connect(self.saveGame) 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 = QAction("About DCS Liberation", self)
self.showAboutDialogAction.setIcon(QIcon.fromTheme("help-about")) self.showAboutDialogAction.setIcon(QIcon.fromTheme("help-about"))
self.showAboutDialogAction.triggered.connect(self.showAboutDialog) self.showAboutDialogAction.triggered.connect(self.showAboutDialog)
@ -88,7 +97,7 @@ class QLiberationWindow(QMainWindow):
def initToolbar(self): def initToolbar(self):
self.tool_bar = self.addToolBar("File") self.tool_bar = self.addToolBar("File")
self.tool_bar.addAction(self.newGameAction) 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) self.tool_bar.addAction(self.saveGameAction)
def initMenuBar(self): def initMenuBar(self):
@ -96,25 +105,23 @@ class QLiberationWindow(QMainWindow):
file_menu = self.menu.addMenu("File") file_menu = self.menu.addMenu("File")
file_menu.addAction(self.newGameAction) 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.saveGameAction)
file_menu.addAction(self.saveAsAction)
file_menu.addSeparator() file_menu.addSeparator()
file_menu.addAction(self.showLiberationPrefDialogAction) file_menu.addAction(self.showLiberationPrefDialogAction)
file_menu.addSeparator() file_menu.addSeparator()
#file_menu.addAction("Save As") # TODO : implement
#file_menu.addAction("Close Current Game", lambda: self.closeGame()) # Not working #file_menu.addAction("Close Current Game", lambda: self.closeGame()) # Not working
file_menu.addAction("Exit" , lambda: self.exit()) file_menu.addAction("Exit" , lambda: self.exit())
help_menu = self.menu.addMenu("Help") 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("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("ED Forum Thread", lambda: webbrowser.open_new_tab(URLS["ForumThread"]))
#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("Report an issue", lambda: webbrowser.open_new_tab(URLS["Issues"])) help_menu.addAction("Report an issue", lambda: webbrowser.open_new_tab(URLS["Issues"]))
help_menu.addSeparator() help_menu.addSeparator()
help_menu.addAction(self.showAboutDialogAction) help_menu.addAction(self.showAboutDialogAction)
@ -163,10 +170,29 @@ class QLiberationWindow(QMainWindow):
wizard.show() wizard.show()
wizard.accepted.connect(lambda: self.onGameGenerated(wizard.generatedGame)) 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): def saveGame(self):
logging.info("Saving game") logging.info("Saving game")
if self.game.savepath:
persistency.save_game(self.game) persistency.save_game(self.game)
GameUpdateSignal.get_instance().updateGame(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): def onGameGenerated(self, game: Game):
logging.info("On Game generated") logging.info("On Game generated")
@ -187,13 +213,15 @@ class QLiberationWindow(QMainWindow):
def showAboutDialog(self): def showAboutDialog(self):
text = "<h3>DCS Liberation</h3>" + \ text = "<h3>DCS Liberation</h3>" + \
"<h4>Repository</h4>" + \ "<b>Source code :</b> https://github.com/khopa/dcs_liberation" + \
"<b>Source code :</b> https://github.com/shdwp/dcs_liberation<br/>" + \ "<h4>Authors</h4>" + \
"<h4>Authors/Contributors</h4><br/>" + \ "<p>DCS Liberation was originally developed by <b>shdwp</b>, DCS Liberation 2.0 is a partial rewrite based on this work by <b>Khopa</b>." \
"<b>shdwp</b>, <b>Khopa</b>, <b>Wrycu</b>, <b>calvinmorrow</b>, <b>JohanAberg</b><br/>" + \ "<h4>Contributors</h4>" + \
"shdwp, Khopa, Wrycu, calvinmorrow, JohanAberg, Deus" + \
"<h4>Special Thanks :</h4>" \ "<h4>Special Thanks :</h4>" \
"<b>rp-</b> <i>for the pydcs framework</i><br/>"\ "<b>rp-</b> <i>for the pydcs framework</i><br/>"\
"<b>Grimes (mrSkortch)</b> & <b>Speed</b> <i>for the MIST framework</i><br/>" "<b>Grimes (mrSkortch)</b> & <b>Speed</b> <i>for the MIST framework</i><br/>"\
"<b>Ciribob </b> <i>for the JTACAutoLase.lua script</i><br/>"
about = QMessageBox() about = QMessageBox()
about.setWindowTitle("About DCS Liberation") about.setWindowTitle("About DCS Liberation")

View File

@ -3,10 +3,12 @@ from __future__ import unicode_literals
import datetime import datetime
from PySide2 import QtGui, QtWidgets from PySide2 import QtGui, QtWidgets
from PySide2.QtWidgets import QHBoxLayout, QVBoxLayout
from dcs.task import CAP, CAS from dcs.task import CAP, CAS
import qt_ui.uiconstants as CONST import qt_ui.uiconstants as CONST
from game import db, Game from game import db, Game
from game.settings import Settings
from gen import namegen from gen import namegen
from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy, thechannel from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy, thechannel
@ -30,13 +32,12 @@ class NewGameWizard(QtWidgets.QWizard):
def accept(self): def accept(self):
blueFaction = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "blue"][self.field("blueFaction")] blueFaction = [c for c in db.FACTIONS][self.field("blueFaction")]
redFaction = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "red"][self.field("redFaction")] redFaction = [c for c in db.FACTIONS][self.field("redFaction")]
playerIsBlue = self.field("playerIsBlue")
isTerrainPg = self.field("isTerrainPg") isTerrainPg = self.field("isTerrainPg")
isTerrainNttr = self.field("isTerrainNttr") isTerrainNttr = self.field("isTerrainNttr")
isTerrainCaucasusSmall = self.field("isTerrainCaucasusSmall") isTerrainCaucasusSmall = self.field("isTerrainCaucasusSmall")
isTerrainCaucasusSmallInverted = self.field("isTerrainCaucasusSmallInverted") isTerrainRussia = self.field("isTerrainRussia")
isTerrainCaucasusNorth= self.field("isTerrainCaucasusNorth") isTerrainCaucasusNorth= self.field("isTerrainCaucasusNorth")
isIranianCampaignTheater = self.field("isIranianCampaignTheater") isIranianCampaignTheater = self.field("isIranianCampaignTheater")
isTerrainNormandy = self.field("isTerrainNormandy") isTerrainNormandy = self.field("isTerrainNormandy")
@ -47,9 +48,15 @@ class NewGameWizard(QtWidgets.QWizard):
timePeriod = db.TIME_PERIODS[list(db.TIME_PERIODS.keys())[self.field("timePeriod")]] timePeriod = db.TIME_PERIODS[list(db.TIME_PERIODS.keys())[self.field("timePeriod")]]
midGame = self.field("midGame") midGame = self.field("midGame")
multiplier = self.field("multiplier") 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 player_name = blueFaction
enemy_name = playerIsBlue and redFaction or blueFaction enemy_name = redFaction
if isTerrainPg: if isTerrainPg:
conflicttheater = persiangulf.PersianGulfTheater() conflicttheater = persiangulf.PersianGulfTheater()
@ -57,8 +64,8 @@ class NewGameWizard(QtWidgets.QWizard):
conflicttheater = nevada.NevadaTheater() conflicttheater = nevada.NevadaTheater()
elif isTerrainCaucasusSmall: elif isTerrainCaucasusSmall:
conflicttheater = caucasus.WesternGeorgia() conflicttheater = caucasus.WesternGeorgia()
elif isTerrainCaucasusSmallInverted: elif isTerrainRussia:
conflicttheater = caucasus.WesternGeorgiaInverted() conflicttheater = caucasus.RussiaSmall()
elif isTerrainCaucasusNorth: elif isTerrainCaucasusNorth:
conflicttheater = caucasus.NorthCaucasus() conflicttheater = caucasus.NorthCaucasus()
elif isIranianCampaignTheater: elif isIranianCampaignTheater:
@ -76,20 +83,25 @@ class NewGameWizard(QtWidgets.QWizard):
else: else:
conflicttheater = caucasus.CaucasusTheater() 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, self.generatedGame = self.start_new_game(player_name, enemy_name, conflicttheater, midGame, multiplier,
timePeriod) timePeriod, settings)
super(NewGameWizard, self).accept() super(NewGameWizard, self).accept()
def start_new_game(self, player_name: str, enemy_name: str, conflicttheater: ConflictTheater, def start_new_game(self, player_name: str, enemy_name: str, conflicttheater: ConflictTheater,
midgame: bool, multiplier: float, period: datetime): midgame: bool, multiplier: float, period: datetime, settings:Settings):
if midgame:
for i in range(0, int(len(conflicttheater.controlpoints) / 2)):
conflicttheater.controlpoints[i].captured = True
# Reset name generator # Reset name generator
namegen.reset() namegen.reset()
start_generator.prepare_theater(conflicttheater, settings, midgame)
print("-- Starting New Game Generator") print("-- Starting New Game Generator")
print("Enemy name : " + enemy_name) print("Enemy name : " + enemy_name)
@ -101,14 +113,15 @@ class NewGameWizard(QtWidgets.QWizard):
game = Game(player_name=player_name, game = Game(player_name=player_name,
enemy_name=enemy_name, enemy_name=enemy_name,
theater=conflicttheater, theater=conflicttheater,
start_date=period) start_date=period,
settings=settings)
print("-- Game Object generated") print("-- Game Object generated")
start_generator.generate_groundobjects(conflicttheater, game) start_generator.generate_groundobjects(conflicttheater, game)
game.budget = int(game.budget * multiplier) game.budget = int(game.budget * multiplier)
game.settings.multiplier = multiplier game.settings.multiplier = multiplier
game.settings.sams = True game.settings.sams = True
game.settings.version = "2.0RC9" game.settings.version = "2.0.10"
if midgame: if midgame:
game.budget = game.budget * 4 * len(list(conflicttheater.conflicts())) game.budget = game.budget * 4 * len(list(conflicttheater.conflicts()))
@ -140,59 +153,59 @@ class FactionSelection(QtWidgets.QWizardPage):
self.setTitle("Faction selection") self.setTitle("Faction selection")
self.setSubTitle("\nChoose the two opposing factions and select the player side.") self.setSubTitle("\nChoose the two opposing factions and select the player side.")
self.setPixmap(QtWidgets.QWizard.LogoPixmap, self.setPixmap(QtWidgets.QWizard.LogoPixmap,
QtGui.QPixmap('./resources/ui/wizard/logo1.png')) QtGui.QPixmap('./resources/ui/misc/generator.png'))
self.setMinimumHeight(250) self.setMinimumHeight(250)
blues = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "blue"] # Factions selection
reds = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "red"] self.factionsGroup = QtWidgets.QGroupBox("Factions")
self.factionsGroupLayout = QtWidgets.QGridLayout()
# Create form blueFaction = QtWidgets.QLabel("<b>Player Faction :</b>")
blueFaction = QtWidgets.QLabel("Blue Faction :")
self.blueFactionSelect = QtWidgets.QComboBox() self.blueFactionSelect = QtWidgets.QComboBox()
for f in blues: for f in db.FACTIONS:
self.blueFactionSelect.addItem(f) self.blueFactionSelect.addItem(f)
blueFaction.setBuddy(self.blueFactionSelect) blueFaction.setBuddy(self.blueFactionSelect)
redFaction = QtWidgets.QLabel("Red Faction :") redFaction = QtWidgets.QLabel("<b>Enemy Faction :</b>")
self.redFactionSelect = QtWidgets.QComboBox() self.redFactionSelect = QtWidgets.QComboBox()
for r in reds: for i, r in enumerate(db.FACTIONS):
self.redFactionSelect.addItem(r) self.redFactionSelect.addItem(r)
if r == "Russia 1990": # Default ennemy
self.redFactionSelect.setCurrentIndex(i)
redFaction.setBuddy(self.redFactionSelect) 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 = QtWidgets.QLabel("")
self.blueSideRecap.setFont(QtGui.QFont("Arial", italic=True)) self.blueSideRecap.setFont(CONST.FONT_PRIMARY_I)
self.blueSideRecap.setWordWrap(True) self.blueSideRecap.setWordWrap(True)
self.redSideRecap = QtWidgets.QLabel("") self.redSideRecap = QtWidgets.QLabel("")
self.redSideRecap.setFont(QtGui.QFont("Arial", italic=True)) self.redSideRecap.setFont(CONST.FONT_PRIMARY_I)
self.redSideRecap.setWordWrap(True) 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("<ul><li>None</li></ul>")
self.requiredModsGroupLayout.addWidget(self.requiredMods)
self.requiredModsGroup.setLayout(self.requiredModsGroupLayout)
# Link form fields # Link form fields
self.registerField('blueFaction', self.blueFactionSelect) self.registerField('blueFaction', self.blueFactionSelect)
self.registerField('redFaction', self.redFactionSelect) self.registerField('redFaction', self.redFactionSelect)
self.registerField('playerIsBlue', blueforRadioButton)
self.registerField('playerIsRed', redforRadioButton)
# Build layout # Build layout
sideGroupLayout = QtWidgets.QVBoxLayout() layout = QtWidgets.QVBoxLayout()
sideGroupLayout.addWidget(blueforRadioButton) layout.addWidget(self.factionsGroup)
sideGroupLayout.addWidget(redforRadioButton) layout.addWidget(self.requiredModsGroup)
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)
self.setLayout(layout) self.setLayout(layout)
self.updateUnitRecap() self.updateUnitRecap()
@ -200,8 +213,14 @@ class FactionSelection(QtWidgets.QWizardPage):
self.redFactionSelect.activated.connect(self.updateUnitRecap) self.redFactionSelect.activated.connect(self.updateUnitRecap)
def updateUnitRecap(self): def updateUnitRecap(self):
red_units = db.FACTIONS[self.redFactionSelect.currentText()]["units"]
blue_units = db.FACTIONS[self.blueFactionSelect.currentText()]["units"] self.requiredMods.setText("<ul>")
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 = "" blue_txt = ""
for u in blue_units: for u in blue_units:
@ -217,6 +236,23 @@ class FactionSelection(QtWidgets.QWizardPage):
red_txt = red_txt + "\n" red_txt = red_txt + "\n"
self.redSideRecap.setText(red_txt) 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<li>" + mod + ": <a href=\""+red_faction["requirements"][mod]+"\">" + red_faction["requirements"][mod] + "</a></li>")
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<li>" + mod + ": <a href=\""+blue_faction["requirements"][mod]+"\">" + blue_faction["requirements"][mod] + "</a></li>")
if has_mod:
self.requiredMods.setText(self.requiredMods.text() + "</ul>\n\n")
else:
self.requiredMods.setText(self.requiredMods.text() + "<li>None</li></ul>\n")
class TheaterConfiguration(QtWidgets.QWizardPage): class TheaterConfiguration(QtWidgets.QWizardPage):
def __init__(self, parent=None): def __init__(self, parent=None):
@ -227,24 +263,27 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
self.setPixmap(QtWidgets.QWizard.LogoPixmap, self.setPixmap(QtWidgets.QWizard.LogoPixmap,
QtGui.QPixmap('./resources/ui/wizard/logo1.png')) QtGui.QPixmap('./resources/ui/wizard/logo1.png'))
self.setPixmap(QtWidgets.QWizard.WatermarkPixmap,
QtGui.QPixmap('./resources/ui/wizard/watermark3.png'))
# Terrain selection # Terrain selection
terrainGroup = QtWidgets.QGroupBox("Terrain") 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"])) terrainCaucasusSmall.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"]))
terrainCaucasusSmallInverted = QtWidgets.QRadioButton("Caucasus - Western Georgia Inverted [RECOMMENDED - Early Cold War Era]") terrainRussia = QtWidgets.QRadioButton("Caucasus - Russia Small")
terrainCaucasusSmallInverted.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"])) terrainRussia.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"]))
terrainCaucasus = QtWidgets.QRadioButton("Caucasus - Full map [NOT TESTED]") terrainCaucasus = QtWidgets.QRadioButton("Caucasus - Full map [NOT RECOMMENDED]")
terrainCaucasus.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"])) 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"])) 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"])) 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"])) 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"])) 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"])) terrainNttr.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Nevada"]))
terrainNormandy = QtWidgets.QRadioButton("Normandy") terrainNormandy = QtWidgets.QRadioButton("Normandy")
terrainNormandy.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_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"])) terrainChannelComplete.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Channel"]))
terrainCaucasusSmall.setChecked(True) 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 # Time Period
timeGroup = QtWidgets.QGroupBox("Time Period") timeGroup = QtWidgets.QGroupBox("Time Period")
timePeriod = QtWidgets.QLabel("Start date :") timePeriod = QtWidgets.QLabel("Start date :")
@ -268,7 +316,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
# Register fields # Register fields
self.registerField('isTerrainCaucasus', terrainCaucasus) self.registerField('isTerrainCaucasus', terrainCaucasus)
self.registerField('isTerrainCaucasusSmall', terrainCaucasusSmall) self.registerField('isTerrainCaucasusSmall', terrainCaucasusSmall)
self.registerField('isTerrainCaucasusSmallInverted', terrainCaucasusSmallInverted) self.registerField('isTerrainRussia', terrainRussia)
self.registerField('isTerrainCaucasusNorth', terrainCaucasusNorth) self.registerField('isTerrainCaucasusNorth', terrainCaucasusNorth)
self.registerField('isTerrainPg', terrainPg) self.registerField('isTerrainPg', terrainPg)
self.registerField('isIranianCampaignTheater', terrainIran) self.registerField('isIranianCampaignTheater', terrainIran)
@ -283,7 +331,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
# Build layout # Build layout
terrainGroupLayout = QtWidgets.QVBoxLayout() terrainGroupLayout = QtWidgets.QVBoxLayout()
terrainGroupLayout.addWidget(terrainCaucasusSmall) terrainGroupLayout.addWidget(terrainCaucasusSmall)
terrainGroupLayout.addWidget(terrainCaucasusSmallInverted) terrainGroupLayout.addWidget(terrainRussia)
terrainGroupLayout.addWidget(terrainCaucasusNorth) terrainGroupLayout.addWidget(terrainCaucasusNorth)
terrainGroupLayout.addWidget(terrainCaucasus) terrainGroupLayout.addWidget(terrainCaucasus)
terrainGroupLayout.addWidget(terrainIran) terrainGroupLayout.addWidget(terrainIran)
@ -303,8 +351,9 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
layout = QtWidgets.QGridLayout() layout = QtWidgets.QGridLayout()
layout.setColumnMinimumWidth(0, 20) layout.setColumnMinimumWidth(0, 20)
layout.addWidget(terrainGroup) layout.addWidget(terrainGroup, 0, 0, 3, 1)
layout.addWidget(timeGroup) layout.addWidget(mapSettingsGroup, 0, 1, 1, 1)
layout.addWidget(timeGroup, 1, 1, 1, 1)
self.setLayout(layout) self.setLayout(layout)
@ -323,15 +372,47 @@ class MiscOptions(QtWidgets.QWizardPage):
multiplier.setMinimum(1) multiplier.setMinimum(1)
multiplier.setMaximum(5) multiplier.setMaximum(5)
miscSettingsGroup = QtWidgets.QGroupBox("Misc Settings")
self.registerField('midGame', midGame) self.registerField('midGame', midGame)
self.registerField('multiplier', multiplier) 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 = QtWidgets.QGridLayout()
layout.addWidget(QtWidgets.QLabel("Start at mid game"), 1, 0) layout.addWidget(QtWidgets.QLabel("Start at mid game"), 1, 0)
layout.addWidget(midGame, 1, 1) layout.addWidget(midGame, 1, 1)
layout.addWidget(QtWidgets.QLabel("Ennemy forces multiplier [Disabled for Now]"), 2, 0) layout.addWidget(QtWidgets.QLabel("Ennemy forces multiplier [Disabled for Now]"), 2, 0)
layout.addWidget(multiplier, 2, 1) 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): class ConclusionPage(QtWidgets.QWizardPage):

View File

@ -1,15 +1,18 @@
import json
import os import os
from PySide2 import QtCore from PySide2 import QtCore
from PySide2.QtCore import QObject, Signal from PySide2.QtCore import QObject, Signal, Qt
from PySide2.QtGui import QMovie, QIcon from PySide2.QtGui import QMovie, QIcon, QPixmap
from PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout, QGroupBox, QGridLayout, QPushButton 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 qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from userdata.debriefing import wait_for_debriefing, Debriefing from userdata.debriefing import wait_for_debriefing, Debriefing
from userdata.persistency import base_path from userdata.persistency import base_path
class DebriefingFileWrittenSignal(QObject): class DebriefingFileWrittenSignal(QObject):
instance = None instance = None
@ -36,48 +39,87 @@ class QWaitingForMissionResultWindow(QDialog):
self.gameEvent = gameEvent self.gameEvent = gameEvent
self.game = game self.game = game
self.setWindowTitle("Waiting for mission completion.") self.setWindowTitle("Waiting for mission completion.")
self.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, False)
self.setWindowIcon(QIcon("./resources/icon.png")) self.setWindowIcon(QIcon("./resources/icon.png"))
self.setMinimumHeight(570)
self.initUi() self.initUi()
DebriefingFileWrittenSignal.get_instance().debriefingReceived.connect(self.updateLayout) 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): def initUi(self):
self.layout = QGridLayout() 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 = QGridLayout()
self.gridLayout.addWidget(QLabel("<b>You are clear for takeoff</b>"), 1, 0) TEXT = "" + \
self.gridLayout.addWidget(QLabel(""), 2, 0) "<b>You are clear for takeoff</b>" + \
self.gridLayout.addWidget(QLabel("<h2>For Singleplayer :</h2>"), 3, 0) "" + \
self.gridLayout.addWidget(QLabel("In DCS, open the Mission Editor, and load the file : "), 4, 0) "<h2>For Singleplayer :</h2>\n" + \
self.gridLayout.addWidget(QLabel("<i>liberation_nextturn</i>"), 5, 0) "In DCS, open the Mission Editor, and load the file : \n" + \
self.gridLayout.addWidget(QLabel("Then once the mission is loaded in ME, in menu \"Flight\", click on FLY Mission to launch"), 6, 0) "<i>liberation_nextturn</i>\n" + \
self.gridLayout.addWidget(QLabel(""), 7, 0) "<p>Then once the mission is loaded in ME, in menu \"Flight\",\n" + \
self.gridLayout.addWidget(QLabel("<h2>For Multiplayer :</h2>"), 8, 0) "click on FLY Mission to launch.</p>\n" + \
self.gridLayout.addWidget(QLabel("In DCS, open the Mission Editor, and load the file : "), 9, 0) "" + \
self.gridLayout.addWidget(QLabel("<i>liberation_nextturn</i>"), 10, 0) "<h2>For Multiplayer :</h2>" + \
self.gridLayout.addWidget(QLabel("Click on File/Save. Then exit the mission editor, and go to Multiplayer."), 11, 0) "In DCS, open the Mission Editor, and load the file : " + \
self.gridLayout.addWidget(QLabel("Then host a server with the mission, and tell your friends to join !"), 12, 0) "<i>liberation_nextturn</i>" + \
self.gridLayout.addWidget(QLabel("(The step in the mission editor is important, and fix a game breaking bug.)"), 13, 0) "<p>Click on File/Save. Then exit the mission editor, and go to Multiplayer.</p>" + \
self.gridLayout.addWidget(QLabel(""), 14, 0) "<p>Then host a server with the mission, and tell your friends to join !</p>" + \
"<i>(The step in the mission editor is important, and fix a game breaking bug.)</i>" + \
"<h2>Finishing</h2>" + \
"<p>Once you have played the mission, click on the \"Accept Results\" button.</p>" + \
"<p>If DCS Liberation does not detect mission end, use the manually submit button, and choose the state.json file.</p>"
self.instructions_text = QTextEdit(TEXT)
self.instructions_text.setReadOnly(True)
self.gridLayout.addWidget(self.instructions_text, 1, 0)
progress = QLabel("") progress = QLabel("")
progress.setAlignment(QtCore.Qt.AlignCenter) progress.setAlignment(QtCore.Qt.AlignCenter)
progressBar = QMovie("./resources/ui/loader.gif") progress_bar = QMovie("./resources/ui/loader.gif")
progress.setMovie(progressBar) progress.setMovie(progress_bar)
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)
progressBar.start() self.actions = QGroupBox("Actions :")
self.layout.addLayout(self.gridLayout,0,0) 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) self.setLayout(self.layout)
def updateLayout(self, debriefing): def updateLayout(self, debriefing):
updateBox = QGroupBox("Mission status") updateBox = QGroupBox("Mission status")
updateLayout = QGridLayout() updateLayout = QGridLayout()
updateBox.setLayout(updateLayout) updateBox.setLayout(updateLayout)
self.debriefing = debriefing
updateLayout.addWidget(QLabel("<b>Aircrafts destroyed</b>"), 0, 0) updateLayout.addWidget(QLabel("<b>Aircrafts destroyed</b>"), 0, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.killed_aircrafts))), 0, 1) updateLayout.addWidget(QLabel(str(len(debriefing.killed_aircrafts))), 0, 1)
@ -85,40 +127,72 @@ class QWaitingForMissionResultWindow(QDialog):
updateLayout.addWidget(QLabel("<b>Ground units destroyed</b>"), 1, 0) updateLayout.addWidget(QLabel("<b>Ground units destroyed</b>"), 1, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.killed_ground_units))), 1, 1) updateLayout.addWidget(QLabel(str(len(debriefing.killed_ground_units))), 1, 1)
updateLayout.addWidget(QLabel("<b>Weapons fired</b>"), 2, 0) #updateLayout.addWidget(QLabel("<b>Weapons fired</b>"), 2, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.weapons_fired))), 2, 1) #updateLayout.addWidget(QLabel(str(len(debriefing.weapons_fired))), 2, 1)
updateLayout.addWidget(QLabel("<b>Base Capture Events</b>"), 3, 0) updateLayout.addWidget(QLabel("<b>Base Capture Events</b>"), 2, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.base_capture_events))), 3, 1) updateLayout.addWidget(QLabel(str(len(debriefing.base_capture_events))), 2, 1)
# Clear previous content of the window # Clear previous content of the window
for i in reversed(range(self.gridLayout.count())): for i in reversed(range(self.gridLayout.count())):
try:
self.gridLayout.itemAt(i).widget().setParent(None) self.gridLayout.itemAt(i).widget().setParent(None)
except:
pass
# Set new window content # Set new window content
self.gridLayout.addWidget(updateBox, 0, 0) self.gridLayout.addWidget(updateBox, 0, 0)
if not debriefing.mission_ended: if not debriefing.mission_ended:
self.gridLayout.addWidget(QLabel("<b>Mission is being played</b>"), 1, 0) self.gridLayout.addWidget(QLabel("<b>Mission is being played</b>"), 1, 0)
self.gridLayout.addWidget(self.actions, 2, 0)
else: else:
#self.gridLayout.addWidget(QLabel("<b>Mission is over !</b>"), 1, 0) self.gridLayout.addWidget(QLabel("<b>Mission is over</b>"), 1, 0)
proceed = QPushButton("Accept results") self.gridLayout.addWidget(self.actions2, 2, 0)
proceed.setProperty("style", "btn-primary")
proceed.clicked.connect(lambda: self.process_debriefing(debriefing))
self.gridLayout.addWidget(proceed, 1, 0)
def on_debriefing_udpate(self, debriefing): def on_debriefing_udpate(self, debriefing):
print("On Debriefing update") try:
logging.info("On Debriefing update")
print(debriefing) print(debriefing)
DebriefingFileWrittenSignal.get_instance().sendDebriefing(debriefing) DebriefingFileWrittenSignal.get_instance().sendDebriefing(debriefing)
wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game) 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): def process_debriefing(self):
self.game.finish_event(event=self.gameEvent, debriefing=debriefing) self.game.finish_event(event=self.gameEvent, debriefing=self.debriefing)
self.game.pass_turn(ignored_cps=[self.gameEvent.to_cp, ]) 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() self.close()
def debriefing_directory_location(self) -> str: def debriefing_directory_location(self) -> str:
return os.path.join(base_path(), "liberation_debriefings") 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

View File

@ -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("<b>" + self.cp.name + "</b>")
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("<b>" + db.unit_type_name(unit_type) + "</b>"), 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("<b>" + db.unit_type_name(unit_type) + "</b>")
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)

View File

@ -1,5 +1,5 @@
from PySide2.QtCore import Qt 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 PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QDialog, QGridLayout
from game import Game from game import Game
@ -35,6 +35,8 @@ class QBaseMenu2(QDialog):
self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setMinimumSize(300, 200) self.setMinimumSize(300, 200)
self.setMinimumWidth(800)
self.setMaximumWidth(800)
self.setModal(True) self.setModal(True)
self.initUi() self.initUi()
@ -46,6 +48,11 @@ class QBaseMenu2(QDialog):
self.topLayoutWidget = QWidget() self.topLayoutWidget = QWidget()
self.topLayout = QHBoxLayout() self.topLayout = QHBoxLayout()
header = QLabel(self)
header.setGeometry(0, 0, 655, 106)
pixmap = QPixmap(self.get_base_image())
header.setPixmap(pixmap)
title = QLabel("<b>" + self.cp.name + "</b>") title = QLabel("<b>" + self.cp.name + "</b>")
title.setAlignment(Qt.AlignLeft | Qt.AlignTop) title.setAlignment(Qt.AlignLeft | Qt.AlignTop)
title.setProperty("style", "base-title") title.setProperty("style", "base-title")
@ -59,10 +66,19 @@ class QBaseMenu2(QDialog):
self.topLayoutWidget.setLayout(self.topLayout) self.topLayoutWidget.setLayout(self.topLayout)
self.mainLayout = QGridLayout() self.mainLayout = QGridLayout()
self.mainLayout.addWidget(self.topLayoutWidget, 0, 0) self.mainLayout.addWidget(header, 0, 0)
self.mainLayout.addWidget(self.qbase_menu_tab, 1, 0) self.mainLayout.addWidget(self.topLayoutWidget, 1, 0)
self.mainLayout.addWidget(self.qbase_menu_tab, 2, 0)
self.setLayout(self.mainLayout) self.setLayout(self.mainLayout)
def closeEvent(self, closeEvent:QCloseEvent): def closeEvent(self, closeEvent:QCloseEvent):
GameUpdateSignal.get_instance().updateGame(self.game) 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"

View File

@ -1,5 +1,5 @@
from PySide2.QtWidgets import QLabel, QPushButton, \ from PySide2.QtWidgets import QLabel, QPushButton, \
QSizePolicy, QSpacerItem QSizePolicy, QSpacerItem, QGroupBox, QHBoxLayout
from dcs.unittype import UnitType from dcs.unittype import UnitType
from theater import db from theater import db
@ -19,54 +19,75 @@ class QRecruitBehaviour:
def add_purchase_row(self, unit_type, layout, row): 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) existing_units = self.cp.base.total_units_of_type(unit_type)
scheduled_units = self.deliveryEvent.units.get(unit_type, 0) scheduled_units = self.deliveryEvent.units.get(unit_type, 0)
unitName = QLabel("<b>" + db.unit_type_name(unit_type) + "</b>") unitName = QLabel("<b>" + db.unit_type_name_2(unit_type) + "</b>")
unitName.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) unitName.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
existing_units = QLabel(str(existing_units)) existing_units = QLabel(str(existing_units))
existing_units.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) existing_units.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
amount_bought = QLabel("[{}]".format(str(scheduled_units))) amount_bought = QLabel("<b>{}</b>".format(str(scheduled_units)))
amount_bought.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) amount_bought.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
self.existing_units_labels[unit_type] = existing_units self.existing_units_labels[unit_type] = existing_units
self.bought_amount_labels[unit_type] = amount_bought self.bought_amount_labels[unit_type] = amount_bought
price = QLabel("{}m".format(db.PRICES[unit_type])) price = QLabel("<b>$ {:02d}</b> m".format(db.PRICES[unit_type]))
price.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) 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 = QPushButton("+")
buy.setProperty("style", "btn-success") buy.setProperty("style", "btn-buy")
buy.setMinimumSize(24, 24) buy.setMinimumSize(16, 16)
buy.setMaximumSize(16, 16)
buy.clicked.connect(lambda: self.buy(unit_type)) buy.clicked.connect(lambda: self.buy(unit_type))
buy.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) buy.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
sell = QPushButton("-") sell = QPushButton("-")
sell.setProperty("style", "btn-danger") sell.setProperty("style", "btn-sell")
sell.setMinimumSize(24, 24) sell.setMinimumSize(16, 16)
sell.setMaximumSize(16, 16)
sell.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) sell.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
sell.clicked.connect(lambda: self.sell(unit_type)) sell.clicked.connect(lambda: self.sell(unit_type))
layout.addWidget(unitName, row, 0)
layout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum), row, 1) existLayout.addWidget(unitName)
layout.addWidget(existing_units, row, 2) existLayout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum))
layout.addWidget(amount_bought, row, 3) existLayout.addWidget(existing_units)
layout.addWidget(price, row, 4) existLayout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum))
layout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum), row, 5) existLayout.addWidget(price)
layout.addWidget(buy, row, 6)
layout.addWidget(sell, row, 7) buysellayout.addWidget(sell)
buysellayout.addWidget(amount_bought)
buysellayout.addWidget(buy)
layout.addWidget(exist, row, 1)
layout.addWidget(buysell, row, 2)
return row + 1 return row + 1
def _update_count_label(self, unit_type: UnitType): def _update_count_label(self, unit_type: UnitType):
self.bought_amount_labels[unit_type].setText("[{}]".format( self.bought_amount_labels[unit_type].setText("<b>{}</b>".format(
unit_type in self.deliveryEvent.units and "{}".format(self.deliveryEvent.units[unit_type]) or "0" 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("<b>{}</b>".format(
self.cp.base.total_units_of_type(unit_type) self.cp.base.total_units_of_type(unit_type)
)) ))

View File

@ -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 game.event import UnitsDeliveryEvent
from qt_ui.windows.basemenu.QRecruitBehaviour import QRecruitBehaviour from qt_ui.windows.basemenu.QRecruitBehaviour import QRecruitBehaviour
@ -6,10 +7,10 @@ from theater import ControlPoint, CAP, CAS, db
from game import Game from game import Game
class QAircraftRecruitmentMenu(QGroupBox, QRecruitBehaviour): class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour):
def __init__(self, cp:ControlPoint, game:Game): def __init__(self, cp:ControlPoint, game:Game):
QGroupBox.__init__(self, "Recruitment") QFrame.__init__(self)
self.cp = cp self.cp = cp
self.game = game self.game = game
@ -25,13 +26,14 @@ class QAircraftRecruitmentMenu(QGroupBox, QRecruitBehaviour):
self.init_ui() self.init_ui()
def init_ui(self): def init_ui(self):
layout = QVBoxLayout() main_layout = QVBoxLayout()
units = { units = {
CAP: db.find_unittype(CAP, self.game.player_name), CAP: db.find_unittype(CAP, self.game.player_name),
CAS: db.find_unittype(CAS, self.game.player_name), CAS: db.find_unittype(CAS, self.game.player_name),
} }
scroll_content = QWidget()
task_box_layout = QGridLayout() task_box_layout = QGridLayout()
row = 0 row = 0
@ -49,6 +51,11 @@ class QAircraftRecruitmentMenu(QGroupBox, QRecruitBehaviour):
stretch.addStretch() stretch.addStretch()
task_box_layout.addLayout(stretch, row, 0) task_box_layout.addLayout(stretch, row, 0)
layout.addLayout(task_box_layout) scroll_content.setLayout(task_box_layout)
layout.addStretch() scroll = QScrollArea()
self.setLayout(layout) scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(True)
scroll.setWidget(scroll_content)
main_layout.addWidget(scroll)
self.setLayout(main_layout)

View File

@ -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 import Game
from game.event import UnitsDeliveryEvent from game.event import UnitsDeliveryEvent
@ -6,10 +7,10 @@ from qt_ui.windows.basemenu.QRecruitBehaviour import QRecruitBehaviour
from theater import ControlPoint, PinpointStrike, db from theater import ControlPoint, PinpointStrike, db
class QArmorRecruitmentMenu(QGroupBox, QRecruitBehaviour): class QArmorRecruitmentMenu(QFrame, QRecruitBehaviour):
def __init__(self, cp:ControlPoint, game:Game): def __init__(self, cp:ControlPoint, game:Game):
QGroupBox.__init__(self, "Recruitment") QFrame.__init__(self)
self.cp = cp self.cp = cp
self.game = game self.game = game
@ -25,13 +26,15 @@ class QArmorRecruitmentMenu(QGroupBox, QRecruitBehaviour):
self.init_ui() self.init_ui()
def init_ui(self): def init_ui(self):
layout = QVBoxLayout() main_layout = QVBoxLayout()
units = { units = {
PinpointStrike: db.find_unittype(PinpointStrike, self.game.player_name), PinpointStrike: db.find_unittype(PinpointStrike, self.game.player_name),
} }
scroll_content = QWidget()
task_box_layout = QGridLayout() task_box_layout = QGridLayout()
scroll_content.setLayout(task_box_layout)
row = 0 row = 0
for task_type in units.keys(): for task_type in units.keys():
@ -44,6 +47,11 @@ class QArmorRecruitmentMenu(QGroupBox, QRecruitBehaviour):
stretch.addStretch() stretch.addStretch()
task_box_layout.addLayout(stretch, row, 0) task_box_layout.addLayout(stretch, row, 0)
layout.addLayout(task_box_layout) scroll_content.setLayout(task_box_layout)
layout.addStretch() scroll = QScrollArea()
self.setLayout(layout) scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(True)
scroll.setWidget(scroll_content)
main_layout.addWidget(scroll)
self.setLayout(main_layout)

View File

@ -22,7 +22,7 @@ class QInfoPanel(QGroupBox):
layout = QVBoxLayout() layout = QVBoxLayout()
layout.addWidget(self.informations_list) layout.addWidget(self.informations_list)
layout.setSpacing(0) layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 20, 0, 0)
self.setLayout(layout) self.setLayout(layout)

View File

@ -16,7 +16,7 @@ class QMissionPlanning(QDialog):
super(QMissionPlanning, self).__init__() super(QMissionPlanning, self).__init__()
self.game = game self.game = game
self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setMinimumSize(1000, 420) self.setMinimumSize(1000, 440)
self.setModal(True) self.setModal(True)
self.setWindowTitle("Mission Preparation") self.setWindowTitle("Mission Preparation")
self.setWindowIcon(EVENT_ICONS["strike"]) self.setWindowIcon(EVENT_ICONS["strike"])
@ -33,10 +33,12 @@ class QMissionPlanning(QDialog):
self.select_airbase = QChooseAirbase(self.game) self.select_airbase = QChooseAirbase(self.game)
self.select_airbase.selected_airbase_changed.connect(self.on_departure_cp_changed) self.select_airbase.selected_airbase_changed.connect(self.on_departure_cp_changed)
self.planned_flight_view = QPlannedFlightsView(None) self.planned_flight_view = QPlannedFlightsView(None)
self.available_aircraft_at_selected_location = {}
if self.captured_cp[0].id in self.game.planners.keys(): if self.captured_cp[0].id in self.game.planners.keys():
self.planner = self.game.planners[self.captured_cp[0].id] self.planner = self.game.planners[self.captured_cp[0].id]
self.planned_flight_view.set_flight_planner(self.planner) self.planned_flight_view.set_flight_planner(self.planner)
self.selected_cp = self.captured_cp[0] 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().setCurrentIndex(self.planned_flight_view.indexAt(QPoint(1, 1)), QItemSelectionModel.Rows)
self.planned_flight_view.selectionModel().selectionChanged.connect(self.on_flight_selection_change) 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 = QPushButton("Add Flight")
self.add_flight_button.clicked.connect(self.on_add_flight) self.add_flight_button.clicked.connect(self.on_add_flight)
self.delete_flight_button = QPushButton("Delete Selected") 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.delete_flight_button.clicked.connect(self.on_delete_flight)
self.button_layout = QHBoxLayout() self.button_layout = QHBoxLayout()
self.button_layout.addStretch() 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.delete_flight_button)
self.button_layout.addWidget(self.add_flight_button)
self.mission_start_button = QPushButton("Take Off") self.mission_start_button = QPushButton("Take Off")
self.mission_start_button.setProperty("style", "start-button") self.mission_start_button.setProperty("style", "start-button")
@ -81,8 +84,10 @@ class QMissionPlanning(QDialog):
if len(cps) == 1: if len(cps) == 1:
self.selected_cp = cps[0] self.selected_cp = cps[0]
self.planner = self.game.planners[cps[0].id] 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) self.planned_flight_view.set_flight_planner(self.planner)
else: else:
self.available_aircraft_at_selected_location = {}
self.planned_flight_view.set_flight_planner(None) self.planned_flight_view.set_flight_planner(None)
def on_flight_selection_change(self): def on_flight_selection_change(self):

View File

@ -40,6 +40,7 @@ class QFlightCreator(QDialog):
for aircraft_type in self.planner.get_available_aircraft().keys(): for aircraft_type in self.planner.get_available_aircraft().keys():
print(aircraft_type) print(aircraft_type)
print(aircraft_type.name) print(aircraft_type.name)
if self.available[aircraft_type] > 0:
self.select_type_aircraft.addItem(aircraft_type.id, userData=aircraft_type) self.select_type_aircraft.addItem(aircraft_type.id, userData=aircraft_type)
self.select_type_aircraft.setCurrentIndex(0) self.select_type_aircraft.setCurrentIndex(0)
@ -61,6 +62,11 @@ class QFlightCreator(QDialog):
self.select_count_of_aircraft.setMaximum(4) self.select_count_of_aircraft.setMaximum(4)
self.select_count_of_aircraft.setValue(2) 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 = QPushButton("Add")
self.add_button.clicked.connect(self.create_flight) self.add_button.clicked.connect(self.create_flight)

View File

@ -12,7 +12,7 @@ from qt_ui.windows.mission.flight.generator.QAbstractMissionGenerator import QAb
class QSTRIKEMissionGenerator(QAbstractMissionGenerator): class QSTRIKEMissionGenerator(QAbstractMissionGenerator):
def __init__(self, game: Game, flight: Flight, flight_waypoint_list): 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 = QStrikeTargetSelectionComboBox(self.game)
self.tgt_selection_box.setMinimumWidth(200) self.tgt_selection_box.setMinimumWidth(200)
@ -33,7 +33,7 @@ class QSTRIKEMissionGenerator(QAbstractMissionGenerator):
layout = QVBoxLayout() layout = QVBoxLayout()
wpt_layout = QHBoxLayout() wpt_layout = QHBoxLayout()
wpt_layout.addWidget(QLabel("SEAD/DEAD target : ")) wpt_layout.addWidget(QLabel("Target : "))
wpt_layout.addStretch() wpt_layout.addStretch()
wpt_layout.addWidget(self.tgt_selection_box, alignment=Qt.AlignRight) wpt_layout.addWidget(self.tgt_selection_box, alignment=Qt.AlignRight)

View File

@ -38,9 +38,13 @@ class QFlightWaypointList(QTableView):
takeoff.description = "Take Off" takeoff.description = "Take Off"
takeoff.name = takeoff.pretty_name = "Take Off from " + self.flight.from_cp.name takeoff.name = takeoff.pretty_name = "Take Off from " + self.flight.from_cp.name
self.model.appendRow(QWaypointItem(takeoff, 0)) 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): for i, point in enumerate(self.flight.points):
self.model.insertRow(self.model.rowCount()) 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, 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) self.selectionModel().setCurrentIndex(self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select)

View File

@ -1,11 +1,16 @@
import os import os
from PySide2 import QtWidgets from PySide2 import QtWidgets
from PySide2.QtCore import QFile
from PySide2.QtGui import Qt from PySide2.QtGui import Qt
from PySide2.QtWidgets import QFrame, QLineEdit, QGridLayout, QVBoxLayout, QLabel, QPushButton, \ 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): class QLiberationPreferences(QFrame):
@ -28,6 +33,8 @@ class QLiberationPreferences(QFrame):
self.browse_saved_game.clicked.connect(self.on_browse_saved_games) self.browse_saved_game.clicked.connect(self.on_browse_saved_games)
self.browse_install_dir = QPushButton("Browse...") self.browse_install_dir = QPushButton("Browse...")
self.browse_install_dir.clicked.connect(self.on_browse_installation_dir) 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() self.initUi()
@ -40,6 +47,9 @@ class QLiberationPreferences(QFrame):
layout.addWidget(QLabel("<strong>DCS installation directory:</strong>"), 2, 0, alignment=Qt.AlignLeft) layout.addWidget(QLabel("<strong>DCS installation directory:</strong>"), 2, 0, alignment=Qt.AlignLeft)
layout.addWidget(self.edit_dcs_install_dir, 3, 0, alignment=Qt.AlignRight) 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(self.browse_install_dir, 3, 1, alignment=Qt.AlignRight)
layout.addWidget(QLabel("<strong>Theme (Requires Restart)</strong>"), 4, 0)
layout.addWidget(self.themeSelect, 4, 1, alignment=Qt.AlignRight)
self.themeSelect.setCurrentIndex(get_theme_index())
main_layout.addLayout(layout) main_layout.addLayout(layout)
main_layout.addStretch() main_layout.addStretch()
@ -63,6 +73,7 @@ class QLiberationPreferences(QFrame):
print("Applying changes") print("Applying changes")
self.saved_game_dir = self.edit_saved_game_dir.text() self.saved_game_dir = self.edit_saved_game_dir.text()
self.dcs_install_dir = self.edit_dcs_install_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): if not os.path.isdir(self.saved_game_dir):
error_dialog = QMessageBox.critical(self, "Wrong DCS Saved Games directory.", error_dialog = QMessageBox.critical(self, "Wrong DCS Saved Games directory.",
@ -78,7 +89,8 @@ class QLiberationPreferences(QFrame):
error_dialog.exec_() error_dialog.exec_()
return False 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.", error_dialog = QMessageBox.critical(self, "Wrong DCS installation directory.",
self.dcs_install_dir + " is not a valid DCS installation directory", self.dcs_install_dir + " is not a valid DCS installation directory",
QMessageBox.StandardButton.Ok) QMessageBox.StandardButton.Ok)
@ -87,7 +99,5 @@ class QLiberationPreferences(QFrame):
liberation_install.setup(self.saved_game_dir, self.dcs_install_dir) liberation_install.setup(self.saved_game_dir, self.dcs_install_dir)
liberation_install.save_config() liberation_install.save_config()
liberation_theme.save_theme_config()
return True return True

View File

@ -166,13 +166,23 @@ class QSettingsWindow(QDialog):
self.generate_marks.setChecked(self.game.settings.generate_marks) self.generate_marks.setChecked(self.game.settings.generate_marks)
self.generate_marks.toggled.connect(self.applySettings) 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(QLabel("Use Supercarrier Module"), 0, 0)
self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight) self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight)
self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0) self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0)
self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight) 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.performance = QGroupBox("Performance")
self.performanceLayout = QGridLayout(); self.performanceLayout = QGridLayout()
self.performanceLayout.setAlignment(Qt.AlignTop) self.performanceLayout.setAlignment(Qt.AlignTop)
self.performance.setLayout(self.performanceLayout) 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.setChecked(self.game.settings.perf_ai_parking_start)
self.ai_parking_start.toggled.connect(self.applySettings) 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 = QCheckBox()
self.culling.setChecked(self.game.settings.perf_culling) self.culling.setChecked(self.game.settings.perf_culling)
self.culling.toggled.connect(self.applySettings) 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(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(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(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(QHorizontalSeparationLine(), 7, 0, 1, 2)
self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 7, 0) self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 8, 0)
self.performanceLayout.addWidget(self.culling, 7, 1, alignment=Qt.AlignRight) self.performanceLayout.addWidget(self.culling, 8, 1, alignment=Qt.AlignRight)
self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 8, 0) self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 9, 0)
self.performanceLayout.addWidget(self.culling_distance, 8, 1, alignment=Qt.AlignRight) self.performanceLayout.addWidget(self.culling_distance, 9, 1, alignment=Qt.AlignRight)
self.generatorLayout.addWidget(self.gameplay) self.generatorLayout.addWidget(self.gameplay)
self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience.")) 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.map_coalition_visibility = self.mapVisibiitySelection.currentData()
self.game.settings.external_views_allowed = self.ext_views.isChecked() self.game.settings.external_views_allowed = self.ext_views.isChecked()
self.game.settings.generate_marks = self.generate_marks.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) 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_moving_units = self.moving_units.isChecked()
self.game.settings.perf_infantry = self.infantry.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_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 = self.culling.isChecked()
self.game.settings.perf_culling_distance = int(self.culling_distance.value()) self.game.settings.perf_culling_distance = int(self.culling_distance.value())

View File

@ -1,4 +1,4 @@
pydcs>=0.9.4 pydcs>=0.9.9
Pyside2>=5.13.0 Pyside2>=5.13.0
pyinstaller==3.6 pyinstaller==3.6
pyproj==2.6.1.post1 pyproj==2.6.1.post1

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 800 KiB

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -2,46 +2,6 @@ local unitPayloads = {
["name"] = "AV8BNA", ["name"] = "AV8BNA",
["payloads"] = { ["payloads"] = {
[1] = { [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", ["name"] = "CAP",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
@ -61,18 +21,15 @@ local unitPayloads = {
["num"] = 7, ["num"] = 7,
}, },
[5] = { [5] = {
["CLSID"] = "{ALQ_164_RF_Jammer}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{GAU_12_Equalizer}", ["CLSID"] = "{GAU_12_Equalizer}",
["num"] = 4, ["num"] = 4,
}, },
}, },
["tasks"] = { ["tasks"] = {
[1] = 31,
}, },
}, },
[3] = { [2] = {
["name"] = "CAS", ["name"] = "CAS",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
@ -80,79 +37,51 @@ local unitPayloads = {
["num"] = 8, ["num"] = 8,
}, },
[2] = { [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}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1, ["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}", ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5, ["num"] = 5,
}, },
}, },
["tasks"] = { ["tasks"] = {
[1] = 33, [1] = 31,
}, },
}, },
[4] = { [3] = {
["name"] = "STRIKE", ["name"] = "STRIKE",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}", ["CLSID"] = "{BRU-42_2*GBU-38_LEFT}",
["num"] = 8, ["num"] = 2,
}, },
[2] = { [2] = {
["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}", ["CLSID"] = "{BRU-42_2*GBU-38_RIGHT}",
["num"] = 7, ["num"] = 7,
}, },
[3] = { [3] = {
["CLSID"] = "{BRU-42_2*Mk-83_RIGHT}", ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 6,
},
[4] = {
["CLSID"] = "{ALQ_164_RF_Jammer}",
["num"] = 5, ["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"] = { ["tasks"] = {
[1] = 32, [1] = 31,
}, },
}, },
[5] = { [4] = {
["name"] = "ANTISHIP", ["name"] = "ANTISHIP",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
@ -160,36 +89,52 @@ local unitPayloads = {
["num"] = 8, ["num"] = 8,
}, },
[2] = { [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}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1, ["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}", ["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5, ["num"] = 5,
}, },
}, },
["tasks"] = { ["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] = { [6] = {
@ -212,23 +157,20 @@ local unitPayloads = {
["num"] = 7, ["num"] = 7,
}, },
[5] = { [5] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}", ["CLSID"] = "{ALQ_164_RF_Jammer}",
["num"] = 5, ["num"] = 5,
}, },
[6] = { [6] = {
["CLSID"] = "{GAU_12_Equalizer}", ["CLSID"] = "LAU_117_AGM_65G",
["num"] = 4, ["num"] = 6,
}, },
[7] = { [7] = {
["CLSID"] = "LAU_117_AGM_65G", ["CLSID"] = "LAU_117_AGM_65G",
["num"] = 3, ["num"] = 3,
}, },
[8] = {
["CLSID"] = "LAU_117_AGM_65G",
["num"] = 6,
},
}, },
["tasks"] = { ["tasks"] = {
[1] = 31,
}, },
}, },
}, },

View File

@ -2,64 +2,10 @@ local unitPayloads = {
["name"] = "F-15C", ["name"] = "F-15C",
["payloads"] = { ["payloads"] = {
[1] = { [1] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
["CLSID"] = "{AIM-9P5}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{E1F29B21-F291-4589-9FD8-3272EEC69506}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}",
["num"] = 4,
},
[5] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{E1F29B21-F291-4589-9FD8-3272EEC69506}",
["num"] = 6,
},
[7] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}",
["num"] = 8,
},
[9] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 9,
},
[10] = {
["CLSID"] = "{E1F29B21-F291-4589-9FD8-3272EEC69506}",
["num"] = 10,
},
[11] = {
["CLSID"] = "{AIM-9P5}",
["num"] = 11,
},
},
["tasks"] = {
[1] = 18,
[2] = 19,
[3] = 11,
},
},
[2] = {
["name"] = "CAS", ["name"] = "CAS",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1, ["num"] = 1,
}, },
[2] = { [2] = {
@ -71,11 +17,11 @@ local unitPayloads = {
["num"] = 3, ["num"] = 3,
}, },
[4] = { [4] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 4, ["num"] = 4,
}, },
[5] = { [5] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 5, ["num"] = 5,
}, },
[6] = { [6] = {
@ -83,11 +29,11 @@ local unitPayloads = {
["num"] = 6, ["num"] = 6,
}, },
[7] = { [7] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 7, ["num"] = 7,
}, },
[8] = { [8] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 8, ["num"] = 8,
}, },
[9] = { [9] = {
@ -99,7 +45,61 @@ local unitPayloads = {
["num"] = 10, ["num"] = 10,
}, },
[11] = { [11] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 11,
},
},
["tasks"] = {
[1] = 18,
[2] = 19,
[3] = 11,
},
},
[2] = {
["name"] = "STRIKE",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{E1F29B21-F291-4589-9FD8-3272EEC69506}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 4,
},
[5] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{E1F29B21-F291-4589-9FD8-3272EEC69506}",
["num"] = 6,
},
[7] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 8,
},
[9] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 9,
},
[10] = {
["CLSID"] = "{E1F29B21-F291-4589-9FD8-3272EEC69506}",
["num"] = 10,
},
[11] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 11, ["num"] = 11,
}, },
}, },
@ -110,10 +110,10 @@ local unitPayloads = {
}, },
}, },
[3] = { [3] = {
["name"] = "STRIKE", ["name"] = "CAP",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1, ["num"] = 1,
}, },
[2] = { [2] = {
@ -125,11 +125,11 @@ local unitPayloads = {
["num"] = 3, ["num"] = 3,
}, },
[4] = { [4] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 4, ["num"] = 4,
}, },
[5] = { [5] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 5, ["num"] = 5,
}, },
[6] = { [6] = {
@ -137,11 +137,11 @@ local unitPayloads = {
["num"] = 6, ["num"] = 6,
}, },
[7] = { [7] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 7, ["num"] = 7,
}, },
[8] = { [8] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 8, ["num"] = 8,
}, },
[9] = { [9] = {
@ -153,7 +153,7 @@ local unitPayloads = {
["num"] = 10, ["num"] = 10,
}, },
[11] = { [11] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 11, ["num"] = 11,
}, },
}, },
@ -167,7 +167,7 @@ local unitPayloads = {
["name"] = "ANTISHIP", ["name"] = "ANTISHIP",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1, ["num"] = 1,
}, },
[2] = { [2] = {
@ -179,11 +179,11 @@ local unitPayloads = {
["num"] = 3, ["num"] = 3,
}, },
[4] = { [4] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 4, ["num"] = 4,
}, },
[5] = { [5] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 5, ["num"] = 5,
}, },
[6] = { [6] = {
@ -191,11 +191,11 @@ local unitPayloads = {
["num"] = 6, ["num"] = 6,
}, },
[7] = { [7] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 7, ["num"] = 7,
}, },
[8] = { [8] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 8, ["num"] = 8,
}, },
[9] = { [9] = {
@ -207,7 +207,7 @@ local unitPayloads = {
["num"] = 10, ["num"] = 10,
}, },
[11] = { [11] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 11, ["num"] = 11,
}, },
}, },
@ -221,7 +221,7 @@ local unitPayloads = {
["name"] = "SEAD", ["name"] = "SEAD",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1, ["num"] = 1,
}, },
[2] = { [2] = {
@ -233,11 +233,11 @@ local unitPayloads = {
["num"] = 3, ["num"] = 3,
}, },
[4] = { [4] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 4, ["num"] = 4,
}, },
[5] = { [5] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 5, ["num"] = 5,
}, },
[6] = { [6] = {
@ -245,11 +245,11 @@ local unitPayloads = {
["num"] = 6, ["num"] = 6,
}, },
[7] = { [7] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 7, ["num"] = 7,
}, },
[8] = { [8] = {
["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", ["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 8, ["num"] = 8,
}, },
[9] = { [9] = {
@ -261,7 +261,7 @@ local unitPayloads = {
["num"] = 10, ["num"] = 10,
}, },
[11] = { [11] = {
["CLSID"] = "{AIM-9P5}", ["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 11, ["num"] = 11,
}, },
}, },

Some files were not shown because too many files have changed in this diff Show More