import typing import enum from datetime import datetime from dcs.countries import get_by_id, country_dict from dcs.vehicles import * from dcs.ships import * from dcs.planes import * from dcs.helicopters import * from dcs.task import * from dcs.unit import * from dcs.unittype import * from dcs.unitgroup import * from game.factions.china_2000 import China_2000 from game.factions.france_1995 import France_1995 from game.factions.germany_1990 import Germany_1990 from game.factions.insurgent import Insurgent from game.factions.iran_2015 import Iran_2015 from game.factions.israel_2000 import Israel_2000 from game.factions.italy_1990 import Italy_1990 from game.factions.netherlands_1990 import Netherlands_1990 from game.factions.north_korea_2000 import NorthKorea_2000 from game.factions.russia_1975 import Russia_1975 from game.factions.germany_1944 import Germany_1944 from game.factions.india_2010 import India_2010 from game.factions.russia_1955 import Russia_1955 from game.factions.russia_1965 import Russia_1965 from game.factions.russia_1990 import Russia_1990 from game.factions.russia_2010 import Russia_2010 from game.factions.spain_1990 import Spain_1990 from game.factions.sweden_1990 import Sweden_1990 from game.factions.turkey_2005 import Turkey_2005 from game.factions.uae_2005 import UAE_2005 from game.factions.uk_1990 import UnitedKingdom_1990 from game.factions.ukraine_2010 import Ukraine_2010 from game.factions.usa_1944 import USA_1944 from game.factions.usa_1955 import USA_1955 from game.factions.usa_1960 import USA_1960 from game.factions.usa_1965 import USA_1965 from game.factions.usa_1990 import USA_1990 from game.factions.usa_2005 import USA_2005 """ ---------- BEGINNING OF CONFIGURATION SECTION """ """ All aircraft names in this file should correspond with naming provided in following files: * https://github.com/pydcs/dcs/blob/master/dcs/planes.py - for planes * https://github.com/pydcs/dcs/blob/master/dcs/helicopters.py - for helicopters * https://github.com/pydcs/dcs/blob/master/dcs/vehicles.py - for vehicles (this include all of the ground vehicles) You can find names at the bottom of the file in following format: x_map = { "Name of the unit in game": Identifier, } from this example `Identifier` should be used (which may or may not include category of the unit and dot + underscore characters). For example, player accessible Hornet is called `FA_18C_hornet`, and MANPAD Igla is called `AirDefence.SAM_SA_18_Igla_S_MANPADS` """ """ Prices for the aircraft. This defines both price for the player (although only aircraft listed in CAP/CAS/Transport/Armor/AirDefense roles will be purchasable) and prioritization for the enemy (i.e. less important bases will receive units with lower price) """ PRICES = { # fighter MiG_23MLD: 13, Su_27: 18, Su_33: 22, MiG_29A: 18, MiG_29S: 20, MiG_29G: 18, MiG_31: 30, J_11A: 26, Su_30: 24, SpitfireLFMkIX:3, SpitfireLFMkIXCW:3, Bf_109K_4:3, FW_190D9:3, FW_190A8:3, F_5E_3: 8, MiG_15bis: 4, MiG_19P: 6, F_86F_Sabre: 4, MiG_21Bis: 8, F_4E: 10, AJS37: 12, C_101CC: 6, AV8BNA: 14, M_2000C: 16, Mirage_2000_5: 22, FA_18C_hornet: 24, F_15C: 26, F_16C_50: 20, F_14B: 22, Tornado_IDS: 24, Tornado_GR4: 24, # bomber Su_17M4: 10, Su_25: 15, Su_25T: 18, L_39ZA: 10, Su_34: 24, Su_24M: 20, Su_24MR: 24, MiG_27K: 20, A_10A: 16, A_10C: 22, # heli Ka_50: 13, SA342M: 8, SA342L: 5, UH_1H: 4, Mi_8MT: 5, Mi_24V: 12, Mi_28N: 16, AH_1W: 10, AH_64A: 12, AH_64D: 16, OH_58D: 6, # Bombers B_52H: 25, B_1B: 50, # special IL_76MD: 13, An_26B: 13, An_30M: 13, Yak_40: 13, S_3B_Tanker: 13, IL_78M: 13, KC_135: 13, A_50: 8, E_3A: 8, C_130: 8, # WW2 P_51D_30_NA: 3, P_51D: 3, # armor Armor.APC_MTLB: 4, Armor.ARV_MTLB_U_BOMAN: 5, Armor.ARV_BRDM_2: 6, Armor.ARV_BTR_RD: 8, Armor.APC_BTR_80: 8, Armor.MBT_T_55: 18, Armor.MBT_T_72B: 25, Armor.MBT_T_80U: 30, Armor.MBT_T_90: 35, Armor.IFV_BMD_1: 8, Armor.IFV_BMP_1: 14, Armor.IFV_BMP_2: 16, Armor.IFV_BMP_3: 18, Armor.ZBD_04A: 12, Armor.APC_Cobra: 4, Armor.APC_M113: 6, Armor.APC_M1043_HMMWV_Armament: 2, Armor.ATGM_M1045_HMMWV_TOW: 8, Armor.IFV_M2A2_Bradley: 12, Armor.APC_M1126_Stryker_ICV: 10, Armor.ATGM_M1134_Stryker: 12, Armor.MBT_M60A3_Patton: 18, Armor.MBT_M1A2_Abrams: 35, Armor.MBT_Leclerc: 35, Armor.MBT_Leopard_1A3: 24, Armor.MBT_Leopard_2: 35, Armor.MBT_Merkava_Mk__4: 35, Armor.TPz_Fuchs: 5, Armor.MBT_Challenger_II: 30, Armor.IFV_Marder: 10, Armor.IFV_MCV_80: 10, Unarmed.Transport_UAZ_469: 3, Unarmed.Transport_Ural_375: 3, Infantry.Infantry_M4: 1, Infantry.Soldier_AK: 1, Unarmed.Transport_M818: 3, AirDefence.AAA_Vulcan_M163: 5, AirDefence.SAM_Linebacker_M6: 10, AirDefence.AAA_ZU_23_Closed: 2, AirDefence.SPAAA_ZSU_23_4_Shilka: 4, AirDefence.SAM_SA_9_Strela_1_9P31: 8, AirDefence.SAM_SA_19_Tunguska_2S6: 15, AirDefence.SAM_SA_6_Kub_LN_2P25: 22, AirDefence.SAM_SA_8_Osa_9A33: 12, AirDefence.SAM_SA_3_S_125_LN_5P73: 20, AirDefence.SAM_SA_2_LN_SM_90: 15, AirDefence.SAM_SA_11_Buk_LN_9A310M1: 25, AirDefence.SAM_Hawk_PCP: 20, AirDefence.SAM_Patriot_LN_M901: 60, AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 60, AirDefence.SAM_Chaparral_M48: 10, # WW2 Armor.MT_Pz_Kpfw_V_Panther_Ausf_G:7, Armor.MT_Pz_Kpfw_IV_Ausf_H:4, Armor.HT_Pz_Kpfw_VI_Tiger_I:10, Armor.HT_Pz_Kpfw_VI_Ausf__B__Tiger_II:12, Armor.APC_Sd_Kfz_251:3, Armor.IFV_Sd_Kfz_234_2_Puma:4, Armor.MT_M4_Sherman:4, Armor.MT_M4A4_Sherman_Firefly:6, Armor.M30_Cargo_Carrier:2, Armor.APC_M2A1:2, AirDefence.AAA_Bofors_40mm:4, AirDefence.AAA_Flak_36:6, AirDefence.AAA_Flak_18:4, # ship CV_1143_5_Admiral_Kuznetsov: 100, CVN_74_John_C__Stennis: 100, LHA_1_Tarawa: 50, Bulk_cargo_ship_Yakushev: 10, Armed_speedboat: 10, Dry_cargo_ship_Ivanov: 10, Tanker_Elnya_160: 10, } """ Units separated by tasks. This will include units for both countries. Be advised that unit could only belong to single task! Following tasks are present: * CAP - figther aircraft for CAP/Escort/Intercept * CAS - CAS aircraft * Transport - transport aircraft (used as targets in intercept operations) * AWACS - awacs * PinpointStrike - armor that will engage in ground war * AirDefense - AA units * Reconnaissance - units that will be used as targets in destroy insurgents operations * Nothing - troops that will be used for helicopter transport operations * Embarking - helicopters that will be used for helicopter transport operations * Carriage - aircraft carriers * CargoTransportation - ships that will be used as targets for ship intercept operations """ UNIT_BY_TASK = { CAP: [ F_5E_3, MiG_23MLD, Su_27, Su_33, MiG_19P, MiG_21Bis, MiG_29A, MiG_29S, FA_18C_hornet, F_15C, F_14B, F_16C_50, M_2000C, Mirage_2000_5, P_51D_30_NA, P_51D, MiG_29G, Su_30, J_11A, F_4E, C_101CC, Bf_109K_4, FW_190D9, FW_190A8, SpitfireLFMkIXCW, SpitfireLFMkIX ], CAS: [ F_86F_Sabre, MiG_15bis, L_39ZA, AV8BNA, AJS37, A_10A, A_10C, Su_17M4, Su_25, Su_25T, Su_34, Ka_50, SA342M, SA342L, Su_24M, Su_24MR, AH_64A, AH_64D, OH_58D, B_52H, B_1B, Tornado_IDS, Tornado_GR4, UH_1H, Mi_8MT, Mi_28N, Mi_24V, MiG_27K, ], Transport: [ IL_76MD, An_26B, An_30M, Yak_40, C_130, ], Refueling: [ IL_78M, KC_135, S_3B_Tanker, ], AWACS: [E_3A, A_50, ], PinpointStrike: [ Armor.APC_MTLB, Armor.APC_MTLB, Armor.APC_MTLB, Armor.APC_MTLB, Armor.APC_MTLB, Armor.ARV_MTLB_U_BOMAN, Armor.ARV_MTLB_U_BOMAN, Armor.ARV_MTLB_U_BOMAN, Armor.ARV_MTLB_U_BOMAN, Armor.ARV_MTLB_U_BOMAN, Armor.ARV_BRDM_2, Armor.ARV_BRDM_2, Armor.ARV_BRDM_2, Armor.ARV_BRDM_2, Armor.ARV_BRDM_2, Armor.ARV_BTR_RD, Armor.ARV_BTR_RD, Armor.ARV_BTR_RD, Armor.ARV_BTR_RD, Armor.APC_BTR_80, Armor.APC_BTR_80, Armor.APC_BTR_80, Armor.APC_BTR_80, Armor.APC_BTR_80, Armor.IFV_BMP_1, Armor.IFV_BMP_1, Armor.IFV_BMP_1, Armor.IFV_BMP_2, Armor.IFV_BMP_2, Armor.IFV_BMP_3, Armor.IFV_BMP_3, Armor.ZBD_04A, Armor.ZBD_04A, Armor.ZBD_04A, Armor.MBT_T_55, Armor.MBT_T_55, Armor.MBT_T_55, Armor.MBT_T_72B, Armor.MBT_T_72B, Armor.MBT_T_80U, Armor.MBT_T_80U, Armor.MBT_T_90, Armor.APC_Cobra, Armor.APC_Cobra, Armor.APC_Cobra, Armor.APC_Cobra, Armor.APC_M113, Armor.APC_M113, Armor.APC_M113, Armor.APC_M113, Armor.TPz_Fuchs, Armor.TPz_Fuchs, Armor.TPz_Fuchs, Armor.TPz_Fuchs, Armor.ATGM_M1045_HMMWV_TOW, Armor.ATGM_M1045_HMMWV_TOW, Armor.APC_M1043_HMMWV_Armament, Armor.APC_M1043_HMMWV_Armament, Armor.IFV_M2A2_Bradley, Armor.IFV_M2A2_Bradley, Armor.ATGM_M1134_Stryker, Armor.ATGM_M1134_Stryker, Armor.APC_M1126_Stryker_ICV, Armor.APC_M1126_Stryker_ICV, Armor.APC_M1126_Stryker_ICV, Armor.IFV_MCV_80, Armor.IFV_MCV_80, Armor.IFV_MCV_80, Armor.IFV_Marder, Armor.IFV_Marder, Armor.IFV_Marder, Armor.IFV_Marder, Armor.MBT_M60A3_Patton, Armor.MBT_M60A3_Patton, Armor.MBT_M60A3_Patton, Armor.MBT_Leopard_1A3, Armor.MBT_Leopard_1A3, Armor.MBT_M1A2_Abrams, Armor.MBT_Leclerc, Armor.MBT_Leopard_2, Armor.MBT_Challenger_II, Armor.MBT_Merkava_Mk__4, Armor.MT_Pz_Kpfw_V_Panther_Ausf_G, Armor.MT_Pz_Kpfw_IV_Ausf_H, Armor.HT_Pz_Kpfw_VI_Tiger_I, Armor.HT_Pz_Kpfw_VI_Ausf__B__Tiger_II, Armor.APC_Sd_Kfz_251, Armor.APC_Sd_Kfz_251, Armor.APC_Sd_Kfz_251, Armor.APC_Sd_Kfz_251, Armor.IFV_Sd_Kfz_234_2_Puma, Armor.IFV_Sd_Kfz_234_2_Puma, Armor.MT_M4_Sherman, Armor.MT_M4A4_Sherman_Firefly, Armor.M30_Cargo_Carrier, Armor.M30_Cargo_Carrier, Armor.APC_M2A1, Armor.APC_M2A1, Armor.APC_M2A1, Armor.APC_M2A1, ], AirDefence: [ # those are listed multiple times here to balance prioritization more into lower tier AAs AirDefence.AAA_Vulcan_M163, AirDefence.AAA_Vulcan_M163, AirDefence.AAA_Vulcan_M163, AirDefence.SAM_Linebacker_M6, AirDefence.SPAAA_ZSU_23_4_Shilka, AirDefence.AAA_ZU_23_Closed, AirDefence.SAM_SA_9_Strela_1_9P31, AirDefence.SAM_SA_8_Osa_9A33, AirDefence.SAM_SA_19_Tunguska_2S6, AirDefence.SAM_SA_6_Kub_LN_2P25, AirDefence.SAM_SA_3_S_125_LN_5P73, AirDefence.SAM_Hawk_PCP, AirDefence.SAM_SA_2_LN_SM_90, AirDefence.SAM_SA_11_Buk_LN_9A310M1, ], Reconnaissance: [Unarmed.Transport_M818, Unarmed.Transport_Ural_375, Unarmed.Transport_UAZ_469], Nothing: [Infantry.Infantry_M4, Infantry.Soldier_AK, ], Embarking: [], Carriage: [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov, ], CargoTransportation: [Dry_cargo_ship_Ivanov, Bulk_cargo_ship_Yakushev, Tanker_Elnya_160, Armed_speedboat, ], } """ Units from AirDefense category of UNIT_BY_TASK that will be removed from use if "No SAM" option is checked at the start of the game """ SAM_BAN = [ AirDefence.SAM_Linebacker_M6, AirDefence.SAM_SA_9_Strela_1_9P31, AirDefence.SAM_SA_8_Osa_9A33, AirDefence.SAM_SA_19_Tunguska_2S6, AirDefence.SAM_SA_6_Kub_LN_2P25, AirDefence.SAM_SA_8_Osa_9A33, AirDefence.SAM_SA_3_S_125_LN_5P73, AirDefence.SAM_Hawk_PCP, AirDefence.SAM_SA_2_LN_SM_90, AirDefence.SAM_SA_11_Buk_LN_9A310M1, ] """ Used to convert SAM site parts to the corresponding site """ SAM_CONVERT = { AirDefence.SAM_SR_P_19: AirDefence.SAM_SA_3_S_125_LN_5P73, AirDefence.SAM_SA_3_S_125_TR_SNR: AirDefence.SAM_SA_3_S_125_LN_5P73, AirDefence.SAM_SA_3_S_125_LN_5P73: AirDefence.SAM_SA_3_S_125_LN_5P73, AirDefence.SAM_SA_6_Kub_LN_2P25: AirDefence.SAM_SA_6_Kub_LN_2P25, AirDefence.SAM_SA_6_Kub_STR_9S91: AirDefence.SAM_SA_6_Kub_LN_2P25, AirDefence.SAM_SA_10_S_300PS_LN_5P85C: AirDefence.SAM_SA_10_S_300PS_LN_5P85C, AirDefence.SAM_SA_10_S_300PS_SR_5N66M: AirDefence.SAM_SA_10_S_300PS_LN_5P85C, AirDefence.SAM_SA_10_S_300PS_TR_30N6: AirDefence.SAM_SA_10_S_300PS_LN_5P85C, AirDefence.SAM_SA_10_S_300PS_CP_54K6: AirDefence.SAM_SA_10_S_300PS_LN_5P85C, AirDefence.SAM_SA_10_S_300PS_SR_64H6E: AirDefence.SAM_SA_10_S_300PS_CP_54K6, AirDefence.SAM_Hawk_TR_AN_MPQ_46: AirDefence.SAM_Hawk_PCP, AirDefence.SAM_Hawk_SR_AN_MPQ_50: AirDefence.SAM_Hawk_PCP, AirDefence.SAM_Hawk_LN_M192: AirDefence.SAM_Hawk_PCP, 'except': { # this radar is shared between the two S300's. if we attempt to find a SAM site at a base and can't find one # model, we can safely assume the other was deployed # well, perhaps not safely, but we'll make the assumption anyway :p AirDefence.SAM_SA_10_S_300PS_TR_30N6: AirDefence.SAM_SA_10_S_300PS_CP_54K6, AirDefence.SAM_SR_P_19: AirDefence.SAM_SA_2_LN_SM_90 } } """ Units that will always be spawned in the air """ TAKEOFF_BAN = [ ] """ Units that will be always spawned in the air if launched from the carrier """ CARRIER_TAKEOFF_BAN = [ Su_33, # Kuznecow is bugged in a way that only 2 aircraft could be spawned ] """ AirDefense units that will be spawned at control points not related to the current operation """ EXTRA_AA = { "Russia": AirDefence.SAM_SA_9_Strela_1_9P31, "USA": AirDefence.SAM_Linebacker_M6, "France": AirDefence.SPAAA_Gepard, "Germany": AirDefence.SPAAA_Gepard, "China": AirDefence.SPAAA_ZSU_23_4_Shilka, "UK": AirDefence.AAA_Vulcan_M163, "Iran": AirDefence.SPAAA_ZSU_23_4_Shilka, "North Korea": AirDefence.AAA_ZU_23_Closed, "Italy": AirDefence.AAA_Vulcan_M163, "Spain": AirDefence.AAA_Vulcan_M163, "The Netherlands": AirDefence.AAA_Vulcan_M163, "Turkey": AirDefence.AAA_Vulcan_M163, "Israel": AirDefence.AAA_Vulcan_M163, "India": AirDefence.SPAAA_ZSU_23_4_Shilka, "United Arab Emirates": AirDefence.Stinger_MANPADS, "Insurgents": AirDefence.AAA_ZU_23_Insurgent_on_Ural_375, "Third Reich": AirDefence.AAA_Flak_Vierling_38, } """ Units separated by country. Currently only Russia and USA are supported. country : DCS Country name """ FACTIONS = { "Russia 1955": Russia_1955, "Russia 1965": Russia_1965, "Russia 1975": Russia_1975, "Russia 1990": Russia_1990, "Russia 2010": Russia_2010, "Iran 2015": Iran_2015, "China 2000": China_2000, "North Korea 2000": NorthKorea_2000, "Insurgent": Insurgent, "USA 2005": USA_2005, "USA 1990": USA_1990, "USA 1965": USA_1965, "USA 1960": USA_1960, "USA 1955 (Require WW2 Pack)": USA_1955, "USA 1944 (Require WW2 Pack)": USA_1944, "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, "Ukrain 2010": Ukraine_2010, "India 2010": India_2010, "Israel 2000": Israel_2000, "Turkey 2005": Turkey_2005, "United Arab Emirates 2005": UAE_2005, "Germany 1944 (Require WW2 Pack)": Germany_1944 } BLUEFOR_FACTIONS = [FACTIONS[f]["country"] for f in FACTIONS if FACTIONS[f]["side"] == "blue"] print(BLUEFOR_FACTIONS) CARRIER_TYPE_BY_PLANE = { FA_18C_hornet: CVN_74_John_C__Stennis, F_14B: CVN_74_John_C__Stennis, Ka_50: LHA_1_Tarawa, SA342M: LHA_1_Tarawa, UH_1H: LHA_1_Tarawa, Mi_8MT: LHA_1_Tarawa, AV8BNA: LHA_1_Tarawa, } """ Aircraft payload overrides. Usually default loadout for the task is loaded during the mission generation. Syntax goes as follows: `AircraftIdentifier`: { "Category": "PayloadName", }, where: * `AircraftIdentifier`: identifier of aircraft (the same that is used troughout the file) * "Category": (in double quotes) is one of the tasks: CAS, CAP, Intercept, Escort or "*" * "PayloadName": payload as found in resources/payloads/UNIT_TYPE.lua file. Sometimes this will match payload names in the mission editor, sometimes it doesn't Payload will be used for operation of following type, "*" category will be used always, no matter the operation. """ PLANE_PAYLOAD_OVERRIDES = { FA_18C_hornet: { CAS: "AIM-9M*2,AGM-65D*2,Mk-82*4,FLIR Pod,Fuel", CAP: "AIM-120*4,AIM-9*2,AIM-7*2,Fuel", Escort: "AIM-120*4,AIM-9*2,AIM-7*2,Fuel", PinpointStrike: "MK-82*8,AIM-9*2,AIM-7,FLIR Pod,Fuel", AntishipStrike: "MK-82*8,AIM-9*2,AIM-7,FLIR Pod,Fuel", SEAD: "AGM-88*2,AIM-9*2,AIM-7,FLIR Pod,Fuel*3" }, F_14B: { CAP: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2", Escort: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2", CAS: "AIM-54A-MK60*1, AIM-7M*1, AIM-9M*2, XT*2, Mk-82*2, LANTIRN", GroundAttack: "AIM54, AIM-9M*2, XT*2, GBU-12*4, LANTIRN", }, Su_25T: { CAS: "APU-8 Vikhr-M*2,Kh-25ML,R-73*2,SPPU-22*2,Mercury LLTV Pod,MPS-410", SEAD: "Kh58*2_Kh25MPU*2_Kh25ML*2_R73*2_L-081_MPS-410" }, Su_33: { CAP: "R-73*4,R-27R*2,R-27ER*6", Escort: "R-73*4,R-27R*2,R-27ER*6", }, AJS37: { CAS: "CAS (75 GUN): RB-75*2, AKAN", }, AV8BNA: { CAS: "AS 2", SEAD: "Stand Off 2" }, AH_64D:{ CAS: "AGM-114K*16" }, A_10C: { CAS: "AGM-65D*2,AGM-65H*2,GBU-12*2,GBU-38*2,AIM-9*2,TGP,ECM,MK151*7", GroundAttack: "AGM-65K*2,GBU-12*8,AIM-9M*2.ECM,TGP", }, Ka_50: { CAS: "12x9A4172, 40xS-8", GroundAttack: "12x9A4172, 40xS-8", }, M_2000C: { CAP: "Combat Air Patrol", Escort: "Combat Air Patrol", GroundAttack: "MK-82S Heavy Strike", }, Mirage_2000_5: { CAP: "R 550*2,MICA IR*2,MICA AR*2,Fuel*3", }, MiG_21Bis: { CAP: "Patrol, medium range", }, Su_24M: { CAS: "S-24*6", SEAD: "Kh25MPU*2_Kh25ML*2_L-081" }, Su_25TM: { SEAD: "Kh-31P*2_Kh-25ML*4_R-73*2_L-081_MPS410", }, Su_17M4: { CAS: "Kh-25MR*4,R-60M*2,Fuel*2", SEAD: "Kh25MPU*2_Kh25ML*2_,R60M*2_Fuel*2" }, Su_30: { SEAD: "Kh-31P*4,R-73*2,R-77*2,ECM", }, Su_34: { SEAD: "Kh-25MPU*6,R-73*2,R-77*2,ECM", }, MiG_27K: { SEAD: "Kh-25MPU*2,R-60M*2,Fuel" }, F_4E: { SEAD: "AGM-45*4,AIM-7*2,ECM" } } """ Aircraft livery overrides. Syntax as follows: `Identifier`: "LiveryName", `Identifier` is aircraft identifier (as used troughout the file) and "LiveryName" (with double quotes) is livery name as found in mission editor. """ PLANE_LIVERY_OVERRIDES = { FA_18C_hornet: "VFA-34", # default livery for the hornet is blue angels one } """ Possible time periods for new games `Name`: daytime(day, month, year), `Identifier` is the name that will appear in the menu The object is a python datetime object """ TIME_PERIODS = { "WW2 - Winter [1944]": datetime(1944, 1, 1), "WW2 - Spring [1944]": datetime(1944, 4, 1), "WW2 - Summer [1944]": datetime(1944, 6, 1), "WW2 - Fall [1944]": datetime(1944, 10, 1), "Early Cold War - Winter [1952]": datetime(1952, 1, 1), "Early Cold War - Spring [1952]": datetime(1952, 4, 1), "Early Cold War - Summer [1952]": datetime(1952, 6, 1), "Early Cold War - Fall [1952]": datetime(1952, 10, 1), "Cold War - Winter [1970]": datetime(1970, 1, 1), "Cold War - Spring [1970]": datetime(1970, 4, 1), "Cold War - Summer [1970]": datetime(1970, 6, 1), "Cold War - Fall [1970]": datetime(1970, 10, 1), "Late Cold War - Winter [1985]": datetime(1985, 1, 1), "Late Cold War - Spring [1985]": datetime(1985, 4, 1), "Late Cold War - Summer [1985]": datetime(1985, 6, 1), "Late Cold War - Fall [1985]": datetime(1985, 10, 1), "Gulf War - Winter [1990]": datetime(1990, 1, 1), "Gulf War - Spring [1990]": datetime(1990, 4, 1), "Gulf War - Summer [1990]": datetime(1990, 6, 1), "Gulf War - Fall [1990]": datetime(1990, 10, 1), "Modern - Winter [2010]": datetime(2010, 1, 1), "Modern - Spring [2010]": datetime(2010, 4, 1), "Modern - Summer [2010]": datetime(2010, 6, 1), "Modern - Fall [2010]": datetime(2010, 10, 1), "Georgian War [2008]": datetime(2008, 8, 7), "Syrian War [2011]": datetime(2011, 8, 7), } CARRIER_CAPABLE = [ FA_18C_hornet, F_14B, AV8BNA, UH_1H, Mi_8MT, Ka_50, SA342L, SA342M, SA342Minigun, SA342Mistral ] """ ---------- END OF CONFIGURATION SECTION """ UnitsDict = typing.Dict[UnitType, int] PlaneDict = typing.Dict[FlyingType, int] HeliDict = typing.Dict[HelicopterType, int] ArmorDict = typing.Dict[VehicleType, int] ShipDict = typing.Dict[ShipType, int] AirDefenseDict = typing.Dict[AirDefence, int] AssignedUnitsDict = typing.Dict[typing.Type[UnitType], typing.Tuple[int, int]] TaskForceDict = typing.Dict[typing.Type[Task], AssignedUnitsDict] StartingPosition = typing.Optional[typing.Union[ShipGroup, StaticGroup, Airport, Point]] def unit_task(unit: UnitType) -> Task: for task, units in UNIT_BY_TASK.items(): if unit in units: return task if unit in SAM_CONVERT: return unit_task(SAM_CONVERT[unit]) print(unit.name + " cause issue") return None def find_unittype(for_task: Task, country_name: str) -> typing.List[UnitType]: return [x for x in UNIT_BY_TASK[for_task] if x in FACTIONS[country_name]["units"]] def unit_type_name(unit_type) -> str: return unit_type.id and unit_type.id or unit_type.name def unit_type_from_name(name: str) -> UnitType: if name in vehicle_map: return vehicle_map[name] elif name in plane_map: return plane_map[name] elif name in ship_map: return ship_map[name] if name in helicopter_map: return helicopter_map[name] else: return None def unit_type_of(unit: Unit) -> UnitType: if isinstance(unit, Vehicle): return vehicle_map[unit.type] elif isinstance(unit, Ship): return ship_map[unit.type] else: return unit.unit_type def task_name(task) -> str: if task == AirDefence: return "AirDefence" elif task == Embarking: return "Transportation" elif task == PinpointStrike: return "Frontline units" else: return task.name def choose_units(for_task: Task, factor: float, count: int, country: str) -> typing.Collection[UnitType]: suitable_unittypes = find_unittype(for_task, country) suitable_unittypes = [x for x in suitable_unittypes if x not in helicopter_map.values()] suitable_unittypes.sort(key=lambda x: PRICES[x]) idx = int(len(suitable_unittypes) * factor) variety = int(count + count * factor / 2) index_start = min(idx, len(suitable_unittypes) - variety) index_end = min(idx + variety, len(suitable_unittypes)) return list(set(suitable_unittypes[index_start:index_end])) def unitdict_append(unit_dict: UnitsDict, unit_type: UnitType, count: int): unit_dict[unit_type] = unit_dict.get(unit_type, 0) + 1 def unitdict_merge(a: UnitsDict, b: UnitsDict) -> UnitsDict: b = b.copy() for k, v in a.items(): b[k] = b.get(k, 0) + v return b def unitdict_split(unit_dict: UnitsDict, count: int): buffer_dict = {} for unit_type, unit_count in unit_dict.items(): for _ in range(unit_count): unitdict_append(buffer_dict, unit_type, 1) if sum(buffer_dict.values()) >= count: yield buffer_dict buffer_dict = {} if len(buffer_dict): yield buffer_dict def unitdict_restrict_count(unit_dict: UnitsDict, total_count: int) -> UnitsDict: if total_count == 0: return {} groups = list(unitdict_split(unit_dict, total_count)) if len(groups) > 0: return groups[0] else: return {} def assigned_units_split(fd: AssignedUnitsDict) -> typing.Tuple[PlaneDict, PlaneDict]: return {k: v1 for k, (v1, v2) in fd.items()}, {k: v2 for k, (v1, v2) in fd.items()}, def assigned_units_from(d: PlaneDict) -> AssignedUnitsDict: return {k: (v, 0) for k, v in d.items()} def assignedunits_split_to_count(dict: AssignedUnitsDict, count: int): buffer_dict = {} for unit_type, (unit_count, client_count) in dict.items(): for _ in range(unit_count): new_count, new_client_count = buffer_dict.get(unit_type, (0, 0)) new_count += 1 if client_count > 0: new_client_count += 1 client_count -= 1 buffer_dict[unit_type] = new_count, new_client_count if new_count >= count: yield buffer_dict buffer_dict = {} if len(buffer_dict): yield buffer_dict def unitdict_from(fd: AssignedUnitsDict) -> Dict: return {k: v1 for k, (v1, v2) in fd.items()} def country_id_from_name(name): for k,v in country_dict.items(): if v.name == name: return k return -1 def _validate_db(): # check unit by task uniquity total_set = set() for t, unit_collection in UNIT_BY_TASK.items(): for unit_type in set(unit_collection): assert unit_type not in total_set, "{} is duplicate for task {}".format(unit_type, t) total_set.add(unit_type) # check country allegiance for unit_type in total_set: did_find = False for country_units_list in FACTIONS.values(): if unit_type in country_units_list["units"]: did_find = True print("WARN : {} not in country list".format(unit_type)) # check prices for unit_type in total_set: assert unit_type in PRICES, "{} not in prices".format(unit_type) _validate_db() class DefaultLiveries: class Default(Enum): af_standard = "" OH_58D.Liveries = DefaultLiveries F_16C_50.Liveries = DefaultLiveries P_51D_30_NA.Liveries = DefaultLiveries