diff --git a/changelog.md b/changelog.md
index de50acec..031729bc 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,15 @@
+# 2.4.2
+
+## Features/Improvements
+
+* **[Factions]** Introduction dates and fallback weapons added for US, Russian, UK, and French weapons. Huge thanks to @TheCandianVendingMachine for the massive amount of data entry!
+* **[Campaigns]** Added 1995 start dates.
+
+## Fixes
+
+* **[Economy]** Pending ground unit purchases will also be transferred when a connected base is captured.
+* **[UI]** Fixed rounding of budget in recruitment menu.
+
# 2.4.1
## Fixes
diff --git a/game/data/weapons.py b/game/data/weapons.py
index afe30035..acbd9456 100644
--- a/game/data/weapons.py
+++ b/game/data/weapons.py
@@ -112,111 +112,435 @@ class Pylon:
_WEAPON_FALLBACKS = [
- # AIM-120C
- (Weapons.AIM_120C, Weapons.AIM_120B),
- (Weapons.LAU_115___AIM_120C, Weapons.LAU_115___AIM_120B),
- (Weapons.LAU_115_2_LAU_127_AIM_120C, Weapons.LAU_115_2_LAU_127_AIM_120B),
-
- # AIM-120B
+ # ADM-141 TALD
+ (Weapons.ADM_141A, None),
+ (Weapons.ADM_141A_, None),
+ (Weapons.ADM_141A__, None),
+ (Weapons.ADM_141B, None),
+
+ # AGM-114K Hellfire
+ (Weapons.AGM114x2_OH_58, Weapons.M260_HYDRA), # assuming OH-58 and not MQ-9
+ (Weapons.AGM_114K, None), # Only for RQ-1
+ (Weapons.AGM_114K___4, Weapons.LAU_61___19_2_75__rockets_MK151_HE),
+
+ # AGM-119 Penguin
+ (Weapons.AGM_119B_Penguin, Weapons.Mk_82),
+
+ # AGM-122 Sidearm
+ (Weapons.AGM_122, None), # No known aircraft carries this
+ (Weapons.AGM_122_Sidearm, Weapons.GBU_12), # outer pylons harrier
+ (Weapons.AGM_122_Sidearm_, Weapons.LAU_117_AGM_65E), # internal pylons harrier
+
+ # AGM-154 JSOW
+ (Weapons.AGM_154A, Weapons.GBU_12),
+ (Weapons.BRU_55___2_x_AGM_154A, Weapons.BRU_33___2_x_GBU_12),
+ (Weapons.BRU_57___2_x_AGM_154A, None), # doesn't exist on any aircraft yet
+
+ (Weapons.AGM_154B, Weapons.CBU_105),
+
+ (Weapons.AGM_154C, Weapons.GBU_12),
+ (Weapons.AGM_154C_4, Weapons.GBU_31_8),
+ (Weapons.BRU_55___2_x_AGM_154C, Weapons.BRU_33___2_x_GBU_12),
+
+ # AGM-45 Shrike
+ (Weapons.AGM_45A, None),
+ (Weapons.AGM_45B, Weapons.AGM_45A),
+ (Weapons.AGM_45B_, Weapons.AGM_45A),
+
+ # AGM-62 Walleye
+ (Weapons.AGM_62, Weapons.Mk_84),
+
+ # AGM-65 Maverick
+ (Weapons.AGM_65D, None), # doesn't exist
+ (Weapons.AGM_65E, None), # doesn't exist
+ (Weapons.AGM_65K, None), # doesn't exist
+ (Weapons.LAU_117_AGM_65A, None), # doesn't exist
+ (Weapons.LAU_117_AGM_65B, None), # doesn't exist
+
+ (Weapons.LAU_117_AGM_65D, Weapons.AGM_62), # Walleye is the predecessor to the maverick
+ (Weapons.LAU_117_AGM_65E, None),
+ (Weapons.LAU_117_AGM_65F, Weapons.LAU_117_AGM_65D),
+ (Weapons.LAU_117_AGM_65G, Weapons.LAU_117_AGM_65D),
+ (Weapons.LAU_117_AGM_65H, Weapons.LAU_117_AGM_65D),
+ (Weapons.LAU_117_AGM_65K, Weapons.LAU_117_AGM_65D),
+ (Weapons.LAU_117_AGM_65L, None),
+
+ (Weapons.LAU_88_AGM_65D_2, None),
+ (Weapons.LAU_88_AGM_65D_2_, None),
+ (Weapons.LAU_88_AGM_65D_3, None),
+ (Weapons.LAU_88_AGM_65D_ONE, None),
+
+ (Weapons.LAU_88_AGM_65E_2, Weapons.LAU_88_AGM_65D_2),
+ (Weapons.LAU_88_AGM_65E_2_, Weapons.LAU_88_AGM_65D_2_),
+ (Weapons.LAU_88_AGM_65E_3, Weapons.LAU_88_AGM_65D_3),
+
+ (Weapons.LAU_88_AGM_65H, Weapons.LAU_88_AGM_65D_2),
+ (Weapons.LAU_88_AGM_65H_2_L, Weapons.LAU_88_AGM_65D_2_),
+ (Weapons.LAU_88_AGM_65H_2_R, Weapons.LAU_88_AGM_65D_2_),
+ (Weapons.LAU_88_AGM_65H_3, Weapons.LAU_88_AGM_65D_3),
+
+ (Weapons.LAU_88_AGM_65K_2, Weapons.LAU_88_AGM_65D_2),
+ (Weapons.LAU_88_AGM_65K_2_, Weapons.LAU_88_AGM_65D_2_),
+ (Weapons.LAU_88_AGM_65K_3, Weapons.LAU_88_AGM_65D_3),
+
+ # AGM-84 Harpoon
+ (Weapons.AGM_84, None), # doesn't exist
+ (Weapons.AGM_84A, Weapons.Mk_82),
+ (Weapons.AGM_84A_8, Weapons._27_Mk_82),
+ (Weapons.AGM_84D, Weapons.AGM_62),
+ (Weapons.AGM_84E, Weapons.LAU_117_AGM_65F),
+ (Weapons.AGM_84H, Weapons.AGM_84E),
+
+ # AGM-86 ALCM
+ (Weapons.AGM_86C, Weapons._27_Mk_82),
+ (Weapons.AGM_86C_20, Weapons._27_Mk_82),
+ (Weapons.AGM_86C_8, Weapons._27_Mk_82),
+ (Weapons.MER_6_AGM_86C, Weapons.MER_12_Mk_82),
+
+ # AGM-88 HARM
+ (Weapons.AGM_88C, Weapons.AGM_65D),
+ (Weapons.AGM_88C_, Weapons.AGM_65D),
+
+ # AIM-120 AMRAAM
(Weapons.AIM_120B, Weapons.AIM_7MH),
(Weapons.LAU_115___AIM_120B, Weapons.LAU_115C_AIM_7MH),
(Weapons.LAU_115_2_LAU_127_AIM_120B, Weapons.LAU_115C_AIM_7MH),
-
- # AIM-7MH
- (Weapons.AIM_7MH, Weapons.AIM_7M),
- (Weapons.AIM_7MH_, Weapons.AIM_7M_),
- (Weapons.AIM_7MH__, Weapons.AIM_7M__),
- (Weapons.LAU_115C_AIM_7MH, Weapons.LAU_115___AIM_7M),
-
- # AIM-7M
- (Weapons.AIM_7M, Weapons.AIM_7F),
- (Weapons.AIM_7M_, None),
- (Weapons.AIM_7M__, None),
- (Weapons.LAU_115___AIM_7M, Weapons.LAU_115C_AIM_7F),
-
- # AIM-7F
- (Weapons.AIM_7F, Weapons.AIM_7E),
- (Weapons.AIM_7F_, Weapons.AIM_7E),
- (Weapons.AIM_7F__, Weapons.AIM_7E),
- (Weapons.LAU_115C_AIM_7F, Weapons.LAU_115C_AIM_7E),
-
- # AIM-7E
- (Weapons.AIM_7E, Weapons.AIM_9X_Sidewinder_IR_AAM),
- (Weapons.LAU_115C_AIM_7E, Weapons.LAU_115_LAU_127_AIM_9X),
-
- # AIM-9X
- (Weapons.AIM_9X_Sidewinder_IR_AAM, Weapons.AIM_9P5_Sidewinder_IR_AAM),
- (Weapons.LAU_7_AIM_9X_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM),
- (Weapons.LAU_115_LAU_127_AIM_9X, Weapons.LAU_115_LAU_127_AIM_9M),
- (Weapons.LAU_115_2_LAU_127_AIM_9X, Weapons.LAU_115_2_LAU_127_AIM_9M),
- (Weapons.LAU_127_AIM_9X, Weapons.LAU_127_AIM_9M),
-
- # AIM-9P5
- (Weapons.AIM_9P5_Sidewinder_IR_AAM, Weapons.AIM_9P_Sidewinder_IR_AAM),
- (Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM),
-
- # AIM-9P
- (Weapons.AIM_9P_Sidewinder_IR_AAM, Weapons.AIM_9M_Sidewinder_IR_AAM),
- (Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9M_Sidewinder_IR_AAM),
-
- # AIM-9M
- (Weapons.AIM_9M_Sidewinder_IR_AAM, Weapons.AIM_9L_Sidewinder_IR_AAM),
- (Weapons.LAU_7_AIM_9M_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9L),
-
- # AIM-9L
- (Weapons.AIM_9L_Sidewinder_IR_AAM, None),
- (Weapons.LAU_7_AIM_9L, None),
-
- # AIM-54C Mk47
- (Weapons.AIM_54C_Mk47, Weapons.AIM_54A_Mk60),
- (Weapons.AIM_54C_Mk47_, Weapons.AIM_54A_Mk60_),
- (Weapons.AIM_54C_Mk47__, Weapons.AIM_54A_Mk60__),
-
- # AIM-54A Mk60
+
+ (Weapons.AIM_120C, Weapons.AIM_120B),
+ (Weapons.LAU_115___AIM_120C, Weapons.LAU_115___AIM_120B),
+ (Weapons.LAU_115_2_LAU_127_AIM_120C, Weapons.LAU_115_2_LAU_127_AIM_120B),
+
+ # AIM-54 Phoenix
+ (Weapons.AIM_54A_Mk47, None),
+ (Weapons.AIM_54A_Mk47_, None),
+ (Weapons.AIM_54A_Mk47__, None),
+
(Weapons.AIM_54A_Mk60, Weapons.AIM_54A_Mk47),
(Weapons.AIM_54A_Mk60_, Weapons.AIM_54A_Mk47_),
(Weapons.AIM_54A_Mk60__, Weapons.AIM_54A_Mk47__),
+
+ (Weapons.AIM_54C_Mk47, Weapons.AIM_54A_Mk60),
+ (Weapons.AIM_54C_Mk47_, Weapons.AIM_54A_Mk60_),
+ (Weapons.AIM_54C_Mk47__, Weapons.AIM_54A_Mk60__),
+
+ # AIM-7 Sparrow
+ (Weapons.AIM_7E, None),
+ (Weapons.AIM_7F, Weapons.AIM_7E),
+ (Weapons.AIM_7F_, None),
+ (Weapons.AIM_7F__, None),
+ (Weapons.AIM_7M, Weapons.AIM_7F),
+ (Weapons.AIM_7M_, Weapons.AIM_7F_),
+ (Weapons.AIM_7M__, Weapons.AIM_7F__),
+ (Weapons.AIM_7MH, Weapons.AIM_7M),
+ (Weapons.AIM_7MH_, Weapons.AIM_7M_),
+ (Weapons.AIM_7MH__, Weapons.AIM_7M__),
+
+ (Weapons.LAU_115C_AIM_7E, None),
+ (Weapons.LAU_115C_AIM_7F, Weapons.LAU_115C_AIM_7E),
+ (Weapons.LAU_115___AIM_7M, Weapons.LAU_115C_AIM_7F),
+ (Weapons.LAU_115C_AIM_7MH, Weapons.LAU_115___AIM_7M),
+
+ # AIM-9 Sidewinder
+ (Weapons.AIM_9L_Sidewinder_IR_AAM, None),
+ (Weapons.AIM_9M_Sidewinder_IR_AAM, Weapons.AIM_9P5_Sidewinder_IR_AAM),
+ (Weapons.AIM_9P5_Sidewinder_IR_AAM, Weapons.AIM_9P_Sidewinder_IR_AAM),
+ (Weapons.AIM_9P_Sidewinder_IR_AAM, Weapons.AIM_9L_Sidewinder_IR_AAM),
+ (Weapons.AIM_9X_Sidewinder_IR_AAM, Weapons.AIM_9P_Sidewinder_IR_AAM),
+
+ (Weapons.LAU_105_1_AIM_9L_L, None),
+ (Weapons.LAU_105_1_AIM_9L_R, None),
+ (Weapons.LAU_105_1_AIM_9M_L, Weapons.LAU_105_1_AIM_9L_L),
+ (Weapons.LAU_105_1_AIM_9M_R, Weapons.LAU_105_1_AIM_9L_R),
+
+ (Weapons.LAU_105_2_AIM_9L, None),
+ (Weapons.LAU_105_2_AIM_9P5, Weapons.LAU_105___2_AIM_9P_Sidewinder_IR_AAM),
+
+ (Weapons.LAU_105___2_AIM_9M_Sidewinder_IR_AAM, Weapons.LAU_105_2_AIM_9L),
+ (Weapons.LAU_105___2_AIM_9P_Sidewinder_IR_AAM, Weapons.LAU_105___2_AIM_9M_Sidewinder_IR_AAM),
+
+ (Weapons.LAU_115_2_LAU_127_AIM_9L, None),
+ (Weapons.LAU_115_2_LAU_127_AIM_9M, Weapons.LAU_115_2_LAU_127_AIM_9L),
+ (Weapons.LAU_115_2_LAU_127_AIM_9X, Weapons.LAU_115_2_LAU_127_AIM_9M),
+
+ (Weapons.LAU_115_LAU_127_AIM_9L, None),
+ (Weapons.LAU_115_LAU_127_AIM_9M, Weapons.LAU_115_LAU_127_AIM_9L),
+ (Weapons.LAU_115_LAU_127_AIM_9X, Weapons.LAU_115_LAU_127_AIM_9M),
+
+ (Weapons.LAU_127_AIM_9L, None),
+ (Weapons.LAU_127_AIM_9M, Weapons.LAU_127_AIM_9L),
+ (Weapons.LAU_127_AIM_9X, Weapons.LAU_127_AIM_9M),
+
+ (Weapons.LAU_138_AIM_9L, None),
+ (Weapons.LAU_138_AIM_9M, Weapons.LAU_138_AIM_9L),
+
+ (Weapons.LAU_7_AIM_9L, None),
+ (Weapons.LAU_7_AIM_9M, Weapons.LAU_7_AIM_9L),
+ (Weapons.LAU_7_AIM_9M_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM),
+ (Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM),
+ (Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9L),
+ (Weapons.LAU_7_AIM_9X_Sidewinder_IR_AAM, Weapons.LAU_7_AIM_9M_Sidewinder_IR_AAM),
+
+ (Weapons.LAU_7___2_AIM_9L_Sidewinder_IR_AAM, None),
+ (Weapons.LAU_7___2_AIM_9M_Sidewinder_IR_AAM, Weapons.LAU_7___2_AIM_9P5_Sidewinder_IR_AAM),
+ (Weapons.LAU_7___2_AIM_9P5_Sidewinder_IR_AAM, Weapons.LAU_7___2_AIM_9P_Sidewinder_IR_AAM),
+ (Weapons.LAU_7___2_AIM_9P_Sidewinder_IR_AAM, Weapons.LAU_7___2_AIM_9L_Sidewinder_IR_AAM),
+
+ # ALQ ECM Pods
+ (Weapons.ALQ_131, None),
+ (Weapons.ALQ_184, Weapons.ALQ_131),
+ (Weapons.AN_ALQ_164_DECM_Pod, None),
+
+ # TGP Pods
+ (Weapons.AN_AAQ_28_LITENING_, None),
+ (Weapons.AN_AAQ_28_LITENING, Weapons.Lantirn_F_16),
+ (Weapons.AN_AAS_38_FLIR, None),
+ (Weapons.AN_ASQ_173_LST_SCAM, None),
+ (Weapons.AWW_13_DATALINK_POD, None),
+ (Weapons.LANTIRN_Targeting_Pod, None),
+ (Weapons.Lantirn_F_16, None),
+ (Weapons.Lantirn_Target_Pod, None),
+ (Weapons.Pavetack_F_111, None),
+
+ # BLU-107
+ (Weapons.BLU_107, None),
+ (Weapons.MER_6_BLU_107, Weapons.MER_6_Mk_82),
- # R-27 (AA-10 Alamo)
+ # GBU-10 LGB
+ (Weapons.DIS_GBU_10, Weapons.Mk_84),
+ (Weapons.GBU_10, Weapons.Mk_84),
+ (Weapons.GBU_10_, Weapons.Mk_84),
+ (Weapons.GBU_10_2, Weapons.Mk_84),
+
+ # GBU-12 LGB
+ (Weapons.AUF2_GBU_12_x_2, None),
+ (Weapons.BRU_33___2_x_GBU_12, Weapons.BRU_33___2_x_Mk_82_),
+ (Weapons.BRU_42_3_GBU_12, Weapons._3_Mk_82),
+ (Weapons.DIS_GBU_12, Weapons.Mk_82),
+ (Weapons.DIS_GBU_12_DUAL, Weapons.BRU_33___2_x_Mk_82_),
+ (Weapons.DIS_GBU_12_DUAL_L, Weapons.BRU_33___2_x_Mk_82_),
+ (Weapons.DIS_GBU_12_DUAL_R, Weapons.BRU_33___2_x_Mk_82_),
+ (Weapons.GBU_12, Weapons.Mk_82),
+ (Weapons.GBU_12_, Weapons.Mk_82_),
+ (Weapons.TER_9A___2_x_GBU_12, Weapons.TER_9A___2_x_Mk_82),
+ (Weapons.TER_9A___2_x_GBU_12_, Weapons.TER_9A___2_x_Mk_82_),
+ (Weapons._2xGBU_12, Weapons.Mk_82),
+ (Weapons._2xGBU_12_, Weapons.Mk_82_),
+ (Weapons._2_GBU_12, Weapons._2_Mk_82),
+ (Weapons._2_GBU_12_, Weapons._2_Mk_82_),
+ (Weapons._3_GBU_12, Weapons._3_Mk_82_),
+
+ # GBU-15 LGB
+ (Weapons.GBU_15, Weapons.Mk_84),
+
+ # GBU-16 LGB
+ (Weapons.BRU_33___2_x_GBU_16, None),
+ (Weapons.DIS_GBU_16, Weapons.Mk_83),
+ (Weapons.GBU_16, Weapons.Mk_83),
+ (Weapons.GBU_16_, Weapons.Mk_83_),
+
+ # GBU-24 LGB
+ (Weapons.GBU_24, Weapons.GBU_10),
+ (Weapons.GBU_24_, Weapons.GBU_10_),
+ (Weapons.GBU_24__, Weapons.GBU_10_),
+
+ # GBU-27 LGB
+ (Weapons.GBU_24, Weapons.GBU_10),
+ (Weapons.GBU_24_, Weapons.GBU_10_),
+ (Weapons.GBU_24__, Weapons.GBU_10_),
+
+ # GBU-28 LGB
+ (Weapons.GBU_28, Weapons.GBU_15),
+
+ # GBU-31 JDAM
+ (Weapons.GBU_31V3B_8, Weapons.B_1B_Mk_84_8),
+ (Weapons.GBU_31_8, Weapons.B_1B_Mk_84_8),
+ (Weapons.GBU_31_V_1_B, Weapons.GBU_24_),
+ (Weapons.GBU_31_V_2_B, Weapons.GBU_24_),
+ (Weapons.GBU_31_V_3_B, Weapons.GBU_24_),
+ (Weapons.GBU_31_V_4_B, Weapons.GBU_24_),
+
+ # GBU-32 JDAM
+ (Weapons.GBU_32_V_2_B, Weapons.GBU_16),
+
+ # GBU-32 JDAM
+ (Weapons.BRU_55___2_x_GBU_38, Weapons.BRU_33___2_x_Mk_82_),
+ (Weapons.BRU_57___2_x_GBU_38, None), # Doesn't exist
+ (Weapons.GBU_38, Weapons.Mk_82),
+ (Weapons.GBU_38_16, Weapons.MK_82_28),
+ (Weapons._2_GBU_38, Weapons._2_Mk_82),
+ (Weapons._2_GBU_38_, Weapons._2_Mk_82_),
+ (Weapons._3_GBU_38, Weapons._3_Mk_82_),
+
+ # GBU-54 LJDAM
+ (Weapons.GBU_54_V_1_B, Weapons.GBU_38),
+ (Weapons._2_GBU_54_V_1_B, Weapons._2_GBU_38),
+ (Weapons._2_GBU_54_V_1_B_, Weapons._2_GBU_38_),
+ (Weapons._3_GBU_54_V_1_B, Weapons._3_GBU_38),
+
+ # CBU-52
+ (Weapons.CBU_52B, None),
+
+ # CBU-87 CEM
+ (Weapons.CBU_87, Weapons.Mk_82),
+ (Weapons.TER_9A___2_x_CBU_87, Weapons.TER_9A___2_x_Mk_82),
+ (Weapons.TER_9A___2_x_CBU_87_, Weapons.TER_9A___2_x_Mk_82_),
+ (Weapons.TER_9A___3_x_CBU_87, Weapons.TER_9A___3_x_Mk_82),
+
+ # CBU-97
+ (Weapons.CBU_97, Weapons.Mk_82),
+ (Weapons.TER_9A___2_x_CBU_97, Weapons.TER_9A___2_x_Mk_82),
+ (Weapons.TER_9A___2_x_CBU_97_, Weapons.TER_9A___2_x_Mk_82_),
+ (Weapons.TER_9A___3_x_CBU_97, Weapons.TER_9A___3_x_Mk_82),
+
+ # CBU-99 (It's a bomb made in 1968, I'm not bothering right now with backups)
+
+ # CBU-103
+ (Weapons.BRU_57___2_x_CBU_103, None), # doesn't exist...
+ (Weapons.CBU_103, Weapons.CBU_87),
+
+ # CBU-105
+ (Weapons.BRU_57___2_x_CBU_105, None), # doesn't exist...
+ (Weapons.CBU_105, Weapons.CBU_97),
+
+ (Weapons.LAU_131_pod___7_x_2_75__Hydra___Laser_Guided_Rkts_M151___HE_APKWS, Weapons.LAU_131___7_2_75__rockets_M151__HE_),
+ (Weapons.LAU_131_pod___7_x_2_75__Hydra___Laser_Guided_Rkts_M282___MPP_APKWS, Weapons.LAU_131___7_2_75__rockets_M151__HE_),
+ (Weapons._3_x_LAU_131_pods___21_x_2_75__Hydra___Laser_Guided_M151___HE_APKWS, Weapons.LAU_68_3___7_2_75__rockets_M151__HE_),
+ (Weapons._3_x_LAU_131_pods___21_x_2_75__Hydra___Laser_Guided_M282___MPP_APKWS, Weapons.LAU_68_3___7_2_75__rockets_M151__HE_),
+
+ # Russia
+ # KAB-1500
+ (Weapons.KAB_1500Kr, None),
+ (Weapons.KAB_1500LG_Pr, Weapons.KAB_1500Kr),
+ (Weapons.KAB_1500L, Weapons.KAB_1500LG_Pr),
+
+ # KAB-500
+ (Weapons.KAB_500kr, Weapons.FAB_500_M62),
+ (Weapons.KAB_500L, Weapons.KAB_500kr),
+ (Weapons.KAB_500S, Weapons.KAB_500L),
+
+ # KH Series
+ (Weapons.Kh_22N, None),
+ (Weapons.Kh_23L, None),
+
+ (Weapons.Kh_25ML, None),
+ (Weapons.Kh_25ML_, None),
+ (Weapons.Kh_25ML__, None),
+
+ (Weapons.Kh_25MP, None),
+ (Weapons.Kh_25MPU, Weapons.Kh_25MP),
+
+ (Weapons.Kh_25MR, None),
+ (Weapons.Kh_25MR_, None),
+
+ (Weapons.Kh_28__AS_9_Kyle_, None),
+
+ (Weapons.Kh_29L, Weapons.Kh_25ML),
+ (Weapons.Kh_29L_, Weapons.Kh_25ML_),
+ (Weapons.Kh_29L__, Weapons.Kh_25ML__),
+ (Weapons.Kh_29T, Weapons.Kh_25MR),
+ (Weapons.Kh_29T_, Weapons.Kh_25MR_),
+ (Weapons.Kh_29T_, Weapons.Kh_25MR_),
+
+ (Weapons.Kh_31A, None),
+ (Weapons.Kh_31A_, None),
+ (Weapons.Kh_31A__, None),
+ (Weapons.Kh_31P, Weapons.Kh_25MP),
+ (Weapons.Kh_31P_, Weapons.Kh_25MP),
+ (Weapons.Kh_31P__, Weapons.Kh_25MP),
+
+ (Weapons.Kh_35, Weapons.Kh_31A),
+ (Weapons.Kh_35_, Weapons.Kh_31A_),
+ (Weapons.Kh_35_6, None),
+
+ (Weapons.Kh_41, None),
+
+ (Weapons.Kh_58U, Weapons.Kh_31P),
+ (Weapons.Kh_58U_, Weapons.Kh_31P_),
+
+ (Weapons.Kh_59M, Weapons.Kh_31A),
+
+ (Weapons.Kh_65, None),
+ (Weapons.Kh_65_6, None),
+ (Weapons.Kh_65_8, None),
+
+ (Weapons.Kh_66_Grom__21__APU_68, None),
+
+ # ECM
+ (Weapons.L175V_Khibiny_ECM_pod, None),
+
+ # R-13
+ (Weapons.R_13M, None),
+ (Weapons.R_13M1, Weapons.R_13M),
+
+ # R-24
+ (Weapons.R_24R, None),
+ (Weapons.R_24T, None),
+
+ # R-27
+ (Weapons.R_27T, Weapons.R_24T),
+ (Weapons.R_27R, Weapons.R_24R),
(Weapons.R_27ER, Weapons.R_27R),
(Weapons.R_27ET, Weapons.R_27T),
-
- # R-77 (AA-12)
- (Weapons.R_77, Weapons.R_27ER),
- (Weapons.R_77_, Weapons.R_27ER),
-
- # R-73 (AA-11)
+
+ # R-33
+ (Weapons.R_33, None),
+
+ # R-3
+ (Weapons.R_3S, Weapons.R_13M),
+ (Weapons.R_3R, Weapons.R_3S),
+
+ # R-40
+ (Weapons.R_40R, None),
+ (Weapons.R_40T, None),
+
+ # R-55
+ (Weapons.R_55, None),
+ (Weapons.RS2US, None),
+
+ # R-60
+ (Weapons.R_60, Weapons.R_13M1),
+ (Weapons.R_60_x_2, Weapons.R_13M1),
+ (Weapons.R_60_x_2_, Weapons.R_13M1),
+
+ (Weapons.APU_60_1_R_60M, Weapons.R_3S),
+ (Weapons.R_60M, Weapons.R_60),
+ (Weapons.R_60M_, Weapons.R_60),
+ (Weapons.R_60M_2, Weapons.R_60M),
+ (Weapons.R_60M_2_, Weapons.R_60M),
+ (Weapons.R_60M_x_2, Weapons.R_60M),
+ (Weapons.R_60M_x_2_, Weapons.R_60M),
+
+ # R-73
(Weapons.R_73, Weapons.R_60M),
- (Weapons.R_73_, Weapons.R_60M_),
-
- # GBU-38 (JDAM)
- (Weapons.GBU_38, Weapons.GBU_12),
- (Weapons.GBU_38_16, Weapons.MK_82_28), # B1-B only
- (Weapons._2_GBU_38_, Weapons._2_GBU_12),
- (Weapons._2_GBU_38, Weapons._2_GBU_12),
- (Weapons._3_GBU_38, Weapons._3_GBU_12),
- (Weapons.BRU_55___2_x_GBU_38, Weapons.BRU_33___2_x_GBU_12),
- (Weapons.BRU_57___2_x_GBU_38, Weapons.BRU_33___2_x_GBU_12),
-
- # AGM-154A (JSOW)
- (Weapons.AGM_154A, Weapons.GBU_12),
- (Weapons.BRU_55___2_x_AGM_154A, Weapons.BRU_33___2_x_GBU_12),
- (Weapons.BRU_57___2_x_AGM_154A, Weapons.BRU_33___2_x_GBU_12),
-
- # AGM-154C (JSOW)
- (Weapons.AGM_154C, Weapons.GBU_12),
- (Weapons.AGM_154C_4, Weapons.MK_82_28), # B1-B only
- (Weapons.BRU_55___2_x_AGM_154C, Weapons.BRU_33___2_x_GBU_12),
-
- # AGM-84E (SLAM)
- (Weapons.AGM_84E, Weapons.LAU_117_AGM_65F),
-
- # CBU-97
- (Weapons.CBU_97, Weapons.GBU_12),
- (Weapons.TER_9A___2_x_CBU_97, Weapons.TER_9A___2_x_GBU_12),
- (Weapons.TER_9A___2_x_CBU_97_, Weapons.TER_9A___2_x_GBU_12),
- (Weapons.TER_9A___3_x_CBU_97, Weapons.TER_9A___2_x_GBU_12),
-
+ (Weapons.R_73_, None),
+
+ # R-77
+ (Weapons.R_77, Weapons.R_27ER),
+ (Weapons.R_77_, None),
+
+ # UK
+ # ALARM
+ (Weapons.ALARM, None),
+ (Weapons.ALARM_2, None),
+
+ # France
+ # BLG-66 Belouga
+ (Weapons.AUF2_BLG_66_AC_x_2, Weapons.AUF2_MK_82_x_2),
+ (Weapons.BLG_66_AC_Belouga, Weapons.Mk_82),
+ (Weapons.BLG_66_AC_Belouga_, Weapons.Mk_82),
+
+ # HOT-3
+ (Weapons.HOT3, None),
+ (Weapons.HOT3_, None),
+
+ # Magic 2
+ (Weapons.Matra_Magic_II, None),
+ (Weapons.R_550_Magic_2, None),
+
+ # Super 530D
+ (Weapons.Matra_Super_530D, Weapons.Matra_Magic_II),
+ (Weapons.Super_530D, None)
+
]
WEAPON_FALLBACK_MAP: Dict[Weapon, Optional[Weapon]] = defaultdict(
@@ -226,101 +550,482 @@ WEAPON_FALLBACK_MAP: Dict[Weapon, Optional[Weapon]] = defaultdict(
WEAPON_INTRODUCTION_YEARS = {
- # AIM-120C
- Weapon.from_pydcs(Weapons.AIM_120C): 1996,
- Weapon.from_pydcs(Weapons.LAU_115_2_LAU_127_AIM_120C): 1996,
- Weapon.from_pydcs(Weapons.LAU_115___AIM_120C): 1996,
-
- # AIM-120B
+ # USA
+ # ADM-141 TALD
+ Weapon.from_pydcs(Weapons.ADM_141A): 1987,
+ Weapon.from_pydcs(Weapons.ADM_141A_): 1987,
+ Weapon.from_pydcs(Weapons.ADM_141A__): 1987,
+ Weapon.from_pydcs(Weapons.ADM_141B): 1987,
+
+ # AGM-114K Hellfire
+ Weapon.from_pydcs(Weapons.AGM114x2_OH_58): 1993,
+ Weapon.from_pydcs(Weapons.AGM_114K): 1993,
+ Weapon.from_pydcs(Weapons.AGM_114K___4): 1993,
+
+ # AGM-119 Penguin
+ Weapon.from_pydcs(Weapons.AGM_119B_Penguin): 1972,
+
+ # AGM-122 Sidearm
+ Weapon.from_pydcs(Weapons.AGM_122): 1986,
+ Weapon.from_pydcs(Weapons.AGM_122_Sidearm): 1986,
+ Weapon.from_pydcs(Weapons.AGM_122_Sidearm_): 1986,
+
+ # AGM-154 JSOW
+ Weapon.from_pydcs(Weapons.AGM_154A): 1998,
+ Weapon.from_pydcs(Weapons.BRU_55___2_x_AGM_154A): 1998,
+ Weapon.from_pydcs(Weapons.BRU_57___2_x_AGM_154A): 1998,
+
+ Weapon.from_pydcs(Weapons.AGM_154B): 2005,
+
+ Weapon.from_pydcs(Weapons.AGM_154C): 2005,
+ Weapon.from_pydcs(Weapons.AGM_154C_4): 2005,
+ Weapon.from_pydcs(Weapons.BRU_55___2_x_AGM_154C): 2005,
+
+ # AGM-45 Shrike
+ Weapon.from_pydcs(Weapons.AGM_45A): 1965,
+ Weapon.from_pydcs(Weapons.AGM_45B): 1970,
+ Weapon.from_pydcs(Weapons.AGM_45B_): 1970,
+
+ # AGM-62 Walleye
+ Weapon.from_pydcs(Weapons.AGM_62): 1972,
+
+ # AGM-65 Maverick
+ Weapon.from_pydcs(Weapons.AGM_65D): 1983,
+ Weapon.from_pydcs(Weapons.AGM_65E): 1985,
+ Weapon.from_pydcs(Weapons.AGM_65K): 2007,
+
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65A): 1972,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65B): 1972,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65D): 1986,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65E): 1990,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65F): 1991,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65G): 1989,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65H): 2002,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65K): 2002,
+ Weapon.from_pydcs(Weapons.LAU_117_AGM_65L): 1985,
+
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65D_2): 1983,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65D_2_): 1983,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65D_3): 1983,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65D_ONE): 1983,
+
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65E_2): 1985,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65E_2_): 1985,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65E_3): 1985,
+
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65H): 2007,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65H_2_L): 2007,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65H_2_R): 2007,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65H_3): 2007,
+
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65K_2): 2007,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65K_2_): 2007,
+ Weapon.from_pydcs(Weapons.LAU_88_AGM_65K_3): 2007,
+
+ # AGM-84 Harpoon
+ Weapon.from_pydcs(Weapons.AGM_84): 1979,
+ Weapon.from_pydcs(Weapons.AGM_84A): 1979,
+ Weapon.from_pydcs(Weapons.AGM_84A_8): 1979,
+ Weapon.from_pydcs(Weapons.AGM_84D): 1979,
+ Weapon.from_pydcs(Weapons.AGM_84E): 1990,
+ Weapon.from_pydcs(Weapons.AGM_84E_SLAM): 1990,
+ Weapon.from_pydcs(Weapons.AGM_84H): 1998,
+
+ # AGM-86 ALCM
+ Weapon.from_pydcs(Weapons.AGM_86C): 1986,
+ Weapon.from_pydcs(Weapons.AGM_86C_20): 1986,
+ Weapon.from_pydcs(Weapons.AGM_86C_8): 1986,
+ Weapon.from_pydcs(Weapons.MER_6_AGM_86C): 1986,
+
+ # AGM-88 HARM
+ Weapon.from_pydcs(Weapons.AGM_88C): 1983,
+ Weapon.from_pydcs(Weapons.AGM_88C_): 1983,
+ # for future reference: 1983 is the A model IOC. B model in 1986 and C model in 1994.
+
+ # AIM-120 AMRAAM
Weapon.from_pydcs(Weapons.AIM_120B): 1994,
+ Weapon.from_pydcs(Weapons.AIM_120C): 1996,
+
Weapon.from_pydcs(Weapons.LAU_115_2_LAU_127_AIM_120B): 1994,
Weapon.from_pydcs(Weapons.LAU_115___AIM_120B): 1994,
-
- # AIM-7MH
- Weapon.from_pydcs(Weapons.AIM_7MH): 1987,
- Weapon.from_pydcs(Weapons.AIM_7MH_): 1987,
- Weapon.from_pydcs(Weapons.AIM_7MH__): 1987,
- Weapon.from_pydcs(Weapons.LAU_115C_AIM_7MH): 1987,
-
- # AIM-7M
- Weapon.from_pydcs(Weapons.AIM_7M): 1982,
- Weapon.from_pydcs(Weapons.AIM_7M_): 1982,
- Weapon.from_pydcs(Weapons.AIM_7M__): 1982,
- Weapon.from_pydcs(Weapons.LAU_115___AIM_7M): 1982,
-
- # AIM-7F
+ Weapon.from_pydcs(Weapons.LAU_115_2_LAU_127_AIM_120C): 1996,
+ Weapon.from_pydcs(Weapons.LAU_115___AIM_120C): 1996,
+
+ # AIM-54 Phoenix
+ Weapon.from_pydcs(Weapons.AIM_54A_Mk47): 1974,
+ Weapon.from_pydcs(Weapons.AIM_54A_Mk47_): 1974,
+ Weapon.from_pydcs(Weapons.AIM_54A_Mk47__): 1974,
+
+ Weapon.from_pydcs(Weapons.AIM_54A_Mk60): 1974,
+ Weapon.from_pydcs(Weapons.AIM_54A_Mk60_): 1974,
+ Weapon.from_pydcs(Weapons.AIM_54A_Mk60__): 1974,
+
+ Weapon.from_pydcs(Weapons.AIM_54C): 1974,
+ Weapon.from_pydcs(Weapons.AIM_54C_Mk47): 1974,
+ Weapon.from_pydcs(Weapons.AIM_54C_Mk47_): 1974,
+ Weapon.from_pydcs(Weapons.AIM_54C_Mk47__): 1974,
+
+ # AIM-7 Sparrow
+ Weapon.from_pydcs(Weapons.AIM_7E): 1963,
Weapon.from_pydcs(Weapons.AIM_7F): 1976,
Weapon.from_pydcs(Weapons.AIM_7F_): 1976,
Weapon.from_pydcs(Weapons.AIM_7F__): 1976,
- Weapon.from_pydcs(Weapons.LAU_115C_AIM_7F): 1976,
-
- # AIM-7E
- Weapon.from_pydcs(Weapons.AIM_7E): 1963,
+ Weapon.from_pydcs(Weapons.AIM_7M): 1982,
+ Weapon.from_pydcs(Weapons.AIM_7M_): 1982,
+ Weapon.from_pydcs(Weapons.AIM_7M__): 1982,
+ Weapon.from_pydcs(Weapons.AIM_7MH): 1987,
+ Weapon.from_pydcs(Weapons.AIM_7MH_): 1987,
+ Weapon.from_pydcs(Weapons.AIM_7MH__): 1987,
+
Weapon.from_pydcs(Weapons.LAU_115C_AIM_7E): 1963,
-
- # AIM-9X
- Weapon.from_pydcs(Weapons.AIM_9X_Sidewinder_IR_AAM): 2003,
- Weapon.from_pydcs(Weapons.LAU_7_AIM_9X_Sidewinder_IR_AAM): 2003,
- Weapon.from_pydcs(Weapons.LAU_115_LAU_127_AIM_9X): 2003,
- Weapon.from_pydcs(Weapons.LAU_115_2_LAU_127_AIM_9X): 2003,
- Weapon.from_pydcs(Weapons.LAU_127_AIM_9X): 2003,
-
- # AIM-9P5
- Weapon.from_pydcs(Weapons.AIM_9P5_Sidewinder_IR_AAM): 1963,
- Weapon.from_pydcs(Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM): 1963,
-
- # AIM-9P
- Weapon.from_pydcs(Weapons.AIM_9P_Sidewinder_IR_AAM): 1978,
- Weapon.from_pydcs(Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM): 1978,
-
- # AIM-9M
- Weapon.from_pydcs(Weapons.AIM_9M_Sidewinder_IR_AAM): 1983,
- Weapon.from_pydcs(Weapons.LAU_7_AIM_9M_Sidewinder_IR_AAM): 1983,
-
- # AIM-9L
+ Weapon.from_pydcs(Weapons.LAU_115C_AIM_7F): 1976,
+ Weapon.from_pydcs(Weapons.LAU_115___AIM_7M): 1982,
+ Weapon.from_pydcs(Weapons.LAU_115C_AIM_7MH): 1987,
+
+ # AIM-9 Sidewinder
Weapon.from_pydcs(Weapons.AIM_9L_Sidewinder_IR_AAM): 1977,
+ Weapon.from_pydcs(Weapons.AIM_9M_Sidewinder_IR_AAM): 1982,
+ Weapon.from_pydcs(Weapons.AIM_9P5_Sidewinder_IR_AAM): 1980,
+ Weapon.from_pydcs(Weapons.AIM_9P_Sidewinder_IR_AAM): 1978,
+ Weapon.from_pydcs(Weapons.AIM_9X_Sidewinder_IR_AAM): 2003,
+
+ Weapon.from_pydcs(Weapons.LAU_105_1_AIM_9L_L): 1977,
+ Weapon.from_pydcs(Weapons.LAU_105_1_AIM_9L_R): 1977,
+ Weapon.from_pydcs(Weapons.LAU_105_1_AIM_9M_L): 1982,
+ Weapon.from_pydcs(Weapons.LAU_105_1_AIM_9M_R): 1982,
+
+ Weapon.from_pydcs(Weapons.LAU_105_2_AIM_9L): 1977,
+ Weapon.from_pydcs(Weapons.LAU_105_2_AIM_9P5): 1980,
+
+ Weapon.from_pydcs(Weapons.LAU_105___2_AIM_9M_Sidewinder_IR_AAM): 1982,
+ Weapon.from_pydcs(Weapons.LAU_105___2_AIM_9P_Sidewinder_IR_AAM): 1978,
+
+ Weapon.from_pydcs(Weapons.LAU_115_2_LAU_127_AIM_9L): 1977,
+ Weapon.from_pydcs(Weapons.LAU_115_2_LAU_127_AIM_9M): 1982,
+ Weapon.from_pydcs(Weapons.LAU_115_2_LAU_127_AIM_9X): 2003,
+
+ Weapon.from_pydcs(Weapons.LAU_115_LAU_127_AIM_9L): 1977,
+ Weapon.from_pydcs(Weapons.LAU_115_LAU_127_AIM_9M): 1982,
+ Weapon.from_pydcs(Weapons.LAU_115_LAU_127_AIM_9X): 2003,
+
+ Weapon.from_pydcs(Weapons.LAU_127_AIM_9L): 1977,
+ Weapon.from_pydcs(Weapons.LAU_127_AIM_9M): 1982,
+ Weapon.from_pydcs(Weapons.LAU_127_AIM_9X): 2003,
+
+ Weapon.from_pydcs(Weapons.LAU_138_AIM_9L): 1977,
+ Weapon.from_pydcs(Weapons.LAU_138_AIM_9M): 1982,
+
Weapon.from_pydcs(Weapons.LAU_7_AIM_9L): 1977,
+ Weapon.from_pydcs(Weapons.LAU_7_AIM_9M): 1982,
+ Weapon.from_pydcs(Weapons.LAU_7_AIM_9M_Sidewinder_IR_AAM): 1982,
+ Weapon.from_pydcs(Weapons.LAU_7_AIM_9P5_Sidewinder_IR_AAM): 1980,
+ Weapon.from_pydcs(Weapons.LAU_7_AIM_9P_Sidewinder_IR_AAM): 1978,
+ Weapon.from_pydcs(Weapons.LAU_7_AIM_9X_Sidewinder_IR_AAM): 2003,
+
+ Weapon.from_pydcs(Weapons.LAU_7___2_AIM_9L_Sidewinder_IR_AAM): 1977,
+ Weapon.from_pydcs(Weapons.LAU_7___2_AIM_9M_Sidewinder_IR_AAM): 1982,
+ Weapon.from_pydcs(Weapons.LAU_7___2_AIM_9P5_Sidewinder_IR_AAM): 1980,
+ Weapon.from_pydcs(Weapons.LAU_7___2_AIM_9P_Sidewinder_IR_AAM): 1978,
+
+ # ALQ ECM Pods
+ Weapon.from_pydcs(Weapons.ALQ_131): 1970,
+ Weapon.from_pydcs(Weapons.ALQ_184): 1989,
+ Weapon.from_pydcs(Weapons.AN_ALQ_164_DECM_Pod): 1984,
+
+ # TGP Pods
+ Weapon.from_pydcs(Weapons.AN_AAQ_28_LITENING): 1995,
+ Weapon.from_pydcs(Weapons.AN_AAQ_28_LITENING_): 1995,
+ Weapon.from_pydcs(Weapons.AN_AAS_38_FLIR): 1993,
+ Weapon.from_pydcs(Weapons.AN_ASQ_173_LST_SCAM): 1993,
+ Weapon.from_pydcs(Weapons.AWW_13_DATALINK_POD): 1967,
+ Weapon.from_pydcs(Weapons.LANTIRN_Targeting_Pod): 1985,
+ Weapon.from_pydcs(Weapons.Lantirn_F_16): 1985,
+ Weapon.from_pydcs(Weapons.Lantirn_Target_Pod): 1985,
+ Weapon.from_pydcs(Weapons.Pavetack_F_111): 1982,
+
+ # BLU-107
+ Weapon.from_pydcs(Weapons.BLU_107): 1983,
+ Weapon.from_pydcs(Weapons.MER_6_BLU_107): 1983,
- # AIM-54C-Mk47
- Weapon.from_pydcs(Weapons.AIM_54C_Mk47): 1986,
- Weapon.from_pydcs(Weapons.AIM_54C_Mk47_): 1986,
- Weapon.from_pydcs(Weapons.AIM_54C_Mk47__): 1986,
- Weapon.from_pydcs(Weapons.AIM_54C): 1986, # this weapon id is unused (legacy F-14A)
+ # GBU-10 LGB
+ Weapon.from_pydcs(Weapons.DIS_GBU_10): 1976,
+ Weapon.from_pydcs(Weapons.GBU_10): 1976,
+ Weapon.from_pydcs(Weapons.GBU_10_): 1976,
+ Weapon.from_pydcs(Weapons.GBU_10_2): 1976,
+
+ # GBU-12 LGB
+ Weapon.from_pydcs(Weapons.AUF2_GBU_12_x_2): 1976,
+ Weapon.from_pydcs(Weapons.BRU_33___2_x_GBU_12): 1976,
+ Weapon.from_pydcs(Weapons.BRU_42_3_GBU_12): 1976,
+ Weapon.from_pydcs(Weapons.DIS_GBU_12): 1976,
+ Weapon.from_pydcs(Weapons.DIS_GBU_12_DUAL): 1976,
+ Weapon.from_pydcs(Weapons.DIS_GBU_12_DUAL_L): 1976,
+ Weapon.from_pydcs(Weapons.DIS_GBU_12_DUAL_R): 1976,
+ Weapon.from_pydcs(Weapons.GBU_12): 1976,
+ Weapon.from_pydcs(Weapons.GBU_12_): 1976,
+ Weapon.from_pydcs(Weapons.TER_9A___2_x_GBU_12): 1976,
+ Weapon.from_pydcs(Weapons.TER_9A___2_x_GBU_12_): 1976,
+ Weapon.from_pydcs(Weapons._2xGBU_12): 1976,
+ Weapon.from_pydcs(Weapons._2xGBU_12_): 1976,
+ Weapon.from_pydcs(Weapons._2_GBU_12): 1976,
+ Weapon.from_pydcs(Weapons._2_GBU_12_): 1976,
+ Weapon.from_pydcs(Weapons._3_GBU_12): 1976,
+
+ # GBU-15 LGB
+ Weapon.from_pydcs(Weapons.GBU_15): 1975,
+
+ # GBU-16 LGB
+ Weapon.from_pydcs(Weapons.BRU_33___2_x_GBU_16): 1976,
+ Weapon.from_pydcs(Weapons.DIS_GBU_16): 1976,
+ Weapon.from_pydcs(Weapons.GBU_16): 1976,
+ Weapon.from_pydcs(Weapons.GBU_16_): 1976,
+ Weapon.from_pydcs(Weapons._2_GBU_16): 1976,
+ Weapon.from_pydcs(Weapons._2_GBU_16_): 1976,
+ Weapon.from_pydcs(Weapons._3_GBU_16): 1976,
+ Weapon.from_pydcs(Weapons._3_GBU_16_): 1976,
+
+ # GBU-24 LGB
+ Weapon.from_pydcs(Weapons.GBU_24): 1986,
+ Weapon.from_pydcs(Weapons.GBU_24_): 1986,
+ Weapon.from_pydcs(Weapons.GBU_24__): 1986,
+
+ # GBU-27 LGB
+ Weapon.from_pydcs(Weapons.GBU_27): 1991,
+ Weapon.from_pydcs(Weapons.GBU_27_2): 1991,
+ Weapon.from_pydcs(Weapons.GBU_27_4): 1991,
+
+ # GBU-28
+ Weapon.from_pydcs(Weapons.GBU_28): 1991,
+
+ # GBU-31 JDAM
+ Weapon.from_pydcs(Weapons.GBU_31V3B_8): 2001,
+ Weapon.from_pydcs(Weapons.GBU_31_8): 2001,
+ Weapon.from_pydcs(Weapons.GBU_31_V_1_B): 2001,
+ Weapon.from_pydcs(Weapons.GBU_31_V_2_B): 2001,
+ Weapon.from_pydcs(Weapons.GBU_31_V_3_B): 2001,
+ Weapon.from_pydcs(Weapons.GBU_31_V_4_B): 2001,
+
+ # GBU-32 JDAM
+ Weapon.from_pydcs(Weapons.GBU_32_V_2_B): 2002,
+
+ # GBU-38 JDAM
+ Weapon.from_pydcs(Weapons.BRU_55___2_x_GBU_38): 2005,
+ Weapon.from_pydcs(Weapons.BRU_57___2_x_GBU_38): 2005,
+ Weapon.from_pydcs(Weapons.GBU_38): 2005,
+ Weapon.from_pydcs(Weapons.GBU_38_16): 2005,
+ Weapon.from_pydcs(Weapons._2_GBU_38): 2005,
+ Weapon.from_pydcs(Weapons._2_GBU_38_): 2005,
+ Weapon.from_pydcs(Weapons._3_GBU_38): 2005,
+
+ # GBU-54 LJDAM
+ Weapon.from_pydcs(Weapons.GBU_54_V_1_B): 2008,
+ Weapon.from_pydcs(Weapons._2_GBU_54_V_1_B): 2008,
+ Weapon.from_pydcs(Weapons._2_GBU_54_V_1_B_): 2008,
+ Weapon.from_pydcs(Weapons._3_GBU_54_V_1_B): 2008,
+
+ # CBU-52
+ Weapon.from_pydcs(Weapons.CBU_52B): 1970,
+
+ # CBU-87 CEM
+ Weapon.from_pydcs(Weapons.CBU_87): 1986,
+ Weapon.from_pydcs(Weapons.TER_9A___2_x_CBU_87): 1986,
+ Weapon.from_pydcs(Weapons.TER_9A___2_x_CBU_87_): 1986,
+ Weapon.from_pydcs(Weapons.TER_9A___3_x_CBU_87): 1986,
+
+ # CBU-97
+ Weapon.from_pydcs(Weapons.CBU_97): 1992,
+ Weapon.from_pydcs(Weapons.TER_9A___2_x_CBU_97): 1992,
+ Weapon.from_pydcs(Weapons.TER_9A___2_x_CBU_97_): 1992,
+ Weapon.from_pydcs(Weapons.TER_9A___3_x_CBU_97): 1992,
+
+ # CBU-99
+ Weapon.from_pydcs(Weapons.BRU_33___2_x_CBU_99): 1968,
+ Weapon.from_pydcs(Weapons.CBU_99): 1968,
+
+ Weapon.from_pydcs(Weapons.BRU_33___2_x_Mk_20_Rockeye): 1968,
+
+ Weapon.from_pydcs(Weapons.DIS_MK_20): 1968,
+ Weapon.from_pydcs(Weapons.DIS_MK_20_DUAL_L): 1968,
+ Weapon.from_pydcs(Weapons.DIS_MK_20_DUAL_R): 1968,
+
+ Weapon.from_pydcs(Weapons.HSAB_9_Mk_20_Rockeye): 1968,
+
+ Weapon.from_pydcs(Weapons.MAK79_2_MK_20): 1968,
+ Weapon.from_pydcs(Weapons.MAK79_2_MK_20_): 1968,
+
+ Weapon.from_pydcs(Weapons.MAK79_MK_20): 1968,
+ Weapon.from_pydcs(Weapons.MAK79_MK_20_): 1968,
+
+ Weapon.from_pydcs(Weapons.MER_6_Mk_20_Rockeye): 1968,
+
+ Weapon.from_pydcs(Weapons.Mk_20): 1968,
+ Weapon.from_pydcs(Weapons.Mk_20_): 1968,
+ Weapon.from_pydcs(Weapons.Mk_20_18): 1968,
+ Weapon.from_pydcs(Weapons.Mk_20_Rockeye__6): 1968,
+
+ Weapon.from_pydcs(Weapons._2_MK_20): 1968,
+ Weapon.from_pydcs(Weapons._2_MK_20_): 1968,
+ Weapon.from_pydcs(Weapons._2_MK_20__): 1968,
+ Weapon.from_pydcs(Weapons._2_MK_20___): 1968,
+ Weapon.from_pydcs(Weapons._2_MK_20____): 1968,
+ Weapon.from_pydcs(Weapons._2_MK_20_____): 1968,
+ Weapon.from_pydcs(Weapons._2_Mk_20_Rockeye): 1968,
+ Weapon.from_pydcs(Weapons._2_Mk_20_Rockeye_): 1968,
+ Weapon.from_pydcs(Weapons._2_Mk_20_Rockeye__): 1968,
+
+ Weapon.from_pydcs(Weapons._3_Mk_20_Rockeye): 1968,
+ Weapon.from_pydcs(Weapons._3_Mk_20_Rockeye_): 1968,
+
+ # CBU-103
+ Weapon.from_pydcs(Weapons.BRU_57___2_x_CBU_103): 2000,
+ Weapon.from_pydcs(Weapons.CBU_103): 2000,
+
+ # CBU-105
+ Weapon.from_pydcs(Weapons.BRU_57___2_x_CBU_105): 2000,
+ Weapon.from_pydcs(Weapons.CBU_105): 2000,
+
+ # APKWS
+ Weapon.from_pydcs(Weapons.LAU_131_pod___7_x_2_75__Hydra___Laser_Guided_Rkts_M151___HE_APKWS): 2016,
+ Weapon.from_pydcs(Weapons.LAU_131_pod___7_x_2_75__Hydra___Laser_Guided_Rkts_M282___MPP_APKWS): 2016,
+ Weapon.from_pydcs(Weapons._3_x_LAU_131_pods___21_x_2_75__Hydra___Laser_Guided_M151___HE_APKWS): 2016,
+ Weapon.from_pydcs(Weapons._3_x_LAU_131_pods___21_x_2_75__Hydra___Laser_Guided_M282___MPP_APKWS): 2016,
+
+ # Russia
- # R-77 (AA-12)
+ # KAB-1500
+ Weapon.from_pydcs(Weapons.KAB_1500Kr): 1985,
+ Weapon.from_pydcs(Weapons.KAB_1500L): 1995,
+ Weapon.from_pydcs(Weapons.KAB_1500LG_Pr): 1990,
+
+ # KAB-500
+ Weapon.from_pydcs(Weapons.KAB_500kr): 1980,
+ Weapon.from_pydcs(Weapons.KAB_500L): 1995,
+ Weapon.from_pydcs(Weapons.KAB_500S): 2000,
+
+ # Kh Series
+ Weapon.from_pydcs(Weapons.Kh_22N): 1962,
+ Weapon.from_pydcs(Weapons.Kh_23L): 1975,
+
+ Weapon.from_pydcs(Weapons.Kh_25ML): 1975,
+ Weapon.from_pydcs(Weapons.Kh_25ML_): 1975,
+ Weapon.from_pydcs(Weapons.Kh_25ML__): 1975,
+
+ Weapon.from_pydcs(Weapons.Kh_25MP): 1975,
+
+ Weapon.from_pydcs(Weapons.Kh_25MPU): 1980,
+ Weapon.from_pydcs(Weapons.Kh_25MPU_): 1980,
+ Weapon.from_pydcs(Weapons.Kh_25MPU__): 1980,
+
+ Weapon.from_pydcs(Weapons.Kh_25MR): 1975,
+ Weapon.from_pydcs(Weapons.Kh_25MR_): 1975,
+
+ Weapon.from_pydcs(Weapons.Kh_28__AS_9_Kyle_): 1973,
+
+ Weapon.from_pydcs(Weapons.Kh_29L): 1980,
+ Weapon.from_pydcs(Weapons.Kh_29L_): 1980,
+ Weapon.from_pydcs(Weapons.Kh_29L__): 1980,
+ Weapon.from_pydcs(Weapons.Kh_29T): 1980,
+ Weapon.from_pydcs(Weapons.Kh_29T_): 1980,
+ Weapon.from_pydcs(Weapons.Kh_29T__): 1980,
+
+ Weapon.from_pydcs(Weapons.Kh_31A): 1980,
+ Weapon.from_pydcs(Weapons.Kh_31A_): 1980,
+ Weapon.from_pydcs(Weapons.Kh_31A__): 1980,
+ Weapon.from_pydcs(Weapons.Kh_31P): 1980,
+ Weapon.from_pydcs(Weapons.Kh_31P_): 1980,
+ Weapon.from_pydcs(Weapons.Kh_31P__): 1980,
+
+ Weapon.from_pydcs(Weapons.Kh_35): 2003,
+ Weapon.from_pydcs(Weapons.Kh_35_): 2003,
+ Weapon.from_pydcs(Weapons.Kh_35_6): 2003,
+
+ Weapon.from_pydcs(Weapons.Kh_41): 1984,
+
+ Weapon.from_pydcs(Weapons.Kh_58U): 1985,
+ Weapon.from_pydcs(Weapons.Kh_58U_): 1985,
+
+ Weapon.from_pydcs(Weapons.Kh_59M): 1990,
+
+ Weapon.from_pydcs(Weapons.Kh_65): 1992,
+ Weapon.from_pydcs(Weapons.Kh_65_6): 1992,
+ Weapon.from_pydcs(Weapons.Kh_65_8): 1992,
+
+ Weapon.from_pydcs(Weapons.Kh_66_Grom__21__APU_68): 1968,
+
+ # ECM
+ Weapon.from_pydcs(Weapons.L175V_Khibiny_ECM_pod): 1982,
+
+ # R-13
+ Weapon.from_pydcs(Weapons.R_13M): 1961,
+ Weapon.from_pydcs(Weapons.R_13M1): 1965,
+
+ # R-24
+ Weapon.from_pydcs(Weapons.R_24R): 1981,
+ Weapon.from_pydcs(Weapons.R_24T): 1981,
+
+ # R-27
+ Weapon.from_pydcs(Weapons.R_27ER): 1983,
+ Weapon.from_pydcs(Weapons.R_27ET): 1986,
+ Weapon.from_pydcs(Weapons.R_27R): 1983,
+ Weapon.from_pydcs(Weapons.R_27T): 1983,
+
+ # R-33
+ Weapon.from_pydcs(Weapons.R_33): 1981,
+
+ # R-3
+ Weapon.from_pydcs(Weapons.R_3R): 1966,
+ Weapon.from_pydcs(Weapons.R_3S): 1962,
+
+ # R-40
+ Weapon.from_pydcs(Weapons.R_40R): 1976,
+ Weapon.from_pydcs(Weapons.R_40T): 1976,
+
+ # R-55
+ Weapon.from_pydcs(Weapons.R_55): 1957,
+ Weapon.from_pydcs(Weapons.RS2US): 1957,
+
+ # R-60
+ Weapon.from_pydcs(Weapons.R_60): 1973,
+ Weapon.from_pydcs(Weapons.R_60_x_2): 1973,
+ Weapon.from_pydcs(Weapons.R_60_x_2_): 1973,
+
+ Weapon.from_pydcs(Weapons.APU_60_1_R_60M): 1982,
+ Weapon.from_pydcs(Weapons.R_60M): 1982,
+ Weapon.from_pydcs(Weapons.R_60M_): 1982,
+ Weapon.from_pydcs(Weapons.R_60M_2): 1982,
+ Weapon.from_pydcs(Weapons.R_60M_2_): 1982,
+ Weapon.from_pydcs(Weapons.R_60M_x_2): 1982,
+ Weapon.from_pydcs(Weapons.R_60M_x_2_): 1982,
+
+ # R-73
+ Weapon.from_pydcs(Weapons.R_73): 1984,
+ Weapon.from_pydcs(Weapons.R_73_): 1984,
+
+ # R-77
Weapon.from_pydcs(Weapons.R_77): 2002,
Weapon.from_pydcs(Weapons.R_77_): 2002,
-
- # R-73 (AA-11)
- Weapon.from_pydcs(Weapons.R_73): 1989,
- Weapon.from_pydcs(Weapons.R_73_): 1989,
-
- # GBU-38 (JDAM)
- Weapon.from_pydcs(Weapons.GBU_38): 1998,
- Weapon.from_pydcs(Weapons.GBU_38_16): 1998, # B1-B only
- Weapon.from_pydcs(Weapons._2_GBU_38_): 1998,
- Weapon.from_pydcs(Weapons._2_GBU_38): 1998,
- Weapon.from_pydcs(Weapons._3_GBU_38): 1998,
- Weapon.from_pydcs(Weapons.BRU_55___2_x_GBU_38): 1998,
- Weapon.from_pydcs(Weapons.BRU_57___2_x_GBU_38): 1998,
-
- # AGM-154A (JSOW)
- Weapon.from_pydcs(Weapons.AGM_154A): 1999,
- Weapon.from_pydcs(Weapons.BRU_55___2_x_AGM_154A): 1999,
- Weapon.from_pydcs(Weapons.BRU_57___2_x_AGM_154A): 1999,
-
- # AGM-154C (JSOW)
- Weapon.from_pydcs(Weapons.AGM_154C): 2005,
- Weapon.from_pydcs(Weapons.AGM_154C_4): 2005, # B1-B only
- Weapon.from_pydcs(Weapons.BRU_55___2_x_AGM_154C): 2005,
-
- # AGM-84E
- Weapon.from_pydcs(Weapons.AGM_84E): 1990,
-
- # CBU-97
- Weapon.from_pydcs(Weapons.CBU_97): 1995,
- Weapon.from_pydcs(Weapons.TER_9A___2_x_CBU_97): 1995,
- Weapon.from_pydcs(Weapons.TER_9A___2_x_CBU_97_): 1995,
- Weapon.from_pydcs(Weapons.TER_9A___3_x_CBU_97): 1995
-
+
+ # UK
+ # ALARM
+ Weapon.from_pydcs(Weapons.ALARM): 1990,
+ Weapon.from_pydcs(Weapons.ALARM_2): 1990,
+
+ # France
+ # BLG-66 Belouga
+ Weapon.from_pydcs(Weapons.AUF2_BLG_66_AC_x_2): 1979,
+ Weapon.from_pydcs(Weapons.BLG_66_AC_Belouga): 1979,
+ Weapon.from_pydcs(Weapons.BLG_66_AC_Belouga_): 1979,
+
+ # HOT-3
+ Weapon.from_pydcs(Weapons.HOT3): 1998,
+ Weapon.from_pydcs(Weapons.HOT3_): 1998,
+
+ # Magic 2
+ Weapon.from_pydcs(Weapons.Matra_Magic_II): 1986,
+ Weapon.from_pydcs(Weapons.R_550_Magic_2): 1986,
+
+ # Super 530D
+ Weapon.from_pydcs(Weapons.Matra_Super_530D): 1988,
+ Weapon.from_pydcs(Weapons.Super_530D): 1988,
+
}
diff --git a/game/db.py b/game/db.py
index 08260e15..0314d0cb 100644
--- a/game/db.py
+++ b/game/db.py
@@ -1300,6 +1300,10 @@ TIME_PERIODS = {
"Gulf War - Winter [1990]": datetime(1990, 1, 1),
"Gulf War - Spring [1990]": datetime(1990, 4, 1),
"Gulf War - Summer [1990]": datetime(1990, 6, 1),
+ "Mid-90s - Winter [1995]": datetime(1995, 1, 1),
+ "Mid-90s - Spring [1995]": datetime(1995, 4, 1),
+ "Mid-90s - Summer [1995]": datetime(1995, 6, 1),
+ "Mid-90s - Fall [1995]": datetime(1995, 10, 1),
"Gulf War - Fall [1990]": datetime(1990, 10, 1),
"Modern - Winter [2010]": datetime(2010, 1, 1),
"Modern - Spring [2010]": datetime(2010, 4, 1),
@@ -1309,7 +1313,7 @@ TIME_PERIODS = {
"Syrian War [2011]": datetime(2011, 3, 15),
"6 days war [1967]": datetime(1967, 6, 5),
"Yom Kippour War [1973]": datetime(1973, 10, 6),
- "Lebanon War [1982]": datetime(1982, 6, 6),
+ "First Lebanon War [1982]": datetime(1982, 6, 6),
"Arab-Israeli War [1948]": datetime(1948, 5, 15),
}
diff --git a/game/event/event.py b/game/event/event.py
index ea7702c9..92e646b8 100644
--- a/game/event/event.py
+++ b/game/event/event.py
@@ -6,7 +6,7 @@ from typing import Dict, Iterator, List, TYPE_CHECKING, Tuple, Type
from dcs.mapping import Point
from dcs.task import Task
-from dcs.unittype import UnitType
+from dcs.unittype import UnitType, VehicleType
from game import persistency
from game.debriefing import AirLosses, Debriefing
@@ -296,45 +296,69 @@ class Event:
self.game.turn)
self.game.informations.append(info)
- def redeploy_units(self, cp):
+ def redeploy_units(self, cp: ControlPoint) -> None:
""""
Auto redeploy units to newly captured base
"""
- ally_connected_cps = [ocp for ocp in cp.connected_points if cp.captured == ocp.captured]
- enemy_connected_cps = [ocp for ocp in cp.connected_points if cp.captured != ocp.captured]
+ ally_connected_cps = [ocp for ocp in cp.connected_points if
+ cp.captured == ocp.captured]
+ enemy_connected_cps = [ocp for ocp in cp.connected_points if
+ cp.captured != ocp.captured]
# If the newly captured cp does not have enemy connected cp,
# then it is not necessary to redeploy frontline units there.
if len(enemy_connected_cps) == 0:
return
+
+ # From each ally cp, send reinforcements
+ for ally_cp in ally_connected_cps:
+ self.redeploy_between(cp, ally_cp)
+
+ def redeploy_between(self, destination: ControlPoint,
+ source: ControlPoint) -> None:
+ total_units_redeployed = 0
+ moved_units = {}
+
+ if source.has_active_frontline or not destination.captured:
+ # If there are still active front lines to defend at the
+ # transferring CP we should not transfer all units.
+ #
+ # Opfor also does not transfer all of their units.
+ # TODO: Balance the CPs rather than moving half from everywhere.
+ move_factor = 0.5
else:
- # From each ally cp, send reinforcements
- for ally_cp in ally_connected_cps:
- total_units_redeployed = 0
- own_enemy_cp = [ocp for ocp in ally_cp.connected_points if ally_cp.captured != ocp.captured]
+ # Otherwise we can move everything.
+ move_factor = 1
- moved_units = {}
+ for frontline_unit, count in source.base.armor.items():
+ moved_units[frontline_unit] = int(count * move_factor)
+ total_units_redeployed = total_units_redeployed + int(
+ count * move_factor)
- # If the connected base, does not have any more enemy cp connected.
- # Or if it is not the opponent redeploying forces there (enemy AI will never redeploy all their forces at once)
- if len(own_enemy_cp) > 0 or not cp.captured:
- for frontline_unit, count in ally_cp.base.armor.items():
- moved_units[frontline_unit] = int(count/2)
- total_units_redeployed = total_units_redeployed + int(count/2)
- else: # So if the old base, does not have any more enemy cp connected, or if it is an enemy base
- for frontline_unit, count in ally_cp.base.armor.items():
- moved_units[frontline_unit] = count
- total_units_redeployed = total_units_redeployed + count
+ destination.base.commision_units(moved_units)
+ source.base.commit_losses(moved_units)
- cp.base.commision_units(moved_units)
- ally_cp.base.commit_losses(moved_units)
+ # Also transfer pending deliveries.
+ for unit_type, count in source.pending_unit_deliveries.units.items():
+ if not issubclass(unit_type, VehicleType):
+ continue
+ if count <= 0:
+ # Don't transfer *sales*...
+ continue
+ move_count = int(count * move_factor)
+ source.pending_unit_deliveries.sell({unit_type: move_count})
+ destination.pending_unit_deliveries.order({unit_type: move_count})
+ total_units_redeployed += move_count
- if total_units_redeployed > 0:
- info = Information("Units redeployed", "", self.game.turn)
- info.text = str(total_units_redeployed) + " units have been redeployed from " + ally_cp.name + " to " + cp.name
- self.game.informations.append(info)
- logging.info(info.text)
+ if total_units_redeployed > 0:
+ text = (
+ f"{total_units_redeployed} units have been redeployed from "
+ f"{source.name} to {destination.name}"
+ )
+ info = Information("Units redeployed", text, self.game.turn)
+ self.game.informations.append(info)
+ logging.info(text)
class UnitsDeliveryEvent:
diff --git a/game/theater/controlpoint.py b/game/theater/controlpoint.py
index 1ca122af..66a534f6 100644
--- a/game/theater/controlpoint.py
+++ b/game/theater/controlpoint.py
@@ -606,6 +606,10 @@ class ControlPoint(MissionTarget, ABC):
def income_per_turn(self) -> int:
return 0
+ @property
+ def has_active_frontline(self) -> bool:
+ return any(
+ not c.is_friendly(self.captured) for c in self.connected_points)
class Airfield(ControlPoint):
diff --git a/game/version.py b/game/version.py
index bb8c3a2c..5f002955 100644
--- a/game/version.py
+++ b/game/version.py
@@ -2,7 +2,7 @@ from pathlib import Path
def _build_version_string() -> str:
- components = ["2.4"]
+ components = ["2.4.2"]
build_number_path = Path("resources/buildnumber")
if build_number_path.exists():
with build_number_path.open("r") as build_number_file:
diff --git a/qt_ui/windows/basemenu/QRecruitBehaviour.py b/qt_ui/windows/basemenu/QRecruitBehaviour.py
index 20deb9a0..799c526b 100644
--- a/qt_ui/windows/basemenu/QRecruitBehaviour.py
+++ b/qt_ui/windows/basemenu/QRecruitBehaviour.py
@@ -28,7 +28,7 @@ class QRecruitBehaviour:
bought_amount_labels = None
maximum_units = -1
recruitable_types = []
- BUDGET_FORMAT = "Available Budget: ${}M"
+ BUDGET_FORMAT = "Available Budget: ${:.2f}M"
def __init__(self) -> None:
self.bought_amount_labels = {}
diff --git a/resources/scripts/MissionScripting.original.lua b/resources/scripts/MissionScripting.original.lua
index 29dcd2fe..86f9cda2 100644
--- a/resources/scripts/MissionScripting.original.lua
+++ b/resources/scripts/MissionScripting.original.lua
@@ -3,7 +3,7 @@
dofile('Scripts/ScriptingSystem.lua')
--Sanitize Mission Scripting environment
---This makes unavailable some unsecure functions.
+--This makes unavailable some unsecure functions.
--Mission downloaded from server to client may contain potentialy harmful lua code that may use these functions.
--You can remove the code below and make availble these functions at your own risk.