mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Compare commits
135 Commits
develop_2_
...
2.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de2e5f861b | ||
|
|
b27a7fc71b | ||
|
|
5861ce6146 | ||
|
|
c732ed556f | ||
|
|
be1a75e520 | ||
|
|
c41d10c581 | ||
|
|
157a59e3c4 | ||
|
|
d24c65c3aa | ||
|
|
d4d441ff9b | ||
|
|
f43fb1223f | ||
|
|
3db275414d | ||
|
|
6e0ff6c805 | ||
|
|
9c359efbff | ||
|
|
c5cc1ea8e8 | ||
|
|
afb6a33131 | ||
|
|
539a11f54d | ||
|
|
9324e549e6 | ||
|
|
c8f6b6df87 | ||
|
|
38f632097e | ||
|
|
e63743f537 | ||
|
|
ce13295cf0 | ||
|
|
23c02a3510 | ||
|
|
01ea7b9ee1 | ||
|
|
6fed1284a1 | ||
|
|
5574d849bd | ||
|
|
c2ce3a6992 | ||
|
|
b61d15fdf4 | ||
|
|
ad5cc83fb3 | ||
|
|
2f53edd775 | ||
|
|
923459c88b | ||
|
|
1192d26448 | ||
|
|
2d5e827417 | ||
|
|
a30d9276b8 | ||
|
|
b963c2272f | ||
|
|
221cb8709b | ||
|
|
648857fc44 | ||
|
|
8091051bb4 | ||
|
|
1e468cd3e0 | ||
|
|
15d2a5bb2b | ||
|
|
5c76229ee5 | ||
|
|
0cd088122e | ||
|
|
b6f3467a89 | ||
|
|
52ce1a5959 | ||
|
|
7ce05762f5 | ||
|
|
cce736bc16 | ||
|
|
2a1127e637 | ||
|
|
8ca68b3d7a | ||
|
|
0f76d893b8 | ||
|
|
ab746b5195 | ||
|
|
828c87df39 | ||
|
|
888aeb621d | ||
|
|
ac2fddf87e | ||
|
|
614304cc81 | ||
|
|
f363d66aac | ||
|
|
1706c42695 | ||
|
|
2b44b2fc0b | ||
|
|
25986aa15c | ||
|
|
264eb01afc | ||
|
|
6db3c3f9f1 | ||
|
|
714992bdcb | ||
|
|
ca7a86b6d7 | ||
|
|
49e729e9ec | ||
|
|
7f0a690c7b | ||
|
|
d07afc603b | ||
|
|
5bd4c00257 | ||
|
|
13272aa280 | ||
|
|
260358c5fb | ||
|
|
0f07b2c095 | ||
|
|
b2fafc22dd | ||
|
|
6200ec8e0e | ||
|
|
831516c5f5 | ||
|
|
fb49d9e6ae | ||
|
|
e660726828 | ||
|
|
4519f47b19 | ||
|
|
47174bbb4d | ||
|
|
de18ce3e7b | ||
|
|
b5934633fa | ||
|
|
4ec8994c38 | ||
|
|
49d6cece50 | ||
|
|
03251d5bd5 | ||
|
|
a6e03184bc | ||
|
|
688a20c312 | ||
|
|
4c1b34461e | ||
|
|
c6939e7194 | ||
|
|
cd9432e395 | ||
|
|
7d5244a5bc | ||
|
|
1aa5d4f7de | ||
|
|
ad74204fe4 | ||
|
|
5cb1a47ed3 | ||
|
|
fff22d3cd1 | ||
|
|
665cd7b996 | ||
|
|
61173196d2 | ||
|
|
03e98ba562 | ||
|
|
6195290adf | ||
|
|
4f1b0055e1 | ||
|
|
dd9fe87ff4 | ||
|
|
5bda4abfce | ||
|
|
f8ae1e9076 | ||
|
|
16b0dcad71 | ||
|
|
9c1265d50d | ||
|
|
8c0e781c94 | ||
|
|
a47bef1f13 | ||
|
|
053663bd76 | ||
|
|
2ffe3bf722 | ||
|
|
f7889b785d | ||
|
|
27829a024a | ||
|
|
a0fda2552f | ||
|
|
65c185ebd2 | ||
|
|
5792eb354c | ||
|
|
dce7d91511 | ||
|
|
3d1afa74d4 | ||
|
|
d8c94f5ece | ||
|
|
61f1e11a48 | ||
|
|
98249b1aca | ||
|
|
8e51b7fc1d | ||
|
|
71914b8a8b | ||
|
|
7a077a0d21 | ||
|
|
d23e4665e7 | ||
|
|
df12b54856 | ||
|
|
ae12053d74 | ||
|
|
0e7695f2d6 | ||
|
|
38cee87ee9 | ||
|
|
c64a6083e2 | ||
|
|
e0501e46e3 | ||
|
|
4a0ccc4c2f | ||
|
|
c92b7240eb | ||
|
|
6a74c3faeb | ||
|
|
c5ae872787 | ||
|
|
2e9ab0a9d7 | ||
|
|
a004f62fe8 | ||
|
|
07ce20fd29 | ||
|
|
df74f7c6c7 | ||
|
|
2a6e2d470d | ||
|
|
643dd65113 | ||
|
|
cee0532b85 |
2
.git-blame-ignore-revs
Normal file
2
.git-blame-ignore-revs
Normal file
@@ -0,0 +1,2 @@
|
||||
# Black
|
||||
a47bef1f1336fd264d0b175f4421758339a30acb
|
||||
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -28,7 +28,8 @@ We will usually need more information for debugging. Include as much of the foll
|
||||
|
||||
- DCS Liberation save file (the `.liberation` file you save from the DCS Liberation window). By default these are located in your DCS saved games directory (`%USERPROFILE%/Saved Games/DCS`).
|
||||
- The generated mission file (the `.miz` file that you load in DCS to play the turn). By default these are located in your missions directory (`%USERPROFILE%/Saved Games/DCS/Missions`).
|
||||
- A tacview track file, especially when demonstrating an issue with AI behavior. By default these are locaed in your Tacview tracks directory (`%USERPROFILE%/Documents/Tacview`).
|
||||
- A tacview track file, especially when demonstrating an issue with AI behavior. By default these are located in your Tacview tracks directory (`%USERPROFILE%/Documents/Tacview`).
|
||||
- The state.json file from the finished mission when the problem is related to results processing. By default these are located in your Liberation install directory.
|
||||
|
||||
**Version information (please complete the following information):**
|
||||
- DCS Liberation [e.g. 2.3.1]:
|
||||
|
||||
13
.github/workflows/black.yml
vendored
Normal file
13
.github/workflows/black.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: Lint
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: psf/black@stable
|
||||
with:
|
||||
args: ". --check"
|
||||
6
.pre-commit-config.yaml
Normal file
6
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 20.8b1
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3
|
||||
36
changelog.md
36
changelog.md
@@ -1,3 +1,38 @@
|
||||
# 2.5.0
|
||||
|
||||
Saves from 2.4 are not compatible with 2.5.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Engine]** DCS 2.7 Support
|
||||
* **[UI]** Improved FOB menu, added a custom banner, and do not display aircraft recruitment menu
|
||||
* **[Flight Planner]** Added AEW&C missions. (by siKruger)
|
||||
* **[Kneeboard]** Added dark kneeboard option (by GvonH)
|
||||
* **[Campaigns]** Multiple EWR sites may now be generated, and EWR sites may be generated outside bases (by SnappyComebacks)
|
||||
* **[Mission Generation]** Cloudy and rainy (but not thunderstorm) weather will use the cloud presets from DCS 2.7.
|
||||
* **[Plugins]** Added LotATC export plugin (by drsoran)
|
||||
* **[Plugins]** Added Splash Damage Plugin (by Wheelijoe)
|
||||
* **[Loadouts]** Replaced Litening with ATFLIR for all default F/A-18C loadouts.
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[Flight Planner]** Front lines now project threat zones, so TARCAP/escorts will not be pruned for flights near the front. Packages may also route around the front line when practical.
|
||||
* **[Flight Planner]** Fixed error when planning BAI at SAMs with dead subgroups.
|
||||
* **[Flight Planner]** Mig-19 was not allowed for CAS roles fixed
|
||||
* **[Flight Planner]** Increased size of navigation planning area to avoid plannign failures with distant waypoints.
|
||||
* **[Flight Planner]** Fixed UI refresh when unchecking the "default loadout" box in the loadout editor.
|
||||
* **[Objective names]** Fixed typos in objective name : ARMADILLLO -> ARMADILLO (by SnappyComebacks)
|
||||
* **[Payloads]** F-86 Sabre was missing a custom payload
|
||||
* **[Payloads]** Added GAR-8 period restrictions (by Mustang-25)
|
||||
* **[Campaign]** Date now progresses.
|
||||
* **[Campaign]** Added game over message when a coalition runs out of functioning airbases.
|
||||
* **[Mission Generation]** Fixed "invalid face handle" error in kneeboard generation that occurred on some machines.
|
||||
|
||||
## Regressions
|
||||
|
||||
* **[Mod Support]** Stopped support for 2.5.5 Rafale Mode, and removed factions that were using it
|
||||
* **[Mod Support]** Su-57 mod support might be out of date
|
||||
|
||||
# 2.4.3
|
||||
|
||||
## Features/Improvements
|
||||
@@ -8,7 +43,6 @@
|
||||
|
||||
* **[Mods]** Updated C-130J mod data to version 6.4
|
||||
* **[Mods]** Updated F-22A mod to latest version
|
||||
* **[Payload]** Mirage-2000C : Added Eclair counter measures pod to all default loadouts
|
||||
|
||||
# 2.4.2
|
||||
|
||||
|
||||
@@ -2,20 +2,21 @@ from dcs.vehicles import AirDefence
|
||||
|
||||
AAA_UNITS = [
|
||||
AirDefence.SPAAA_Gepard,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.AAA_ZU_23_Closed,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement,
|
||||
AirDefence.AAA_ZU_23_Emplacement,
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.AAA_ZU_23_Insurgent_Closed,
|
||||
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement_Insurgent,
|
||||
AirDefence.SPAAA_ZU_23_2_Insurgent_Mounted_Ural_375,
|
||||
AirDefence.AAA_ZU_23_Insurgent,
|
||||
AirDefence.AAA_8_8cm_Flak_18,
|
||||
AirDefence.AAA_Flak_38,
|
||||
AirDefence.AAA_Flak_38_20mm,
|
||||
AirDefence.AAA_8_8cm_Flak_36,
|
||||
AirDefence.AAA_8_8cm_Flak_37,
|
||||
AirDefence.AAA_Flak_Vierling_38,
|
||||
AirDefence.AAA_Kdo_G_40,
|
||||
AirDefence.AAA_Flak_Vierling_38_Quad_20mm,
|
||||
AirDefence.AAA_SP_Kdo_G_40,
|
||||
AirDefence.AAA_8_8cm_Flak_41,
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
AirDefence.AAA_40mm_Bofors,
|
||||
AirDefence.AAA_S_60_57mm,
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from dcs.ships import (
|
||||
CGN_1144_2_Pyotr_Velikiy,
|
||||
CG_1164_Moskva,
|
||||
Battlecruiser_1144_2_Pyotr_Velikiy,
|
||||
Cruiser_1164_Moskva,
|
||||
CVN_70_Carl_Vinson,
|
||||
CVN_71_Theodore_Roosevelt,
|
||||
CVN_72_Abraham_Lincoln,
|
||||
@@ -8,63 +8,63 @@ from dcs.ships import (
|
||||
CVN_74_John_C__Stennis,
|
||||
CV_1143_5_Admiral_Kuznetsov,
|
||||
CV_1143_5_Admiral_Kuznetsov_2017,
|
||||
FFG_11540_Neustrashimy,
|
||||
FFL_1124_4_Grisha,
|
||||
FF_1135M_Rezky,
|
||||
FSG_1241_1MP_Molniya,
|
||||
Frigate_11540_Neustrashimy,
|
||||
Corvette_1124_4_Grisha,
|
||||
Frigate_1135M_Rezky,
|
||||
Corvette_1241_1_Molniya,
|
||||
LHA_1_Tarawa,
|
||||
Oliver_Hazzard_Perry_class,
|
||||
Ticonderoga_class,
|
||||
FFG_Oliver_Hazzard_Perry,
|
||||
CG_Ticonderoga,
|
||||
Type_052B_Destroyer,
|
||||
Type_052C_Destroyer,
|
||||
Type_054A_Frigate,
|
||||
USS_Arleigh_Burke_IIa,
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
)
|
||||
from dcs.vehicles import AirDefence
|
||||
|
||||
UNITS_WITH_RADAR = [
|
||||
# Radars
|
||||
AirDefence.SAM_SA_15_Tor_9A331,
|
||||
AirDefence.SAM_SA_11_Buk_CC_9S470M1,
|
||||
AirDefence.SAM_Patriot_AMG_AN_MRC_137,
|
||||
AirDefence.SAM_Patriot_ECS_AN_MSQ_104,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_C2,
|
||||
AirDefence.SAM_Patriot_CR__AMG_AN_MRC_137,
|
||||
AirDefence.SAM_Patriot_ECS,
|
||||
AirDefence.SPAAA_Gepard,
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
AirDefence.EWR_1L13,
|
||||
AirDefence.SAM_SA_6_Kub_STR_9S91,
|
||||
AirDefence.SAM_SA_10_S_300PS_TR_30N6,
|
||||
AirDefence.SAM_SA_10_S_300PS_SR_5N66M,
|
||||
AirDefence.SAM_SA_6_Kub_Long_Track_STR,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Flap_Lid_TR,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Clam_Shell_SR,
|
||||
AirDefence.EWR_55G6,
|
||||
AirDefence.SAM_SA_10_S_300PS_SR_64H6E,
|
||||
AirDefence.SAM_SA_11_Buk_SR_9S18M1,
|
||||
AirDefence.CP_9S80M1_Sborka,
|
||||
AirDefence.SAM_Hawk_TR_AN_MPQ_46,
|
||||
AirDefence.SAM_Hawk_SR_AN_MPQ_50,
|
||||
AirDefence.SAM_Patriot_STR_AN_MPQ_53,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Big_Bird_SR,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Snow_Drift_SR,
|
||||
AirDefence.MCC_SR_Sborka_Dog_Ear_SR,
|
||||
AirDefence.SAM_Hawk_TR__AN_MPQ_46,
|
||||
AirDefence.SAM_Hawk_SR__AN_MPQ_50,
|
||||
AirDefence.SAM_Patriot_STR,
|
||||
AirDefence.SAM_Hawk_CWAR_AN_MPQ_55,
|
||||
AirDefence.SAM_SR_P_19,
|
||||
AirDefence.SAM_P19_Flat_Face_SR__SA_2_3,
|
||||
AirDefence.SAM_Roland_EWR,
|
||||
AirDefence.SAM_SA_3_S_125_TR_SNR,
|
||||
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song,
|
||||
AirDefence.SAM_SA_3_S_125_Low_Blow_TR,
|
||||
AirDefence.SAM_SA_2_S_75_Fan_Song_TR,
|
||||
AirDefence.HQ_7_Self_Propelled_STR,
|
||||
# Ships
|
||||
CVN_70_Carl_Vinson,
|
||||
Oliver_Hazzard_Perry_class,
|
||||
Ticonderoga_class,
|
||||
FFL_1124_4_Grisha,
|
||||
FFG_Oliver_Hazzard_Perry,
|
||||
CG_Ticonderoga,
|
||||
Corvette_1124_4_Grisha,
|
||||
CV_1143_5_Admiral_Kuznetsov,
|
||||
FSG_1241_1MP_Molniya,
|
||||
CG_1164_Moskva,
|
||||
FFG_11540_Neustrashimy,
|
||||
CGN_1144_2_Pyotr_Velikiy,
|
||||
FF_1135M_Rezky,
|
||||
Corvette_1241_1_Molniya,
|
||||
Cruiser_1164_Moskva,
|
||||
Frigate_11540_Neustrashimy,
|
||||
Battlecruiser_1144_2_Pyotr_Velikiy,
|
||||
Frigate_1135M_Rezky,
|
||||
CV_1143_5_Admiral_Kuznetsov_2017,
|
||||
CVN_74_John_C__Stennis,
|
||||
CVN_71_Theodore_Roosevelt,
|
||||
CVN_72_Abraham_Lincoln,
|
||||
CVN_73_George_Washington,
|
||||
USS_Arleigh_Burke_IIa,
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
LHA_1_Tarawa,
|
||||
Type_052B_Destroyer,
|
||||
Type_054A_Frigate,
|
||||
|
||||
1081
game/data/weapons.py
1081
game/data/weapons.py
File diff suppressed because it is too large
Load Diff
538
game/db.py
538
game/db.py
@@ -51,7 +51,6 @@ from dcs.planes import (
|
||||
F_117A,
|
||||
F_14A_135_GR,
|
||||
F_14B,
|
||||
F_111F,
|
||||
F_15C,
|
||||
F_15E,
|
||||
F_16A,
|
||||
@@ -116,8 +115,8 @@ from dcs.planes import (
|
||||
I_16,
|
||||
)
|
||||
from dcs.ships import (
|
||||
Armed_speedboat,
|
||||
Bulk_cargo_ship_Yakushev,
|
||||
Boat_Armed_Hi_speed,
|
||||
Bulker_Yakushev,
|
||||
CVN_71_Theodore_Roosevelt,
|
||||
CVN_72_Abraham_Lincoln,
|
||||
CVN_73_George_Washington,
|
||||
@@ -125,7 +124,7 @@ from dcs.ships import (
|
||||
CVN_75_Harry_S__Truman,
|
||||
CV_1143_5_Admiral_Kuznetsov,
|
||||
CV_1143_5_Admiral_Kuznetsov_2017,
|
||||
Dry_cargo_ship_Ivanov,
|
||||
Cargo_Ivanov,
|
||||
LHA_1_Tarawa,
|
||||
Tanker_Elnya_160,
|
||||
ship_map,
|
||||
@@ -174,7 +173,6 @@ from pydcs_extensions.a4ec.a4ec import A_4E_C
|
||||
from pydcs_extensions.f22a.f22a import F_22A
|
||||
from pydcs_extensions.hercules.hercules import Hercules
|
||||
from pydcs_extensions.mb339.mb339 import MB_339PAN
|
||||
from pydcs_extensions.rafale.rafale import Rafale_A_S, Rafale_M, Rafale_B
|
||||
from pydcs_extensions.su57.su57 import Su_57
|
||||
|
||||
UNITINFOTEXT_PATH = Path("./resources/units/unit_info_text.json")
|
||||
@@ -182,9 +180,6 @@ UNITINFOTEXT_PATH = Path("./resources/units/unit_info_text.json")
|
||||
plane_map["A-4E-C"] = A_4E_C
|
||||
plane_map["F-22A"] = F_22A
|
||||
plane_map["MB-339PAN"] = MB_339PAN
|
||||
plane_map["Rafale_M"] = Rafale_M
|
||||
plane_map["Rafale_A_S"] = Rafale_A_S
|
||||
plane_map["Rafale_B"] = Rafale_B
|
||||
plane_map["Su-57"] = Su_57
|
||||
plane_map["Hercules"] = Hercules
|
||||
|
||||
@@ -360,7 +355,7 @@ x_map = {
|
||||
}
|
||||
|
||||
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`
|
||||
For example, player accessible Hornet is called `FA_18C_hornet`, and MANPAD Igla is called `AirDefence.MANPADS_SA_18_Igla_S_Grouse`
|
||||
"""
|
||||
|
||||
# This should probably be much higher, but the AI doesn't rollover their budget
|
||||
@@ -453,7 +448,6 @@ PRICES = {
|
||||
Tu_160: 50,
|
||||
Tu_22M3: 40,
|
||||
Tu_95MS: 35,
|
||||
F_111F: 21,
|
||||
# special
|
||||
IL_76MD: 30,
|
||||
An_26B: 25,
|
||||
@@ -481,15 +475,11 @@ PRICES = {
|
||||
MQ_9_Reaper: 12,
|
||||
RQ_1A_Predator: 6,
|
||||
WingLoong_I: 6,
|
||||
# Modded
|
||||
Rafale_M: 26,
|
||||
Rafale_A_S: 26,
|
||||
Rafale_B: 26,
|
||||
# armor
|
||||
Armor.APC_MTLB: 4,
|
||||
Armor.FDDM_Grad: 4,
|
||||
Armor.ARV_BRDM_2: 6,
|
||||
Armor.ARV_BTR_RD: 6,
|
||||
Artillery.Grad_MRL_FDDM__FC: 4,
|
||||
Armor.IFV_BRDM_2: 6,
|
||||
Armor.APC_BTR_RD: 6,
|
||||
Armor.APC_BTR_80: 8,
|
||||
Armor.APC_BTR_82A: 10,
|
||||
Armor.MBT_T_55: 18,
|
||||
@@ -503,147 +493,149 @@ PRICES = {
|
||||
Armor.IFV_BMP_3: 18,
|
||||
Armor.ZBD_04A: 12,
|
||||
Armor.ZTZ_96B: 30,
|
||||
Armor.APC_Cobra: 4,
|
||||
Armor.APC_Cobra__Scout: 4,
|
||||
Armor.APC_M113: 6,
|
||||
Armor.APC_M1043_HMMWV_Armament: 2,
|
||||
Armor.ATGM_M1045_HMMWV_TOW: 8,
|
||||
Armor.APC_HMMWV__Scout: 2,
|
||||
Armor.ATGM_HMMWV: 8,
|
||||
Armor.IFV_M2A2_Bradley: 12,
|
||||
Armor.APC_M1126_Stryker_ICV: 10,
|
||||
Armor.SPG_M1128_Stryker_MGS: 14,
|
||||
Armor.ATGM_M1134_Stryker: 12,
|
||||
Armor.IFV_M1126_Stryker_ICV: 10,
|
||||
Armor.SPG_Stryker_MGS: 14,
|
||||
Armor.ATGM_Stryker: 12,
|
||||
Armor.MBT_M60A3_Patton: 16,
|
||||
Armor.MBT_M1A2_Abrams: 25,
|
||||
Armor.MBT_Leclerc: 25,
|
||||
Armor.MBT_Leopard_1A3: 20,
|
||||
Armor.MBT_Leopard_2: 25,
|
||||
Armor.MBT_Merkava_Mk__4: 25,
|
||||
Armor.TPz_Fuchs: 5,
|
||||
Armor.MBT_Merkava_IV: 25,
|
||||
Armor.APC_TPz_Fuchs: 5,
|
||||
Armor.MBT_Challenger_II: 25,
|
||||
Armor.IFV_Marder: 10,
|
||||
Armor.IFV_MCV_80: 10,
|
||||
Armor.IFV_Warrior: 10,
|
||||
Armor.IFV_LAV_25: 7,
|
||||
Artillery.MLRS_M270: 55,
|
||||
Artillery.SPH_M109_Paladin: 25,
|
||||
Artillery.SPH_2S9_Nona: 12,
|
||||
Artillery.SPH_2S1_Gvozdika: 18,
|
||||
Artillery.SPH_2S3_Akatsia: 24,
|
||||
Artillery.SPH_2S19_Msta: 30,
|
||||
Artillery.MLRS_BM_21_Grad: 15,
|
||||
Artillery.MLRS_9K57_Uragan_BM_27: 50,
|
||||
Artillery.MLRS_9A52_Smerch: 40,
|
||||
Artillery._2B11_mortar: 4,
|
||||
Artillery.SpGH_Dana: 26,
|
||||
Unarmed.Transport_UAZ_469: 3,
|
||||
Unarmed.Transport_Ural_375: 3,
|
||||
Artillery.MLRS_M270_227mm: 55,
|
||||
Artillery.SPH_M109_Paladin_155mm: 25,
|
||||
Artillery.SPH_2S9_Nona_120mm_M: 12,
|
||||
Artillery.SPH_2S1_Gvozdika_122mm: 18,
|
||||
Artillery.SPH_2S3_Akatsia_152mm: 24,
|
||||
Artillery.SPH_2S19_Msta_152mm: 30,
|
||||
Artillery.MLRS_BM_21_Grad_122mm: 15,
|
||||
Artillery.MLRS_BM_27_Uragan_220mm: 50,
|
||||
Artillery.MLRS_9A52_Smerch_HE_300mm: 40,
|
||||
Artillery.Mortar_2B11_120mm: 4,
|
||||
Artillery.SPH_Dana_vz77_152mm: 26,
|
||||
Artillery.PLZ_05: 25,
|
||||
Unarmed.LUV_UAZ_469_Jeep: 3,
|
||||
Unarmed.Truck_Ural_375: 3,
|
||||
Infantry.Infantry_M4: 1,
|
||||
Infantry.Soldier_AK: 1,
|
||||
Unarmed.Transport_M818: 3,
|
||||
Infantry.Infantry_AK_74: 1,
|
||||
Unarmed.Truck_M818_6x6: 3,
|
||||
# WW2
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G: 24,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H: 16,
|
||||
Armor.MT_PzIV_H: 16,
|
||||
Armor.HT_Pz_Kpfw_VI_Tiger_I: 24,
|
||||
Armor.HT_Pz_Kpfw_VI_Ausf__B_Tiger_II: 26,
|
||||
Armor.TD_Jagdpanther_G1: 18,
|
||||
Armor.TD_Jagdpanzer_IV: 11,
|
||||
Armor.Sd_Kfz_184_Elefant: 18,
|
||||
Armor.APC_Sd_Kfz_251: 4,
|
||||
Armor.AC_Sd_Kfz_234_2_Puma: 8,
|
||||
Armor.SPG_Jagdpanther_G1: 18,
|
||||
Armor.SPG_Jagdpanzer_IV: 11,
|
||||
Armor.SPG_Sd_Kfz_184_Elefant: 18,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack: 4,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma: 8,
|
||||
Armor.MT_M4_Sherman: 12,
|
||||
Armor.MT_M4A4_Sherman_Firefly: 16,
|
||||
Armor.CT_Cromwell_IV: 12,
|
||||
Armor.M30_Cargo_Carrier: 2,
|
||||
Armor.APC_M2A1: 4,
|
||||
Unarmed.Carrier_M30_Cargo: 2,
|
||||
Armor.APC_M2A1_Halftrack: 4,
|
||||
Armor.CT_Centaur_IV: 10,
|
||||
Armor.HIT_Churchill_VII: 16,
|
||||
Armor.LAC_M8_Greyhound: 8,
|
||||
Armor.TD_M10_GMC: 14,
|
||||
Armor.StuG_III_Ausf__G: 12,
|
||||
Armor.StuG_IV: 14,
|
||||
Artillery.M12_GMC: 10,
|
||||
Artillery.Sturmpanzer_IV_Brummbär: 10,
|
||||
Armor.Daimler_Armoured_Car: 8,
|
||||
Armor.Car_M8_Greyhound_Armored: 8,
|
||||
Armor.SPG_M10_GMC: 14,
|
||||
Armor.SPG_StuG_III_Ausf__G: 12,
|
||||
Armor.SPG_StuG_IV: 14,
|
||||
Artillery.SPG_M12_GMC_155mm: 10,
|
||||
Artillery.SPG_Sturmpanzer_IV_Brummbar: 10,
|
||||
Armor.Car_Daimler_Armored: 8,
|
||||
Armor.LT_Mk_VII_Tetrarch: 8,
|
||||
Armor.M4_Tractor: 2,
|
||||
Unarmed.Tractor_M4_Hi_Speed: 2,
|
||||
# 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,
|
||||
Bulker_Yakushev: 10,
|
||||
Boat_Armed_Hi_speed: 10,
|
||||
Cargo_Ivanov: 10,
|
||||
Tanker_Elnya_160: 10,
|
||||
# Air Defence units
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6: 30,
|
||||
AirDefence.SAM_SA_6_Kub_LN_2P25: 20,
|
||||
AirDefence.SAM_SA_3_S_125_LN_5P73: 6,
|
||||
AirDefence.SAM_SA_11_Buk_LN_9A310M1: 30,
|
||||
AirDefence.SAM_SA_11_Buk_CC_9S470M1: 25,
|
||||
AirDefence.SAM_SA_11_Buk_SR_9S18M1: 28,
|
||||
AirDefence.SAM_SA_8_Osa_9A33: 28,
|
||||
AirDefence.SAM_SA_15_Tor_9A331: 40,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_9A35M3: 16,
|
||||
AirDefence.SAM_SA_9_Strela_1_9P31: 12,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison: 30,
|
||||
AirDefence.SAM_SA_6_Kub_Gainful_TEL: 20,
|
||||
AirDefence.SAM_SA_3_S_125_Goa_LN: 6,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Fire_Dome_TEL: 30,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_C2: 25,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Snow_Drift_SR: 28,
|
||||
AirDefence.SAM_SA_8_Osa_Gecko_TEL: 28,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet: 40,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_Gopher_TEL: 16,
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL: 12,
|
||||
AirDefence.SAM_SA_8_Osa_LD_9T217: 22,
|
||||
AirDefence.SAM_Patriot_AMG_AN_MRC_137: 35,
|
||||
AirDefence.SAM_Patriot_ECS_AN_MSQ_104: 30,
|
||||
AirDefence.SAM_Patriot_CR__AMG_AN_MRC_137: 35,
|
||||
AirDefence.SAM_Patriot_ECS: 30,
|
||||
AirDefence.SPAAA_Gepard: 24,
|
||||
AirDefence.SAM_Hawk_PCP: 14,
|
||||
AirDefence.AAA_Vulcan_M163: 10,
|
||||
AirDefence.SAM_Hawk_Generator__PCP: 14,
|
||||
AirDefence.SPAAA_Vulcan_M163: 10,
|
||||
AirDefence.SAM_Hawk_LN_M192: 8,
|
||||
AirDefence.SAM_Chaparral_M48: 16,
|
||||
AirDefence.SAM_Linebacker_M6: 18,
|
||||
AirDefence.SAM_Patriot_LN_M901: 15,
|
||||
AirDefence.SAM_Avenger_M1097: 20,
|
||||
AirDefence.SAM_Linebacker___Bradley_M6: 18,
|
||||
AirDefence.SAM_Patriot_LN: 15,
|
||||
AirDefence.SAM_Avenger__Stinger: 20,
|
||||
AirDefence.SAM_Patriot_EPP_III: 15,
|
||||
AirDefence.SAM_Patriot_ICC: 18,
|
||||
AirDefence.SAM_Patriot_C2_ICC: 18,
|
||||
AirDefence.SAM_Roland_ADS: 12,
|
||||
AirDefence.Stinger_MANPADS: 6,
|
||||
AirDefence.SAM_Stinger_comm_dsr: 4,
|
||||
AirDefence.SAM_Stinger_comm: 4,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka: 10,
|
||||
AirDefence.AAA_ZSU_57_2: 12,
|
||||
AirDefence.AAA_ZU_23_Closed: 6,
|
||||
AirDefence.MANPADS_Stinger: 6,
|
||||
AirDefence.MANPADS_Stinger_C2_Desert: 4,
|
||||
AirDefence.MANPADS_Stinger_C2: 4,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish: 10,
|
||||
AirDefence.SPAAA_ZSU_57_2: 12,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement: 6,
|
||||
AirDefence.AAA_ZU_23_Emplacement: 6,
|
||||
AirDefence.AAA_ZU_23_on_Ural_375: 7,
|
||||
AirDefence.AAA_ZU_23_Insurgent_Closed: 6,
|
||||
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375: 7,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375: 7,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement_Insurgent: 6,
|
||||
AirDefence.SPAAA_ZU_23_2_Insurgent_Mounted_Ural_375: 7,
|
||||
AirDefence.AAA_ZU_23_Insurgent: 6,
|
||||
AirDefence.SAM_SA_18_Igla_MANPADS: 10,
|
||||
AirDefence.SAM_SA_18_Igla_comm: 8,
|
||||
AirDefence.SAM_SA_18_Igla_S_MANPADS: 12,
|
||||
AirDefence.SAM_SA_18_Igla_S_comm: 8,
|
||||
AirDefence.MANPADS_SA_18_Igla_Grouse: 10,
|
||||
AirDefence.MANPADS_SA_18_Igla_Grouse_C2: 8,
|
||||
AirDefence.MANPADS_SA_18_Igla_S_Grouse: 12,
|
||||
AirDefence.MANPADS_SA_18_Igla_S_Grouse_C2: 8,
|
||||
AirDefence.EWR_1L13: 30,
|
||||
AirDefence.SAM_SA_6_Kub_STR_9S91: 22,
|
||||
AirDefence.SAM_SA_6_Kub_Long_Track_STR: 22,
|
||||
AirDefence.EWR_55G6: 30,
|
||||
AirDefence.CP_9S80M1_Sborka: 10,
|
||||
AirDefence.SAM_Hawk_TR_AN_MPQ_46: 14,
|
||||
AirDefence.SAM_Hawk_SR_AN_MPQ_50: 18,
|
||||
AirDefence.SAM_Patriot_STR_AN_MPQ_53: 22,
|
||||
AirDefence.MCC_SR_Sborka_Dog_Ear_SR: 10,
|
||||
AirDefence.SAM_Hawk_TR__AN_MPQ_46: 14,
|
||||
AirDefence.SAM_Hawk_SR__AN_MPQ_50: 18,
|
||||
AirDefence.SAM_Patriot_STR: 22,
|
||||
AirDefence.SAM_Hawk_CWAR_AN_MPQ_55: 20,
|
||||
AirDefence.SAM_SR_P_19: 14,
|
||||
AirDefence.SAM_P19_Flat_Face_SR__SA_2_3: 14,
|
||||
AirDefence.SAM_Roland_EWR: 16,
|
||||
AirDefence.SAM_SA_3_S_125_TR_SNR: 14,
|
||||
AirDefence.SAM_SA_2_LN_SM_90: 8,
|
||||
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song: 12,
|
||||
AirDefence.Rapier_FSA_Launcher: 6,
|
||||
AirDefence.Rapier_FSA_Optical_Tracker: 6,
|
||||
AirDefence.Rapier_FSA_Blindfire_Tracker: 8,
|
||||
AirDefence.SAM_SA_3_S_125_Low_Blow_TR: 14,
|
||||
AirDefence.SAM_SA_2_S_75_Guideline_LN: 8,
|
||||
AirDefence.SAM_SA_2_S_75_Fan_Song_TR: 12,
|
||||
AirDefence.SAM_Rapier_LN: 6,
|
||||
AirDefence.SAM_Rapier_Tracker: 6,
|
||||
AirDefence.SAM_Rapier_Blindfire_TR: 8,
|
||||
AirDefence.HQ_7_Self_Propelled_LN: 20,
|
||||
AirDefence.HQ_7_Self_Propelled_STR: 24,
|
||||
AirDefence.AAA_8_8cm_Flak_18: 6,
|
||||
AirDefence.AAA_Flak_38: 6,
|
||||
AirDefence.AAA_Flak_38_20mm: 6,
|
||||
AirDefence.AAA_8_8cm_Flak_36: 8,
|
||||
AirDefence.AAA_8_8cm_Flak_37: 9,
|
||||
AirDefence.AAA_Flak_Vierling_38: 5,
|
||||
AirDefence.AAA_Kdo_G_40: 8,
|
||||
AirDefence.Flak_Searchlight_37: 4,
|
||||
AirDefence.Maschinensatz_33: 10,
|
||||
AirDefence.AAA_Flak_Vierling_38_Quad_20mm: 5,
|
||||
AirDefence.AAA_SP_Kdo_G_40: 8,
|
||||
AirDefence.SL_Flakscheinwerfer_37: 4,
|
||||
AirDefence.PU_Maschinensatz_33: 10,
|
||||
AirDefence.AAA_8_8cm_Flak_41: 10,
|
||||
AirDefence.EWR_FuMG_401_Freya_LZ: 25,
|
||||
AirDefence.AAA_Bofors_40mm: 8,
|
||||
AirDefence.AAA_40mm_Bofors: 8,
|
||||
AirDefence.AAA_S_60_57mm: 8,
|
||||
AirDefence.AAA_M1_37mm: 7,
|
||||
AirDefence.AAA_M45_Quadmount: 4,
|
||||
AirDefence.AA_gun_QF_3_7: 10,
|
||||
AirDefence.AAA_M45_Quadmount_HB_12_7mm: 4,
|
||||
AirDefence.AAA_QF_3_7: 10,
|
||||
# FRENCH PACK MOD
|
||||
frenchpack.AMX_10RCR: 10,
|
||||
frenchpack.AMX_10RCR_SEPAR: 12,
|
||||
@@ -674,12 +666,12 @@ PRICES = {
|
||||
frenchpack.DIM__TOYOTA_DESERT: 2,
|
||||
frenchpack.DIM__KAMIKAZE: 6,
|
||||
# SA-10
|
||||
AirDefence.SAM_SA_10_S_300PS_CP_54K6: 18,
|
||||
AirDefence.SAM_SA_10_S_300PS_TR_30N6: 24,
|
||||
AirDefence.SAM_SA_10_S_300PS_SR_5N66M: 30,
|
||||
AirDefence.SAM_SA_10_S_300PS_SR_64H6E: 30,
|
||||
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 22,
|
||||
AirDefence.SAM_SA_10_S_300PS_LN_5P85D: 22,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_C2: 18,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Flap_Lid_TR: 24,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Clam_Shell_SR: 30,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Big_Bird_SR: 30,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_TEL_C: 22,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_TEL_D: 22,
|
||||
# High digit sams mod
|
||||
highdigitsams.AAA_SON_9_Fire_Can: 8,
|
||||
highdigitsams.AAA_100mm_KS_19: 10,
|
||||
@@ -772,7 +764,6 @@ UNIT_BY_TASK = {
|
||||
SpitfireLFMkIXCW,
|
||||
SpitfireLFMkIX,
|
||||
A_4E_C,
|
||||
Rafale_M,
|
||||
SA342Mistral,
|
||||
],
|
||||
CAS: [
|
||||
@@ -786,7 +777,6 @@ UNIT_BY_TASK = {
|
||||
A_10C_2,
|
||||
A_20G,
|
||||
B_17G,
|
||||
F_111F,
|
||||
B_1B,
|
||||
B_52H,
|
||||
F_117A,
|
||||
@@ -807,8 +797,6 @@ UNIT_BY_TASK = {
|
||||
P_47D_30bl1,
|
||||
P_47D_40,
|
||||
RQ_1A_Predator,
|
||||
Rafale_A_S,
|
||||
Rafale_B,
|
||||
S_3B,
|
||||
SA342L,
|
||||
SA342M,
|
||||
@@ -844,18 +832,18 @@ UNIT_BY_TASK = {
|
||||
Armor.APC_MTLB,
|
||||
Armor.APC_MTLB,
|
||||
Armor.APC_MTLB,
|
||||
Armor.FDDM_Grad,
|
||||
Armor.FDDM_Grad,
|
||||
Armor.FDDM_Grad,
|
||||
Armor.FDDM_Grad,
|
||||
Armor.FDDM_Grad,
|
||||
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,
|
||||
Artillery.Grad_MRL_FDDM__FC,
|
||||
Artillery.Grad_MRL_FDDM__FC,
|
||||
Artillery.Grad_MRL_FDDM__FC,
|
||||
Artillery.Grad_MRL_FDDM__FC,
|
||||
Artillery.Grad_MRL_FDDM__FC,
|
||||
Armor.IFV_BRDM_2,
|
||||
Armor.IFV_BRDM_2,
|
||||
Armor.IFV_BRDM_2,
|
||||
Armor.APC_BTR_RD,
|
||||
Armor.APC_BTR_RD,
|
||||
Armor.APC_BTR_RD,
|
||||
Armor.APC_BTR_RD,
|
||||
Armor.APC_BTR_80,
|
||||
Armor.APC_BTR_80,
|
||||
Armor.APC_BTR_80,
|
||||
@@ -885,33 +873,33 @@ UNIT_BY_TASK = {
|
||||
Armor.MBT_T_80U,
|
||||
Armor.MBT_T_90,
|
||||
Armor.ZTZ_96B,
|
||||
Armor.APC_Cobra,
|
||||
Armor.APC_Cobra,
|
||||
Armor.APC_Cobra,
|
||||
Armor.APC_Cobra,
|
||||
Armor.APC_Cobra__Scout,
|
||||
Armor.APC_Cobra__Scout,
|
||||
Armor.APC_Cobra__Scout,
|
||||
Armor.APC_Cobra__Scout,
|
||||
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.APC_TPz_Fuchs,
|
||||
Armor.APC_TPz_Fuchs,
|
||||
Armor.APC_TPz_Fuchs,
|
||||
Armor.APC_TPz_Fuchs,
|
||||
Armor.ATGM_HMMWV,
|
||||
Armor.ATGM_HMMWV,
|
||||
Armor.APC_HMMWV__Scout,
|
||||
Armor.APC_HMMWV__Scout,
|
||||
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.SPG_M1128_Stryker_MGS,
|
||||
Armor.IFV_MCV_80,
|
||||
Armor.IFV_MCV_80,
|
||||
Armor.IFV_MCV_80,
|
||||
Armor.ATGM_Stryker,
|
||||
Armor.ATGM_Stryker,
|
||||
Armor.IFV_M1126_Stryker_ICV,
|
||||
Armor.IFV_M1126_Stryker_ICV,
|
||||
Armor.IFV_M1126_Stryker_ICV,
|
||||
Armor.SPG_Stryker_MGS,
|
||||
Armor.IFV_Warrior,
|
||||
Armor.IFV_Warrior,
|
||||
Armor.IFV_Warrior,
|
||||
Armor.IFV_LAV_25,
|
||||
Armor.IFV_LAV_25,
|
||||
Armor.IFV_Marder,
|
||||
@@ -927,92 +915,94 @@ UNIT_BY_TASK = {
|
||||
Armor.MBT_Leclerc,
|
||||
Armor.MBT_Leopard_2,
|
||||
Armor.MBT_Challenger_II,
|
||||
Armor.MBT_Merkava_Mk__4,
|
||||
Armor.MBT_Merkava_IV,
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H,
|
||||
Armor.MT_PzIV_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.AC_Sd_Kfz_234_2_Puma,
|
||||
Armor.AC_Sd_Kfz_234_2_Puma,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma,
|
||||
Armor.MT_M4_Sherman,
|
||||
Armor.MT_M4A4_Sherman_Firefly,
|
||||
Armor.CT_Cromwell_IV,
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_M2A1,
|
||||
Unarmed.Carrier_M30_Cargo,
|
||||
Unarmed.Carrier_M30_Cargo,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H,
|
||||
Armor.MT_PzIV_H,
|
||||
Armor.HT_Pz_Kpfw_VI_Tiger_I,
|
||||
Armor.HT_Pz_Kpfw_VI_Ausf__B_Tiger_II,
|
||||
Armor.TD_Jagdpanther_G1,
|
||||
Armor.TD_Jagdpanzer_IV,
|
||||
Armor.Sd_Kfz_184_Elefant,
|
||||
Armor.APC_Sd_Kfz_251,
|
||||
Armor.AC_Sd_Kfz_234_2_Puma,
|
||||
Armor.SPG_Jagdpanther_G1,
|
||||
Armor.SPG_Jagdpanzer_IV,
|
||||
Armor.SPG_Sd_Kfz_184_Elefant,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma,
|
||||
Armor.MT_M4_Sherman,
|
||||
Armor.MT_M4A4_Sherman_Firefly,
|
||||
Armor.CT_Cromwell_IV,
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_M2A1,
|
||||
Unarmed.Carrier_M30_Cargo,
|
||||
Unarmed.Carrier_M30_Cargo,
|
||||
Unarmed.Carrier_M30_Cargo,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.CT_Centaur_IV,
|
||||
Armor.CT_Centaur_IV,
|
||||
Armor.HIT_Churchill_VII,
|
||||
Armor.LAC_M8_Greyhound,
|
||||
Armor.LAC_M8_Greyhound,
|
||||
Armor.TD_M10_GMC,
|
||||
Armor.TD_M10_GMC,
|
||||
Armor.StuG_III_Ausf__G,
|
||||
Armor.StuG_IV,
|
||||
Artillery.M12_GMC,
|
||||
Artillery.Sturmpanzer_IV_Brummbär,
|
||||
Armor.Daimler_Armoured_Car,
|
||||
Armor.Car_M8_Greyhound_Armored,
|
||||
Armor.Car_M8_Greyhound_Armored,
|
||||
Armor.SPG_M10_GMC,
|
||||
Armor.SPG_M10_GMC,
|
||||
Armor.SPG_StuG_III_Ausf__G,
|
||||
Armor.SPG_StuG_IV,
|
||||
Artillery.SPG_M12_GMC_155mm,
|
||||
Artillery.SPG_Sturmpanzer_IV_Brummbar,
|
||||
Armor.Car_Daimler_Armored,
|
||||
Armor.LT_Mk_VII_Tetrarch,
|
||||
Artillery.MLRS_M270,
|
||||
Artillery.SPH_M109_Paladin,
|
||||
Artillery.SPH_2S9_Nona,
|
||||
Artillery.SPH_2S1_Gvozdika,
|
||||
Artillery.SPH_2S3_Akatsia,
|
||||
Artillery.SPH_2S19_Msta,
|
||||
Artillery.MLRS_BM_21_Grad,
|
||||
Artillery.MLRS_BM_21_Grad,
|
||||
Artillery.MLRS_9K57_Uragan_BM_27,
|
||||
Artillery.MLRS_9A52_Smerch,
|
||||
Artillery.SpGH_Dana,
|
||||
Artillery.M12_GMC,
|
||||
Artillery.Sturmpanzer_IV_Brummbär,
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375,
|
||||
AirDefence.AAA_ZSU_57_2,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
||||
AirDefence.SAM_SA_8_Osa_9A33,
|
||||
AirDefence.SAM_SA_9_Strela_1_9P31,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_9A35M3,
|
||||
AirDefence.SAM_SA_15_Tor_9A331,
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||
Artillery.MLRS_M270_227mm,
|
||||
Artillery.SPH_M109_Paladin_155mm,
|
||||
Artillery.SPH_2S9_Nona_120mm_M,
|
||||
Artillery.SPH_2S1_Gvozdika_122mm,
|
||||
Artillery.SPH_2S3_Akatsia_152mm,
|
||||
Artillery.SPH_2S19_Msta_152mm,
|
||||
Artillery.MLRS_BM_21_Grad_122mm,
|
||||
Artillery.MLRS_BM_21_Grad_122mm,
|
||||
Artillery.MLRS_BM_27_Uragan_220mm,
|
||||
Artillery.MLRS_9A52_Smerch_HE_300mm,
|
||||
Artillery.SPH_Dana_vz77_152mm,
|
||||
Artillery.PLZ_05,
|
||||
Artillery.SPG_M12_GMC_155mm,
|
||||
Artillery.SPG_Sturmpanzer_IV_Brummbar,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375,
|
||||
AirDefence.SPAAA_ZU_23_2_Insurgent_Mounted_Ural_375,
|
||||
AirDefence.SPAAA_ZSU_57_2,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
AirDefence.SAM_SA_8_Osa_Gecko_TEL,
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_Gopher_TEL,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison,
|
||||
AirDefence.SPAAA_Gepard,
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SAM_Linebacker_M6,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
AirDefence.SAM_Linebacker___Bradley_M6,
|
||||
AirDefence.SAM_Chaparral_M48,
|
||||
AirDefence.SAM_Avenger_M1097,
|
||||
AirDefence.SAM_Avenger__Stinger,
|
||||
AirDefence.SAM_Roland_ADS,
|
||||
AirDefence.HQ_7_Self_Propelled_LN,
|
||||
AirDefence.AAA_8_8cm_Flak_18,
|
||||
AirDefence.AAA_8_8cm_Flak_36,
|
||||
AirDefence.AAA_8_8cm_Flak_37,
|
||||
AirDefence.AAA_8_8cm_Flak_41,
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
AirDefence.AAA_40mm_Bofors,
|
||||
AirDefence.AAA_S_60_57mm,
|
||||
AirDefence.AAA_M1_37mm,
|
||||
AirDefence.AA_gun_QF_3_7,
|
||||
AirDefence.AAA_QF_3_7,
|
||||
frenchpack.DIM__TOYOTA_BLUE,
|
||||
frenchpack.DIM__TOYOTA_DESERT,
|
||||
frenchpack.DIM__TOYOTA_GREEN,
|
||||
@@ -1037,13 +1027,13 @@ UNIT_BY_TASK = {
|
||||
],
|
||||
AirDefence: [],
|
||||
Reconnaissance: [
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Transport_Ural_375,
|
||||
Unarmed.Transport_UAZ_469,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
Unarmed.Truck_Ural_375,
|
||||
Unarmed.LUV_UAZ_469_Jeep,
|
||||
],
|
||||
Nothing: [
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Soldier_AK,
|
||||
Infantry.Infantry_AK_74,
|
||||
],
|
||||
Embarking: [],
|
||||
Carriage: [
|
||||
@@ -1052,10 +1042,10 @@ UNIT_BY_TASK = {
|
||||
CV_1143_5_Admiral_Kuznetsov,
|
||||
],
|
||||
CargoTransportation: [
|
||||
Dry_cargo_ship_Ivanov,
|
||||
Bulk_cargo_ship_Yakushev,
|
||||
Cargo_Ivanov,
|
||||
Bulker_Yakushev,
|
||||
Tanker_Elnya_160,
|
||||
Armed_speedboat,
|
||||
Boat_Armed_Hi_speed,
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1063,41 +1053,41 @@ UNIT_BY_TASK = {
|
||||
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,
|
||||
AirDefence.SAM_Linebacker___Bradley_M6,
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL,
|
||||
AirDefence.SAM_SA_8_Osa_Gecko_TEL,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison,
|
||||
AirDefence.SAM_SA_6_Kub_Gainful_TEL,
|
||||
AirDefence.SAM_SA_8_Osa_Gecko_TEL,
|
||||
AirDefence.SAM_SA_3_S_125_Goa_LN,
|
||||
AirDefence.SAM_Hawk_Generator__PCP,
|
||||
AirDefence.SAM_SA_2_S_75_Guideline_LN,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Fire_Dome_TEL,
|
||||
]
|
||||
|
||||
"""
|
||||
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,
|
||||
AirDefence.SAM_P19_Flat_Face_SR__SA_2_3: AirDefence.SAM_SA_3_S_125_Goa_LN,
|
||||
AirDefence.SAM_SA_3_S_125_Low_Blow_TR: AirDefence.SAM_SA_3_S_125_Goa_LN,
|
||||
AirDefence.SAM_SA_3_S_125_Goa_LN: AirDefence.SAM_SA_3_S_125_Goa_LN,
|
||||
AirDefence.SAM_SA_6_Kub_Gainful_TEL: AirDefence.SAM_SA_6_Kub_Gainful_TEL,
|
||||
AirDefence.SAM_SA_6_Kub_Long_Track_STR: AirDefence.SAM_SA_6_Kub_Gainful_TEL,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_TEL_C: AirDefence.SAM_SA_10_S_300_Grumble_TEL_C,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Clam_Shell_SR: AirDefence.SAM_SA_10_S_300_Grumble_TEL_C,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Flap_Lid_TR: AirDefence.SAM_SA_10_S_300_Grumble_TEL_C,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_C2: AirDefence.SAM_SA_10_S_300_Grumble_TEL_C,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Big_Bird_SR: AirDefence.SAM_SA_10_S_300_Grumble_C2,
|
||||
AirDefence.SAM_Hawk_TR__AN_MPQ_46: AirDefence.SAM_Hawk_Generator__PCP,
|
||||
AirDefence.SAM_Hawk_SR__AN_MPQ_50: AirDefence.SAM_Hawk_Generator__PCP,
|
||||
AirDefence.SAM_Hawk_LN_M192: AirDefence.SAM_Hawk_Generator__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,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_Flap_Lid_TR: AirDefence.SAM_SA_10_S_300_Grumble_C2,
|
||||
AirDefence.SAM_P19_Flat_Face_SR__SA_2_3: AirDefence.SAM_SA_2_S_75_Guideline_LN,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1158,6 +1148,7 @@ COMMON_OVERRIDE = {
|
||||
Escort: "CAP",
|
||||
RunwayAttack: "RUNWAY_ATTACK",
|
||||
FighterSweep: "CAP",
|
||||
AWACS: "AEW&C",
|
||||
}
|
||||
|
||||
"""
|
||||
@@ -1226,7 +1217,6 @@ PLANE_PAYLOAD_OVERRIDES: Dict[Type[PlaneType], Dict[Type[Task], str]] = {
|
||||
F_14A_135_GR: COMMON_OVERRIDE,
|
||||
F_14B: COMMON_OVERRIDE,
|
||||
F_15C: COMMON_OVERRIDE,
|
||||
F_111F: COMMON_OVERRIDE,
|
||||
F_22A: COMMON_OVERRIDE,
|
||||
F_16C_50: COMMON_OVERRIDE,
|
||||
JF_17: COMMON_OVERRIDE,
|
||||
@@ -1279,9 +1269,6 @@ PLANE_PAYLOAD_OVERRIDES: Dict[Type[PlaneType], Dict[Type[Task], str]] = {
|
||||
A_20G: COMMON_OVERRIDE,
|
||||
A_4E_C: COMMON_OVERRIDE,
|
||||
MB_339PAN: COMMON_OVERRIDE,
|
||||
Rafale_M: COMMON_OVERRIDE,
|
||||
Rafale_A_S: COMMON_OVERRIDE,
|
||||
Rafale_B: COMMON_OVERRIDE,
|
||||
OH_58D: COMMON_OVERRIDE,
|
||||
F_16A: COMMON_OVERRIDE,
|
||||
MQ_9_Reaper: COMMON_OVERRIDE,
|
||||
@@ -1292,6 +1279,7 @@ PLANE_PAYLOAD_OVERRIDES: Dict[Type[PlaneType], Dict[Type[Task], str]] = {
|
||||
AH_64A: COMMON_OVERRIDE,
|
||||
SH_60B: COMMON_OVERRIDE,
|
||||
Hercules: COMMON_OVERRIDE,
|
||||
F_86F_Sabre: COMMON_OVERRIDE,
|
||||
Su_25TM: {
|
||||
SEAD: "Kh-31P*2_Kh-25ML*4_R-73*2_L-081_MPS410",
|
||||
},
|
||||
@@ -1375,8 +1363,8 @@ CARRIER_CAPABLE = [
|
||||
AV8BNA,
|
||||
Su_33,
|
||||
A_4E_C,
|
||||
Rafale_M,
|
||||
S_3B,
|
||||
E_2C,
|
||||
UH_1H,
|
||||
Mi_8MT,
|
||||
Ka_50,
|
||||
@@ -1432,6 +1420,8 @@ def upgrade_to_supercarrier(unit, name: str):
|
||||
return CVN_73_George_Washington
|
||||
elif name == "CVN-75 Harry S. Truman":
|
||||
return CVN_75_Harry_S__Truman
|
||||
elif name == "Carrier Strike Group 8":
|
||||
return CVN_75_Harry_S__Truman
|
||||
else:
|
||||
return CVN_71_Theodore_Roosevelt
|
||||
elif unit == CV_1143_5_Admiral_Kuznetsov:
|
||||
@@ -1457,9 +1447,9 @@ def find_unittype(for_task: Task, country_name: str) -> List[Type[UnitType]]:
|
||||
|
||||
|
||||
MANPADS: List[VehicleType] = [
|
||||
AirDefence.SAM_SA_18_Igla_MANPADS,
|
||||
AirDefence.SAM_SA_18_Igla_S_MANPADS,
|
||||
AirDefence.Stinger_MANPADS,
|
||||
AirDefence.MANPADS_SA_18_Igla_Grouse,
|
||||
AirDefence.MANPADS_SA_18_Igla_S_Grouse,
|
||||
AirDefence.MANPADS_Stinger,
|
||||
]
|
||||
|
||||
INFANTRY: List[VehicleType] = [
|
||||
@@ -1468,28 +1458,28 @@ INFANTRY: List[VehicleType] = [
|
||||
Infantry.Paratrooper_AKS,
|
||||
Infantry.Paratrooper_AKS,
|
||||
Infantry.Paratrooper_AKS,
|
||||
Infantry.Soldier_RPG,
|
||||
Infantry.Infantry_RPG,
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Soldier_M249,
|
||||
Artillery._2B11_mortar,
|
||||
Infantry.Soldier_AK,
|
||||
Infantry.Soldier_AK,
|
||||
Infantry.Soldier_AK,
|
||||
Infantry.Soldier_AK,
|
||||
Infantry.Soldier_AK,
|
||||
Infantry.Infantry_M249,
|
||||
Artillery.Mortar_2B11_120mm,
|
||||
Infantry.Infantry_AK_74,
|
||||
Infantry.Infantry_AK_74,
|
||||
Infantry.Infantry_AK_74,
|
||||
Infantry.Infantry_AK_74,
|
||||
Infantry.Infantry_AK_74,
|
||||
Infantry.Paratrooper_RPG_16,
|
||||
Infantry.Georgian_soldier_with_M4,
|
||||
Infantry.Georgian_soldier_with_M4,
|
||||
Infantry.Georgian_soldier_with_M4,
|
||||
Infantry.Georgian_soldier_with_M4,
|
||||
Infantry.Infantry_Soldier_Rus,
|
||||
Infantry.Infantry_Soldier_Rus,
|
||||
Infantry.Infantry_Soldier_Rus,
|
||||
Infantry.Infantry_Soldier_Rus,
|
||||
Infantry.Infantry_M4_Georgia,
|
||||
Infantry.Infantry_M4_Georgia,
|
||||
Infantry.Infantry_M4_Georgia,
|
||||
Infantry.Infantry_M4_Georgia,
|
||||
Infantry.Infantry_AK_74_Rus,
|
||||
Infantry.Infantry_AK_74_Rus,
|
||||
Infantry.Infantry_AK_74_Rus,
|
||||
Infantry.Infantry_AK_74_Rus,
|
||||
Infantry.Infantry_SMLE_No_4_Mk_1,
|
||||
Infantry.Infantry_SMLE_No_4_Mk_1,
|
||||
Infantry.Infantry_SMLE_No_4_Mk_1,
|
||||
@@ -1500,9 +1490,9 @@ INFANTRY: List[VehicleType] = [
|
||||
Infantry.Infantry_M1_Garand,
|
||||
Infantry.Infantry_M1_Garand,
|
||||
Infantry.Infantry_M1_Garand,
|
||||
Infantry.Infantry_Soldier_Insurgents,
|
||||
Infantry.Infantry_Soldier_Insurgents,
|
||||
Infantry.Infantry_Soldier_Insurgents,
|
||||
Infantry.Insurgent_AK_74,
|
||||
Infantry.Insurgent_AK_74,
|
||||
Infantry.Insurgent_AK_74,
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ class Faction:
|
||||
# Possible Missile site generators for this faction
|
||||
missiles: List[str] = field(default_factory=list)
|
||||
|
||||
# Possible costal site generators for this faction
|
||||
coastal_defenses: List[str] = field(default_factory=list)
|
||||
|
||||
# Required mods or asset packs
|
||||
requirements: Dict[str, str] = field(default_factory=dict)
|
||||
|
||||
@@ -100,6 +103,9 @@ class Faction:
|
||||
# How many missiles group should we try to generate per CP on startup for this faction
|
||||
missiles_group_count: int = field(default=1)
|
||||
|
||||
# How many coastal group should we try to generate per CP on startup for this faction
|
||||
coastal_group_count: int = field(default=1)
|
||||
|
||||
# Whether this faction has JTAC access
|
||||
has_jtac: bool = field(default=False)
|
||||
|
||||
@@ -162,6 +168,7 @@ class Faction:
|
||||
faction.air_defenses.extend(json.get("shorads", []))
|
||||
|
||||
faction.missiles = json.get("missiles", [])
|
||||
faction.coastal_defenses = json.get("coastal_defenses", [])
|
||||
faction.requirements = json.get("requirements", {})
|
||||
|
||||
faction.carrier_names = json.get("carrier_names", [])
|
||||
@@ -179,6 +186,7 @@ class Faction:
|
||||
faction.jtac_unit = None
|
||||
faction.navy_group_count = int(json.get("navy_group_count", 1))
|
||||
faction.missiles_group_count = int(json.get("missiles_group_count", 0))
|
||||
faction.coastal_group_count = int(json.get("coastal_group_count", 0))
|
||||
|
||||
# Load doctrine
|
||||
doctrine = json.get("doctrine", "modern")
|
||||
|
||||
16
game/game.py
16
game/game.py
@@ -96,6 +96,7 @@ class Game:
|
||||
self.enemy_name = enemy_name
|
||||
self.enemy_country = db.FACTIONS[enemy_name].country
|
||||
self.turn = 0
|
||||
# NB: This is the *start* date. It is never updated.
|
||||
self.date = date(start_date.year, start_date.month, start_date.day)
|
||||
self.game_stats = GameStats()
|
||||
self.game_stats.update(self)
|
||||
@@ -152,7 +153,7 @@ class Game:
|
||||
|
||||
def generate_conditions(self) -> Conditions:
|
||||
return Conditions.generate(
|
||||
self.theater, self.date, self.current_turn_time_of_day, self.settings
|
||||
self.theater, self.current_day, self.current_turn_time_of_day, self.settings
|
||||
)
|
||||
|
||||
def sanitize_sides(self):
|
||||
@@ -283,11 +284,18 @@ class Game:
|
||||
persistency.autosave(self)
|
||||
|
||||
def check_win_loss(self):
|
||||
captured_states = {i.captured for i in self.theater.controlpoints}
|
||||
if True not in captured_states:
|
||||
player_airbases = {
|
||||
cp for cp in self.theater.player_points() if cp.runway_is_operational()
|
||||
}
|
||||
if not player_airbases:
|
||||
return TurnState.LOSS
|
||||
if False not in captured_states:
|
||||
|
||||
enemy_airbases = {
|
||||
cp for cp in self.theater.enemy_points() if cp.runway_is_operational()
|
||||
}
|
||||
if not enemy_airbases:
|
||||
return TurnState.WIN
|
||||
|
||||
return TurnState.CONTINUE
|
||||
|
||||
def initialize_turn(self) -> None:
|
||||
|
||||
@@ -21,6 +21,10 @@ from game.threatzones import ThreatZones
|
||||
from game.utils import nautical_miles
|
||||
|
||||
|
||||
class NavMeshError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class NavMeshPoly:
|
||||
def __init__(self, ident: int, poly: Polygon, threatened: bool) -> None:
|
||||
self.ident = ident
|
||||
@@ -125,7 +129,7 @@ class NavMesh:
|
||||
path.append(current.world_point)
|
||||
previous = came_from[current]
|
||||
if previous is None:
|
||||
raise RuntimeError(
|
||||
raise NavMeshError(
|
||||
f"Could not reconstruct path to {destination} from {origin}"
|
||||
)
|
||||
current = previous
|
||||
@@ -140,10 +144,12 @@ class NavMesh:
|
||||
def shortest_path(self, origin: Point, destination: Point) -> List[Point]:
|
||||
origin_poly = self.localize(origin)
|
||||
if origin_poly is None:
|
||||
raise ValueError(f"Origin point {origin} is outside the navmesh")
|
||||
raise NavMeshError(f"Origin point {origin} is outside the navmesh")
|
||||
destination_poly = self.localize(destination)
|
||||
if destination_poly is None:
|
||||
raise ValueError(f"Origin point {destination} is outside the navmesh")
|
||||
raise NavMeshError(
|
||||
f"Destination point {destination} is outside the navmesh"
|
||||
)
|
||||
|
||||
return self._shortest_path(
|
||||
NavPoint(self.dcs_to_shapely_point(origin), origin_poly),
|
||||
@@ -203,7 +209,7 @@ class NavMesh:
|
||||
# threatened airbases at the map edges have room to retreat from the
|
||||
# threat without running off the navmesh.
|
||||
return box(*LineString(points).bounds).buffer(
|
||||
nautical_miles(100).meters, resolution=1
|
||||
nautical_miles(200).meters, resolution=1
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -166,6 +166,7 @@ class Operation:
|
||||
airgen: AircraftConflictGenerator,
|
||||
):
|
||||
"""Generates subscribed MissionInfoGenerator objects (currently kneeboards and briefings)"""
|
||||
|
||||
gens: List[MissionInfoGenerator] = [
|
||||
KneeboardGenerator(cls.current_mission, cls.game),
|
||||
BriefingGenerator(cls.current_mission, cls.game),
|
||||
@@ -177,9 +178,8 @@ class Operation:
|
||||
for tanker in airsupportgen.air_support.tankers:
|
||||
gen.add_tanker(tanker)
|
||||
|
||||
if cls.player_awacs_enabled:
|
||||
for awacs in airsupportgen.air_support.awacs:
|
||||
gen.add_awacs(awacs)
|
||||
for aewc in airsupportgen.air_support.awacs:
|
||||
gen.add_awacs(aewc)
|
||||
|
||||
for jtac in jtacs:
|
||||
gen.add_jtac(jtac)
|
||||
@@ -378,7 +378,9 @@ class Operation:
|
||||
cls.game,
|
||||
cls.radio_registry,
|
||||
cls.unit_map,
|
||||
air_support=cls.airsupportgen.air_support,
|
||||
)
|
||||
|
||||
cls.airgen.clear_parking_slots()
|
||||
|
||||
cls.airgen.generate_flights(
|
||||
@@ -444,6 +446,8 @@ class Operation:
|
||||
"AWACs": {},
|
||||
"JTACs": {},
|
||||
"TargetPoints": {},
|
||||
"RedAA": {},
|
||||
"BlueAA": {},
|
||||
} # type: ignore
|
||||
|
||||
for tanker in airsupportgen.air_support.tankers:
|
||||
@@ -501,6 +505,26 @@ class Operation:
|
||||
},
|
||||
}
|
||||
|
||||
for cp in cls.game.theater.controlpoints:
|
||||
for ground_object in cp.ground_objects:
|
||||
if ground_object.might_have_aa and not ground_object.is_dead:
|
||||
for g in ground_object.groups:
|
||||
threat_range = ground_object.threat_range(g)
|
||||
|
||||
if not threat_range:
|
||||
continue
|
||||
|
||||
faction = "BlueAA" if cp.captured else "RedAA"
|
||||
|
||||
luaData[faction][g.name] = {
|
||||
"name": ground_object.name,
|
||||
"range": threat_range.meters,
|
||||
"position": {
|
||||
"x": ground_object.position.x,
|
||||
"y": ground_object.position.y,
|
||||
},
|
||||
}
|
||||
|
||||
# set a LUA table with data from Liberation that we want to set
|
||||
# at the moment it contains Liberation's install path, and an overridable definition for the JTACAutoLase function
|
||||
# later, we'll add data about the units and points having been generated, in order to facilitate the configuration of the plugin lua scripts
|
||||
@@ -593,7 +617,33 @@ class Operation:
|
||||
-- list the aircraft carriers generated by Liberation
|
||||
-- dcsLiberation.Carriers = {}
|
||||
|
||||
-- later, we'll add more data to the table
|
||||
-- list the Red AA generated by Liberation
|
||||
dcsLiberation.RedAA = {
|
||||
"""
|
||||
for key in luaData["RedAA"]:
|
||||
data = luaData["RedAA"][key]
|
||||
name = data["name"]
|
||||
radius = data["range"]
|
||||
positionX = data["position"]["x"]
|
||||
positionY = data["position"]["y"]
|
||||
lua += f" {{dcsGroupName='{key}', name='{name}', range='{radius}', positionX='{positionX}', positionY='{positionY}' }}, \n"
|
||||
lua += "}"
|
||||
|
||||
lua += """
|
||||
|
||||
-- list the Blue AA generated by Liberation
|
||||
dcsLiberation.BlueAA = {
|
||||
"""
|
||||
for key in luaData["BlueAA"]:
|
||||
data = luaData["BlueAA"][key]
|
||||
name = data["name"]
|
||||
radius = data["range"]
|
||||
positionX = data["position"]["x"]
|
||||
positionY = data["position"]["y"]
|
||||
lua += f" {{dcsGroupName='{key}', name='{name}', range='{radius}', positionX='{positionX}', positionY='{positionY}' }}, \n"
|
||||
lua += "}"
|
||||
|
||||
lua += """
|
||||
|
||||
"""
|
||||
|
||||
|
||||
15
game/point_with_heading.py
Normal file
15
game/point_with_heading.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from dcs import Point
|
||||
|
||||
|
||||
class PointWithHeading(Point):
|
||||
def __init__(self):
|
||||
super(PointWithHeading, self).__init__(0, 0)
|
||||
self.heading = 0
|
||||
|
||||
@staticmethod
|
||||
def from_point(point: Point, heading: int):
|
||||
p = PointWithHeading()
|
||||
p.x = point.x
|
||||
p.y = point.y
|
||||
p.heading = heading
|
||||
return p
|
||||
@@ -30,6 +30,8 @@ class Settings:
|
||||
automate_front_line_reinforcements: bool = False
|
||||
automate_aircraft_reinforcements: bool = False
|
||||
restrict_weapons_by_date: bool = False
|
||||
disable_legacy_aewc: bool = False
|
||||
generate_dark_kneeboard: bool = False
|
||||
|
||||
# Performance oriented
|
||||
perf_red_alert_state: bool = True
|
||||
|
||||
@@ -4,7 +4,7 @@ import math
|
||||
import typing
|
||||
from typing import Dict, Type
|
||||
|
||||
from dcs.task import CAP, CAS, Embarking, PinpointStrike, Task
|
||||
from dcs.task import AWACS, CAP, CAS, Embarking, PinpointStrike, Task
|
||||
from dcs.unittype import FlyingType, UnitType, VehicleType
|
||||
from dcs.vehicles import AirDefence, Armor
|
||||
|
||||
@@ -147,7 +147,12 @@ class Base:
|
||||
for_task = db.unit_task(unit_type)
|
||||
|
||||
target_dict = None
|
||||
if for_task == CAS or for_task == CAP or for_task == Embarking:
|
||||
if (
|
||||
for_task == AWACS
|
||||
or for_task == CAS
|
||||
or for_task == CAP
|
||||
or for_task == Embarking
|
||||
):
|
||||
target_dict = self.aircraft
|
||||
elif for_task == PinpointStrike:
|
||||
target_dict = self.armor
|
||||
|
||||
@@ -23,7 +23,7 @@ from dcs.planes import F_15C
|
||||
from dcs.ships import (
|
||||
CVN_74_John_C__Stennis,
|
||||
LHA_1_Tarawa,
|
||||
USS_Arleigh_Burke_IIa,
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
)
|
||||
from dcs.statics import Fortification
|
||||
from dcs.terrain import (
|
||||
@@ -55,6 +55,7 @@ from .controlpoint import (
|
||||
Fob,
|
||||
)
|
||||
from .landmap import Landmap, load_landmap, poly_contains
|
||||
from ..point_with_heading import PointWithHeading
|
||||
from ..utils import Distance, meters, nautical_miles
|
||||
|
||||
Numeric = Union[int, float]
|
||||
@@ -92,30 +93,33 @@ class MizCampaignLoader:
|
||||
LHA_UNIT_TYPE = LHA_1_Tarawa.id
|
||||
FRONT_LINE_UNIT_TYPE = Armor.APC_M113.id
|
||||
|
||||
FOB_UNIT_TYPE = Unarmed.CP_SKP_11_ATC_Mobile_Command_Post.id
|
||||
FOB_UNIT_TYPE = Unarmed.Truck_SKP_11_Mobile_ATC.id
|
||||
FARP_HELIPAD = "SINGLE_HELIPAD"
|
||||
|
||||
EWR_UNIT_TYPE = AirDefence.EWR_55G6.id
|
||||
SAM_UNIT_TYPE = AirDefence.SAM_SA_10_S_300PS_SR_64H6E.id
|
||||
GARRISON_UNIT_TYPE = AirDefence.SAM_SA_19_Tunguska_2S6.id
|
||||
SAM_UNIT_TYPE = AirDefence.SAM_SA_10_S_300_Grumble_Big_Bird_SR.id
|
||||
GARRISON_UNIT_TYPE = AirDefence.SAM_SA_19_Tunguska_Grison.id
|
||||
OFFSHORE_STRIKE_TARGET_UNIT_TYPE = Fortification.Oil_platform.id
|
||||
SHIP_UNIT_TYPE = USS_Arleigh_Burke_IIa.id
|
||||
MISSILE_SITE_UNIT_TYPE = MissilesSS.SRBM_SS_1C_Scud_B_9K72_LN_9P117M.id
|
||||
COASTAL_DEFENSE_UNIT_TYPE = MissilesSS.SS_N_2_Silkworm.id
|
||||
SHIP_UNIT_TYPE = DDG_Arleigh_Burke_IIa.id
|
||||
MISSILE_SITE_UNIT_TYPE = MissilesSS.SSM_SS_1C_Scud_B.id
|
||||
COASTAL_DEFENSE_UNIT_TYPE = MissilesSS.AShM_SS_N_2_Silkworm.id
|
||||
|
||||
# Multiple options for the required SAMs so campaign designers can more
|
||||
# accurately see the coverage of their IADS for the expected type.
|
||||
REQUIRED_LONG_RANGE_SAM_UNIT_TYPES = {
|
||||
AirDefence.SAM_Patriot_LN_M901.id,
|
||||
AirDefence.SAM_SA_10_S_300PS_LN_5P85C.id,
|
||||
AirDefence.SAM_SA_10_S_300PS_LN_5P85D.id,
|
||||
AirDefence.SAM_Patriot_LN.id,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_TEL_C.id,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_TEL_D.id,
|
||||
}
|
||||
|
||||
REQUIRED_MEDIUM_RANGE_SAM_UNIT_TYPES = {
|
||||
AirDefence.SAM_Hawk_LN_M192.id,
|
||||
AirDefence.SAM_SA_2_LN_SM_90.id,
|
||||
AirDefence.SAM_SA_3_S_125_LN_5P73.id,
|
||||
AirDefence.SAM_SA_2_S_75_Guideline_LN.id,
|
||||
AirDefence.SAM_SA_3_S_125_Goa_LN.id,
|
||||
}
|
||||
|
||||
REQUIRED_EWR_UNIT_TYPE = AirDefence.EWR_1L13.id
|
||||
|
||||
BASE_DEFENSE_RADIUS = nautical_miles(2)
|
||||
|
||||
def __init__(self, miz: Path, theater: ConflictTheater) -> None:
|
||||
@@ -245,6 +249,18 @@ class MizCampaignLoader:
|
||||
if group.units[0].type in self.REQUIRED_MEDIUM_RANGE_SAM_UNIT_TYPES:
|
||||
yield group
|
||||
|
||||
@property
|
||||
def required_ewrs(self) -> Iterator[VehicleGroup]:
|
||||
for group in self.red.vehicle_group:
|
||||
if group.units[0].type in self.REQUIRED_EWR_UNIT_TYPE:
|
||||
yield group
|
||||
|
||||
@property
|
||||
def helipads(self) -> Iterator[StaticGroup]:
|
||||
for group in self.blue.static_group:
|
||||
if group.units[0].type == self.FARP_HELIPAD:
|
||||
yield group
|
||||
|
||||
@cached_property
|
||||
def control_points(self) -> Dict[int, ControlPoint]:
|
||||
control_points = {}
|
||||
@@ -270,7 +286,7 @@ class MizCampaignLoader:
|
||||
control_point.captured_invert = group.late_activation
|
||||
control_points[control_point.id] = control_point
|
||||
for group in self.lhas(blue):
|
||||
# TODO: Name the LHA.
|
||||
# TODO: Name the LHA.db
|
||||
control_point = Lha("lha", group.position, next(self.control_point_id))
|
||||
control_point.captured = blue
|
||||
control_point.captured_invert = group.late_activation
|
||||
@@ -329,44 +345,81 @@ class MizCampaignLoader:
|
||||
for group in self.garrisons:
|
||||
closest, distance = self.objective_info(group)
|
||||
if distance < self.BASE_DEFENSE_RADIUS:
|
||||
closest.preset_locations.base_garrisons.append(group.position)
|
||||
closest.preset_locations.base_garrisons.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
else:
|
||||
logging.warning(f"Found garrison unit too far from base: {group.name}")
|
||||
|
||||
for group in self.sams:
|
||||
closest, distance = self.objective_info(group)
|
||||
if distance < self.BASE_DEFENSE_RADIUS:
|
||||
closest.preset_locations.base_air_defense.append(group.position)
|
||||
closest.preset_locations.base_air_defense.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
else:
|
||||
closest.preset_locations.strike_locations.append(group.position)
|
||||
closest.preset_locations.strike_locations.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.ewrs:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.ewrs.append(group.position)
|
||||
if distance < self.BASE_DEFENSE_RADIUS:
|
||||
closest.preset_locations.ewrs.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
else:
|
||||
closest.preset_locations.ewrs.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.offshore_strike_targets:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.offshore_strike_locations.append(group.position)
|
||||
closest.preset_locations.offshore_strike_locations.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.ships:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.ships.append(group.position)
|
||||
closest.preset_locations.ships.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.missile_sites:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.missile_sites.append(group.position)
|
||||
closest.preset_locations.missile_sites.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.coastal_defenses:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.coastal_defenses.append(group.position)
|
||||
closest.preset_locations.coastal_defenses.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.required_long_range_sams:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.required_long_range_sams.append(group.position)
|
||||
closest.preset_locations.required_long_range_sams.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.required_medium_range_sams:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.required_medium_range_sams.append(group.position)
|
||||
closest.preset_locations.required_medium_range_sams.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.required_ewrs:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.required_ewrs.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.helipads:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.helipads.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
def populate_theater(self) -> None:
|
||||
for control_point in self.control_points.values():
|
||||
@@ -677,8 +730,8 @@ class PersianGulfTheater(ConflictTheater):
|
||||
terrain = persiangulf.PersianGulf()
|
||||
overview_image = "persiangulf.gif"
|
||||
reference_points = (
|
||||
ReferencePoint(persiangulf.Jiroft_Airport.position, Point(1692, 1343)),
|
||||
ReferencePoint(persiangulf.Liwa_Airbase.position, Point(358, 3238)),
|
||||
ReferencePoint(persiangulf.Jiroft.position, Point(1692, 1343)),
|
||||
ReferencePoint(persiangulf.Liwa_AFB.position, Point(358, 3238)),
|
||||
)
|
||||
landmap = load_landmap("resources\\gulflandmap.p")
|
||||
daytime_map = {
|
||||
@@ -811,6 +864,7 @@ class FrontLine(MissionTarget):
|
||||
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
||||
yield from [
|
||||
FlightType.CAS,
|
||||
FlightType.AEWC,
|
||||
# TODO: FlightType.TROOP_TRANSPORT
|
||||
# TODO: FlightType.EVAC
|
||||
]
|
||||
|
||||
@@ -4,7 +4,6 @@ import heapq
|
||||
import itertools
|
||||
import logging
|
||||
import random
|
||||
import re
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
@@ -28,6 +27,7 @@ from gen.ground_forces.combat_stance import CombatStance
|
||||
from gen.runways import RunwayAssigner, RunwayData
|
||||
from .base import Base
|
||||
from .missiontarget import MissionTarget
|
||||
from game.point_with_heading import PointWithHeading
|
||||
from .theatergroundobject import (
|
||||
BaseDefenseGroundObject,
|
||||
EwrGroundObject,
|
||||
@@ -77,38 +77,41 @@ class PresetLocations:
|
||||
"""Defines the preset locations loaded from the campaign mission file."""
|
||||
|
||||
#: Locations used for spawning ground defenses for bases.
|
||||
base_garrisons: List[Point] = field(default_factory=list)
|
||||
base_garrisons: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations used for spawning air defenses for bases. Used by SAMs, AAA,
|
||||
#: and SHORADs.
|
||||
base_air_defense: List[Point] = field(default_factory=list)
|
||||
base_air_defense: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations used by EWRs.
|
||||
ewrs: List[Point] = field(default_factory=list)
|
||||
ewrs: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations used by non-carrier ships. Carriers and LHAs are not random.
|
||||
ships: List[Point] = field(default_factory=list)
|
||||
ships: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations used by coastal defenses.
|
||||
coastal_defenses: List[Point] = field(default_factory=list)
|
||||
coastal_defenses: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations used by ground based strike objectives.
|
||||
strike_locations: List[Point] = field(default_factory=list)
|
||||
strike_locations: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations used by offshore strike objectives.
|
||||
offshore_strike_locations: List[Point] = field(default_factory=list)
|
||||
offshore_strike_locations: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations used by missile sites like scuds and V-2s.
|
||||
missile_sites: List[Point] = field(default_factory=list)
|
||||
missile_sites: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations of long range SAMs which should always be spawned.
|
||||
required_long_range_sams: List[Point] = field(default_factory=list)
|
||||
required_long_range_sams: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations of medium range SAMs which should always be spawned.
|
||||
required_medium_range_sams: List[Point] = field(default_factory=list)
|
||||
required_medium_range_sams: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations of EWRs which should always be spawned.
|
||||
required_ewrs: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
@staticmethod
|
||||
def _random_from(points: List[Point]) -> Optional[Point]:
|
||||
def _random_from(points: List[PointWithHeading]) -> Optional[PointWithHeading]:
|
||||
"""Finds, removes, and returns a random position from the given list."""
|
||||
if not points:
|
||||
return None
|
||||
@@ -116,7 +119,7 @@ class PresetLocations:
|
||||
points.remove(point)
|
||||
return point
|
||||
|
||||
def random_for(self, location_type: LocationType) -> Optional[Point]:
|
||||
def random_for(self, location_type: LocationType) -> Optional[PointWithHeading]:
|
||||
"""Returns a position suitable for the given location type.
|
||||
|
||||
The location, if found, will be claimed by the caller and not available
|
||||
@@ -250,6 +253,7 @@ class ControlPoint(MissionTarget, ABC):
|
||||
self.connected_objectives: List[TheaterGroundObject] = []
|
||||
self.base_defenses: List[BaseDefenseGroundObject] = []
|
||||
self.preset_locations = PresetLocations()
|
||||
self.helipads: List[PointWithHeading] = []
|
||||
|
||||
# TODO: Should be Airbase specific.
|
||||
self.size = size
|
||||
@@ -386,18 +390,19 @@ class ControlPoint(MissionTarget, ABC):
|
||||
# TODO: Should be Airbase specific.
|
||||
def clear_base_defenses(self) -> None:
|
||||
for base_defense in self.base_defenses:
|
||||
p = PointWithHeading.from_point(base_defense.position, base_defense.heading)
|
||||
if isinstance(base_defense, EwrGroundObject):
|
||||
self.preset_locations.ewrs.append(base_defense.position)
|
||||
self.preset_locations.ewrs.append(p)
|
||||
elif isinstance(base_defense, SamGroundObject):
|
||||
self.preset_locations.base_air_defense.append(base_defense.position)
|
||||
self.preset_locations.base_air_defense.append(p)
|
||||
elif isinstance(base_defense, VehicleGroupGroundObject):
|
||||
self.preset_locations.base_garrisons.append(base_defense.position)
|
||||
self.preset_locations.base_garrisons.append(p)
|
||||
else:
|
||||
logging.error(
|
||||
"Could not determine preset location type for "
|
||||
f"{base_defense}. Assuming garrison type."
|
||||
)
|
||||
self.preset_locations.base_garrisons.append(base_defense.position)
|
||||
self.preset_locations.base_garrisons.append(p)
|
||||
self.base_defenses = []
|
||||
|
||||
def capture_equipment(self, game: Game) -> None:
|
||||
@@ -633,6 +638,15 @@ class ControlPoint(MissionTarget, ABC):
|
||||
def income_per_turn(self) -> int:
|
||||
return 0
|
||||
|
||||
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
||||
from gen.flights.flight import FlightType
|
||||
|
||||
if self.is_friendly(for_player):
|
||||
yield from [
|
||||
FlightType.AEWC,
|
||||
]
|
||||
yield from super().mission_types(for_player)
|
||||
|
||||
@property
|
||||
def has_active_frontline(self) -> bool:
|
||||
return any(not c.is_friendly(self.captured) for c in self.connected_points)
|
||||
|
||||
@@ -13,7 +13,7 @@ from dcs.vehicles import AirDefence
|
||||
|
||||
from game import Game, db
|
||||
from game.factions.faction import Faction
|
||||
from game.theater import Carrier, Lha, LocationType
|
||||
from game.theater import Carrier, Lha, LocationType, PointWithHeading
|
||||
from game.theater.theatergroundobject import (
|
||||
BuildingGroundObject,
|
||||
CarrierGroundObject,
|
||||
@@ -23,9 +23,11 @@ from game.theater.theatergroundobject import (
|
||||
SamGroundObject,
|
||||
ShipGroundObject,
|
||||
VehicleGroupGroundObject,
|
||||
CoastalSiteGroundObject,
|
||||
)
|
||||
from game.version import VERSION
|
||||
from gen import namegen
|
||||
from gen.coastal.coastal_group_generator import generate_coastal_group
|
||||
from gen.defenses.armor_group_generator import generate_armor_group
|
||||
from gen.fleet.ship_group_generator import (
|
||||
generate_carrier_group,
|
||||
@@ -35,10 +37,8 @@ from gen.fleet.ship_group_generator import (
|
||||
from gen.locations.preset_location_finder import MizDataLocationFinder
|
||||
from gen.missiles.missiles_group_generator import generate_missile_group
|
||||
from gen.sam.airdefensegroupgenerator import AirDefenseRange
|
||||
from gen.sam.sam_group_generator import (
|
||||
generate_anti_air_group,
|
||||
generate_ewr_group,
|
||||
)
|
||||
from gen.sam.sam_group_generator import generate_anti_air_group
|
||||
from gen.sam.ewr_group_generator import generate_ewr_group
|
||||
from . import (
|
||||
ConflictTheater,
|
||||
ControlPoint,
|
||||
@@ -148,13 +148,13 @@ class LocationFinder:
|
||||
game.theater.terrain.name, control_point.full_name
|
||||
)
|
||||
|
||||
def location_for(self, location_type: LocationType) -> Optional[Point]:
|
||||
def location_for(self, location_type: LocationType) -> Optional[PointWithHeading]:
|
||||
position = self.control_point.preset_locations.random_for(location_type)
|
||||
if position is not None:
|
||||
return position
|
||||
|
||||
logging.warning(
|
||||
f"No campaign location for %s at %s",
|
||||
f"No campaign location for %s Mat %s",
|
||||
location_type.value,
|
||||
self.control_point,
|
||||
)
|
||||
@@ -178,7 +178,7 @@ class LocationFinder:
|
||||
)
|
||||
return None
|
||||
|
||||
def random_from_miz_data(self, offshore: bool) -> Optional[Point]:
|
||||
def random_from_miz_data(self, offshore: bool) -> Optional[PointWithHeading]:
|
||||
if offshore:
|
||||
locations = self.miz_data.offshore_locations
|
||||
else:
|
||||
@@ -186,11 +186,18 @@ class LocationFinder:
|
||||
if self.miz_data.offshore_locations:
|
||||
preset = random.choice(locations)
|
||||
locations.remove(preset)
|
||||
return preset.position
|
||||
return PointWithHeading.from_point(preset.position, preset.heading)
|
||||
return None
|
||||
|
||||
def random_position(self, location_type: LocationType) -> Optional[Point]:
|
||||
def random_position(
|
||||
self, location_type: LocationType
|
||||
) -> Optional[PointWithHeading]:
|
||||
# TODO: Flesh out preset locations so we never hit this case.
|
||||
|
||||
if location_type == LocationType.Coastal:
|
||||
# No coastal locations generated randomly
|
||||
return None
|
||||
|
||||
logging.warning(
|
||||
"Falling back to random location for %s at %s",
|
||||
location_type.value,
|
||||
@@ -250,7 +257,7 @@ class LocationFinder:
|
||||
on_ground: bool,
|
||||
is_base_defense: bool,
|
||||
avoid_others: bool,
|
||||
) -> Optional[Point]:
|
||||
) -> Optional[PointWithHeading]:
|
||||
"""
|
||||
Find a valid ground object location
|
||||
:param on_ground: Whether it should be on ground or on sea (True = on
|
||||
@@ -263,7 +270,7 @@ class LocationFinder:
|
||||
near = self.control_point.position
|
||||
others = self.control_point.ground_objects
|
||||
|
||||
def is_valid(point: Optional[Point]) -> bool:
|
||||
def is_valid(point: Optional[PointWithHeading]) -> bool:
|
||||
if point is None:
|
||||
return False
|
||||
|
||||
@@ -294,7 +301,9 @@ class LocationFinder:
|
||||
|
||||
for _ in range(300):
|
||||
# Check if on land or sea
|
||||
p = near.random_point_within(max_range, min_range)
|
||||
p = PointWithHeading.from_point(
|
||||
near.random_point_within(max_range, min_range), random.randint(0, 360)
|
||||
)
|
||||
if is_valid(p):
|
||||
return p
|
||||
return None
|
||||
@@ -453,7 +462,11 @@ class BaseDefenseGenerator:
|
||||
group_id = self.game.next_group_id()
|
||||
|
||||
g = EwrGroundObject(
|
||||
namegen.random_objective_name(), group_id, position, self.control_point
|
||||
namegen.random_objective_name(),
|
||||
group_id,
|
||||
position,
|
||||
self.control_point,
|
||||
True,
|
||||
)
|
||||
|
||||
group = generate_ewr_group(self.game, g, self.faction)
|
||||
@@ -590,11 +603,15 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||
if self.faction.missiles:
|
||||
self.generate_missile_sites()
|
||||
|
||||
if self.faction.coastal_defenses:
|
||||
self.generate_coastal_sites()
|
||||
|
||||
return True
|
||||
|
||||
def generate_ground_points(self) -> None:
|
||||
"""Generate ground objects and AA sites for the control point."""
|
||||
skip_sams = self.generate_required_aa()
|
||||
skip_ewrs = self.generate_required_ewr()
|
||||
|
||||
if self.control_point.is_global:
|
||||
return
|
||||
@@ -611,6 +628,12 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||
skip_sams -= 1
|
||||
else:
|
||||
self.generate_aa_site()
|
||||
# 1 in 4 additional objectives are EWR.
|
||||
elif random.randint(0, 3) == 0:
|
||||
if skip_ewrs > 0:
|
||||
skip_ewrs -= 1
|
||||
else:
|
||||
self.generate_ewr_site()
|
||||
else:
|
||||
self.generate_ground_point()
|
||||
|
||||
@@ -642,6 +665,17 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||
presets.required_medium_range_sams
|
||||
)
|
||||
|
||||
def generate_required_ewr(self) -> int:
|
||||
"""Generates the EWR sites that are required by the campaign.
|
||||
|
||||
Returns:
|
||||
The number of EWR sites that were generated.
|
||||
"""
|
||||
presets = self.control_point.preset_locations
|
||||
for position in presets.required_ewrs:
|
||||
self.generate_ewr_at(position)
|
||||
return len(presets.required_ewrs)
|
||||
|
||||
def generate_ground_point(self) -> None:
|
||||
try:
|
||||
category = random.choice(self.faction.building_set)
|
||||
@@ -719,6 +753,33 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||
g.groups = groups
|
||||
self.control_point.connected_objectives.append(g)
|
||||
|
||||
def generate_ewr_site(self) -> None:
|
||||
position = self.location_finder.location_for(LocationType.Ewr)
|
||||
if position is None:
|
||||
return
|
||||
self.generate_ewr_at(position)
|
||||
|
||||
def generate_ewr_at(self, position: Point) -> None:
|
||||
group_id = self.game.next_group_id()
|
||||
|
||||
g = EwrGroundObject(
|
||||
namegen.random_objective_name(),
|
||||
group_id,
|
||||
position,
|
||||
self.control_point,
|
||||
for_airbase=False,
|
||||
)
|
||||
group = generate_ewr_group(self.game, g, self.faction)
|
||||
if group is None:
|
||||
logging.error(
|
||||
"Could not generate ewr group for %s at %s",
|
||||
g.name,
|
||||
self.control_point,
|
||||
)
|
||||
return
|
||||
g.groups = [group]
|
||||
self.control_point.connected_objectives.append(g)
|
||||
|
||||
def generate_missile_sites(self) -> None:
|
||||
for i in range(self.faction.missiles_group_count):
|
||||
self.generate_missile_site()
|
||||
@@ -740,6 +801,31 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||
self.control_point.connected_objectives.append(g)
|
||||
return
|
||||
|
||||
def generate_coastal_sites(self) -> None:
|
||||
for i in range(self.faction.coastal_group_count):
|
||||
self.generate_coastal_site()
|
||||
|
||||
def generate_coastal_site(self) -> None:
|
||||
position = self.location_finder.location_for(LocationType.Coastal)
|
||||
if position is None:
|
||||
return
|
||||
|
||||
group_id = self.game.next_group_id()
|
||||
|
||||
g = CoastalSiteGroundObject(
|
||||
namegen.random_objective_name(),
|
||||
group_id,
|
||||
position,
|
||||
self.control_point,
|
||||
position.heading,
|
||||
)
|
||||
group = generate_coastal_group(self.game, g, self.faction_name)
|
||||
g.groups = []
|
||||
if group is not None:
|
||||
g.groups.append(group)
|
||||
self.control_point.connected_objectives.append(g)
|
||||
return
|
||||
|
||||
|
||||
class FobGroundObjectGenerator(AirbaseGroundObjectGenerator):
|
||||
def generate(self) -> bool:
|
||||
|
||||
@@ -344,6 +344,28 @@ class MissileSiteGroundObject(TheaterGroundObject):
|
||||
)
|
||||
|
||||
|
||||
class CoastalSiteGroundObject(TheaterGroundObject):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
group_id: int,
|
||||
position: Point,
|
||||
control_point: ControlPoint,
|
||||
heading,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
name=name,
|
||||
category="aa",
|
||||
group_id=group_id,
|
||||
position=position,
|
||||
heading=heading,
|
||||
control_point=control_point,
|
||||
dcs_identifier="AA",
|
||||
airbase_group=False,
|
||||
sea_object=False,
|
||||
)
|
||||
|
||||
|
||||
class BaseDefenseGroundObject(TheaterGroundObject):
|
||||
"""Base type for all base defenses."""
|
||||
|
||||
@@ -420,7 +442,12 @@ class VehicleGroupGroundObject(BaseDefenseGroundObject):
|
||||
|
||||
class EwrGroundObject(BaseDefenseGroundObject):
|
||||
def __init__(
|
||||
self, name: str, group_id: int, position: Point, control_point: ControlPoint
|
||||
self,
|
||||
name: str,
|
||||
group_id: int,
|
||||
position: Point,
|
||||
control_point: ControlPoint,
|
||||
for_airbase: bool,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
name=name,
|
||||
@@ -430,7 +457,7 @@ class EwrGroundObject(BaseDefenseGroundObject):
|
||||
heading=0,
|
||||
control_point=control_point,
|
||||
dcs_identifier="EWR",
|
||||
airbase_group=True,
|
||||
airbase_group=for_airbase,
|
||||
sea_object=False,
|
||||
)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ from shapely.ops import nearest_points, unary_union
|
||||
|
||||
from game.theater import ControlPoint
|
||||
from game.utils import Distance, meters, nautical_miles
|
||||
from gen import Conflict
|
||||
from gen.flights.closestairfields import ObjectiveDistanceCache
|
||||
from gen.flights.flight import Flight
|
||||
|
||||
@@ -131,7 +132,7 @@ class ThreatZones:
|
||||
zone belongs to the player, it is the zone that will be avoided by
|
||||
the enemy and vice versa.
|
||||
"""
|
||||
airbases = []
|
||||
air_threats = []
|
||||
air_defenses = []
|
||||
for control_point in game.theater.controlpoints:
|
||||
if control_point.captured != player:
|
||||
@@ -139,7 +140,7 @@ class ThreatZones:
|
||||
if control_point.runway_is_operational():
|
||||
point = ShapelyPoint(control_point.position.x, control_point.position.y)
|
||||
cap_threat_range = cls.barcap_threat_range(game, control_point)
|
||||
airbases.append(point.buffer(cap_threat_range.meters))
|
||||
air_threats.append(point.buffer(cap_threat_range.meters))
|
||||
|
||||
for tgo in control_point.ground_objects:
|
||||
for group in tgo.groups:
|
||||
@@ -151,8 +152,25 @@ class ThreatZones:
|
||||
threat_zone = point.buffer(threat_range.meters)
|
||||
air_defenses.append(threat_zone)
|
||||
|
||||
for front_line in game.theater.conflicts(player):
|
||||
vector = Conflict.frontline_vector(
|
||||
front_line.control_point_a, front_line.control_point_b, game.theater
|
||||
)
|
||||
|
||||
start = vector[0]
|
||||
end = vector[0].point_from_heading(vector[1], vector[2])
|
||||
|
||||
line = LineString(
|
||||
[
|
||||
ShapelyPoint(start.x, start.y),
|
||||
ShapelyPoint(end.x, end.y),
|
||||
]
|
||||
)
|
||||
doctrine = game.faction_for(player).doctrine
|
||||
air_threats.append(line.buffer(doctrine.cap_engagement_range.meters))
|
||||
|
||||
return cls(
|
||||
airbases=unary_union(airbases), air_defenses=unary_union(air_defenses)
|
||||
airbases=unary_union(air_threats), air_defenses=unary_union(air_defenses)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -2,7 +2,7 @@ from pathlib import Path
|
||||
|
||||
|
||||
def _build_version_string() -> str:
|
||||
components = ["2.4.4"]
|
||||
components = ["2.5"]
|
||||
build_number_path = Path("resources/buildnumber")
|
||||
if build_number_path.exists():
|
||||
with build_number_path.open("r") as build_number_file:
|
||||
|
||||
@@ -3,11 +3,12 @@ from __future__ import annotations
|
||||
import datetime
|
||||
import logging
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from dcs.weather import Weather as PydcsWeather, Wind
|
||||
from dcs.cloud_presets import Clouds as PydcsClouds
|
||||
from dcs.weather import CloudPreset, Weather as PydcsWeather, Wind
|
||||
|
||||
from game.settings import Settings
|
||||
from game.utils import Distance, meters
|
||||
@@ -36,6 +37,23 @@ class Clouds:
|
||||
density: int
|
||||
thickness: int
|
||||
precipitation: PydcsWeather.Preceptions
|
||||
preset: Optional[CloudPreset] = field(default=None)
|
||||
|
||||
@classmethod
|
||||
def random_preset(cls, rain: bool) -> Clouds:
|
||||
clouds = (p.value for p in PydcsClouds)
|
||||
if rain:
|
||||
presets = [p for p in clouds if "Rain" in p.name]
|
||||
else:
|
||||
presets = [p for p in clouds if "Rain" not in p.name]
|
||||
preset = random.choice(presets)
|
||||
return Clouds(
|
||||
base=random.randint(preset.min_base, preset.max_base),
|
||||
density=0,
|
||||
thickness=0,
|
||||
precipitation=PydcsWeather.Preceptions.None_,
|
||||
preset=preset,
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -101,12 +119,11 @@ class ClearSkies(Weather):
|
||||
|
||||
class Cloudy(Weather):
|
||||
def generate_clouds(self) -> Optional[Clouds]:
|
||||
return Clouds(
|
||||
base=self.random_cloud_base(),
|
||||
density=random.randint(1, 8),
|
||||
thickness=self.random_cloud_thickness(),
|
||||
precipitation=PydcsWeather.Preceptions.None_,
|
||||
)
|
||||
return Clouds.random_preset(rain=False)
|
||||
|
||||
def generate_fog(self) -> Optional[Fog]:
|
||||
# DCS 2.7 says to not use fog with the cloud presets.
|
||||
return None
|
||||
|
||||
def generate_wind(self) -> WindConditions:
|
||||
return self.random_wind(0, 4)
|
||||
@@ -114,12 +131,11 @@ class Cloudy(Weather):
|
||||
|
||||
class Raining(Weather):
|
||||
def generate_clouds(self) -> Optional[Clouds]:
|
||||
return Clouds(
|
||||
base=self.random_cloud_base(),
|
||||
density=random.randint(5, 8),
|
||||
thickness=self.random_cloud_thickness(),
|
||||
precipitation=PydcsWeather.Preceptions.Rain,
|
||||
)
|
||||
return Clouds.random_preset(rain=True)
|
||||
|
||||
def generate_fog(self) -> Optional[Fog]:
|
||||
# DCS 2.7 says to not use fog with the cloud presets.
|
||||
return None
|
||||
|
||||
def generate_wind(self) -> WindConditions:
|
||||
return self.random_wind(0, 6)
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import timedelta
|
||||
from functools import cached_property
|
||||
from typing import Dict, List, Optional, TYPE_CHECKING, Type, Union
|
||||
@@ -41,6 +41,7 @@ from dcs.planes import (
|
||||
)
|
||||
from dcs.point import MovingPoint, PointAction
|
||||
from dcs.task import (
|
||||
AWACS,
|
||||
AntishipStrike,
|
||||
AttackGroup,
|
||||
Bombing,
|
||||
@@ -66,6 +67,8 @@ from dcs.task import (
|
||||
Targets,
|
||||
Task,
|
||||
WeaponType,
|
||||
AWACSTaskAction,
|
||||
SetFrequencyCommand,
|
||||
)
|
||||
from dcs.terrain.terrain import Airport, NoParkingSlotError
|
||||
from dcs.triggers import Event, TriggerOnce, TriggerRule
|
||||
@@ -87,10 +90,8 @@ from game.theater.controlpoint import (
|
||||
from game.theater.theatergroundobject import TheaterGroundObject
|
||||
from game.unitmap import UnitMap
|
||||
from game.utils import Distance, meters, nautical_miles
|
||||
from gen.airsupportgen import AirSupport
|
||||
from gen.ato import AirTaskingOrder, Package
|
||||
from gen.callsigns import create_group_callsign_from_unit
|
||||
from gen.conflictgen import FRONTLINE_LENGTH
|
||||
from gen.flights.flight import (
|
||||
Flight,
|
||||
FlightType,
|
||||
@@ -104,9 +105,12 @@ from .flights.flightplan import (
|
||||
LoiterFlightPlan,
|
||||
PatrollingFlightPlan,
|
||||
SweepFlightPlan,
|
||||
AwacsFlightPlan,
|
||||
)
|
||||
from .flights.traveltime import GroundSpeed, TotEstimator
|
||||
from .naming import namegen
|
||||
from .airsupportgen import AirSupport, AwacsInfo
|
||||
from .callsigns import callsign_for_support_unit
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
@@ -134,6 +138,7 @@ TARGET_WAYPOINTS = (
|
||||
FlightWaypointType.TARGET_SHIP,
|
||||
)
|
||||
|
||||
|
||||
# TODO: Get radio information for all the special cases.
|
||||
def get_fallback_channel(unit_type: UnitType) -> RadioFrequency:
|
||||
if unit_type in helicopter_map.values() and unit_type != UH_1H:
|
||||
@@ -318,6 +323,7 @@ class FlightData:
|
||||
intra_flight_channel: RadioFrequency,
|
||||
bingo_fuel: Optional[int],
|
||||
joker_fuel: Optional[int],
|
||||
custom_name: Optional[str],
|
||||
) -> None:
|
||||
self.package = package
|
||||
self.country = country
|
||||
@@ -335,6 +341,7 @@ class FlightData:
|
||||
self.bingo_fuel = bingo_fuel
|
||||
self.joker_fuel = joker_fuel
|
||||
self.callsign = create_group_callsign_from_unit(self.units[0])
|
||||
self.custom_name = custom_name
|
||||
|
||||
@property
|
||||
def client_units(self) -> List[FlyingUnit]:
|
||||
@@ -669,6 +676,7 @@ class AircraftConflictGenerator:
|
||||
game: Game,
|
||||
radio_registry: RadioRegistry,
|
||||
unit_map: UnitMap,
|
||||
air_support: AirSupport,
|
||||
) -> None:
|
||||
self.m = mission
|
||||
self.game = game
|
||||
@@ -676,6 +684,7 @@ class AircraftConflictGenerator:
|
||||
self.radio_registry = radio_registry
|
||||
self.unit_map = unit_map
|
||||
self.flights: List[FlightData] = []
|
||||
self.air_support = air_support
|
||||
|
||||
@cached_property
|
||||
def use_client(self) -> bool:
|
||||
@@ -790,7 +799,10 @@ class AircraftConflictGenerator:
|
||||
OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)
|
||||
)
|
||||
|
||||
channel = self.get_intra_flight_channel(unit_type)
|
||||
if flight.flight_type == FlightType.AEWC:
|
||||
channel = self.radio_registry.alloc_uhf()
|
||||
else:
|
||||
channel = self.get_intra_flight_channel(unit_type)
|
||||
group.set_frequency(channel.mhz)
|
||||
|
||||
divert = None
|
||||
@@ -819,6 +831,7 @@ class AircraftConflictGenerator:
|
||||
intra_flight_channel=channel,
|
||||
bingo_fuel=flight.flight_plan.bingo_fuel,
|
||||
joker_fuel=flight.flight_plan.joker_fuel,
|
||||
custom_name=flight.custom_name,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -826,6 +839,20 @@ class AircraftConflictGenerator:
|
||||
if unit_type in [Su_33, C_101EB, C_101CC]:
|
||||
self.set_reduced_fuel(flight, group, unit_type)
|
||||
|
||||
if isinstance(flight.flight_plan, AwacsFlightPlan):
|
||||
callsign = callsign_for_support_unit(group)
|
||||
|
||||
self.air_support.awacs.append(
|
||||
AwacsInfo(
|
||||
dcsGroupName=str(group.name),
|
||||
callsign=callsign,
|
||||
freq=channel,
|
||||
depature_location=flight.departure.name,
|
||||
end_time=flight.flight_plan.mission_departure_time,
|
||||
start_time=flight.flight_plan.mission_start_time,
|
||||
)
|
||||
)
|
||||
|
||||
def _generate_at_airport(
|
||||
self,
|
||||
name: str,
|
||||
@@ -1350,6 +1377,33 @@ class AircraftConflictGenerator:
|
||||
restrict_jettison=True,
|
||||
)
|
||||
|
||||
def configure_awacs(
|
||||
self,
|
||||
group: FlyingGroup,
|
||||
package: Package,
|
||||
flight: Flight,
|
||||
dynamic_runways: Dict[str, RunwayData],
|
||||
) -> None:
|
||||
group.task = AWACS.name
|
||||
|
||||
if not isinstance(flight.flight_plan, AwacsFlightPlan):
|
||||
logging.error(
|
||||
f"Cannot configure AEW&C tasks for {flight} because it does not have an AEW&C flight plan."
|
||||
)
|
||||
return
|
||||
|
||||
self._setup_group(group, AWACS, package, flight, dynamic_runways)
|
||||
|
||||
# Awacs task action
|
||||
self.configure_behavior(
|
||||
group,
|
||||
react_on_threat=OptReactOnThreat.Values.EvadeFire,
|
||||
roe=OptROE.Values.WeaponHold,
|
||||
restrict_jettison=True,
|
||||
)
|
||||
|
||||
group.points[0].tasks.append(AWACSTaskAction())
|
||||
|
||||
def configure_escort(
|
||||
self,
|
||||
group: FlyingGroup,
|
||||
@@ -1386,6 +1440,8 @@ class AircraftConflictGenerator:
|
||||
self.configure_cap(group, package, flight, dynamic_runways)
|
||||
elif flight_type == FlightType.SWEEP:
|
||||
self.configure_sweep(group, package, flight, dynamic_runways)
|
||||
elif flight_type == FlightType.AEWC:
|
||||
self.configure_awacs(group, package, flight, dynamic_runways)
|
||||
elif flight_type in [FlightType.CAS, FlightType.BAI]:
|
||||
self.configure_cas(group, package, flight, dynamic_runways)
|
||||
elif flight_type == FlightType.DEAD:
|
||||
|
||||
239
gen/airfields.py
239
gen/airfields.py
@@ -383,8 +383,8 @@ AIRFIELD_DATA = {
|
||||
"31": ("IVZ", MHz(108, 750)),
|
||||
},
|
||||
),
|
||||
# TODO : PERSIAN GULF MAP
|
||||
"Liwa Airbase": AirfieldData(
|
||||
# PERSIAN GULF MAP
|
||||
"Liwa AFB": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMLW",
|
||||
elevation=400,
|
||||
@@ -394,7 +394,7 @@ AIRFIELD_DATA = {
|
||||
vor=("OMLW", MHz(117, 400)),
|
||||
atc=AtcData(MHz(4, 225), MHz(39, 350), MHz(119, 300), MHz(250, 950)),
|
||||
),
|
||||
"Al Dhafra AB": AirfieldData(
|
||||
"Al Dhafra AFB": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMAM",
|
||||
elevation=52,
|
||||
@@ -402,50 +402,50 @@ AIRFIELD_DATA = {
|
||||
tacan=TacanChannel(96, TacanBand.X),
|
||||
tacan_callsign="MA",
|
||||
vor=("MA", MHz(114, 900)),
|
||||
atc=AtcData(MHz(4, 250), MHz(39, 400), MHz(126, 500), MHz(251, 000)),
|
||||
atc=AtcData(MHz(4, 300), MHz(39, 500), MHz(126, 500), MHz(251, 100)),
|
||||
ils={
|
||||
"13": ("MMA", MHz(111, 100)),
|
||||
"31": ("IMA", MHz(109, 100)),
|
||||
},
|
||||
),
|
||||
"Al-Bateen Airport": AirfieldData(
|
||||
"Al-Bateen": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMAD",
|
||||
elevation=11,
|
||||
runway_length=6808,
|
||||
vor=("ALB", MHz(114, 0)),
|
||||
atc=AtcData(MHz(4, 25), MHz(38, 950), MHz(119, 900), MHz(250, 550)),
|
||||
atc=AtcData(MHz(4, 75), MHz(39, 50), MHz(119, 900), MHz(250, 600)),
|
||||
),
|
||||
"Sas Al Nakheel Airport": AirfieldData(
|
||||
"Sas Al Nakheel": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMNK",
|
||||
elevation=9,
|
||||
runway_length=5387,
|
||||
vor=("SAS", MHz(128, 930)),
|
||||
atc=AtcData(MHz(3, 975), MHz(38, 850), MHz(128, 900), MHz(250, 450)),
|
||||
atc=AtcData(MHz(4, 0), MHz(38, 900), MHz(128, 900), MHz(250, 450)),
|
||||
),
|
||||
"Abu Dhabi International Airport": AirfieldData(
|
||||
"Abu Dhabi Intl": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMAA",
|
||||
elevation=91,
|
||||
runway_length=12817,
|
||||
vor=("ADV", MHz(114, 250)),
|
||||
atc=AtcData(MHz(4, 000), MHz(38, 900), MHz(119, 200), MHz(250, 500)),
|
||||
atc=AtcData(MHz(4, 50), MHz(39, 0), MHz(119, 200), MHz(250, 550)),
|
||||
),
|
||||
"Al Ain International Airport": AirfieldData(
|
||||
"Al Ain Intl": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMAL",
|
||||
elevation=813,
|
||||
runway_length=11267,
|
||||
vor=("ALN", MHz(112, 600)),
|
||||
atc=AtcData(MHz(4, 75), MHz(39, 50), MHz(119, 850), MHz(250, 650)),
|
||||
atc=AtcData(MHz(4, 125), MHz(39, 150), MHz(119, 850), MHz(250, 700)),
|
||||
),
|
||||
"Al Maktoum Intl": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMDW",
|
||||
elevation=123,
|
||||
runway_length=11500,
|
||||
atc=AtcData(MHz(4, 300), MHz(39, 500), MHz(118, 650), MHz(251, 100)),
|
||||
atc=AtcData(MHz(4, 350), MHz(39, 600), MHz(118, 600), MHz(251, 200)),
|
||||
ils={
|
||||
"30": ("IJWA", MHz(109, 750)),
|
||||
"12": ("IMA", MHz(111, 750)),
|
||||
@@ -458,7 +458,7 @@ AIRFIELD_DATA = {
|
||||
runway_length=11865,
|
||||
tacan=TacanChannel(99, TacanBand.X),
|
||||
tacan_callsign="MIN",
|
||||
atc=AtcData(MHz(3, 800), MHz(38, 500), MHz(121, 800), MHz(250, 100)),
|
||||
atc=AtcData(MHz(3, 800), MHz(38, 500), MHz(118, 550), MHz(250, 100)),
|
||||
ils={
|
||||
"27": ("IMNR", MHz(110, 750)),
|
||||
"9": ("IMNW", MHz(110, 700)),
|
||||
@@ -469,7 +469,7 @@ AIRFIELD_DATA = {
|
||||
icao="OMDB",
|
||||
elevation=16,
|
||||
runway_length=11018,
|
||||
atc=AtcData(MHz(4, 275), MHz(39, 450), MHz(118, 750), MHz(251, 50)),
|
||||
atc=AtcData(MHz(4, 325), MHz(39, 550), MHz(118, 750), MHz(251, 150)),
|
||||
ils={
|
||||
"30": ("IDBL", MHz(110, 900)),
|
||||
"12": ("IDBR", MHz(110, 100)),
|
||||
@@ -480,7 +480,7 @@ AIRFIELD_DATA = {
|
||||
icao="OMSJ",
|
||||
elevation=98,
|
||||
runway_length=10535,
|
||||
atc=AtcData(MHz(3, 850), MHz(38, 600), MHz(118, 600), MHz(252, 200)),
|
||||
atc=AtcData(MHz(3, 850), MHz(38, 600), MHz(118, 600), MHz(250, 200)),
|
||||
ils={
|
||||
"30": ("ISHW", MHz(111, 950)),
|
||||
"12": ("ISRE", MHz(108, 550)),
|
||||
@@ -492,18 +492,18 @@ AIRFIELD_DATA = {
|
||||
elevation=60,
|
||||
runway_length=9437,
|
||||
vor=("FJV", MHz(113, 800)),
|
||||
atc=AtcData(MHz(4, 325), MHz(39, 550), MHz(124, 600), MHz(251, 150)),
|
||||
atc=AtcData(MHz(4, 375), MHz(39, 650), MHz(124, 600), MHz(251, 250)),
|
||||
ils={
|
||||
"29": ("IFJR", MHz(111, 500)),
|
||||
},
|
||||
),
|
||||
"Ras AL Khaimah": AirfieldData(
|
||||
"Ras Al Khaimah Intl": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OMRK",
|
||||
elevation=70,
|
||||
runway_length=8406,
|
||||
vor=("OMRK", MHz(113, 600)),
|
||||
atc=AtcData(MHz(4, 150), MHz(39, 200), MHz(121, 600), MHz(250, 800)),
|
||||
atc=AtcData(MHz(4, 200), MHz(39, 300), MHz(121, 600), MHz(250, 900)),
|
||||
),
|
||||
"Khasab": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
@@ -516,7 +516,11 @@ AIRFIELD_DATA = {
|
||||
},
|
||||
),
|
||||
"Sir Abu Nuayr": AirfieldData(
|
||||
theater="Persian Gulf", icao="OMSN", elevation=25, runway_length=2229
|
||||
theater="Persian Gulf",
|
||||
icao="OMSN",
|
||||
elevation=25,
|
||||
runway_length=2229,
|
||||
atc=AtcData(MHz(3, 900), MHz(38, 700), MHz(118, 0), MHz(250, 800)),
|
||||
),
|
||||
"Sirri Island": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
@@ -526,7 +530,7 @@ AIRFIELD_DATA = {
|
||||
vor=("SIR", MHz(113, 750)),
|
||||
atc=AtcData(MHz(3, 875), MHz(38, 650), MHz(135, 50), MHz(250, 250)),
|
||||
),
|
||||
"Abu Musa Island Airport": AirfieldData(
|
||||
"Abu Musa Island": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OIBA",
|
||||
elevation=16,
|
||||
@@ -555,13 +559,13 @@ AIRFIELD_DATA = {
|
||||
vor=("KHM", MHz(117, 100)),
|
||||
atc=AtcData(MHz(3, 825), MHz(38, 550), MHz(118, 50), MHz(250, 150)),
|
||||
),
|
||||
"Bandar-e-Jask airfield": AirfieldData(
|
||||
"Bandar-e-Jask": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OIZJ",
|
||||
elevation=26,
|
||||
runway_length=6842,
|
||||
vor=("KHM", MHz(116, 300)),
|
||||
atc=AtcData(MHz(3, 825), MHz(38, 550), MHz(118, 50), MHz(250, 150)),
|
||||
atc=AtcData(MHz(4, 25), MHz(38, 950), MHz(118, 150), MHz(250, 500)),
|
||||
),
|
||||
"Bandar Lengeh": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
@@ -569,26 +573,26 @@ AIRFIELD_DATA = {
|
||||
elevation=80,
|
||||
runway_length=7625,
|
||||
vor=("LEN", MHz(114, 800)),
|
||||
atc=AtcData(MHz(4, 225), MHz(39, 350), MHz(121, 700), MHz(250, 950)),
|
||||
atc=AtcData(MHz(4, 275), MHz(39, 450), MHz(121, 700), MHz(251, 50)),
|
||||
),
|
||||
"Kish International Airport": AirfieldData(
|
||||
"Kish Intl": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OIBK",
|
||||
elevation=114,
|
||||
runway_length=10617,
|
||||
tacan=TacanChannel(112, TacanBand.X),
|
||||
tacan_callsign="KIH",
|
||||
atc=AtcData(MHz(4, 50), MHz(39, 000), MHz(121, 650), MHz(250, 600)),
|
||||
atc=AtcData(MHz(4, 100), MHz(39, 100), MHz(121, 650), MHz(250, 650)),
|
||||
),
|
||||
"Lavan Island Airport": AirfieldData(
|
||||
"Lavan Island": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OIBV",
|
||||
elevation=75,
|
||||
runway_length=8234,
|
||||
vor=("LVA", MHz(116, 850)),
|
||||
atc=AtcData(MHz(4, 100), MHz(39, 100), MHz(128, 550), MHz(250, 700)),
|
||||
atc=AtcData(MHz(4, 150), MHz(39, 200), MHz(128, 550), MHz(250, 750)),
|
||||
),
|
||||
"Lar Airbase": AirfieldData(
|
||||
"Lar": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OISL",
|
||||
elevation=2635,
|
||||
@@ -603,7 +607,7 @@ AIRFIELD_DATA = {
|
||||
runway_length=7300,
|
||||
tacan=TacanChannel(47, TacanBand.X),
|
||||
tacan_callsign="HDR",
|
||||
atc=AtcData(MHz(4, 350), MHz(39, 600), MHz(123, 150), MHz(251, 200)),
|
||||
atc=AtcData(MHz(4, 400), MHz(39, 700), MHz(123, 150), MHz(251, 300)),
|
||||
ils={
|
||||
"8": ("IBHD", MHz(108, 900)),
|
||||
},
|
||||
@@ -616,19 +620,19 @@ AIRFIELD_DATA = {
|
||||
tacan=TacanChannel(78, TacanBand.X),
|
||||
tacan_callsign="BND",
|
||||
vor=("BND", MHz(117, 200)),
|
||||
atc=AtcData(MHz(4, 200), MHz(39, 300), MHz(118, 100), MHz(250, 900)),
|
||||
atc=AtcData(MHz(4, 250), MHz(39, 401), MHz(118, 100), MHz(251, 0)),
|
||||
ils={
|
||||
"21": ("IBND", MHz(333, 800)),
|
||||
},
|
||||
),
|
||||
"Jiroft Airport": AirfieldData(
|
||||
"Jiroft": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OIKJ",
|
||||
elevation=2664,
|
||||
runway_length=9160,
|
||||
atc=AtcData(MHz(4, 125), MHz(39, 120), MHz(136, 0), MHz(250, 750)),
|
||||
),
|
||||
"Kerman Airport": AirfieldData(
|
||||
"Kerman": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OIKK",
|
||||
elevation=5746,
|
||||
@@ -636,9 +640,9 @@ AIRFIELD_DATA = {
|
||||
tacan=TacanChannel(97, TacanBand.X),
|
||||
tacan_callsign="KER",
|
||||
vor=("KER", MHz(112, 0)),
|
||||
atc=AtcData(MHz(3, 900), MHz(38, 700), MHz(118, 250), MHz(250, 300)),
|
||||
atc=AtcData(MHz(3, 925), MHz(38, 750), MHz(118, 250), MHz(250, 300)),
|
||||
),
|
||||
"Shiraz International Airport": AirfieldData(
|
||||
"Shiraz Intl": AirfieldData(
|
||||
theater="Persian Gulf",
|
||||
icao="OISS",
|
||||
elevation=4878,
|
||||
@@ -646,7 +650,7 @@ AIRFIELD_DATA = {
|
||||
tacan=TacanChannel(94, TacanBand.X),
|
||||
tacan_callsign="SYZ1",
|
||||
vor=("SYZ", MHz(112, 0)),
|
||||
atc=AtcData(MHz(3, 925), MHz(38, 750), MHz(121, 900), MHz(250, 350)),
|
||||
atc=AtcData(MHz(3, 950), MHz(38, 800), MHz(121, 900), MHz(250, 350)),
|
||||
),
|
||||
# Syria Map
|
||||
"Adana Sakirpasa": AirfieldData(
|
||||
@@ -655,7 +659,7 @@ AIRFIELD_DATA = {
|
||||
elevation=55,
|
||||
runway_length=8115,
|
||||
vor=("ADA", MHz(112, 700)),
|
||||
atc=AtcData(MHz(4, 225), MHz(39, 350), MHz(121, 100), MHz(250, 900)),
|
||||
atc=AtcData(MHz(4, 275), MHz(39, 450), MHz(121, 100), MHz(251, 0)),
|
||||
ils={
|
||||
"05": ("IADA", MHz(108, 700)),
|
||||
},
|
||||
@@ -668,7 +672,7 @@ AIRFIELD_DATA = {
|
||||
tacan=TacanChannel(21, TacanBand.X),
|
||||
tacan_callsign="DAN",
|
||||
vor=("DAN", MHz(108, 400)),
|
||||
atc=AtcData(MHz(3, 850), MHz(38, 600), MHz(129, 400), MHz(360, 100)),
|
||||
atc=AtcData(MHz(3, 900), MHz(38, 700), MHz(122, 100), MHz(360, 100)),
|
||||
ils={
|
||||
"50": ("IDAN", MHz(109, 300)),
|
||||
"23": ("DANM", MHz(111, 700)),
|
||||
@@ -679,7 +683,7 @@ AIRFIELD_DATA = {
|
||||
icao="OS71",
|
||||
elevation=1614,
|
||||
runway_length=4648,
|
||||
atc=AtcData(MHz(4, 125), MHz(39, 150), MHz(120, 600), MHz(250, 700)),
|
||||
atc=AtcData(MHz(4, 175), MHz(39, 250), MHz(120, 600), MHz(250, 800)),
|
||||
),
|
||||
"Hatay": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -687,7 +691,7 @@ AIRFIELD_DATA = {
|
||||
elevation=253,
|
||||
runway_length=9052,
|
||||
vor=("HTY", MHz(112, 500)),
|
||||
atc=AtcData(MHz(3, 825), MHz(38, 550), MHz(128, 500), MHz(250, 150)),
|
||||
atc=AtcData(MHz(3, 875), MHz(38, 650), MHz(128, 500), MHz(250, 250)),
|
||||
ils={
|
||||
"22": ("IHTY", MHz(108, 150)),
|
||||
"04": ("IHAT", MHz(108, 900)),
|
||||
@@ -698,25 +702,21 @@ AIRFIELD_DATA = {
|
||||
icao="OS66",
|
||||
elevation=1200,
|
||||
runway_length=6662,
|
||||
atc=AtcData(MHz(4, 275), MHz(39, 450), MHz(120, 500), MHz(251)),
|
||||
atc=AtcData(MHz(4, 325), MHz(39, 550), MHz(120, 500), MHz(251, 100)),
|
||||
),
|
||||
"Aleppo": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OSAP",
|
||||
elevation=1253,
|
||||
runway_length=8332,
|
||||
atc=AtcData(MHz(4, 150), MHz(39, 200), MHz(119, 100), MHz(250, 750)),
|
||||
ils={
|
||||
"50": ("IDAN", MHz(109, 300)),
|
||||
"23": ("DANM", MHz(111, 700)),
|
||||
},
|
||||
atc=AtcData(MHz(4, 200), MHz(39, 300), MHz(119, 100), MHz(250, 850)),
|
||||
),
|
||||
"Jirah": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS62",
|
||||
elevation=1170,
|
||||
runway_length=9090,
|
||||
atc=AtcData(MHz(3, 875), MHz(38, 650), MHz(118, 100), MHz(250, 200)),
|
||||
atc=AtcData(MHz(3, 925), MHz(38, 750), MHz(118, 100), MHz(250, 300)),
|
||||
),
|
||||
"Taftanaz": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -729,14 +729,14 @@ AIRFIELD_DATA = {
|
||||
icao="OS59",
|
||||
elevation=1083,
|
||||
runway_length=9036,
|
||||
atc=AtcData(MHz(4, 350), MHz(39, 600), MHz(118, 500), MHz(251, 150)),
|
||||
atc=AtcData(MHz(4, 500), MHz(39, 900), MHz(122, 800), MHz(251, 450)),
|
||||
),
|
||||
"Abu al-Dahur": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS57",
|
||||
elevation=820,
|
||||
runway_length=8728,
|
||||
atc=AtcData(MHz(3, 950), MHz(38, 800), MHz(122, 200), MHz(250, 350)),
|
||||
atc=AtcData(MHz(4, 0), MHz(38, 900), MHz(122, 200), MHz(250, 450)),
|
||||
),
|
||||
"Bassel Al-Assad": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -744,7 +744,7 @@ AIRFIELD_DATA = {
|
||||
elevation=93,
|
||||
runway_length=7305,
|
||||
vor=("LTK", MHz(114, 800)),
|
||||
atc=AtcData(MHz(4), MHz(38, 900), MHz(118, 100), MHz(250, 450)),
|
||||
atc=AtcData(MHz(4, 50), MHz(39, 0), MHz(118, 100), MHz(250, 550)),
|
||||
ils={
|
||||
"17": ("IBA", MHz(109, 100)),
|
||||
},
|
||||
@@ -754,28 +754,28 @@ AIRFIELD_DATA = {
|
||||
icao="OS58",
|
||||
elevation=983,
|
||||
runway_length=7957,
|
||||
atc=AtcData(MHz(3, 800), MHz(38, 500), MHz(118, 50), MHz(250, 100)),
|
||||
atc=AtcData(MHz(3, 850), MHz(38, 600), MHz(118, 50), MHz(250, 200)),
|
||||
),
|
||||
"Rene Mouawad": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OLKA",
|
||||
elevation=14,
|
||||
runway_length=8614,
|
||||
atc=AtcData(MHz(4, 325), MHz(39, 550), MHz(129, 500), MHz(251, 100)),
|
||||
atc=AtcData(MHz(4, 375), MHz(39, 650), MHz(121, 0), MHz(251, 200)),
|
||||
),
|
||||
"Al Quasayr": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS70",
|
||||
elevation=1729,
|
||||
runway_length=8585,
|
||||
atc=AtcData(MHz(4, 400), MHz(39, 700), MHz(119, 200), MHz(251, 250)),
|
||||
atc=AtcData(MHz(4, 550), MHz(40, 0), MHz(119, 200), MHz(251, 550)),
|
||||
),
|
||||
"Palmyra": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OSPR",
|
||||
elevation=1267,
|
||||
runway_length=8704,
|
||||
atc=AtcData(MHz(4, 175), MHz(39, 250), MHz(121, 900), MHz(250, 800)),
|
||||
atc=AtcData(MHz(4, 225), MHz(39, 350), MHz(121, 900), MHz(250, 900)),
|
||||
),
|
||||
"Wujah Al Hajar": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -783,14 +783,14 @@ AIRFIELD_DATA = {
|
||||
elevation=619,
|
||||
runway_length=4717,
|
||||
vor=("CAK", MHz(116, 200)),
|
||||
atc=AtcData(MHz(4, 425), MHz(39, 750), MHz(121, 500), MHz(251, 300)),
|
||||
atc=AtcData(MHz(4, 575), MHz(40, 50), MHz(121, 500), MHz(251, 600)),
|
||||
),
|
||||
"An Nasiriyah": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS64",
|
||||
elevation=2746,
|
||||
runway_length=8172,
|
||||
atc=AtcData(MHz(4, 450), MHz(39, 800), MHz(122, 300), MHz(251, 350)),
|
||||
atc=AtcData(MHz(4, 600), MHz(40, 100), MHz(122, 300), MHz(251, 650)),
|
||||
),
|
||||
"Rayak": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -798,7 +798,7 @@ AIRFIELD_DATA = {
|
||||
elevation=2934,
|
||||
runway_length=8699,
|
||||
vor=("HTY", MHz(124, 400)),
|
||||
atc=AtcData(MHz(4, 300), MHz(39, 500), MHz(124, 400), MHz(251, 50)),
|
||||
atc=AtcData(MHz(4, 350), MHz(39, 600), MHz(124, 400), MHz(251, 150)),
|
||||
),
|
||||
"Beirut-Rafic Hariri": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -806,7 +806,7 @@ AIRFIELD_DATA = {
|
||||
elevation=39,
|
||||
runway_length=9463,
|
||||
vor=("KAD", MHz(112, 600)),
|
||||
atc=AtcData(MHz(4, 475), MHz(39, 850), MHz(118, 900), MHz(251, 400)),
|
||||
atc=AtcData(MHz(4, 675), MHz(40, 250), MHz(118, 900), MHz(251, 800)),
|
||||
ils={
|
||||
"17": ("BIL", MHz(109, 500)),
|
||||
},
|
||||
@@ -816,32 +816,32 @@ AIRFIELD_DATA = {
|
||||
icao="OS61",
|
||||
elevation=2066,
|
||||
runway_length=8902,
|
||||
atc=AtcData(MHz(4, 550), MHz(40), MHz(120, 300), MHz(251, 550)),
|
||||
atc=AtcData(MHz(4, 750), MHz(40, 400), MHz(120, 300), MHz(251, 950)),
|
||||
),
|
||||
"Marj as Sultan North": AirfieldData(
|
||||
theater="Syria",
|
||||
elevation=2007,
|
||||
runway_length=268,
|
||||
atc=AtcData(MHz(4, 25), MHz(38, 950), MHz(122, 700), MHz(250, 500)),
|
||||
atc=AtcData(MHz(4, 75), MHz(38, 50), MHz(122, 700), MHz(250, 600)),
|
||||
),
|
||||
"Marj as Sultan South": AirfieldData(
|
||||
theater="Syria",
|
||||
elevation=2007,
|
||||
runway_length=166,
|
||||
atc=AtcData(MHz(4, 525), MHz(39, 950), MHz(122, 900), MHz(251, 500)),
|
||||
atc=AtcData(MHz(4, 725), MHz(40, 350), MHz(122, 900), MHz(251, 900)),
|
||||
),
|
||||
"Mezzeh": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS67",
|
||||
elevation=2355,
|
||||
runway_length=7522,
|
||||
atc=AtcData(MHz(4, 100), MHz(39, 100), MHz(120, 700), MHz(250, 650)),
|
||||
atc=AtcData(MHz(4, 150), MHz(39, 200), MHz(120, 700), MHz(250, 750)),
|
||||
),
|
||||
"Qabr as Sitt": AirfieldData(
|
||||
theater="Syria",
|
||||
elevation=2134,
|
||||
runway_length=489,
|
||||
atc=AtcData(MHz(4, 200), MHz(39, 300), MHz(122, 600), MHz(250, 850)),
|
||||
atc=AtcData(MHz(4, 250), MHz(39, 400), MHz(122, 600), MHz(250, 950)),
|
||||
),
|
||||
"Damascus": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -849,7 +849,7 @@ AIRFIELD_DATA = {
|
||||
elevation=2007,
|
||||
runway_length=11423,
|
||||
vor=("DAM", MHz(116)),
|
||||
atc=AtcData(MHz(4, 500), MHz(39, 900), MHz(118, 500), MHz(251, 450)),
|
||||
atc=AtcData(MHz(4, 700), MHz(40, 300), MHz(118, 500), MHz(251, 850)),
|
||||
ils={
|
||||
"24": ("IDA", MHz(109, 900)),
|
||||
},
|
||||
@@ -859,42 +859,42 @@ AIRFIELD_DATA = {
|
||||
icao="OS63",
|
||||
elevation=2160,
|
||||
runway_length=7576,
|
||||
atc=AtcData(MHz(4, 50), MHz(39), MHz(120, 800), MHz(250, 550)),
|
||||
atc=AtcData(MHz(4, 100), MHz(39, 100), MHz(120, 800), MHz(250, 6550)),
|
||||
),
|
||||
"Kiryat Shmona": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="LLKS",
|
||||
elevation=328,
|
||||
runway_length=3258,
|
||||
atc=AtcData(MHz(3, 975), MHz(38, 850), MHz(118, 400), MHz(250, 400)),
|
||||
atc=AtcData(MHz(4, 25), MHz(38, 950), MHz(118, 400), MHz(250, 500)),
|
||||
),
|
||||
"Khalkhalah": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS69",
|
||||
elevation=2337,
|
||||
runway_length=8248,
|
||||
atc=AtcData(MHz(3, 900), MHz(38, 700), MHz(122, 500), MHz(250, 250)),
|
||||
atc=AtcData(MHz(3, 950), MHz(38, 800), MHz(122, 500), MHz(250, 350)),
|
||||
),
|
||||
"Haifa": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="LLHA",
|
||||
elevation=19,
|
||||
runway_length=3253,
|
||||
atc=AtcData(MHz(3, 775), MHz(38, 450), MHz(127, 800), MHz(250, 50)),
|
||||
atc=AtcData(MHz(3, 825), MHz(38, 550), MHz(127, 800), MHz(250, 150)),
|
||||
),
|
||||
"Ramat David": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="LLRD",
|
||||
elevation=105,
|
||||
runway_length=7037,
|
||||
atc=AtcData(MHz(4, 250), MHz(39, 400), MHz(118, 600), MHz(250, 950)),
|
||||
atc=AtcData(MHz(4, 300), MHz(39, 500), MHz(118, 600), MHz(251, 50)),
|
||||
),
|
||||
"Megiddo": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="LLMG",
|
||||
elevation=180,
|
||||
runway_length=6098,
|
||||
atc=AtcData(MHz(4, 75), MHz(39, 50), MHz(119, 900), MHz(250, 600)),
|
||||
atc=AtcData(MHz(4, 125), MHz(39, 150), MHz(119, 900), MHz(250, 700)),
|
||||
),
|
||||
"Eyn Shemer": AirfieldData(
|
||||
theater="Syria",
|
||||
@@ -908,7 +908,66 @@ AIRFIELD_DATA = {
|
||||
icao="OJMF",
|
||||
elevation=2204,
|
||||
runway_length=8595,
|
||||
atc=AtcData(MHz(3, 925), MHz(38, 750), MHz(118, 300), MHz(250, 300)),
|
||||
atc=AtcData(MHz(3, 975), MHz(38, 850), MHz(118, 300), MHz(250, 400)),
|
||||
),
|
||||
"Tha'lah": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS60",
|
||||
elevation=2381,
|
||||
runway_length=8025,
|
||||
atc=AtcData(MHz(4, 650), MHz(40, 200), MHz(122, 400), MHz(251, 750)),
|
||||
),
|
||||
"Shayrat": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS60",
|
||||
elevation=2637,
|
||||
runway_length=8553,
|
||||
atc=AtcData(MHz(4, 450), MHz(39, 800), MHz(122, 200), MHz(251, 350)),
|
||||
),
|
||||
"Tiyas": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS72",
|
||||
elevation=1797,
|
||||
runway_length=9420,
|
||||
atc=AtcData(MHz(4, 525), MHz(39, 950), MHz(120, 500), MHz(251, 500)),
|
||||
),
|
||||
"Rosh Pina": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="LLIB",
|
||||
elevation=865,
|
||||
runway_length=2711,
|
||||
atc=AtcData(MHz(4, 400), MHz(39, 700), MHz(118, 450), MHz(251, 250)),
|
||||
),
|
||||
"Sayqal": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OS68",
|
||||
elevation=2273,
|
||||
runway_length=8536,
|
||||
atc=AtcData(MHz(4, 425), MHz(39, 750), MHz(120, 400), MHz(251, 300)),
|
||||
),
|
||||
"H4": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="OJHR",
|
||||
elevation=2257,
|
||||
runway_length=7179,
|
||||
atc=AtcData(MHz(3, 800), MHz(38, 500), MHz(120, 400), MHz(250, 100)),
|
||||
),
|
||||
"Naqoura": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="",
|
||||
elevation=378,
|
||||
runway_length=0,
|
||||
atc=AtcData(MHz(4, 625), MHz(40, 150), MHz(122, 000), MHz(251, 700)),
|
||||
),
|
||||
"Gaziantep": AirfieldData(
|
||||
theater="Syria",
|
||||
icao="LTAJ",
|
||||
elevation=2287,
|
||||
runway_length=8871,
|
||||
atc=AtcData(MHz(3, 775), MHz(38, 450), MHz(120, 100), MHz(250, 50)),
|
||||
ils={
|
||||
"28": ("IGNP", MHz(109, 10)),
|
||||
},
|
||||
),
|
||||
# NTTR
|
||||
"Mina Airport 3Q0": AirfieldData(
|
||||
@@ -1304,55 +1363,73 @@ AIRFIELD_DATA = {
|
||||
"Detling": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=623,
|
||||
runway_length=2557,
|
||||
atc=AtcData(MHz(3, 950), MHz(118, 400), MHz(38, 800), MHz(250, 400)),
|
||||
runway_length=3482,
|
||||
atc=AtcData(MHz(4, 50), MHz(118, 600), MHz(39, 0), MHz(250, 600)),
|
||||
),
|
||||
"High Halden": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=104,
|
||||
runway_length=3296,
|
||||
atc=AtcData(MHz(3, 750), MHz(118, 800), MHz(38, 400), MHz(250, 0)),
|
||||
atc=AtcData(MHz(3, 800), MHz(118, 100), MHz(38, 500), MHz(250, 100)),
|
||||
),
|
||||
"Lympne": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=351,
|
||||
runway_length=2548,
|
||||
atc=AtcData(MHz(3, 925), MHz(118, 350), MHz(38, 750), MHz(250, 350)),
|
||||
runway_length=3054,
|
||||
atc=AtcData(MHz(4, 25), MHz(118, 550), MHz(38, 950), MHz(250, 550)),
|
||||
),
|
||||
"Hawkinge": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=524,
|
||||
runway_length=3013,
|
||||
atc=AtcData(MHz(3, 900), MHz(118, 300), MHz(38, 700), MHz(250, 300)),
|
||||
atc=AtcData(MHz(4, 0), MHz(118, 500), MHz(38, 900), MHz(250, 500)),
|
||||
),
|
||||
"Manston": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=160,
|
||||
runway_length=8626,
|
||||
atc=AtcData(MHz(3, 875), MHz(118, 250), MHz(38, 650), MHz(250, 250)),
|
||||
atc=AtcData(MHz(3, 975), MHz(118, 250), MHz(38, 650), MHz(250, 250)),
|
||||
),
|
||||
"Dunkirk Mardyck": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=16,
|
||||
runway_length=1737,
|
||||
atc=AtcData(MHz(3, 850), MHz(118, 200), MHz(38, 600), MHz(250, 200)),
|
||||
atc=AtcData(MHz(3, 950), MHz(118, 450), MHz(38, 850), MHz(250, 450)),
|
||||
),
|
||||
"Saint Omer Longuenesse": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=219,
|
||||
runway_length=1929,
|
||||
atc=AtcData(MHz(3, 825), MHz(118, 150), MHz(38, 550), MHz(250, 150)),
|
||||
atc=AtcData(MHz(3, 925), MHz(118, 350), MHz(38, 750), MHz(250, 350)),
|
||||
),
|
||||
"Merville Calonne": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=52,
|
||||
runway_length=7580,
|
||||
atc=AtcData(MHz(3, 800), MHz(118, 100), MHz(38, 500), MHz(250, 100)),
|
||||
atc=AtcData(MHz(3, 900), MHz(118, 300), MHz(38, 700), MHz(250, 300)),
|
||||
),
|
||||
"Abbeville Drucat": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=183,
|
||||
runway_length=4726,
|
||||
atc=AtcData(MHz(3, 875), MHz(118, 250), MHz(38, 650), MHz(250, 250)),
|
||||
),
|
||||
"Eastchurch": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=30,
|
||||
runway_length=2983,
|
||||
atc=AtcData(MHz(3, 775), MHz(118, 50), MHz(38, 450), MHz(250, 50)),
|
||||
),
|
||||
"Headcorn": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=114,
|
||||
runway_length=3680,
|
||||
atc=AtcData(MHz(3, 825), MHz(118, 150), MHz(38, 550), MHz(250, 150)),
|
||||
),
|
||||
"Biggin Hill": AirfieldData(
|
||||
theater="Channel",
|
||||
elevation=552,
|
||||
runway_length=3953,
|
||||
atc=AtcData(MHz(3, 850), MHz(118, 200), MHz(38, 600), MHz(250, 200)),
|
||||
),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Type, Tuple
|
||||
from datetime import timedelta
|
||||
from typing import List, Type, Tuple, Optional
|
||||
|
||||
from dcs.mission import Mission, StartType
|
||||
from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135
|
||||
@@ -21,6 +22,7 @@ from .conflictgen import Conflict
|
||||
from .radios import RadioFrequency, RadioRegistry
|
||||
from .tacan import TacanBand, TacanChannel, TacanRegistry
|
||||
|
||||
|
||||
TANKER_DISTANCE = 15000
|
||||
TANKER_ALT = 4572
|
||||
TANKER_HEADING_OFFSET = 45
|
||||
@@ -36,6 +38,9 @@ class AwacsInfo:
|
||||
dcsGroupName: str
|
||||
callsign: str
|
||||
freq: RadioFrequency
|
||||
depature_location: Optional[str]
|
||||
start_time: Optional[timedelta]
|
||||
end_time: Optional[timedelta]
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -163,37 +168,41 @@ class AirSupportConflictGenerator:
|
||||
TankerInfo(str(tanker_group.name), callsign, variant, freq, tacan)
|
||||
)
|
||||
|
||||
possible_awacs = db.find_unittype(AWACS, self.conflict.attackers_side)
|
||||
if not self.game.settings.disable_legacy_aewc:
|
||||
possible_awacs = db.find_unittype(AWACS, self.conflict.attackers_side)
|
||||
|
||||
if len(possible_awacs) > 0:
|
||||
awacs_unit = possible_awacs[0]
|
||||
freq = self.radio_registry.alloc_uhf()
|
||||
if len(possible_awacs) > 0:
|
||||
awacs_unit = possible_awacs[0]
|
||||
freq = self.radio_registry.alloc_uhf()
|
||||
|
||||
awacs_flight = self.mission.awacs_flight(
|
||||
country=self.mission.country(self.game.player_country),
|
||||
name=namegen.next_awacs_name(
|
||||
self.mission.country(self.game.player_country)
|
||||
),
|
||||
plane_type=awacs_unit,
|
||||
altitude=AWACS_ALT,
|
||||
airport=None,
|
||||
position=self.conflict.position.random_point_within(
|
||||
AWACS_DISTANCE, AWACS_DISTANCE
|
||||
),
|
||||
frequency=freq.mhz,
|
||||
start_type=StartType.Warm,
|
||||
)
|
||||
awacs_flight.set_frequency(freq.mhz)
|
||||
|
||||
awacs_flight.points[0].tasks.append(SetInvisibleCommand(True))
|
||||
awacs_flight.points[0].tasks.append(SetImmortalCommand(True))
|
||||
|
||||
self.air_support.awacs.append(
|
||||
AwacsInfo(
|
||||
str(awacs_flight.name),
|
||||
callsign_for_support_unit(awacs_flight),
|
||||
freq,
|
||||
awacs_flight = self.mission.awacs_flight(
|
||||
country=self.mission.country(self.game.player_country),
|
||||
name=namegen.next_awacs_name(
|
||||
self.mission.country(self.game.player_country)
|
||||
),
|
||||
plane_type=awacs_unit,
|
||||
altitude=AWACS_ALT,
|
||||
airport=None,
|
||||
position=self.conflict.position.random_point_within(
|
||||
AWACS_DISTANCE, AWACS_DISTANCE
|
||||
),
|
||||
frequency=freq.mhz,
|
||||
start_type=StartType.Warm,
|
||||
)
|
||||
)
|
||||
else:
|
||||
logging.warning("No AWACS for faction")
|
||||
awacs_flight.set_frequency(freq.mhz)
|
||||
|
||||
awacs_flight.points[0].tasks.append(SetInvisibleCommand(True))
|
||||
awacs_flight.points[0].tasks.append(SetImmortalCommand(True))
|
||||
|
||||
self.air_support.awacs.append(
|
||||
AwacsInfo(
|
||||
dcsGroupName=str(awacs_flight.name),
|
||||
callsign=callsign_for_support_unit(awacs_flight),
|
||||
freq=freq,
|
||||
depature_location=None,
|
||||
start_time=None,
|
||||
end_time=None,
|
||||
)
|
||||
)
|
||||
else:
|
||||
logging.warning("No AWACS for faction")
|
||||
|
||||
@@ -175,6 +175,7 @@ class Package:
|
||||
FlightType.SEAD,
|
||||
FlightType.TARCAP,
|
||||
FlightType.BARCAP,
|
||||
FlightType.AEWC,
|
||||
FlightType.SWEEP,
|
||||
FlightType.ESCORT,
|
||||
]
|
||||
|
||||
@@ -20,6 +20,7 @@ from .ground_forces.combat_stance import CombatStance
|
||||
from .radios import RadioFrequency
|
||||
from .runways import RunwayData
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
|
||||
|
||||
31
gen/coastal/coastal_group_generator.py
Normal file
31
gen/coastal/coastal_group_generator.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import logging
|
||||
import random
|
||||
from game import db
|
||||
from gen.coastal.silkworm import SilkwormGenerator
|
||||
|
||||
COASTAL_MAP = {
|
||||
"SilkwormGenerator": SilkwormGenerator,
|
||||
}
|
||||
|
||||
|
||||
def generate_coastal_group(game, ground_object, faction_name: str):
|
||||
"""
|
||||
This generate a coastal defenses group
|
||||
:return: Nothing, but put the group reference inside the ground object
|
||||
"""
|
||||
faction = db.FACTIONS[faction_name]
|
||||
if len(faction.coastal_defenses) > 0:
|
||||
generators = faction.coastal_defenses
|
||||
if len(generators) > 0:
|
||||
gen = random.choice(generators)
|
||||
if gen in COASTAL_MAP.keys():
|
||||
generator = COASTAL_MAP[gen](game, ground_object, faction)
|
||||
generator.generate()
|
||||
return generator.get_generated_group()
|
||||
else:
|
||||
logging.info(
|
||||
"Unable to generate missile group, generator : "
|
||||
+ str(gen)
|
||||
+ "does not exists"
|
||||
)
|
||||
return None
|
||||
58
gen/coastal/silkworm.py
Normal file
58
gen/coastal/silkworm.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from dcs.vehicles import MissilesSS, Unarmed, AirDefence
|
||||
|
||||
from gen.sam.group_generator import GroupGenerator
|
||||
|
||||
|
||||
class SilkwormGenerator(GroupGenerator):
|
||||
def __init__(self, game, ground_object, faction):
|
||||
super(SilkwormGenerator, self).__init__(game, ground_object)
|
||||
self.faction = faction
|
||||
|
||||
def generate(self):
|
||||
|
||||
positions = self.get_circular_position(5, launcher_distance=120, coverage=180)
|
||||
|
||||
self.add_unit(
|
||||
MissilesSS.AShM_Silkworm_SR,
|
||||
"SR#0",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Launchers
|
||||
for i, p in enumerate(positions):
|
||||
self.add_unit(
|
||||
MissilesSS.AShM_SS_N_2_Silkworm,
|
||||
"Missile#" + str(i),
|
||||
p[0],
|
||||
p[1],
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Commander
|
||||
self.add_unit(
|
||||
Unarmed.Truck_KAMAZ_43101,
|
||||
"KAMAZ#0",
|
||||
self.position.x - 35,
|
||||
self.position.y - 20,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Shorad
|
||||
self.add_unit(
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
"SHILKA#0",
|
||||
self.position.x - 55,
|
||||
self.position.y - 38,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Shorad 2
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL,
|
||||
"STRELA#0",
|
||||
self.position.x + 200,
|
||||
self.position.y + 15,
|
||||
90,
|
||||
)
|
||||
@@ -17,6 +17,7 @@ class EnvironmentGenerator:
|
||||
self.mission.weather.clouds_thickness = clouds.thickness
|
||||
self.mission.weather.clouds_density = clouds.density
|
||||
self.mission.weather.clouds_iprecptns = clouds.precipitation
|
||||
self.mission.weather.clouds_preset = clouds.preset
|
||||
|
||||
def set_fog(self, fog: Optional[Fog]) -> None:
|
||||
if fog is None:
|
||||
|
||||
@@ -2,50 +2,122 @@ import random
|
||||
|
||||
from gen.sam.group_generator import ShipGroupGenerator
|
||||
|
||||
from dcs.ships import DDG_Arleigh_Burke_IIa, CG_Ticonderoga
|
||||
|
||||
|
||||
class CarrierGroupGenerator(ShipGroupGenerator):
|
||||
def generate(self):
|
||||
|
||||
# Add carrier
|
||||
if len(self.faction.aircraft_carrier) > 0:
|
||||
# Carrier Strike Group 8
|
||||
if self.faction.carrier_names[0] == "Carrier Strike Group 8":
|
||||
carrier_type = random.choice(self.faction.aircraft_carrier)
|
||||
|
||||
self.add_unit(
|
||||
carrier_type, "Carrier", self.position.x, self.position.y, self.heading
|
||||
carrier_type,
|
||||
"CVN-75 Harry S. Truman",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Add Arleigh Burke escort
|
||||
self.add_unit(
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
"USS Ramage",
|
||||
self.position.x + 6482,
|
||||
self.position.y + 6667,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
self.add_unit(
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
"USS Mitscher",
|
||||
self.position.x - 7963,
|
||||
self.position.y + 7037,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
self.add_unit(
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
"USS Forrest Sherman",
|
||||
self.position.x - 7408,
|
||||
self.position.y - 7408,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
self.add_unit(
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
"USS Lassen",
|
||||
self.position.x + 8704,
|
||||
self.position.y - 6296,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Add Ticonderoga escort
|
||||
if self.heading >= 180:
|
||||
self.add_unit(
|
||||
CG_Ticonderoga,
|
||||
"USS Hué City",
|
||||
self.position.x + 2222,
|
||||
self.position.y - 3333,
|
||||
self.heading,
|
||||
)
|
||||
else:
|
||||
self.add_unit(
|
||||
CG_Ticonderoga,
|
||||
"USS Hué City",
|
||||
self.position.x - 3333,
|
||||
self.position.y + 2222,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
self.get_generated_group().points[0].speed = 20
|
||||
##################################################################################################
|
||||
# Add carrier for normal generation
|
||||
else:
|
||||
return
|
||||
if len(self.faction.aircraft_carrier) > 0:
|
||||
carrier_type = random.choice(self.faction.aircraft_carrier)
|
||||
self.add_unit(
|
||||
carrier_type,
|
||||
"Carrier",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
else:
|
||||
return
|
||||
|
||||
# Add destroyers escort
|
||||
if len(self.faction.destroyers) > 0:
|
||||
dd_type = random.choice(self.faction.destroyers)
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD1",
|
||||
self.position.x + 2500,
|
||||
self.position.y + 4500,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD2",
|
||||
self.position.x + 2500,
|
||||
self.position.y - 4500,
|
||||
self.heading,
|
||||
)
|
||||
# Add destroyers escort
|
||||
if len(self.faction.destroyers) > 0:
|
||||
dd_type = random.choice(self.faction.destroyers)
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD1",
|
||||
self.position.x + 2500,
|
||||
self.position.y + 4500,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD2",
|
||||
self.position.x + 2500,
|
||||
self.position.y - 4500,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD3",
|
||||
self.position.x + 4500,
|
||||
self.position.y + 8500,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD4",
|
||||
self.position.x + 4500,
|
||||
self.position.y - 8500,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD3",
|
||||
self.position.x + 4500,
|
||||
self.position.y + 8500,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD4",
|
||||
self.position.x + 4500,
|
||||
self.position.y - 8500,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
self.get_generated_group().points[0].speed = 20
|
||||
self.get_generated_group().points[0].speed = 20
|
||||
|
||||
@@ -6,7 +6,7 @@ from game.theater.theatergroundobject import TheaterGroundObject
|
||||
|
||||
from gen.sam.group_generator import ShipGroupGenerator
|
||||
from dcs.unittype import ShipType
|
||||
from dcs.ships import Oliver_Hazzard_Perry_class, USS_Arleigh_Burke_IIa
|
||||
from dcs.ships import FFG_Oliver_Hazzard_Perry, DDG_Arleigh_Burke_IIa
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.game import Game
|
||||
@@ -46,7 +46,7 @@ class OliverHazardPerryGroupGenerator(DDGroupGenerator):
|
||||
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
|
||||
):
|
||||
super(OliverHazardPerryGroupGenerator, self).__init__(
|
||||
game, ground_object, faction, Oliver_Hazzard_Perry_class
|
||||
game, ground_object, faction, FFG_Oliver_Hazzard_Perry
|
||||
)
|
||||
|
||||
|
||||
@@ -55,5 +55,5 @@ class ArleighBurkeGroupGenerator(DDGroupGenerator):
|
||||
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
|
||||
):
|
||||
super(ArleighBurkeGroupGenerator, self).__init__(
|
||||
game, ground_object, faction, USS_Arleigh_Burke_IIa
|
||||
game, ground_object, faction, DDG_Arleigh_Burke_IIa
|
||||
)
|
||||
|
||||
@@ -3,13 +3,13 @@ import random
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from dcs.ships import (
|
||||
FFL_1124_4_Grisha,
|
||||
FSG_1241_1MP_Molniya,
|
||||
FFG_11540_Neustrashimy,
|
||||
FF_1135M_Rezky,
|
||||
CG_1164_Moskva,
|
||||
SSK_877,
|
||||
SSK_641B,
|
||||
Corvette_1124_4_Grisha,
|
||||
Corvette_1241_1_Molniya,
|
||||
Frigate_11540_Neustrashimy,
|
||||
Frigate_1135M_Rezky,
|
||||
Cruiser_1164_Moskva,
|
||||
SSK_877V_Kilo,
|
||||
SSK_641B_Tango,
|
||||
)
|
||||
|
||||
from gen.fleet.dd_group import DDGroupGenerator
|
||||
@@ -37,7 +37,9 @@ class RussianNavyGroupGenerator(ShipGroupGenerator):
|
||||
include_frigate = True
|
||||
|
||||
if include_frigate:
|
||||
frigate_type = random.choice([FFL_1124_4_Grisha, FSG_1241_1MP_Molniya])
|
||||
frigate_type = random.choice(
|
||||
[Corvette_1124_4_Grisha, Corvette_1241_1_Molniya]
|
||||
)
|
||||
self.add_unit(
|
||||
frigate_type,
|
||||
"FF1",
|
||||
@@ -54,7 +56,7 @@ class RussianNavyGroupGenerator(ShipGroupGenerator):
|
||||
)
|
||||
|
||||
if include_dd:
|
||||
dd_type = random.choice([FFG_11540_Neustrashimy, FF_1135M_Rezky])
|
||||
dd_type = random.choice([Frigate_11540_Neustrashimy, Frigate_1135M_Rezky])
|
||||
self.add_unit(
|
||||
dd_type,
|
||||
"DD1",
|
||||
@@ -74,7 +76,11 @@ class RussianNavyGroupGenerator(ShipGroupGenerator):
|
||||
# Only include the Moskva for now, the Pyotry Velikiy is an unkillable monster.
|
||||
# See https://github.com/Khopa/dcs_liberation/issues/567
|
||||
self.add_unit(
|
||||
CG_1164_Moskva, "CC1", self.position.x, self.position.y, self.heading
|
||||
Cruiser_1164_Moskva,
|
||||
"CC1",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
self.get_generated_group().points[0].speed = 20
|
||||
@@ -85,7 +91,7 @@ class GrishaGroupGenerator(DDGroupGenerator):
|
||||
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
|
||||
):
|
||||
super(GrishaGroupGenerator, self).__init__(
|
||||
game, ground_object, faction, FFL_1124_4_Grisha
|
||||
game, ground_object, faction, Corvette_1124_4_Grisha
|
||||
)
|
||||
|
||||
|
||||
@@ -94,7 +100,7 @@ class MolniyaGroupGenerator(DDGroupGenerator):
|
||||
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
|
||||
):
|
||||
super(MolniyaGroupGenerator, self).__init__(
|
||||
game, ground_object, faction, FSG_1241_1MP_Molniya
|
||||
game, ground_object, faction, Corvette_1241_1_Molniya
|
||||
)
|
||||
|
||||
|
||||
@@ -103,7 +109,7 @@ class KiloSubGroupGenerator(DDGroupGenerator):
|
||||
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
|
||||
):
|
||||
super(KiloSubGroupGenerator, self).__init__(
|
||||
game, ground_object, faction, SSK_877
|
||||
game, ground_object, faction, SSK_877V_Kilo
|
||||
)
|
||||
|
||||
|
||||
@@ -112,5 +118,5 @@ class TangoSubGroupGenerator(DDGroupGenerator):
|
||||
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
|
||||
):
|
||||
super(TangoSubGroupGenerator, self).__init__(
|
||||
game, ground_object, faction, SSK_641B
|
||||
game, ground_object, faction, SSK_641B_Tango
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import random
|
||||
|
||||
from dcs.ships import Schnellboot_type_S130
|
||||
from dcs.ships import Boat_Schnellboot_type_S130
|
||||
|
||||
from gen.sam.group_generator import ShipGroupGenerator
|
||||
|
||||
@@ -10,7 +10,7 @@ class SchnellbootGroupGenerator(ShipGroupGenerator):
|
||||
|
||||
for i in range(random.randint(2, 4)):
|
||||
self.add_unit(
|
||||
Schnellboot_type_S130,
|
||||
Boat_Schnellboot_type_S130,
|
||||
"Schnellboot" + str(i),
|
||||
self.position.x + i * random.randint(100, 250),
|
||||
self.position.y + (random.randint(100, 200) - 100),
|
||||
|
||||
@@ -47,6 +47,7 @@ def generate_ship_group(game, ground_object, faction_name: str):
|
||||
gen = random.choice(faction.navy_generators)
|
||||
if gen in SHIP_MAP.keys():
|
||||
generator = SHIP_MAP[gen](game, ground_object, faction)
|
||||
print(generator.position)
|
||||
generator.generate()
|
||||
return generator.get_generated_group()
|
||||
else:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import random
|
||||
|
||||
from dcs.ships import Uboat_VIIC_U_flak
|
||||
from dcs.ships import U_boat_VIIC_U_flak
|
||||
|
||||
from gen.sam.group_generator import ShipGroupGenerator
|
||||
|
||||
@@ -10,7 +10,7 @@ class UBoatGroupGenerator(ShipGroupGenerator):
|
||||
|
||||
for i in range(random.randint(1, 4)):
|
||||
self.add_unit(
|
||||
Uboat_VIIC_U_flak,
|
||||
U_boat_VIIC_U_flak,
|
||||
"Uboat" + str(i),
|
||||
self.position.x + i * random.randint(100, 250),
|
||||
self.position.y + (random.randint(100, 200) - 100),
|
||||
|
||||
@@ -450,6 +450,22 @@ class ObjectiveFinder:
|
||||
c for c in self.game.theater.controlpoints if c.is_friendly(self.is_player)
|
||||
)
|
||||
|
||||
def farthest_friendly_control_point(self) -> ControlPoint:
|
||||
"""
|
||||
Iterates over all friendly control points and find the one farthest away from the frontline
|
||||
BUT! prefer Cvs. Everybody likes CVs!
|
||||
"""
|
||||
from_frontline = 0
|
||||
|
||||
for c in self.game.theater.controlpoints:
|
||||
if c.is_carrier and c.is_friendly(self.is_player):
|
||||
return c
|
||||
if c.is_friendly(self.is_player) and c.has_frontline:
|
||||
if c.distance_to(self.front_lines().__next__()) > from_frontline:
|
||||
from_frontline = c.distance_to(self.front_lines().__next__())
|
||||
cp = c
|
||||
return cp
|
||||
|
||||
def enemy_control_points(self) -> Iterator[ControlPoint]:
|
||||
"""Iterates over all enemy control points."""
|
||||
return (
|
||||
@@ -507,6 +523,7 @@ class CoalitionMissionPlanner:
|
||||
MAX_OCA_RANGE = nautical_miles(150)
|
||||
MAX_SEAD_RANGE = nautical_miles(150)
|
||||
MAX_STRIKE_RANGE = nautical_miles(150)
|
||||
MAX_AWEC_RANGE = nautical_miles(200)
|
||||
|
||||
def __init__(self, game: Game, is_player: bool) -> None:
|
||||
self.game = game
|
||||
@@ -526,6 +543,13 @@ class CoalitionMissionPlanner:
|
||||
ensure that they can be planned again next turn even if all aircraft are
|
||||
eliminated this turn.
|
||||
"""
|
||||
|
||||
# Find farthest, friendly CP for AEWC
|
||||
cp = self.objective_finder.farthest_friendly_control_point()
|
||||
yield ProposedMission(
|
||||
cp, [ProposedFlight(FlightType.AEWC, 1, self.MAX_AWEC_RANGE)]
|
||||
)
|
||||
|
||||
# Find friendly CPs within 100 nmi from an enemy airfield, plan CAP.
|
||||
for cp in self.objective_finder.vulnerable_control_points():
|
||||
# Plan three rounds of CAP to give ~90 minutes coverage. Spacing
|
||||
|
||||
@@ -12,8 +12,8 @@ from dcs.helicopters import (
|
||||
OH_58D,
|
||||
SA342L,
|
||||
SA342M,
|
||||
UH_1H,
|
||||
SH_60B,
|
||||
UH_1H,
|
||||
)
|
||||
from dcs.planes import (
|
||||
AJS37,
|
||||
@@ -22,11 +22,14 @@ from dcs.planes import (
|
||||
A_10C,
|
||||
A_10C_2,
|
||||
A_20G,
|
||||
A_50,
|
||||
B_17G,
|
||||
B_1B,
|
||||
B_52H,
|
||||
Bf_109K_4,
|
||||
C_101CC,
|
||||
E_2C,
|
||||
E_3A,
|
||||
FA_18C_hornet,
|
||||
FW_190A8,
|
||||
FW_190D9,
|
||||
@@ -40,9 +43,11 @@ from dcs.planes import (
|
||||
F_4E,
|
||||
F_5E_3,
|
||||
F_86F_Sabre,
|
||||
I_16,
|
||||
JF_17,
|
||||
J_11A,
|
||||
Ju_88A4,
|
||||
KJ_2000,
|
||||
L_39ZA,
|
||||
MQ_9_Reaper,
|
||||
M_2000C,
|
||||
@@ -54,7 +59,6 @@ from dcs.planes import (
|
||||
MiG_27K,
|
||||
MiG_29A,
|
||||
MiG_29G,
|
||||
MiG_29K,
|
||||
MiG_29S,
|
||||
MiG_31,
|
||||
Mirage_2000_5,
|
||||
@@ -88,13 +92,11 @@ from dcs.planes import (
|
||||
from dcs.unittype import FlyingType
|
||||
|
||||
from gen.flights.flight import FlightType
|
||||
|
||||
from pydcs_extensions.a4ec.a4ec import A_4E_C
|
||||
from pydcs_extensions.f22a.f22a import F_22A
|
||||
from pydcs_extensions.mb339.mb339 import MB_339PAN
|
||||
from pydcs_extensions.rafale.rafale import Rafale_A_S, Rafale_M, Rafale_B
|
||||
from pydcs_extensions.su57.su57 import Su_57
|
||||
from pydcs_extensions.hercules.hercules import Hercules
|
||||
from pydcs_extensions.mb339.mb339 import MB_339PAN
|
||||
from pydcs_extensions.su57.su57 import Su_57
|
||||
|
||||
# All aircraft lists are in priority order. Aircraft higher in the list will be
|
||||
# preferred over those lower in the list.
|
||||
@@ -111,14 +113,12 @@ CAP_CAPABLE = [
|
||||
F_14B,
|
||||
F_14A_135_GR,
|
||||
MiG_25PD,
|
||||
Rafale_M,
|
||||
Su_33,
|
||||
Su_30,
|
||||
Su_27,
|
||||
J_11A,
|
||||
F_15C,
|
||||
MiG_29S,
|
||||
MiG_29K,
|
||||
MiG_29G,
|
||||
MiG_29A,
|
||||
F_16C_50,
|
||||
@@ -155,8 +155,8 @@ CAP_CAPABLE = [
|
||||
# Used for CAS (Close air support) and BAI (Battlefield Interdiction)
|
||||
CAS_CAPABLE = [
|
||||
A_10C_2,
|
||||
A_10C,
|
||||
B_1B,
|
||||
A_10C,
|
||||
F_14B,
|
||||
F_14A_135_GR,
|
||||
Su_25TM,
|
||||
@@ -165,8 +165,6 @@ CAS_CAPABLE = [
|
||||
F_15E,
|
||||
F_16C_50,
|
||||
FA_18C_hornet,
|
||||
Rafale_A_S,
|
||||
Rafale_B,
|
||||
Tornado_GR4,
|
||||
Tornado_IDS,
|
||||
JF_17,
|
||||
@@ -180,6 +178,7 @@ CAS_CAPABLE = [
|
||||
S_3B,
|
||||
Su_34,
|
||||
Su_30,
|
||||
MiG_19P,
|
||||
MiG_29S,
|
||||
MiG_27K,
|
||||
MiG_29A,
|
||||
@@ -227,8 +226,6 @@ SEAD_CAPABLE = [
|
||||
Tornado_IDS,
|
||||
Su_25T,
|
||||
Su_25TM,
|
||||
Rafale_A_S,
|
||||
Rafale_B,
|
||||
F_4E,
|
||||
A_4E_C,
|
||||
AV8BNA,
|
||||
@@ -276,8 +273,6 @@ STRIKE_CAPABLE = [
|
||||
Tu_22M3,
|
||||
F_15E,
|
||||
AJS37,
|
||||
Rafale_A_S,
|
||||
Rafale_B,
|
||||
Tornado_GR4,
|
||||
F_16C_50,
|
||||
FA_18C_hornet,
|
||||
@@ -296,7 +291,6 @@ STRIKE_CAPABLE = [
|
||||
Su_30,
|
||||
Su_27,
|
||||
MiG_29S,
|
||||
MiG_29K,
|
||||
MiG_29G,
|
||||
MiG_29A,
|
||||
JF_17,
|
||||
@@ -333,8 +327,6 @@ ANTISHIP_CAPABLE = [
|
||||
AJS37,
|
||||
Tu_22M3,
|
||||
FA_18C_hornet,
|
||||
Rafale_A_S,
|
||||
Rafale_B,
|
||||
Su_24M,
|
||||
Su_17M4,
|
||||
JF_17,
|
||||
@@ -369,6 +361,13 @@ TRANSPORT_CAPABLE = [
|
||||
|
||||
DRONES = [MQ_9_Reaper, RQ_1A_Predator, WingLoong_I]
|
||||
|
||||
AEWC_CAPABLE = [
|
||||
E_3A,
|
||||
E_2C,
|
||||
A_50,
|
||||
KJ_2000,
|
||||
]
|
||||
|
||||
|
||||
def aircraft_for_task(task: FlightType) -> List[Type[FlyingType]]:
|
||||
cap_missions = (FlightType.BARCAP, FlightType.TARCAP)
|
||||
@@ -392,6 +391,8 @@ def aircraft_for_task(task: FlightType) -> List[Type[FlyingType]]:
|
||||
return STRIKE_CAPABLE
|
||||
elif task == FlightType.ESCORT:
|
||||
return CAP_CAPABLE
|
||||
elif task == FlightType.AEWC:
|
||||
return AEWC_CAPABLE
|
||||
else:
|
||||
logging.error(f"Unplannable flight type: {task}")
|
||||
return []
|
||||
|
||||
@@ -20,6 +20,15 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class FlightType(Enum):
|
||||
"""Enumeration of mission types.
|
||||
|
||||
The value of each enumeration is the name that will be shown in the UI.
|
||||
|
||||
These values are persisted to the save game as well since they are a part of
|
||||
each flight and thus a part of the ATO, so changing these values will break
|
||||
save compat.
|
||||
"""
|
||||
|
||||
TARCAP = "TARCAP"
|
||||
BARCAP = "BARCAP"
|
||||
CAS = "CAS"
|
||||
@@ -33,6 +42,7 @@ class FlightType(Enum):
|
||||
SWEEP = "Fighter sweep"
|
||||
OCA_RUNWAY = "OCA/Runway"
|
||||
OCA_AIRCRAFT = "OCA/Aircraft"
|
||||
AEWC = "AEW&C"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
|
||||
@@ -15,6 +15,8 @@ from datetime import timedelta
|
||||
from functools import cached_property
|
||||
from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple
|
||||
|
||||
from dcs.planes import E_3A, E_2C, A_50, KJ_2000
|
||||
|
||||
from dcs.mapping import Point
|
||||
from dcs.unit import Unit
|
||||
from shapely.geometry import Point as ShapelyPoint
|
||||
@@ -29,7 +31,7 @@ from game.theater import (
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from game.theater.theatergroundobject import EwrGroundObject
|
||||
from game.utils import Distance, Speed, meters, nautical_miles
|
||||
from game.utils import Distance, Speed, feet, meters, nautical_miles
|
||||
from .closestairfields import ObjectiveDistanceCache
|
||||
from .flight import Flight, FlightType, FlightWaypoint, FlightWaypointType
|
||||
from .traveltime import GroundSpeed, TravelTime
|
||||
@@ -278,11 +280,11 @@ class LoiterFlightPlan(FlightPlan):
|
||||
travel_time = super().travel_time_between_waypoints(a, b)
|
||||
if a != self.hold:
|
||||
return travel_time
|
||||
try:
|
||||
return travel_time + self.hold_duration
|
||||
except AttributeError:
|
||||
# Save compat for 2.3.
|
||||
return travel_time + timedelta(minutes=5)
|
||||
return travel_time + self.hold_duration
|
||||
|
||||
@property
|
||||
def mission_departure_time(self) -> timedelta:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -694,6 +696,45 @@ class SweepFlightPlan(LoiterFlightPlan):
|
||||
return self.sweep_end_time
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AwacsFlightPlan(LoiterFlightPlan):
|
||||
takeoff: FlightWaypoint
|
||||
nav_to: List[FlightWaypoint]
|
||||
nav_from: List[FlightWaypoint]
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.takeoff
|
||||
yield from self.nav_to
|
||||
yield self.hold
|
||||
yield from self.nav_from
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
|
||||
@property
|
||||
def mission_start_time(self) -> Optional[timedelta]:
|
||||
return self.takeoff_time()
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
||||
if waypoint == self.hold:
|
||||
return self.package.time_over_target
|
||||
return None
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||
return self.hold
|
||||
|
||||
@property
|
||||
def push_time(self) -> timedelta:
|
||||
return self.package.time_over_target + self.hold_duration
|
||||
|
||||
@property
|
||||
def mission_departure_time(self) -> timedelta:
|
||||
return self.push_time
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CustomFlightPlan(FlightPlan):
|
||||
custom_waypoints: List[FlightWaypoint]
|
||||
@@ -759,7 +800,17 @@ class FlightPlanBuilder:
|
||||
raise RuntimeError("Flight must be a part of the package")
|
||||
if self.package.waypoints is None:
|
||||
self.regenerate_package_waypoints()
|
||||
flight.flight_plan = self.generate_flight_plan(flight, custom_targets)
|
||||
|
||||
from game.navmesh import NavMeshError
|
||||
|
||||
try:
|
||||
flight.flight_plan = self.generate_flight_plan(flight, custom_targets)
|
||||
except NavMeshError as ex:
|
||||
color = "blue" if self.is_player else "red"
|
||||
raise PlanningError(
|
||||
f"Could not plan {color} {flight.flight_type.value} from "
|
||||
f"{flight.departure} to {flight.package.target}"
|
||||
) from ex
|
||||
|
||||
def generate_flight_plan(
|
||||
self, flight: Flight, custom_targets: Optional[List[Unit]]
|
||||
@@ -790,6 +841,8 @@ class FlightPlanBuilder:
|
||||
return self.generate_sweep(flight)
|
||||
elif task == FlightType.TARCAP:
|
||||
return self.generate_tarcap(flight)
|
||||
elif task == FlightType.AEWC:
|
||||
return self.generate_aewc(flight)
|
||||
raise PlanningError(f"{task} flight plan generation not implemented")
|
||||
|
||||
def regenerate_package_waypoints(self) -> None:
|
||||
@@ -920,6 +973,47 @@ class FlightPlanBuilder:
|
||||
flight, location, FlightWaypointType.INGRESS_STRIKE, targets
|
||||
)
|
||||
|
||||
def generate_aewc(self, flight: Flight) -> AwacsFlightPlan:
|
||||
"""Generate a AWACS flight at a given location.
|
||||
|
||||
Args:
|
||||
flight: The flight to generate the flight plan for.
|
||||
"""
|
||||
location = self.package.target
|
||||
|
||||
start = self.aewc_orbit(location)
|
||||
|
||||
# As high as possible to maximize detection and on-station time.
|
||||
if flight.unit_type == E_2C:
|
||||
patrol_alt = feet(30000)
|
||||
elif flight.unit_type == E_3A:
|
||||
patrol_alt = feet(35000)
|
||||
elif flight.unit_type == A_50:
|
||||
patrol_alt = feet(33000)
|
||||
elif flight.unit_type == KJ_2000:
|
||||
patrol_alt = feet(40000)
|
||||
else:
|
||||
patrol_alt = feet(25000)
|
||||
|
||||
builder = WaypointBuilder(flight, self.game, self.is_player)
|
||||
start = builder.orbit(start, patrol_alt)
|
||||
|
||||
return AwacsFlightPlan(
|
||||
package=self.package,
|
||||
flight=flight,
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
nav_to=builder.nav_path(
|
||||
flight.departure.position, start.position, patrol_alt
|
||||
),
|
||||
nav_from=builder.nav_path(
|
||||
start.position, flight.arrival.position, patrol_alt
|
||||
),
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
hold=start,
|
||||
hold_duration=timedelta(hours=4),
|
||||
)
|
||||
|
||||
def generate_bai(self, flight: Flight) -> StrikeFlightPlan:
|
||||
"""Generates a BAI flight plan.
|
||||
|
||||
@@ -933,7 +1027,8 @@ class FlightPlanBuilder:
|
||||
|
||||
targets: List[StrikeTarget] = []
|
||||
for group in location.groups:
|
||||
targets.append(StrikeTarget(f"{group.name} at {location.name}", group))
|
||||
if group.units:
|
||||
targets.append(StrikeTarget(f"{group.name} at {location.name}", group))
|
||||
|
||||
return self.strike_flightplan(
|
||||
flight, location, FlightWaypointType.INGRESS_BAI, targets
|
||||
@@ -1102,6 +1197,22 @@ class FlightPlanBuilder:
|
||||
start = end.point_from_heading(heading - 180, diameter)
|
||||
return start, end
|
||||
|
||||
def aewc_orbit(self, location: MissionTarget) -> Point:
|
||||
# in threat zone
|
||||
if self.threat_zones.threatened(location.position):
|
||||
# Borderpoint
|
||||
closest_boundary = self.threat_zones.closest_boundary(location.position)
|
||||
|
||||
# Heading + Distance to border point
|
||||
heading = location.position.heading_between_point(closest_boundary)
|
||||
distance = location.position.distance_to_point(closest_boundary)
|
||||
|
||||
return location.position.point_from_heading(heading, distance)
|
||||
|
||||
# this Part is fine. No threat zone, just use our point
|
||||
else:
|
||||
return location.position
|
||||
|
||||
def racetrack_for_frontline(
|
||||
self, origin: Point, front_line: FrontLine
|
||||
) -> Tuple[Point, Point]:
|
||||
|
||||
@@ -14,7 +14,7 @@ from typing import (
|
||||
|
||||
from dcs.mapping import Point
|
||||
from dcs.unit import Unit
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
from dcs.unitgroup import Group, VehicleGroup
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
@@ -32,7 +32,7 @@ from .flight import Flight, FlightWaypoint, FlightWaypointType
|
||||
@dataclass(frozen=True)
|
||||
class StrikeTarget:
|
||||
name: str
|
||||
target: Union[VehicleGroup, TheaterGroundObject, Unit]
|
||||
target: Union[VehicleGroup, TheaterGroundObject, Unit, Group]
|
||||
|
||||
|
||||
class WaypointBuilder:
|
||||
@@ -161,8 +161,10 @@ class WaypointBuilder:
|
||||
FlightWaypointType.JOIN,
|
||||
position.x,
|
||||
position.y,
|
||||
meters(500) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
meters(80) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
)
|
||||
if self.is_helo:
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.pretty_name = "Join"
|
||||
waypoint.description = "Rendezvous with package"
|
||||
waypoint.name = "JOIN"
|
||||
@@ -173,8 +175,10 @@ class WaypointBuilder:
|
||||
FlightWaypointType.SPLIT,
|
||||
position.x,
|
||||
position.y,
|
||||
meters(500) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
meters(80) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
)
|
||||
if self.is_helo:
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.pretty_name = "Split"
|
||||
waypoint.description = "Depart from package"
|
||||
waypoint.name = "SPLIT"
|
||||
@@ -190,8 +194,10 @@ class WaypointBuilder:
|
||||
ingress_type,
|
||||
position.x,
|
||||
position.y,
|
||||
meters(500) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
meters(50) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
)
|
||||
if self.is_helo:
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.pretty_name = "INGRESS on " + objective.name
|
||||
waypoint.description = "INGRESS on " + objective.name
|
||||
waypoint.name = "INGRESS"
|
||||
@@ -204,8 +210,10 @@ class WaypointBuilder:
|
||||
FlightWaypointType.EGRESS,
|
||||
position.x,
|
||||
position.y,
|
||||
meters(500) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
meters(50) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
)
|
||||
if self.is_helo:
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.pretty_name = "EGRESS from " + target.name
|
||||
waypoint.description = "EGRESS from " + target.name
|
||||
waypoint.name = "EGRESS"
|
||||
@@ -286,7 +294,7 @@ class WaypointBuilder:
|
||||
FlightWaypointType.CAS,
|
||||
position.x,
|
||||
position.y,
|
||||
meters(500) if self.is_helo else meters(1000),
|
||||
meters(50) if self.is_helo else meters(1000),
|
||||
)
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.description = "Provide CAS"
|
||||
@@ -341,6 +349,21 @@ class WaypointBuilder:
|
||||
self.race_track_end(end, altitude),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def orbit(start: Point, altitude: Distance) -> FlightWaypoint:
|
||||
"""Creates an circular orbit point.
|
||||
|
||||
Args:
|
||||
start: Position of the waypoint.
|
||||
altitude: Altitude of the racetrack.
|
||||
"""
|
||||
|
||||
waypoint = FlightWaypoint(FlightWaypointType.LOITER, start.x, start.y, altitude)
|
||||
waypoint.name = "ORBIT"
|
||||
waypoint.description = "Anchor and hold at this point"
|
||||
waypoint.pretty_name = "Orbit"
|
||||
return waypoint
|
||||
|
||||
@staticmethod
|
||||
def sweep_start(position: Point, altitude: Distance) -> FlightWaypoint:
|
||||
"""Creates a sweep start waypoint.
|
||||
@@ -407,8 +430,10 @@ class WaypointBuilder:
|
||||
FlightWaypointType.TARGET_GROUP_LOC,
|
||||
target.position.x,
|
||||
target.position.y,
|
||||
meters(500) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
meters(50) if self.is_helo else self.doctrine.ingress_altitude,
|
||||
)
|
||||
if self.is_helo:
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.name = "TARGET"
|
||||
waypoint.description = "Escort the package"
|
||||
waypoint.pretty_name = "Target area"
|
||||
|
||||
@@ -14,16 +14,16 @@ TYPE_TANKS = [
|
||||
Armor.MBT_Challenger_II,
|
||||
Armor.MBT_M1A2_Abrams,
|
||||
Armor.MBT_M60A3_Patton,
|
||||
Armor.MBT_Merkava_Mk__4,
|
||||
Armor.MBT_Merkava_IV,
|
||||
Armor.ZTZ_96B,
|
||||
# WW2
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H,
|
||||
Armor.MT_PzIV_H,
|
||||
Armor.HT_Pz_Kpfw_VI_Tiger_I,
|
||||
Armor.HT_Pz_Kpfw_VI_Ausf__B_Tiger_II,
|
||||
Armor.MT_M4_Sherman,
|
||||
Armor.MT_M4A4_Sherman_Firefly,
|
||||
Armor.StuG_IV,
|
||||
Armor.SPG_StuG_IV,
|
||||
Armor.CT_Centaur_IV,
|
||||
Armor.CT_Cromwell_IV,
|
||||
Armor.HIT_Churchill_VII,
|
||||
@@ -40,14 +40,14 @@ TYPE_TANKS = [
|
||||
]
|
||||
|
||||
TYPE_ATGM = [
|
||||
Armor.ATGM_M1045_HMMWV_TOW,
|
||||
Armor.ATGM_M1134_Stryker,
|
||||
Armor.ATGM_HMMWV,
|
||||
Armor.ATGM_Stryker,
|
||||
Armor.IFV_BMP_2,
|
||||
# WW2 (Tank Destroyers)
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.TD_Jagdpanzer_IV,
|
||||
Armor.TD_Jagdpanther_G1,
|
||||
Armor.TD_M10_GMC,
|
||||
Unarmed.Carrier_M30_Cargo,
|
||||
Armor.SPG_Jagdpanzer_IV,
|
||||
Armor.SPG_Jagdpanther_G1,
|
||||
Armor.SPG_M10_GMC,
|
||||
# Mods
|
||||
frenchpack.VBAE_CRAB_MMP,
|
||||
frenchpack.VAB_MEPHISTO,
|
||||
@@ -59,17 +59,17 @@ TYPE_IFV = [
|
||||
Armor.IFV_BMP_2,
|
||||
Armor.IFV_BMP_1,
|
||||
Armor.IFV_Marder,
|
||||
Armor.IFV_MCV_80,
|
||||
Armor.IFV_Warrior,
|
||||
Armor.IFV_LAV_25,
|
||||
Armor.SPG_M1128_Stryker_MGS,
|
||||
Armor.AC_Sd_Kfz_234_2_Puma,
|
||||
Armor.SPG_Stryker_MGS,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma,
|
||||
Armor.IFV_M2A2_Bradley,
|
||||
Armor.IFV_BMD_1,
|
||||
Armor.ZBD_04A,
|
||||
# WW2
|
||||
Armor.AC_Sd_Kfz_234_2_Puma,
|
||||
Armor.LAC_M8_Greyhound,
|
||||
Armor.Daimler_Armoured_Car,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma,
|
||||
Armor.Car_M8_Greyhound_Armored,
|
||||
Armor.Car_Daimler_Armored,
|
||||
# Mods
|
||||
frenchpack.ERC_90,
|
||||
frenchpack.VBAE_CRAB,
|
||||
@@ -77,23 +77,23 @@ TYPE_IFV = [
|
||||
]
|
||||
|
||||
TYPE_APC = [
|
||||
Armor.APC_M1043_HMMWV_Armament,
|
||||
Armor.APC_M1126_Stryker_ICV,
|
||||
Armor.APC_HMMWV__Scout,
|
||||
Armor.IFV_M1126_Stryker_ICV,
|
||||
Armor.APC_M113,
|
||||
Armor.APC_BTR_80,
|
||||
Armor.APC_BTR_82A,
|
||||
Armor.APC_MTLB,
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_Cobra,
|
||||
Armor.APC_Sd_Kfz_251,
|
||||
Armor.APC_AAV_7,
|
||||
Armor.TPz_Fuchs,
|
||||
Armor.ARV_BRDM_2,
|
||||
Armor.ARV_BTR_RD,
|
||||
Armor.FDDM_Grad,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.APC_Cobra__Scout,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack,
|
||||
Armor.APC_AAV_7_Amphibious,
|
||||
Armor.APC_TPz_Fuchs,
|
||||
Armor.IFV_BRDM_2,
|
||||
Armor.APC_BTR_RD,
|
||||
Artillery.Grad_MRL_FDDM__FC,
|
||||
# WW2
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_Sd_Kfz_251,
|
||||
Armor.APC_M2A1_Halftrack,
|
||||
Armor.APC_Sd_Kfz_251_Halftrack,
|
||||
# Mods
|
||||
frenchpack.VAB__50,
|
||||
frenchpack.VBL__50,
|
||||
@@ -101,80 +101,82 @@ TYPE_APC = [
|
||||
]
|
||||
|
||||
TYPE_ARTILLERY = [
|
||||
Artillery.MLRS_9A52_Smerch,
|
||||
Artillery.SPH_2S1_Gvozdika,
|
||||
Artillery.SPH_2S3_Akatsia,
|
||||
Artillery.MLRS_BM_21_Grad,
|
||||
Artillery.MLRS_9K57_Uragan_BM_27,
|
||||
Artillery.SPH_M109_Paladin,
|
||||
Artillery.MLRS_M270,
|
||||
Artillery.SPH_2S9_Nona,
|
||||
Artillery.SpGH_Dana,
|
||||
Artillery.SPH_2S19_Msta,
|
||||
Artillery.MLRS_FDDM,
|
||||
Artillery.MLRS_9A52_Smerch_HE_300mm,
|
||||
Artillery.SPH_2S1_Gvozdika_122mm,
|
||||
Artillery.SPH_2S3_Akatsia_152mm,
|
||||
Artillery.MLRS_BM_21_Grad_122mm,
|
||||
Artillery.MLRS_BM_27_Uragan_220mm,
|
||||
Artillery.SPH_M109_Paladin_155mm,
|
||||
Artillery.MLRS_M270_227mm,
|
||||
Artillery.SPH_2S9_Nona_120mm_M,
|
||||
Artillery.SPH_Dana_vz77_152mm,
|
||||
Artillery.PLZ_05,
|
||||
Artillery.SPH_2S19_Msta_152mm,
|
||||
Artillery.MLRS_9A52_Smerch_CM_300mm,
|
||||
# WW2
|
||||
Artillery.Sturmpanzer_IV_Brummbär,
|
||||
Artillery.M12_GMC,
|
||||
Artillery.SPG_Sturmpanzer_IV_Brummbar,
|
||||
Artillery.SPG_M12_GMC_155mm,
|
||||
]
|
||||
|
||||
TYPE_LOGI = [
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Transport_KAMAZ_43101,
|
||||
Unarmed.Transport_Ural_375,
|
||||
Unarmed.Transport_GAZ_66,
|
||||
Unarmed.Transport_GAZ_3307,
|
||||
Unarmed.Transport_GAZ_3308,
|
||||
Unarmed.Transport_Ural_4320_31_Armored,
|
||||
Unarmed.Transport_Ural_4320T,
|
||||
Unarmed.Blitz_3_6_6700A,
|
||||
Unarmed.Kübelwagen_82,
|
||||
Unarmed.Sd_Kfz_7,
|
||||
Unarmed.Sd_Kfz_2,
|
||||
Unarmed.Willys_MB,
|
||||
Unarmed.Land_Rover_109_S3,
|
||||
Unarmed.Land_Rover_101_FC,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
Unarmed.Truck_KAMAZ_43101,
|
||||
Unarmed.Truck_Ural_375,
|
||||
Unarmed.Truck_GAZ_66,
|
||||
Unarmed.Truck_GAZ_3307,
|
||||
Unarmed.Truck_GAZ_3308,
|
||||
Unarmed.Truck_Ural_4320_31_Arm_d,
|
||||
Unarmed.Truck_Ural_4320T,
|
||||
Unarmed.Truck_Opel_Blitz,
|
||||
Unarmed.LUV_Kubelwagen_82,
|
||||
Unarmed.Carrier_Sd_Kfz_7_Tractor,
|
||||
Unarmed.LUV_Kettenrad,
|
||||
Unarmed.Car_Willys_Jeep,
|
||||
Unarmed.LUV_Land_Rover_109,
|
||||
Unarmed.Truck_Land_Rover_101_FC,
|
||||
# Mods
|
||||
frenchpack.VBL,
|
||||
frenchpack.VAB,
|
||||
]
|
||||
|
||||
TYPE_INFANTRY = [
|
||||
Infantry.Infantry_Soldier_Insurgents,
|
||||
Infantry.Soldier_AK,
|
||||
Infantry.Insurgent_AK_74,
|
||||
Infantry.Infantry_AK_74,
|
||||
Infantry.Infantry_M1_Garand,
|
||||
Infantry.Infantry_Mauser_98,
|
||||
Infantry.Infantry_SMLE_No_4_Mk_1,
|
||||
Infantry.Georgian_soldier_with_M4,
|
||||
Infantry.Infantry_Soldier_Rus,
|
||||
Infantry.Infantry_M4_Georgia,
|
||||
Infantry.Infantry_AK_74_Rus,
|
||||
Infantry.Paratrooper_AKS,
|
||||
Infantry.Paratrooper_RPG_16,
|
||||
Infantry.Soldier_M249,
|
||||
Infantry.Infantry_M249,
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Soldier_RPG,
|
||||
Infantry.Infantry_RPG,
|
||||
]
|
||||
|
||||
TYPE_SHORAD = [
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375,
|
||||
AirDefence.AAA_ZSU_57_2,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
||||
AirDefence.SAM_SA_8_Osa_9A33,
|
||||
AirDefence.SAM_SA_9_Strela_1_9P31,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_9A35M3,
|
||||
AirDefence.SAM_SA_15_Tor_9A331,
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375,
|
||||
AirDefence.SPAAA_ZU_23_2_Insurgent_Mounted_Ural_375,
|
||||
AirDefence.SPAAA_ZSU_57_2,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
AirDefence.SAM_SA_8_Osa_Gecko_TEL,
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_Gopher_TEL,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison,
|
||||
AirDefence.SPAAA_Gepard,
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SAM_Linebacker_M6,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
AirDefence.SAM_Linebacker___Bradley_M6,
|
||||
AirDefence.SAM_Chaparral_M48,
|
||||
AirDefence.SAM_Avenger_M1097,
|
||||
AirDefence.SAM_Avenger__Stinger,
|
||||
AirDefence.SAM_Roland_ADS,
|
||||
AirDefence.HQ_7_Self_Propelled_LN,
|
||||
AirDefence.AAA_8_8cm_Flak_18,
|
||||
AirDefence.AAA_8_8cm_Flak_36,
|
||||
AirDefence.AAA_8_8cm_Flak_37,
|
||||
AirDefence.AAA_8_8cm_Flak_41,
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
AirDefence.AAA_40mm_Bofors,
|
||||
AirDefence.AAA_S_60_57mm,
|
||||
AirDefence.AAA_M1_37mm,
|
||||
AirDefence.AA_gun_QF_3_7,
|
||||
AirDefence.AAA_QF_3_7,
|
||||
]
|
||||
|
||||
@@ -11,9 +11,10 @@ import logging
|
||||
import random
|
||||
from typing import Dict, Iterator, Optional, TYPE_CHECKING, Type, List
|
||||
|
||||
from dcs import Mission, Point
|
||||
from dcs import Mission, Point, unitgroup
|
||||
from dcs.country import Country
|
||||
from dcs.statics import fortification_map, warehouse_map
|
||||
from dcs.point import StaticPoint
|
||||
from dcs.statics import fortification_map, warehouse_map, Warehouse
|
||||
from dcs.task import (
|
||||
ActivateBeaconCommand,
|
||||
ActivateICLSCommand,
|
||||
@@ -21,7 +22,7 @@ from dcs.task import (
|
||||
OptAlarmState,
|
||||
FireAtPoint,
|
||||
)
|
||||
from dcs.unit import Ship, Unit, Vehicle
|
||||
from dcs.unit import Ship, Unit, Vehicle, SingleHeliPad, Static
|
||||
from dcs.unitgroup import Group, ShipGroup, StaticGroup, VehicleGroup
|
||||
from dcs.unittype import StaticType, UnitType
|
||||
from dcs.vehicles import vehicle_map
|
||||
@@ -47,7 +48,6 @@ from .tacan import TacanBand, TacanChannel, TacanRegistry
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
|
||||
|
||||
FARP_FRONTLINE_DISTANCE = 10000
|
||||
AA_CP_MIN_DISTANCE = 40000
|
||||
|
||||
@@ -402,20 +402,23 @@ class CarrierGenerator(GenericCarrierGenerator):
|
||||
|
||||
def tacan_callsign(self) -> str:
|
||||
# TODO: Assign these properly.
|
||||
return random.choice(
|
||||
[
|
||||
"STE",
|
||||
"CVN",
|
||||
"CVH",
|
||||
"CCV",
|
||||
"ACC",
|
||||
"ARC",
|
||||
"GER",
|
||||
"ABR",
|
||||
"LIN",
|
||||
"TRU",
|
||||
]
|
||||
)
|
||||
if self.control_point.name == "Carrier Strike Group 8":
|
||||
return "TRU"
|
||||
else:
|
||||
return random.choice(
|
||||
[
|
||||
"STE",
|
||||
"CVN",
|
||||
"CVH",
|
||||
"CCV",
|
||||
"ACC",
|
||||
"ARC",
|
||||
"GER",
|
||||
"ABR",
|
||||
"LIN",
|
||||
"TRU",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class LhaGenerator(GenericCarrierGenerator):
|
||||
@@ -474,6 +477,48 @@ class ShipObjectGenerator(GenericGroundObjectGenerator):
|
||||
self._register_unit_group(group_def, group)
|
||||
|
||||
|
||||
class HelipadGenerator:
|
||||
"""
|
||||
Generates helipads for given control point
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mission: Mission,
|
||||
cp: ControlPoint,
|
||||
game: Game,
|
||||
radio_registry: RadioRegistry,
|
||||
tacan_registry: TacanRegistry,
|
||||
):
|
||||
self.m = mission
|
||||
self.cp = cp
|
||||
self.game = game
|
||||
self.radio_registry = radio_registry
|
||||
self.tacan_registry = tacan_registry
|
||||
|
||||
def generate(self) -> None:
|
||||
|
||||
if self.cp.captured:
|
||||
country_name = self.game.player_country
|
||||
else:
|
||||
country_name = self.game.enemy_country
|
||||
country = self.m.country(country_name)
|
||||
|
||||
for i, helipad in enumerate(self.cp.helipads):
|
||||
name = self.cp.name + "_helipad_" + str(i)
|
||||
logging.info("Generating helipad : " + name)
|
||||
pad = SingleHeliPad(name=self.m.string(name + "_unit"))
|
||||
pad.position = Point(helipad.x, helipad.y)
|
||||
pad.heading = helipad.heading
|
||||
# pad.heliport_frequency = self.radio_registry.alloc_uhf() TODO : alloc radio & callsign
|
||||
sg = unitgroup.StaticGroup(self.m.next_group_id(), self.m.string(name))
|
||||
sg.add_unit(pad)
|
||||
sp = StaticPoint()
|
||||
sp.position = pad.position
|
||||
sg.add_point(sp)
|
||||
country.add_static_group(sg)
|
||||
|
||||
|
||||
class GroundObjectsGenerator:
|
||||
"""Creates DCS groups and statics for the theater during mission generation.
|
||||
|
||||
@@ -507,6 +552,10 @@ class GroundObjectsGenerator:
|
||||
country_name = self.game.enemy_country
|
||||
country = self.m.country(country_name)
|
||||
|
||||
HelipadGenerator(
|
||||
self.m, cp, self.game, self.radio_registry, self.tacan_registry
|
||||
).generate()
|
||||
|
||||
for ground_object in cp.ground_objects:
|
||||
if isinstance(ground_object, BuildingGroundObject):
|
||||
generator = BuildingSiteGenerator(
|
||||
|
||||
@@ -41,6 +41,7 @@ from .flights.flight import FlightWaypoint, FlightWaypointType
|
||||
from .radios import RadioFrequency
|
||||
from .runways import RunwayData
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
|
||||
@@ -48,17 +49,33 @@ if TYPE_CHECKING:
|
||||
class KneeboardPageWriter:
|
||||
"""Creates kneeboard images."""
|
||||
|
||||
def __init__(self, page_margin: int = 24, line_spacing: int = 12) -> None:
|
||||
self.image = Image.new("RGB", (768, 1024), (0xFF, 0xFF, 0xFF))
|
||||
def __init__(
|
||||
self, page_margin: int = 24, line_spacing: int = 12, dark_theme: bool = False
|
||||
) -> None:
|
||||
if dark_theme:
|
||||
self.foreground_fill = (215, 200, 200)
|
||||
self.background_fill = (10, 5, 5)
|
||||
else:
|
||||
self.foreground_fill = (15, 15, 15)
|
||||
self.background_fill = (255, 252, 252)
|
||||
self.image = Image.new("RGB", (768, 1024), self.background_fill)
|
||||
# These font sizes create a relatively full page for current sorties. If
|
||||
# we start generating more complicated flight plans, or start including
|
||||
# more information in the comm ladder (the latter of which we should
|
||||
# probably do), we'll need to split some of this information off into a
|
||||
# second page.
|
||||
self.title_font = ImageFont.truetype("arial.ttf", 32)
|
||||
self.heading_font = ImageFont.truetype("arial.ttf", 24)
|
||||
self.content_font = ImageFont.truetype("arial.ttf", 20)
|
||||
self.table_font = ImageFont.truetype("resources/fonts/Inconsolata.otf", 20)
|
||||
self.title_font = ImageFont.truetype(
|
||||
"arial.ttf", 32, layout_engine=ImageFont.LAYOUT_BASIC
|
||||
)
|
||||
self.heading_font = ImageFont.truetype(
|
||||
"arial.ttf", 24, layout_engine=ImageFont.LAYOUT_BASIC
|
||||
)
|
||||
self.content_font = ImageFont.truetype(
|
||||
"arial.ttf", 20, layout_engine=ImageFont.LAYOUT_BASIC
|
||||
)
|
||||
self.table_font = ImageFont.truetype(
|
||||
"resources/fonts/Inconsolata.otf", 20, layout_engine=ImageFont.LAYOUT_BASIC
|
||||
)
|
||||
self.draw = ImageDraw.Draw(self.image)
|
||||
self.x = page_margin
|
||||
self.y = page_margin
|
||||
@@ -79,10 +96,10 @@ class KneeboardPageWriter:
|
||||
self.y += height + self.line_spacing
|
||||
|
||||
def title(self, title: str) -> None:
|
||||
self.text(title, font=self.title_font)
|
||||
self.text(title, font=self.title_font, fill=self.foreground_fill)
|
||||
|
||||
def heading(self, text: str) -> None:
|
||||
self.text(text, font=self.heading_font)
|
||||
self.text(text, font=self.heading_font, fill=self.foreground_fill)
|
||||
|
||||
def table(
|
||||
self, cells: List[List[str]], headers: Optional[List[str]] = None
|
||||
@@ -90,7 +107,7 @@ class KneeboardPageWriter:
|
||||
if headers is None:
|
||||
headers = []
|
||||
table = tabulate(cells, headers=headers, numalign="right")
|
||||
self.text(table, font=self.table_font)
|
||||
self.text(table, font=self.table_font, fill=self.foreground_fill)
|
||||
|
||||
def write(self, path: Path) -> None:
|
||||
self.image.save(path)
|
||||
@@ -237,6 +254,7 @@ class BriefingPage(KneeboardPage):
|
||||
tankers: List[TankerInfo],
|
||||
jtacs: List[JtacInfo],
|
||||
start_time: datetime.datetime,
|
||||
dark_kneeboard: bool,
|
||||
) -> None:
|
||||
self.flight = flight
|
||||
self.comms = list(comms)
|
||||
@@ -244,11 +262,16 @@ class BriefingPage(KneeboardPage):
|
||||
self.tankers = tankers
|
||||
self.jtacs = jtacs
|
||||
self.start_time = start_time
|
||||
self.dark_kneeboard = dark_kneeboard
|
||||
self.comms.append(CommInfo("Flight", self.flight.intra_flight_channel))
|
||||
|
||||
def write(self, path: Path) -> None:
|
||||
writer = KneeboardPageWriter()
|
||||
writer.title(f"{self.flight.callsign} Mission Info")
|
||||
writer = KneeboardPageWriter(dark_theme=self.dark_kneeboard)
|
||||
if self.flight.custom_name is not None:
|
||||
custom_name_title = ' ("{}")'.format(self.flight.custom_name)
|
||||
else:
|
||||
custom_name_title = ""
|
||||
writer.title(f"{self.flight.callsign} Mission Info{custom_name_title}")
|
||||
|
||||
# TODO: Handle carriers.
|
||||
writer.heading("Airfield Info")
|
||||
@@ -281,6 +304,34 @@ class BriefingPage(KneeboardPage):
|
||||
["Bingo", "Joker"],
|
||||
)
|
||||
|
||||
# AEW&C
|
||||
writer.heading("AEW&C")
|
||||
aewc_ladder = []
|
||||
|
||||
for single_aewc in self.awacs:
|
||||
|
||||
if single_aewc.depature_location is None:
|
||||
dep = "-"
|
||||
arr = "-"
|
||||
else:
|
||||
dep = self._format_time(single_aewc.start_time)
|
||||
arr = self._format_time(single_aewc.end_time)
|
||||
|
||||
aewc_ladder.append(
|
||||
[
|
||||
str(single_aewc.callsign),
|
||||
str(single_aewc.freq),
|
||||
str(single_aewc.depature_location),
|
||||
str(dep),
|
||||
str(arr),
|
||||
]
|
||||
)
|
||||
|
||||
writer.table(
|
||||
aewc_ladder,
|
||||
headers=["Callsign", "FREQ", "Depature", "ETD", "ETA"],
|
||||
)
|
||||
|
||||
# Package Section
|
||||
writer.heading("Comm ladder")
|
||||
comm_ladder = []
|
||||
@@ -289,10 +340,6 @@ class BriefingPage(KneeboardPage):
|
||||
[comm.name, "", "", "", self.format_frequency(comm.freq)]
|
||||
)
|
||||
|
||||
for a in self.awacs:
|
||||
comm_ladder.append(
|
||||
[a.callsign, "AWACS", "", "", self.format_frequency(a.freq)]
|
||||
)
|
||||
for tanker in self.tankers:
|
||||
comm_ladder.append(
|
||||
[
|
||||
@@ -361,12 +408,21 @@ class BriefingPage(KneeboardPage):
|
||||
channel_name = namer.channel_name(channel.radio_id, channel.channel)
|
||||
return f"{channel_name} {frequency}"
|
||||
|
||||
def _format_time(self, time: Optional[datetime.timedelta]) -> str:
|
||||
if time is None:
|
||||
return ""
|
||||
local_time = self.start_time + time
|
||||
return local_time.strftime(f"%H:%M:%S")
|
||||
|
||||
|
||||
class KneeboardGenerator(MissionInfoGenerator):
|
||||
"""Creates kneeboard pages for each client flight in the mission."""
|
||||
|
||||
def __init__(self, mission: Mission, game: "Game") -> None:
|
||||
super().__init__(mission, game)
|
||||
self.dark_kneeboard = self.game.settings.generate_dark_kneeboard and (
|
||||
self.mission.start_time.hour > 19 or self.mission.start_time.hour < 7
|
||||
)
|
||||
|
||||
def generate(self) -> None:
|
||||
"""Generates a kneeboard per client flight."""
|
||||
@@ -410,5 +466,6 @@ class KneeboardGenerator(MissionInfoGenerator):
|
||||
self.tankers,
|
||||
self.jtacs,
|
||||
self.mission.start_time,
|
||||
self.dark_kneeboard,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -9,7 +9,7 @@ from gen.locations.preset_locations import PresetLocation
|
||||
class PresetControlPointLocations:
|
||||
"""A repository of preset locations for a given control point"""
|
||||
|
||||
# List of possible ashore locations to generate objects (Represented in miz file by an APC_AAV_7)
|
||||
# List of possible ashore locations to generate objects (Represented in miz file by an APC_AAV_7_Amphibious)
|
||||
ashore_locations: List[PresetLocation] = field(default_factory=list)
|
||||
|
||||
# List of possible offshore locations to generate ship groups (Represented in miz file by an Oliver Hazard Perry)
|
||||
|
||||
@@ -44,7 +44,7 @@ class MizDataLocationFinder:
|
||||
for ship_group in m.country("USA").ship_group:
|
||||
if (
|
||||
len(ship_group.units) > 0
|
||||
and ship_group.units[0].type == ships.Oliver_Hazzard_Perry_class.id
|
||||
and ship_group.units[0].type == ships.FFG_Oliver_Hazzard_Perry.id
|
||||
):
|
||||
offshore_locations.append(
|
||||
PresetLocation(
|
||||
@@ -68,7 +68,8 @@ class MizDataLocationFinder:
|
||||
for vehicle_group in m.country("Iran").vehicle_group:
|
||||
if (
|
||||
len(vehicle_group.units) > 0
|
||||
and vehicle_group.units[0].type == MissilesSS.SS_N_2_Silkworm.id
|
||||
and vehicle_group.units[0].type
|
||||
== MissilesSS.AShM_SS_N_2_Silkworm.id
|
||||
):
|
||||
antiship_locations.append(
|
||||
PresetLocation(
|
||||
|
||||
@@ -9,7 +9,7 @@ MISSILES_MAP = {"V1GroupGenerator": V1GroupGenerator, "ScudGenerator": ScudGener
|
||||
|
||||
def generate_missile_group(game, ground_object, faction_name: str):
|
||||
"""
|
||||
This generate a ship group
|
||||
This generate a missiles group
|
||||
:return: Nothing, but put the group reference inside the ground object
|
||||
"""
|
||||
faction = db.FACTIONS[faction_name]
|
||||
|
||||
@@ -14,21 +14,21 @@ class ScudGenerator(GroupGenerator):
|
||||
|
||||
# Scuds
|
||||
self.add_unit(
|
||||
MissilesSS.SRBM_SS_1C_Scud_B_9K72_LN_9P117M,
|
||||
MissilesSS.SSM_SS_1C_Scud_B,
|
||||
"V1#0",
|
||||
self.position.x,
|
||||
self.position.y + random.randint(1, 8),
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
MissilesSS.SRBM_SS_1C_Scud_B_9K72_LN_9P117M,
|
||||
MissilesSS.SSM_SS_1C_Scud_B,
|
||||
"V1#1",
|
||||
self.position.x + 50,
|
||||
self.position.y + random.randint(1, 8),
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
MissilesSS.SRBM_SS_1C_Scud_B_9K72_LN_9P117M,
|
||||
MissilesSS.SSM_SS_1C_Scud_B,
|
||||
"V1#2",
|
||||
self.position.x + 100,
|
||||
self.position.y + random.randint(1, 8),
|
||||
@@ -37,7 +37,7 @@ class ScudGenerator(GroupGenerator):
|
||||
|
||||
# Commander
|
||||
self.add_unit(
|
||||
Unarmed.Transport_UAZ_469,
|
||||
Unarmed.LUV_UAZ_469_Jeep,
|
||||
"Kubel#0",
|
||||
self.position.x - 35,
|
||||
self.position.y - 20,
|
||||
@@ -46,7 +46,7 @@ class ScudGenerator(GroupGenerator):
|
||||
|
||||
# Shorad
|
||||
self.add_unit(
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
"SHILKA#0",
|
||||
self.position.x - 55,
|
||||
self.position.y - 38,
|
||||
@@ -54,7 +54,7 @@ class ScudGenerator(GroupGenerator):
|
||||
)
|
||||
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_9_Strela_1_9P31,
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL,
|
||||
"STRELA#0",
|
||||
self.position.x + 200,
|
||||
self.position.y + 15,
|
||||
|
||||
@@ -14,21 +14,21 @@ class V1GroupGenerator(GroupGenerator):
|
||||
|
||||
# Ramps
|
||||
self.add_unit(
|
||||
MissilesSS.V_1_ramp,
|
||||
MissilesSS.SSM_V_1_Launcher,
|
||||
"V1#0",
|
||||
self.position.x,
|
||||
self.position.y + random.randint(1, 8),
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
MissilesSS.V_1_ramp,
|
||||
MissilesSS.SSM_V_1_Launcher,
|
||||
"V1#1",
|
||||
self.position.x + 50,
|
||||
self.position.y + random.randint(1, 8),
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
MissilesSS.V_1_ramp,
|
||||
MissilesSS.SSM_V_1_Launcher,
|
||||
"V1#2",
|
||||
self.position.x + 100,
|
||||
self.position.y + random.randint(1, 8),
|
||||
@@ -37,7 +37,7 @@ class V1GroupGenerator(GroupGenerator):
|
||||
|
||||
# Commander
|
||||
self.add_unit(
|
||||
Unarmed.Kübelwagen_82,
|
||||
Unarmed.LUV_Kubelwagen_82,
|
||||
"Kubel#0",
|
||||
self.position.x - 35,
|
||||
self.position.y - 20,
|
||||
@@ -46,7 +46,7 @@ class V1GroupGenerator(GroupGenerator):
|
||||
|
||||
# Self defense flak
|
||||
flak_unit = random.choice(
|
||||
[AirDefence.AAA_Flak_Vierling_38, AirDefence.AAA_Flak_38]
|
||||
[AirDefence.AAA_Flak_Vierling_38_Quad_20mm, AirDefence.AAA_Flak_38_20mm]
|
||||
)
|
||||
|
||||
self.add_unit(
|
||||
@@ -58,7 +58,7 @@ class V1GroupGenerator(GroupGenerator):
|
||||
)
|
||||
|
||||
self.add_unit(
|
||||
Unarmed.Blitz_3_6_6700A,
|
||||
Unarmed.Truck_Opel_Blitz,
|
||||
"Blitz#0",
|
||||
self.position.x + 200,
|
||||
self.position.y + 15,
|
||||
|
||||
@@ -61,7 +61,7 @@ ANIMALS = [
|
||||
"MAMBA",
|
||||
"DOLPHIN",
|
||||
"PHEASANT",
|
||||
"ARMADILLLO",
|
||||
"ARMADILLO",
|
||||
"RACOON",
|
||||
"ZEBRA",
|
||||
"COW",
|
||||
|
||||
@@ -27,7 +27,7 @@ class BoforsGenerator(AirDefenseGroupGenerator):
|
||||
for j in range(grid_y):
|
||||
index = index + 1
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
AirDefence.AAA_40mm_Bofors,
|
||||
"AAA#" + str(index),
|
||||
self.position.x + spacing * i,
|
||||
self.position.y + spacing * j,
|
||||
|
||||
@@ -8,12 +8,12 @@ from gen.sam.airdefensegroupgenerator import (
|
||||
)
|
||||
|
||||
GFLAK = [
|
||||
AirDefence.AAA_Flak_Vierling_38,
|
||||
AirDefence.AAA_Flak_Vierling_38_Quad_20mm,
|
||||
AirDefence.AAA_8_8cm_Flak_18,
|
||||
AirDefence.AAA_8_8cm_Flak_36,
|
||||
AirDefence.AAA_8_8cm_Flak_37,
|
||||
AirDefence.AAA_8_8cm_Flak_41,
|
||||
AirDefence.AAA_Flak_38,
|
||||
AirDefence.AAA_Flak_38_20mm,
|
||||
]
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ class FlakGenerator(AirDefenseGroupGenerator):
|
||||
search_pos = self.get_circular_position(random.randint(2, 3), 80)
|
||||
for index, pos in enumerate(search_pos):
|
||||
self.add_unit(
|
||||
AirDefence.Flak_Searchlight_37,
|
||||
AirDefence.SL_Flakscheinwerfer_37,
|
||||
"SearchLight#" + str(index),
|
||||
pos[0],
|
||||
pos[1],
|
||||
@@ -62,14 +62,14 @@ class FlakGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
# Support
|
||||
self.add_unit(
|
||||
AirDefence.Maschinensatz_33,
|
||||
AirDefence.PU_Maschinensatz_33,
|
||||
"MC33#",
|
||||
self.position.x - 20,
|
||||
self.position.y - 20,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Kdo_G_40,
|
||||
AirDefence.AAA_SP_Kdo_G_40,
|
||||
"KDO#",
|
||||
self.position.x - 25,
|
||||
self.position.y - 20,
|
||||
@@ -78,7 +78,7 @@ class FlakGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
# Commander
|
||||
self.add_unit(
|
||||
Unarmed.Kübelwagen_82,
|
||||
Unarmed.LUV_Kubelwagen_82,
|
||||
"Kubel#",
|
||||
self.position.x - 35,
|
||||
self.position.y - 20,
|
||||
@@ -89,7 +89,7 @@ class FlakGenerator(AirDefenseGroupGenerator):
|
||||
for i in range(int(max(1, grid_x / 2))):
|
||||
for j in range(int(max(1, grid_x / 2))):
|
||||
self.add_unit(
|
||||
Unarmed.Blitz_3_6_6700A,
|
||||
Unarmed.Truck_Opel_Blitz,
|
||||
"BLITZ#" + str(index),
|
||||
self.position.x + 125 + 15 * i + random.randint(1, 5),
|
||||
self.position.y + 15 * j + random.randint(1, 5),
|
||||
|
||||
@@ -34,7 +34,7 @@ class Flak18Generator(AirDefenseGroupGenerator):
|
||||
|
||||
# Add a commander truck
|
||||
self.add_unit(
|
||||
Unarmed.Blitz_3_6_6700A,
|
||||
Unarmed.Truck_Opel_Blitz,
|
||||
"Blitz#",
|
||||
self.position.x - 35,
|
||||
self.position.y - 20,
|
||||
|
||||
@@ -21,7 +21,7 @@ class AllyWW2FlakGenerator(AirDefenseGroupGenerator):
|
||||
positions = self.get_circular_position(4, launcher_distance=30, coverage=360)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.AA_gun_QF_3_7,
|
||||
AirDefence.AAA_QF_3_7,
|
||||
"AA#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
@@ -41,7 +41,7 @@ class AllyWW2FlakGenerator(AirDefenseGroupGenerator):
|
||||
positions = self.get_circular_position(8, launcher_distance=90, coverage=360)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.AAA_M45_Quadmount,
|
||||
AirDefence.AAA_M45_Quadmount_HB_12_7mm,
|
||||
"AA#" + str(12 + i),
|
||||
position[0],
|
||||
position[1],
|
||||
@@ -50,28 +50,28 @@ class AllyWW2FlakGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
# Add a commander truck
|
||||
self.add_unit(
|
||||
Unarmed.Willys_MB,
|
||||
Unarmed.Car_Willys_Jeep,
|
||||
"CMD#1",
|
||||
self.position.x,
|
||||
self.position.y - 20,
|
||||
random.randint(0, 360),
|
||||
)
|
||||
self.add_unit(
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Unarmed.Carrier_M30_Cargo,
|
||||
"LOG#1",
|
||||
self.position.x,
|
||||
self.position.y + 20,
|
||||
random.randint(0, 360),
|
||||
)
|
||||
self.add_unit(
|
||||
Armor.M4_Tractor,
|
||||
Unarmed.Tractor_M4_Hi_Speed,
|
||||
"LOG#2",
|
||||
self.position.x + 20,
|
||||
self.position.y,
|
||||
random.randint(0, 360),
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Bedford_MWD,
|
||||
Unarmed.Truck_Bedford,
|
||||
"LOG#3",
|
||||
self.position.x - 20,
|
||||
self.position.y,
|
||||
|
||||
@@ -21,7 +21,7 @@ class ZSU57Generator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZSU_57_2,
|
||||
AirDefence.SPAAA_ZSU_57_2,
|
||||
"SPAA#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -27,7 +27,7 @@ class ZU23InsurgentGenerator(AirDefenseGroupGenerator):
|
||||
for j in range(grid_y):
|
||||
index = index + 1
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Insurgent_Closed,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement_Insurgent,
|
||||
"AAA#" + str(index),
|
||||
self.position.x + spacing * i,
|
||||
self.position.y + spacing * j,
|
||||
|
||||
@@ -12,13 +12,13 @@ from gen.sam.group_generator import GroupGenerator
|
||||
class EarlyColdWarFlakGenerator(AirDefenseGroupGenerator):
|
||||
"""
|
||||
This generator attempt to mimic an early cold-war era flak AAA site.
|
||||
The Flak 18 88mm is used as the main long range gun and 2 Bofors 40mm guns provide short range protection.
|
||||
The Flak 18 88mm is used as the main long range gun, S-60 is used as a mid range gun and 2 Bofors 40mm guns provide short range protection.
|
||||
|
||||
This does not include search lights and telemeter computer (Kdo.G 40) because these are paid units only available in WW2 asset pack
|
||||
"""
|
||||
|
||||
name = "Early Cold War Flak Site"
|
||||
price = 58
|
||||
price = 74
|
||||
|
||||
def generate(self):
|
||||
|
||||
@@ -37,25 +37,41 @@ class EarlyColdWarFlakGenerator(AirDefenseGroupGenerator):
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Short range guns
|
||||
# Medium range guns
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
AirDefence.AAA_S_60_57mm,
|
||||
"SHO#1",
|
||||
self.position.x - 40,
|
||||
self.position.y - 40,
|
||||
self.heading + 180,
|
||||
),
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
AirDefence.AAA_S_60_57mm,
|
||||
"SHO#2",
|
||||
self.position.x + spacing * 2 + 40,
|
||||
self.position.y + spacing + 40,
|
||||
self.heading,
|
||||
),
|
||||
|
||||
# Short range guns
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement,
|
||||
"SHO#3",
|
||||
self.position.x - 80,
|
||||
self.position.y - 40,
|
||||
self.heading + 180,
|
||||
),
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement,
|
||||
"SHO#4",
|
||||
self.position.x + spacing * 2 + 80,
|
||||
self.position.y + spacing + 40,
|
||||
self.heading,
|
||||
),
|
||||
|
||||
# Add a truck
|
||||
self.add_unit(
|
||||
Unarmed.Transport_KAMAZ_43101,
|
||||
Unarmed.Truck_KAMAZ_43101,
|
||||
"Truck#",
|
||||
self.position.x - 60,
|
||||
self.position.y - 20,
|
||||
@@ -70,7 +86,7 @@ class EarlyColdWarFlakGenerator(AirDefenseGroupGenerator):
|
||||
class ColdWarFlakGenerator(AirDefenseGroupGenerator):
|
||||
"""
|
||||
This generator attempt to mimic a cold-war era flak AAA site.
|
||||
The Flak 18 88mm is used as the main long range gun while 2 Zu-23 guns provide short range protection.
|
||||
The Flak 18 88mm is used as the main long range gun, 2 S-60 57mm gun improve mid range firepower, while 2 Zu-23 guns even provide short range protection.
|
||||
The site is also fitted with a P-19 radar for early detection.
|
||||
"""
|
||||
|
||||
@@ -94,25 +110,41 @@ class ColdWarFlakGenerator(AirDefenseGroupGenerator):
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Short range guns
|
||||
# Medium range guns
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Closed,
|
||||
AirDefence.AAA_S_60_57mm,
|
||||
"SHO#1",
|
||||
self.position.x - 40,
|
||||
self.position.y - 40,
|
||||
self.heading + 180,
|
||||
),
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Closed,
|
||||
AirDefence.AAA_S_60_57mm,
|
||||
"SHO#2",
|
||||
self.position.x + spacing * 2 + 40,
|
||||
self.position.y + spacing + 40,
|
||||
self.heading,
|
||||
),
|
||||
|
||||
# Short range guns
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement,
|
||||
"SHO#3",
|
||||
self.position.x - 80,
|
||||
self.position.y - 40,
|
||||
self.heading + 180,
|
||||
),
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement,
|
||||
"SHO#4",
|
||||
self.position.x + spacing * 2 + 80,
|
||||
self.position.y + spacing + 40,
|
||||
self.heading,
|
||||
),
|
||||
|
||||
# Add a P19 Radar for EWR
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SR_P_19,
|
||||
AirDefence.SAM_P19_Flat_Face_SR__SA_2_3,
|
||||
"SR#0",
|
||||
self.position.x - 60,
|
||||
self.position.y - 20,
|
||||
|
||||
63
gen/sam/ewr_group_generator.py
Normal file
63
gen/sam/ewr_group_generator.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import random
|
||||
from typing import List, Optional, Type
|
||||
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
|
||||
from game import Game
|
||||
from game.factions.faction import Faction
|
||||
from game.theater.theatergroundobject import EwrGroundObject
|
||||
from gen.sam.ewrs import (
|
||||
BigBirdGenerator,
|
||||
BoxSpringGenerator,
|
||||
DogEarGenerator,
|
||||
FlatFaceGenerator,
|
||||
HawkEwrGenerator,
|
||||
PatriotEwrGenerator,
|
||||
RolandEwrGenerator,
|
||||
SnowDriftGenerator,
|
||||
StraightFlushGenerator,
|
||||
TallRackGenerator,
|
||||
)
|
||||
from gen.sam.group_generator import GroupGenerator
|
||||
|
||||
EWR_MAP = {
|
||||
"BoxSpringGenerator": BoxSpringGenerator,
|
||||
"TallRackGenerator": TallRackGenerator,
|
||||
"DogEarGenerator": DogEarGenerator,
|
||||
"RolandEwrGenerator": RolandEwrGenerator,
|
||||
"FlatFaceGenerator": FlatFaceGenerator,
|
||||
"PatriotEwrGenerator": PatriotEwrGenerator,
|
||||
"BigBirdGenerator": BigBirdGenerator,
|
||||
"SnowDriftGenerator": SnowDriftGenerator,
|
||||
"StraightFlushGenerator": StraightFlushGenerator,
|
||||
"HawkEwrGenerator": HawkEwrGenerator,
|
||||
}
|
||||
|
||||
|
||||
def get_faction_possible_ewrs_generator(
|
||||
faction: Faction,
|
||||
) -> List[Type[GroupGenerator]]:
|
||||
"""
|
||||
Return the list of possible EWR generators for the given faction
|
||||
:param faction: Faction name to search units for
|
||||
"""
|
||||
return [EWR_MAP[s] for s in faction.ewrs]
|
||||
|
||||
|
||||
def generate_ewr_group(
|
||||
game: Game, ground_object: EwrGroundObject, faction: Faction
|
||||
) -> Optional[VehicleGroup]:
|
||||
"""Generates an early warning radar group.
|
||||
|
||||
:param game: The Game.
|
||||
:param ground_object: The ground object which will own the EWR group.
|
||||
:param faction: Owner faction.
|
||||
:return: The generated group, or None if one could not be generated.
|
||||
"""
|
||||
generators = get_faction_possible_ewrs_generator(faction)
|
||||
if len(generators) > 0:
|
||||
generator_class = random.choice(generators)
|
||||
generator = generator_class(game, ground_object)
|
||||
generator.generate()
|
||||
return generator.get_generated_group()
|
||||
return None
|
||||
@@ -33,7 +33,7 @@ class DogEarGenerator(EwrGenerator):
|
||||
This is the SA-8 search radar, but used as an early warning radar.
|
||||
"""
|
||||
|
||||
unit_type = AirDefence.CP_9S80M1_Sborka
|
||||
unit_type = AirDefence.MCC_SR_Sborka_Dog_Ear_SR
|
||||
|
||||
|
||||
class RolandEwrGenerator(EwrGenerator):
|
||||
@@ -51,7 +51,7 @@ class FlatFaceGenerator(EwrGenerator):
|
||||
This is the SA-3 search radar, but used as an early warning radar.
|
||||
"""
|
||||
|
||||
unit_type = AirDefence.SAM_SR_P_19
|
||||
unit_type = AirDefence.SAM_P19_Flat_Face_SR__SA_2_3
|
||||
|
||||
|
||||
class PatriotEwrGenerator(EwrGenerator):
|
||||
@@ -60,7 +60,7 @@ class PatriotEwrGenerator(EwrGenerator):
|
||||
This is the Patriot search/track radar, but used as an early warning radar.
|
||||
"""
|
||||
|
||||
unit_type = AirDefence.SAM_Patriot_STR_AN_MPQ_53
|
||||
unit_type = AirDefence.SAM_Patriot_STR
|
||||
|
||||
|
||||
class BigBirdGenerator(EwrGenerator):
|
||||
@@ -69,7 +69,7 @@ class BigBirdGenerator(EwrGenerator):
|
||||
This is the SA-10 track radar, but used as an early warning radar.
|
||||
"""
|
||||
|
||||
unit_type = AirDefence.SAM_SA_10_S_300PS_SR_64H6E
|
||||
unit_type = AirDefence.SAM_SA_10_S_300_Grumble_Big_Bird_SR
|
||||
|
||||
|
||||
class SnowDriftGenerator(EwrGenerator):
|
||||
@@ -78,7 +78,7 @@ class SnowDriftGenerator(EwrGenerator):
|
||||
This is the SA-11 search radar, but used as an early warning radar.
|
||||
"""
|
||||
|
||||
unit_type = AirDefence.SAM_SA_11_Buk_SR_9S18M1
|
||||
unit_type = AirDefence.SAM_SA_11_Buk_Gadfly_Snow_Drift_SR
|
||||
|
||||
|
||||
class StraightFlushGenerator(EwrGenerator):
|
||||
@@ -87,7 +87,7 @@ class StraightFlushGenerator(EwrGenerator):
|
||||
This is the SA-6 search/track radar, but used as an early warning radar.
|
||||
"""
|
||||
|
||||
unit_type = AirDefence.SAM_SA_6_Kub_STR_9S91
|
||||
unit_type = AirDefence.SAM_SA_6_Kub_Long_Track_STR
|
||||
|
||||
|
||||
class HawkEwrGenerator(EwrGenerator):
|
||||
@@ -96,4 +96,4 @@ class HawkEwrGenerator(EwrGenerator):
|
||||
This is the Hawk search radar, but used as an early warning radar.
|
||||
"""
|
||||
|
||||
unit_type = AirDefence.SAM_Hawk_SR_AN_MPQ_50
|
||||
unit_type = AirDefence.SAM_Hawk_SR__AN_MPQ_50
|
||||
|
||||
@@ -28,7 +28,7 @@ class FreyaGenerator(AirDefenseGroupGenerator):
|
||||
positions = self.get_circular_position(4, launcher_distance=50, coverage=360)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Flak_Vierling_38,
|
||||
AirDefence.AAA_Flak_Vierling_38_Quad_20mm,
|
||||
"AA#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
@@ -47,37 +47,37 @@ class FreyaGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
# Command/Logi
|
||||
self.add_unit(
|
||||
Unarmed.Kübelwagen_82,
|
||||
Unarmed.LUV_Kubelwagen_82,
|
||||
"Kubel#1",
|
||||
self.position.x - 20,
|
||||
self.position.y - 20,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Sd_Kfz_7,
|
||||
Unarmed.Carrier_Sd_Kfz_7_Tractor,
|
||||
"Sdkfz#1",
|
||||
self.position.x + 20,
|
||||
self.position.y + 22,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Sd_Kfz_2,
|
||||
Unarmed.LUV_Kettenrad,
|
||||
"Sdkfz#2",
|
||||
self.position.x - 22,
|
||||
self.position.y + 20,
|
||||
self.heading,
|
||||
)
|
||||
|
||||
# Maschinensatz_33 and Kdo.g 40 Telemeter
|
||||
# PU_Maschinensatz_33 and Kdo.g 40 Telemeter
|
||||
self.add_unit(
|
||||
AirDefence.Maschinensatz_33,
|
||||
AirDefence.PU_Maschinensatz_33,
|
||||
"Energy#1",
|
||||
self.position.x + 20,
|
||||
self.position.y - 20,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Kdo_G_40,
|
||||
AirDefence.AAA_SP_Kdo_G_40,
|
||||
"Telemeter#1",
|
||||
self.position.x + 20,
|
||||
self.position.y - 10,
|
||||
|
||||
@@ -20,7 +20,7 @@ class AvengerGenerator(AirDefenseGroupGenerator):
|
||||
num_launchers = random.randint(2, 3)
|
||||
|
||||
self.add_unit(
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
"TRUCK",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
@@ -31,7 +31,7 @@ class AvengerGenerator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Avenger_M1097,
|
||||
AirDefence.SAM_Avenger__Stinger,
|
||||
"SPAA#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -20,7 +20,7 @@ class ChaparralGenerator(AirDefenseGroupGenerator):
|
||||
num_launchers = random.randint(2, 4)
|
||||
|
||||
self.add_unit(
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
"TRUCK",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
|
||||
@@ -33,7 +33,7 @@ class GepardGenerator(AirDefenseGroupGenerator):
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
"TRUCK",
|
||||
self.position.x + 80,
|
||||
self.position.y,
|
||||
|
||||
@@ -6,7 +6,6 @@ from dcs.vehicles import AirDefence
|
||||
|
||||
from game import Game
|
||||
from game.factions.faction import Faction
|
||||
from game.theater import TheaterGroundObject
|
||||
from game.theater.theatergroundobject import SamGroundObject
|
||||
from gen.sam.aaa_bofors import BoforsGenerator
|
||||
from gen.sam.aaa_flak import FlakGenerator
|
||||
@@ -23,20 +22,7 @@ from gen.sam.cold_war_flak import (
|
||||
ColdWarFlakGenerator,
|
||||
EarlyColdWarFlakGenerator,
|
||||
)
|
||||
from gen.sam.ewrs import (
|
||||
BigBirdGenerator,
|
||||
BoxSpringGenerator,
|
||||
DogEarGenerator,
|
||||
FlatFaceGenerator,
|
||||
HawkEwrGenerator,
|
||||
PatriotEwrGenerator,
|
||||
RolandEwrGenerator,
|
||||
SnowDriftGenerator,
|
||||
StraightFlushGenerator,
|
||||
TallRackGenerator,
|
||||
)
|
||||
from gen.sam.freya_ewr import FreyaGenerator
|
||||
from gen.sam.group_generator import GroupGenerator
|
||||
from gen.sam.sam_avenger import AvengerGenerator
|
||||
from gen.sam.sam_chaparral import ChaparralGenerator
|
||||
from gen.sam.sam_gepard import GepardGenerator
|
||||
@@ -119,52 +105,39 @@ SAM_MAP: Dict[str, Type[AirDefenseGroupGenerator]] = {
|
||||
|
||||
|
||||
SAM_PRICES = {
|
||||
AirDefence.SAM_Hawk_PCP: 35,
|
||||
AirDefence.SAM_Hawk_Generator__PCP: 35,
|
||||
AirDefence.AAA_ZU_23_Emplacement: 10,
|
||||
AirDefence.AAA_ZU_23_Closed: 10,
|
||||
AirDefence.AAA_ZU_23_on_Ural_375: 10,
|
||||
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375: 10,
|
||||
AirDefence.AAA_ZU_23_Insurgent_Closed: 10,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement: 10,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375: 10,
|
||||
AirDefence.SPAAA_ZU_23_2_Insurgent_Mounted_Ural_375: 10,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement_Insurgent: 10,
|
||||
AirDefence.AAA_ZU_23_Insurgent: 10,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka: 10,
|
||||
AirDefence.AAA_Vulcan_M163: 15,
|
||||
AirDefence.SAM_Linebacker_M6: 20,
|
||||
AirDefence.Rapier_FSA_Launcher: 20,
|
||||
AirDefence.SAM_Avenger_M1097: 22,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish: 10,
|
||||
AirDefence.SPAAA_Vulcan_M163: 15,
|
||||
AirDefence.SAM_Linebacker___Bradley_M6: 20,
|
||||
AirDefence.SAM_Rapier_LN: 20,
|
||||
AirDefence.SAM_Avenger__Stinger: 22,
|
||||
AirDefence.SPAAA_Gepard: 24,
|
||||
AirDefence.SAM_Roland_ADS: 40,
|
||||
AirDefence.SAM_Patriot_LN_M901: 85,
|
||||
AirDefence.SAM_Patriot_LN: 85,
|
||||
AirDefence.SAM_Patriot_EPP_III: 85,
|
||||
AirDefence.SAM_Chaparral_M48: 25,
|
||||
AirDefence.AAA_Bofors_40mm: 15,
|
||||
AirDefence.AAA_40mm_Bofors: 15,
|
||||
AirDefence.AAA_8_8cm_Flak_36: 15,
|
||||
AirDefence.SAM_SA_2_LN_SM_90: 30,
|
||||
AirDefence.SAM_SA_3_S_125_LN_5P73: 35,
|
||||
AirDefence.SAM_SA_6_Kub_LN_2P25: 45,
|
||||
AirDefence.SAM_SA_8_Osa_9A33: 30,
|
||||
AirDefence.SAM_SA_9_Strela_1_9P31: 25,
|
||||
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 80,
|
||||
AirDefence.SAM_SA_10_S_300PS_CP_54K6: 80,
|
||||
AirDefence.SAM_SA_11_Buk_LN_9A310M1: 60,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_9A35M3: 30,
|
||||
AirDefence.SAM_SA_15_Tor_9A331: 40,
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6: 35,
|
||||
AirDefence.SAM_SA_2_S_75_Guideline_LN: 30,
|
||||
AirDefence.SAM_SA_3_S_125_Goa_LN: 35,
|
||||
AirDefence.SAM_SA_6_Kub_Gainful_TEL: 45,
|
||||
AirDefence.SAM_SA_8_Osa_Gecko_TEL: 30,
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL: 25,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_TEL_C: 80,
|
||||
AirDefence.SAM_SA_10_S_300_Grumble_C2: 80,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Fire_Dome_TEL: 60,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_Gopher_TEL: 30,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet: 40,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison: 35,
|
||||
AirDefence.HQ_7_Self_Propelled_LN: 35,
|
||||
}
|
||||
|
||||
EWR_MAP = {
|
||||
"BoxSpringGenerator": BoxSpringGenerator,
|
||||
"TallRackGenerator": TallRackGenerator,
|
||||
"DogEarGenerator": DogEarGenerator,
|
||||
"RolandEwrGenerator": RolandEwrGenerator,
|
||||
"FlatFaceGenerator": FlatFaceGenerator,
|
||||
"PatriotEwrGenerator": PatriotEwrGenerator,
|
||||
"BigBirdGenerator": BigBirdGenerator,
|
||||
"SnowDriftGenerator": SnowDriftGenerator,
|
||||
"StraightFlushGenerator": StraightFlushGenerator,
|
||||
"HawkEwrGenerator": HawkEwrGenerator,
|
||||
}
|
||||
|
||||
|
||||
def get_faction_possible_sams_generator(
|
||||
faction: Faction,
|
||||
@@ -176,14 +149,6 @@ def get_faction_possible_sams_generator(
|
||||
return [SAM_MAP[s] for s in faction.air_defenses]
|
||||
|
||||
|
||||
def get_faction_possible_ewrs_generator(faction: Faction) -> List[Type[GroupGenerator]]:
|
||||
"""
|
||||
Return the list of possible SAM generator for the given faction
|
||||
:param faction: Faction name to search units for
|
||||
"""
|
||||
return [EWR_MAP[s] for s in faction.ewrs]
|
||||
|
||||
|
||||
def _generate_anti_air_from(
|
||||
generators: Sequence[Type[AirDefenseGroupGenerator]],
|
||||
game: Game,
|
||||
@@ -236,22 +201,3 @@ def generate_anti_air_group(
|
||||
if groups:
|
||||
return groups
|
||||
return []
|
||||
|
||||
|
||||
def generate_ewr_group(
|
||||
game: Game, ground_object: TheaterGroundObject, faction: Faction
|
||||
) -> Optional[VehicleGroup]:
|
||||
"""Generates an early warning radar group.
|
||||
|
||||
:param game: The Game.
|
||||
:param ground_object: The ground object which will own the EWR group.
|
||||
:param faction: Owner faction.
|
||||
:return: The generated group, or None if one could not be generated.
|
||||
"""
|
||||
generators = get_faction_possible_ewrs_generator(faction)
|
||||
if len(generators) > 0:
|
||||
generator_class = random.choice(generators)
|
||||
generator = generator_class(game, ground_object)
|
||||
generator.generate()
|
||||
return generator.get_generated_group()
|
||||
return None
|
||||
|
||||
@@ -19,21 +19,21 @@ class HawkGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Hawk_SR_AN_MPQ_50,
|
||||
AirDefence.SAM_Hawk_SR__AN_MPQ_50,
|
||||
"SR",
|
||||
self.position.x + 20,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Hawk_PCP,
|
||||
AirDefence.SAM_Hawk_Generator__PCP,
|
||||
"PCP",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Hawk_TR_AN_MPQ_46,
|
||||
AirDefence.SAM_Hawk_TR__AN_MPQ_46,
|
||||
"TR",
|
||||
self.position.x + 40,
|
||||
self.position.y,
|
||||
@@ -44,7 +44,7 @@ class HawkGenerator(AirDefenseGroupGenerator):
|
||||
aa_group = self.add_auxiliary_group("AA")
|
||||
self.add_unit_to_group(
|
||||
aa_group,
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
"AAA",
|
||||
self.position + Point(20, 30),
|
||||
self.heading,
|
||||
|
||||
@@ -37,14 +37,14 @@ class HQ7Generator(AirDefenseGroupGenerator):
|
||||
aa_group = self.add_auxiliary_group("AA")
|
||||
self.add_unit_to_group(
|
||||
aa_group,
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375,
|
||||
"AAA1",
|
||||
self.position + Point(20, 30),
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit_to_group(
|
||||
aa_group,
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375,
|
||||
"AAA2",
|
||||
self.position - Point(20, 30),
|
||||
self.heading,
|
||||
|
||||
@@ -20,7 +20,7 @@ class LinebackerGenerator(AirDefenseGroupGenerator):
|
||||
num_launchers = random.randint(2, 4)
|
||||
|
||||
self.add_unit(
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
"TRUCK",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
@@ -31,7 +31,7 @@ class LinebackerGenerator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Linebacker_M6,
|
||||
AirDefence.SAM_Linebacker___Bradley_M6,
|
||||
"M6#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -20,28 +20,28 @@ class PatriotGenerator(AirDefenseGroupGenerator):
|
||||
def generate(self):
|
||||
# Command Post
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Patriot_STR_AN_MPQ_53,
|
||||
AirDefence.SAM_Patriot_STR,
|
||||
"STR",
|
||||
self.position.x + 30,
|
||||
self.position.y + 30,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Patriot_AMG_AN_MRC_137,
|
||||
AirDefence.SAM_Patriot_CR__AMG_AN_MRC_137,
|
||||
"MRC",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Patriot_ECS_AN_MSQ_104,
|
||||
AirDefence.SAM_Patriot_ECS,
|
||||
"MSQ",
|
||||
self.position.x + 30,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Patriot_ICC,
|
||||
AirDefence.SAM_Patriot_C2_ICC,
|
||||
"ICC",
|
||||
self.position.x + 60,
|
||||
self.position.y,
|
||||
@@ -61,7 +61,7 @@ class PatriotGenerator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_Patriot_LN_M901,
|
||||
AirDefence.SAM_Patriot_LN,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
@@ -76,7 +76,11 @@ class PatriotGenerator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, (x, y, heading) in enumerate(positions):
|
||||
self.add_unit_to_group(
|
||||
aa_group, AirDefence.AAA_Vulcan_M163, f"SPAAA#{i}", Point(x, y), heading
|
||||
aa_group,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
f"SPAAA#{i}",
|
||||
Point(x, y),
|
||||
heading,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -18,14 +18,14 @@ class RapierGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.Rapier_FSA_Blindfire_Tracker,
|
||||
AirDefence.SAM_Rapier_Blindfire_TR,
|
||||
"BT",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.Rapier_FSA_Optical_Tracker,
|
||||
AirDefence.SAM_Rapier_Tracker,
|
||||
"OT",
|
||||
self.position.x + 20,
|
||||
self.position.y,
|
||||
@@ -39,7 +39,7 @@ class RapierGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.Rapier_FSA_Launcher,
|
||||
AirDefence.SAM_Rapier_LN,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -30,7 +30,7 @@ class RolandGenerator(AirDefenseGroupGenerator):
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
"TRUCK",
|
||||
self.position.x + 80,
|
||||
self.position.y,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import random
|
||||
|
||||
from dcs.mapping import Point
|
||||
from dcs.unittype import VehicleType
|
||||
from dcs.vehicles import AirDefence
|
||||
|
||||
from game import Game
|
||||
@@ -18,18 +17,18 @@ class SA10Generator(AirDefenseGroupGenerator):
|
||||
This generate a SA-10 group
|
||||
"""
|
||||
|
||||
name = "SA-10/S-300PS Battery"
|
||||
name = "SA-10/S-300PS Battery - With ZSU-23"
|
||||
price = 550
|
||||
|
||||
def __init__(self, game: Game, ground_object: SamGroundObject):
|
||||
super().__init__(game, ground_object)
|
||||
self.sr1 = AirDefence.SAM_SA_10_S_300PS_SR_5N66M
|
||||
self.sr2 = AirDefence.SAM_SA_10_S_300PS_SR_64H6E
|
||||
self.cp = AirDefence.SAM_SA_10_S_300PS_CP_54K6
|
||||
self.tr1 = AirDefence.SAM_SA_10_S_300PS_TR_30N6
|
||||
self.tr2 = AirDefence.SAM_SA_10_S_300PS_TR_30N6
|
||||
self.ln1 = AirDefence.SAM_SA_10_S_300PS_LN_5P85C
|
||||
self.ln2 = AirDefence.SAM_SA_10_S_300PS_LN_5P85D
|
||||
self.sr1 = AirDefence.SAM_SA_10_S_300_Grumble_Clam_Shell_SR
|
||||
self.sr2 = AirDefence.SAM_SA_10_S_300_Grumble_Big_Bird_SR
|
||||
self.cp = AirDefence.SAM_SA_10_S_300_Grumble_C2
|
||||
self.tr1 = AirDefence.SAM_SA_10_S_300_Grumble_Flap_Lid_TR
|
||||
self.tr2 = AirDefence.SAM_SA_10_S_300_Grumble_Flap_Lid_TR
|
||||
self.ln1 = AirDefence.SAM_SA_10_S_300_Grumble_TEL_C
|
||||
self.ln2 = AirDefence.SAM_SA_10_S_300_Grumble_TEL_D
|
||||
|
||||
def generate(self):
|
||||
# Search Radar
|
||||
@@ -85,7 +84,7 @@ class SA10Generator(AirDefenseGroupGenerator):
|
||||
for i, (x, y, heading) in enumerate(positions):
|
||||
self.add_unit_to_group(
|
||||
aa_group,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
f"AA#{i}",
|
||||
Point(x, y),
|
||||
heading,
|
||||
@@ -93,6 +92,10 @@ class SA10Generator(AirDefenseGroupGenerator):
|
||||
|
||||
|
||||
class Tier2SA10Generator(SA10Generator):
|
||||
|
||||
name = "SA-10/S-300PS Battery - With SA-15 PD"
|
||||
price = 650
|
||||
|
||||
def generate_defensive_groups(self) -> None:
|
||||
# Create AAA the way the main group does.
|
||||
super().generate_defensive_groups()
|
||||
@@ -106,7 +109,7 @@ class Tier2SA10Generator(SA10Generator):
|
||||
for i, (x, y, heading) in enumerate(positions):
|
||||
self.add_unit_to_group(
|
||||
pd_group,
|
||||
AirDefence.SAM_SA_15_Tor_9A331,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet,
|
||||
f"PD#{i}",
|
||||
Point(x, y),
|
||||
heading,
|
||||
@@ -114,6 +117,10 @@ class Tier2SA10Generator(SA10Generator):
|
||||
|
||||
|
||||
class Tier3SA10Generator(SA10Generator):
|
||||
|
||||
name = "SA-10/S-300PS Battery - With SA-15 PD & SA-19 SHORAD"
|
||||
price = 750
|
||||
|
||||
def generate_defensive_groups(self) -> None:
|
||||
# AAA for defending against close targets.
|
||||
aa_group = self.add_auxiliary_group("AA")
|
||||
@@ -124,7 +131,7 @@ class Tier3SA10Generator(SA10Generator):
|
||||
for i, (x, y, heading) in enumerate(positions):
|
||||
self.add_unit_to_group(
|
||||
aa_group,
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison,
|
||||
f"AA#{i}",
|
||||
Point(x, y),
|
||||
heading,
|
||||
@@ -139,7 +146,7 @@ class Tier3SA10Generator(SA10Generator):
|
||||
for i, (x, y, heading) in enumerate(positions):
|
||||
self.add_unit_to_group(
|
||||
pd_group,
|
||||
AirDefence.SAM_SA_15_Tor_9A331,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet,
|
||||
f"PD#{i}",
|
||||
Point(x, y),
|
||||
heading,
|
||||
|
||||
@@ -18,14 +18,14 @@ class SA11Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_11_Buk_SR_9S18M1,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Snow_Drift_SR,
|
||||
"SR",
|
||||
self.position.x + 20,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_11_Buk_CC_9S470M1,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_C2,
|
||||
"CC",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
@@ -39,7 +39,7 @@ class SA11Generator(AirDefenseGroupGenerator):
|
||||
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_11_Buk_LN_9A310M1,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Fire_Dome_TEL,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -18,14 +18,14 @@ class SA13Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
Unarmed.Transport_UAZ_469,
|
||||
Unarmed.LUV_UAZ_469_Jeep,
|
||||
"UAZ",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Transport_KAMAZ_43101,
|
||||
Unarmed.Truck_KAMAZ_43101,
|
||||
"TRUCK",
|
||||
self.position.x + 40,
|
||||
self.position.y,
|
||||
@@ -38,7 +38,7 @@ class SA13Generator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_13_Strela_10M3_9A35M3,
|
||||
AirDefence.SAM_SA_13_Strela_10M3_Gopher_TEL,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -16,21 +16,21 @@ class SA15Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_15_Tor_9A331,
|
||||
AirDefence.SAM_SA_15_Tor_Gauntlet,
|
||||
"ADS",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Transport_UAZ_469,
|
||||
Unarmed.LUV_UAZ_469_Jeep,
|
||||
"EWR",
|
||||
self.position.x + 40,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Transport_KAMAZ_43101,
|
||||
Unarmed.Truck_KAMAZ_43101,
|
||||
"TRUCK",
|
||||
self.position.x + 80,
|
||||
self.position.y,
|
||||
|
||||
@@ -17,14 +17,14 @@ class SA17Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_11_Buk_SR_9S18M1,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_Snow_Drift_SR,
|
||||
"SR",
|
||||
self.position.x + 20,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_11_Buk_CC_9S470M1,
|
||||
AirDefence.SAM_SA_11_Buk_Gadfly_C2,
|
||||
"CC",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
|
||||
@@ -21,7 +21,7 @@ class SA19Generator(AirDefenseGroupGenerator):
|
||||
|
||||
if num_launchers == 1:
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison,
|
||||
"LN#0",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
@@ -33,7 +33,7 @@ class SA19Generator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||
AirDefence.SAM_SA_19_Tunguska_Grison,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -18,10 +18,14 @@ class SA2Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SR_P_19, "SR", self.position.x, self.position.y, self.heading
|
||||
AirDefence.SAM_P19_Flat_Face_SR__SA_2_3,
|
||||
"SR",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song,
|
||||
AirDefence.SAM_SA_2_S_75_Fan_Song_TR,
|
||||
"TR",
|
||||
self.position.x + 20,
|
||||
self.position.y,
|
||||
@@ -35,7 +39,7 @@ class SA2Generator(AirDefenseGroupGenerator):
|
||||
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_2_LN_SM_90,
|
||||
AirDefence.SAM_SA_2_S_75_Guideline_LN,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -18,10 +18,14 @@ class SA3Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SR_P_19, "SR", self.position.x, self.position.y, self.heading
|
||||
AirDefence.SAM_P19_Flat_Face_SR__SA_2_3,
|
||||
"SR",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_3_S_125_TR_SNR,
|
||||
AirDefence.SAM_SA_3_S_125_Low_Blow_TR,
|
||||
"TR",
|
||||
self.position.x + 20,
|
||||
self.position.y,
|
||||
@@ -35,7 +39,7 @@ class SA3Generator(AirDefenseGroupGenerator):
|
||||
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_3_S_125_LN_5P73,
|
||||
AirDefence.SAM_SA_3_S_125_Goa_LN,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -18,7 +18,7 @@ class SA6Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_6_Kub_STR_9S91,
|
||||
AirDefence.SAM_SA_6_Kub_Long_Track_STR,
|
||||
"STR",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
@@ -32,7 +32,7 @@ class SA6Generator(AirDefenseGroupGenerator):
|
||||
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_6_Kub_LN_2P25,
|
||||
AirDefence.SAM_SA_6_Kub_Gainful_TEL,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -16,7 +16,7 @@ class SA8Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_8_Osa_9A33,
|
||||
AirDefence.SAM_SA_8_Osa_Gecko_TEL,
|
||||
"OSA",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
|
||||
@@ -18,14 +18,14 @@ class SA9Generator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
Unarmed.Transport_UAZ_469,
|
||||
Unarmed.LUV_UAZ_469_Jeep,
|
||||
"UAZ",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Transport_KAMAZ_43101,
|
||||
Unarmed.Truck_KAMAZ_43101,
|
||||
"TRUCK",
|
||||
self.position.x + 40,
|
||||
self.position.y,
|
||||
@@ -38,7 +38,7 @@ class SA9Generator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SAM_SA_9_Strela_1_9P31,
|
||||
AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL,
|
||||
"LN#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -18,7 +18,7 @@ class VulcanGenerator(AirDefenseGroupGenerator):
|
||||
|
||||
def generate(self):
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
"SPAAA",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
@@ -26,14 +26,14 @@ class VulcanGenerator(AirDefenseGroupGenerator):
|
||||
)
|
||||
if random.randint(0, 1) == 1:
|
||||
self.add_unit(
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SPAAA_Vulcan_M163,
|
||||
"SPAAA2",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading,
|
||||
)
|
||||
self.add_unit(
|
||||
Unarmed.Transport_M818,
|
||||
Unarmed.Truck_M818_6x6,
|
||||
"TRUCK",
|
||||
self.position.x + 80,
|
||||
self.position.y,
|
||||
|
||||
@@ -24,7 +24,7 @@ class ZSU23Generator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
||||
AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
"SPAA#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -27,7 +27,7 @@ class ZU23Generator(AirDefenseGroupGenerator):
|
||||
for j in range(grid_y):
|
||||
index = index + 1
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Closed,
|
||||
AirDefence.AAA_ZU_23_Closed_Emplacement,
|
||||
"AAA#" + str(index),
|
||||
self.position.x + spacing * i,
|
||||
self.position.y + spacing * j,
|
||||
|
||||
@@ -24,7 +24,7 @@ class ZU23UralGenerator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375,
|
||||
"SPAA#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
@@ -24,7 +24,7 @@ class ZU23UralInsurgentGenerator(AirDefenseGroupGenerator):
|
||||
)
|
||||
for i, position in enumerate(positions):
|
||||
self.add_unit(
|
||||
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375,
|
||||
AirDefence.SPAAA_ZU_23_2_Insurgent_Mounted_Ural_375,
|
||||
"SPAA#" + str(i),
|
||||
position[0],
|
||||
position[1],
|
||||
|
||||
2
pydcs
2
pydcs
Submodule pydcs updated: 42de2ec352...cd14f0a049
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,7 @@ class F_22A(PlaneType):
|
||||
chaff_charge_size = 1
|
||||
flare_charge_size = 2
|
||||
eplrs = True
|
||||
category = "Interceptor" #{78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
category = "Interceptor" # {78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
radio_frequency = 127.5
|
||||
|
||||
property_defaults = {
|
||||
@@ -36,7 +36,6 @@ class F_22A(PlaneType):
|
||||
id = "BAY_DOOR_OPTION"
|
||||
|
||||
class Liveries:
|
||||
|
||||
class USSR(Enum):
|
||||
default = "default"
|
||||
_154_wg = "154 wg"
|
||||
@@ -1767,15 +1766,15 @@ class F_22A(PlaneType):
|
||||
Fuel_tank_610_gal = (2, Weapons.Fuel_tank_610_gal)
|
||||
|
||||
class Pylon3:
|
||||
AIM_120C = (3, Weapons.AIM_120C)
|
||||
AIM_120C = (3, Weapons.AIM_120C_5_AMRAAM___Active_Rdr_AAM)
|
||||
AIM_120D = (3, F22AWeapons.AIM_120D)
|
||||
|
||||
class Pylon4:
|
||||
AIM_120C = (4, Weapons.AIM_120C)
|
||||
AIM_120C = (4, Weapons.AIM_120C_5_AMRAAM___Active_Rdr_AAM)
|
||||
AIM_120D = (4, F22AWeapons.AIM_120D)
|
||||
|
||||
class Pylon5:
|
||||
AIM_120C = (5, Weapons.AIM_120C)
|
||||
AIM_120C = (5, Weapons.AIM_120C_5_AMRAAM___Active_Rdr_AAM)
|
||||
AIM_120D = (5, F22AWeapons.AIM_120D)
|
||||
|
||||
class Pylon6:
|
||||
@@ -1786,15 +1785,15 @@ class F_22A(PlaneType):
|
||||
Smokewinder___yellow = (6, Weapons.Smokewinder___yellow)
|
||||
|
||||
class Pylon7:
|
||||
AIM_120C = (7, Weapons.AIM_120C)
|
||||
AIM_120C = (7, Weapons.AIM_120C_5_AMRAAM___Active_Rdr_AAM)
|
||||
AIM_120D = (7, F22AWeapons.AIM_120D)
|
||||
|
||||
class Pylon8:
|
||||
AIM_120C = (8, Weapons.AIM_120C)
|
||||
AIM_120C = (8, Weapons.AIM_120C_5_AMRAAM___Active_Rdr_AAM)
|
||||
AIM_120D = (8, F22AWeapons.AIM_120D)
|
||||
|
||||
class Pylon9:
|
||||
AIM_120C = (9, Weapons.AIM_120C)
|
||||
AIM_120C = (9, Weapons.AIM_120C_5_AMRAAM___Active_Rdr_AAM)
|
||||
AIM_120D = (9, F22AWeapons.AIM_120D)
|
||||
|
||||
class Pylon10:
|
||||
@@ -1806,5 +1805,11 @@ class F_22A(PlaneType):
|
||||
|
||||
pylons = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
|
||||
|
||||
tasks = [task.CAP, task.Escort, task.FighterSweep, task.Intercept, task.Reconnaissance]
|
||||
tasks = [
|
||||
task.CAP,
|
||||
task.Escort,
|
||||
task.FighterSweep,
|
||||
task.Intercept,
|
||||
task.Reconnaissance,
|
||||
]
|
||||
task_default = task.CAP
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
from dcs import unittype
|
||||
|
||||
|
||||
class AMX_10RCR(unittype.VehicleType):
|
||||
id = "AMX10RCR"
|
||||
name = "AMX-10RCR"
|
||||
@@ -150,8 +151,10 @@ class DIM__KAMIKAZE(unittype.VehicleType):
|
||||
air_weapon_dist = 50
|
||||
eplrs = True
|
||||
|
||||
|
||||
## FORTIFICATION
|
||||
|
||||
|
||||
class _FIELD_HIDE(unittype.VehicleType):
|
||||
id = "FieldHL"
|
||||
name = "*FIELD HIDE"
|
||||
@@ -159,6 +162,7 @@ class _FIELD_HIDE(unittype.VehicleType):
|
||||
threat_range = 0
|
||||
air_weapon_dist = 0
|
||||
|
||||
|
||||
class _FIELD_HIDE_SMALL(unittype.VehicleType):
|
||||
id = "HARRIERH"
|
||||
name = "*FIELD HIDE SMALL"
|
||||
@@ -166,6 +170,7 @@ class _FIELD_HIDE_SMALL(unittype.VehicleType):
|
||||
threat_range = 0
|
||||
air_weapon_dist = 0
|
||||
|
||||
|
||||
class SmokeD1(unittype.VehicleType):
|
||||
id = "SmokeD1"
|
||||
name = "SmokeD1"
|
||||
@@ -173,6 +178,7 @@ class SmokeD1(unittype.VehicleType):
|
||||
threat_range = 0
|
||||
air_weapon_dist = 0
|
||||
|
||||
|
||||
class SmokeD3(unittype.VehicleType):
|
||||
id = "SmokeD3"
|
||||
name = "SmokeD3"
|
||||
@@ -189,6 +195,7 @@ class TRM_2000(unittype.VehicleType):
|
||||
air_weapon_dist = 0
|
||||
eplrs = True
|
||||
|
||||
|
||||
class TRM_2000_Fuel(unittype.VehicleType):
|
||||
id = "TRM2000_Citerne"
|
||||
name = "TRM-2000 Fuel"
|
||||
@@ -197,6 +204,7 @@ class TRM_2000_Fuel(unittype.VehicleType):
|
||||
air_weapon_dist = 0
|
||||
eplrs = True
|
||||
|
||||
|
||||
class VAB_MEDICAL(unittype.VehicleType):
|
||||
id = "VABH"
|
||||
name = "VAB MEDICAL"
|
||||
@@ -205,6 +213,7 @@ class VAB_MEDICAL(unittype.VehicleType):
|
||||
air_weapon_dist = 0
|
||||
eplrs = True
|
||||
|
||||
|
||||
class VAB(unittype.VehicleType):
|
||||
id = "VAB_RADIO"
|
||||
name = "VAB"
|
||||
@@ -213,6 +222,7 @@ class VAB(unittype.VehicleType):
|
||||
air_weapon_dist = 0
|
||||
eplrs = True
|
||||
|
||||
|
||||
class VBL(unittype.VehicleType):
|
||||
id = "VBL-Radio"
|
||||
name = "VBL"
|
||||
@@ -221,6 +231,7 @@ class VBL(unittype.VehicleType):
|
||||
air_weapon_dist = 0
|
||||
eplrs = True
|
||||
|
||||
|
||||
class Tracma_TD_1500(unittype.VehicleType):
|
||||
id = "Tracma"
|
||||
name = "Tracma TD 1500"
|
||||
@@ -228,8 +239,10 @@ class Tracma_TD_1500(unittype.VehicleType):
|
||||
threat_range = 0
|
||||
air_weapon_dist = 0
|
||||
|
||||
|
||||
## AIRDEFENCE
|
||||
|
||||
|
||||
class SMOKE_SAM_IR(unittype.VehicleType):
|
||||
id = "SMOKESAM"
|
||||
name = "SMOKE SAM IR"
|
||||
@@ -238,6 +251,7 @@ class SMOKE_SAM_IR(unittype.VehicleType):
|
||||
air_weapon_dist = 20000
|
||||
eplrs = True
|
||||
|
||||
|
||||
class _53T2(unittype.VehicleType):
|
||||
id = "AA20"
|
||||
name = "53T2"
|
||||
@@ -245,6 +259,7 @@ class _53T2(unittype.VehicleType):
|
||||
threat_range = 2000
|
||||
air_weapon_dist = 2000
|
||||
|
||||
|
||||
class TRM_2000_53T2(unittype.VehicleType):
|
||||
id = "TRM2000_AA20"
|
||||
name = "TRM-2000 53T2"
|
||||
@@ -253,6 +268,7 @@ class TRM_2000_53T2(unittype.VehicleType):
|
||||
air_weapon_dist = 2000
|
||||
eplrs = True
|
||||
|
||||
|
||||
class TRM_2000_PAMELA(unittype.VehicleType):
|
||||
id = "TRMMISTRAL"
|
||||
name = "TRM-2000 PAMELA"
|
||||
@@ -261,8 +277,10 @@ class TRM_2000_PAMELA(unittype.VehicleType):
|
||||
air_weapon_dist = 10000
|
||||
eplrs = True
|
||||
|
||||
|
||||
## INFANTRY
|
||||
|
||||
|
||||
class Infantry_Soldier_JTAC(unittype.VehicleType):
|
||||
id = "JTACFP"
|
||||
name = "Infantry Soldier JTAC"
|
||||
@@ -270,8 +288,10 @@ class Infantry_Soldier_JTAC(unittype.VehicleType):
|
||||
threat_range = 500
|
||||
air_weapon_dist = 500
|
||||
|
||||
|
||||
## ARTILERY
|
||||
|
||||
|
||||
class MO_120_RT(unittype.VehicleType):
|
||||
id = "M120"
|
||||
name = "MO 120 RT"
|
||||
@@ -279,10 +299,11 @@ class MO_120_RT(unittype.VehicleType):
|
||||
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
|
||||
eplrs = True
|
||||
eplrs = True
|
||||
|
||||
@@ -1056,7 +1056,7 @@ class Hercules(PlaneType):
|
||||
class Pylon2:
|
||||
LAU_68___7_2_75__rockets_M257__Parachute_illumination_ = (
|
||||
2,
|
||||
Weapons.LAU_68___7_2_75__rockets_M257__Parachute_illumination_,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
)
|
||||
Smokewinder___red = (2, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (2, Weapons.Smokewinder___green)
|
||||
@@ -1064,13 +1064,13 @@ class Hercules(PlaneType):
|
||||
Smokewinder___white = (2, Weapons.Smokewinder___white)
|
||||
Smokewinder___yellow = (2, Weapons.Smokewinder___yellow)
|
||||
Smokewinder___orange = (2, Weapons.Smokewinder___orange)
|
||||
MER_6_Mk_82 = (2, Weapons.MER_6_Mk_82)
|
||||
MER_6_Mk_82 = (2, Weapons.MER6_with_6_x_Mk_82___500lb_GP_Bombs_LD)
|
||||
Herc_Ext_Fuel_Tank = (2, HerculesWeapons.Herc_Ext_Fuel_Tank)
|
||||
|
||||
class Pylon3:
|
||||
LAU_68___7_2_75__rockets_M257__Parachute_illumination_ = (
|
||||
3,
|
||||
Weapons.LAU_68___7_2_75__rockets_M257__Parachute_illumination_,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
)
|
||||
Smokewinder___red = (3, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (3, Weapons.Smokewinder___green)
|
||||
@@ -1078,13 +1078,13 @@ class Hercules(PlaneType):
|
||||
Smokewinder___white = (3, Weapons.Smokewinder___white)
|
||||
Smokewinder___yellow = (3, Weapons.Smokewinder___yellow)
|
||||
Smokewinder___orange = (3, Weapons.Smokewinder___orange)
|
||||
MER_6_Mk_82 = (3, Weapons.MER_6_Mk_82)
|
||||
MER_6_Mk_82 = (3, Weapons.MER6_with_6_x_Mk_82___500lb_GP_Bombs_LD)
|
||||
Herc_Ext_Fuel_Tank = (3, HerculesWeapons.Herc_Ext_Fuel_Tank)
|
||||
|
||||
class Pylon4:
|
||||
LAU_68___7_2_75__rockets_M257__Parachute_illumination_ = (
|
||||
4,
|
||||
Weapons.LAU_68___7_2_75__rockets_M257__Parachute_illumination_,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
)
|
||||
Smokewinder___red = (4, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (4, Weapons.Smokewinder___green)
|
||||
@@ -1092,13 +1092,13 @@ class Hercules(PlaneType):
|
||||
Smokewinder___white = (4, Weapons.Smokewinder___white)
|
||||
Smokewinder___yellow = (4, Weapons.Smokewinder___yellow)
|
||||
Smokewinder___orange = (4, Weapons.Smokewinder___orange)
|
||||
MER_6_Mk_82 = (4, Weapons.MER_6_Mk_82)
|
||||
MER_6_Mk_82 = (4, Weapons.MER6_with_6_x_Mk_82___500lb_GP_Bombs_LD)
|
||||
Herc_Ext_Fuel_Tank = (4, HerculesWeapons.Herc_Ext_Fuel_Tank)
|
||||
|
||||
class Pylon5:
|
||||
LAU_68___7_2_75__rockets_M257__Parachute_illumination_ = (
|
||||
5,
|
||||
Weapons.LAU_68___7_2_75__rockets_M257__Parachute_illumination_,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
)
|
||||
Smokewinder___red = (5, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (5, Weapons.Smokewinder___green)
|
||||
@@ -1106,7 +1106,7 @@ class Hercules(PlaneType):
|
||||
Smokewinder___white = (5, Weapons.Smokewinder___white)
|
||||
Smokewinder___yellow = (5, Weapons.Smokewinder___yellow)
|
||||
Smokewinder___orange = (5, Weapons.Smokewinder___orange)
|
||||
MER_6_Mk_82 = (5, Weapons.MER_6_Mk_82)
|
||||
MER_6_Mk_82 = (5, Weapons.MER6_with_6_x_Mk_82___500lb_GP_Bombs_LD)
|
||||
Herc_Ext_Fuel_Tank = (5, HerculesWeapons.Herc_Ext_Fuel_Tank)
|
||||
|
||||
class Pylon6:
|
||||
|
||||
@@ -335,4 +335,3 @@ class _34Ya6E_Gazetchik_E_decoy(unittype.VehicleType):
|
||||
detection_range = 20000
|
||||
threat_range = 0
|
||||
air_weapon_dist = 0
|
||||
|
||||
|
||||
@@ -7,32 +7,104 @@ 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}
|
||||
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}
|
||||
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}
|
||||
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_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}
|
||||
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}
|
||||
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):
|
||||
@@ -43,7 +115,7 @@ class MB_339PAN(PlaneType):
|
||||
length = 12.13
|
||||
fuel_max = 626
|
||||
max_speed = 763.2
|
||||
category = "Interceptor" #{78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
category = "Interceptor" # {78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
radio_frequency = 124
|
||||
|
||||
panel_radio = {
|
||||
@@ -68,7 +140,7 @@ class MB_339PAN(PlaneType):
|
||||
7: 262,
|
||||
14: 266,
|
||||
19: 268,
|
||||
15: 265
|
||||
15: 265,
|
||||
},
|
||||
},
|
||||
2: {
|
||||
@@ -102,7 +174,7 @@ class MB_339PAN(PlaneType):
|
||||
28: 257,
|
||||
23: 260,
|
||||
29: 253,
|
||||
15: 265
|
||||
15: 265,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -113,7 +185,6 @@ class MB_339PAN(PlaneType):
|
||||
}
|
||||
|
||||
class Properties:
|
||||
|
||||
class SoloFlight:
|
||||
id = "SoloFlight"
|
||||
|
||||
@@ -127,7 +198,6 @@ class MB_339PAN(PlaneType):
|
||||
Equally_Responsible = -2
|
||||
|
||||
class Liveries:
|
||||
|
||||
class Georgia(Enum):
|
||||
MB339AA__ARMADA____Crippa = "MB339AA 'ARMADA' - Crippa"
|
||||
MB339AA__ARMADA____Yellow_Band = "MB339AA 'ARMADA' - Yellow Band"
|
||||
@@ -370,7 +440,10 @@ class MB_339PAN(PlaneType):
|
||||
|
||||
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)
|
||||
Tip_Fuel_Tank_Ellittici_320lt = (
|
||||
1,
|
||||
MB_339PAN_Weapons.Tip_Fuel_Tank_Ellittici_320lt,
|
||||
)
|
||||
|
||||
class Pylon2:
|
||||
Empty_Pylon = (2, MB_339PAN_Weapons.Empty_Pylon)
|
||||
@@ -386,7 +459,10 @@ class MB_339PAN(PlaneType):
|
||||
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_)
|
||||
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:
|
||||
@@ -427,7 +503,10 @@ class MB_339PAN(PlaneType):
|
||||
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_)
|
||||
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)
|
||||
@@ -438,9 +517,18 @@ class MB_339PAN(PlaneType):
|
||||
|
||||
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_)
|
||||
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
|
||||
tasks = [
|
||||
task.GroundAttack,
|
||||
task.RunwayAttack,
|
||||
task.CAS,
|
||||
task.AntishipStrike,
|
||||
task.Reconnaissance,
|
||||
]
|
||||
task_default = task.Nothing
|
||||
|
||||
@@ -3,11 +3,16 @@ from pydcs_extensions.f22a.f22a import F_22A
|
||||
from pydcs_extensions.hercules.hercules import Hercules
|
||||
from pydcs_extensions.highdigitsams import highdigitsams
|
||||
from pydcs_extensions.mb339.mb339 import MB_339PAN
|
||||
from pydcs_extensions.rafale.rafale import Rafale_M, Rafale_A_S, Rafale_B
|
||||
from pydcs_extensions.su57.su57 import Su_57
|
||||
import pydcs_extensions.frenchpack.frenchpack as frenchpack
|
||||
|
||||
MODDED_AIRPLANES = [A_4E_C, MB_339PAN, Rafale_A_S, Rafale_M, Rafale_B, Su_57, F_22A, Hercules]
|
||||
MODDED_AIRPLANES = [
|
||||
A_4E_C,
|
||||
MB_339PAN,
|
||||
Su_57,
|
||||
F_22A,
|
||||
Hercules,
|
||||
]
|
||||
MODDED_VEHICLES = [
|
||||
frenchpack._FIELD_HIDE,
|
||||
frenchpack._FIELD_HIDE_SMALL,
|
||||
@@ -84,5 +89,5 @@ MODDED_VEHICLES = [
|
||||
highdigitsams.SAM_SA_24_Igla_S_manpad,
|
||||
highdigitsams.SAM_SA_14_Strela_3_manpad,
|
||||
highdigitsams.Polyana_D4M1_C2_node,
|
||||
highdigitsams._34Ya6E_Gazetchik_E_decoy
|
||||
]
|
||||
highdigitsams._34Ya6E_Gazetchik_E_decoy,
|
||||
]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,11 @@ class Su57Weapons:
|
||||
RVV_BD = {"clsid": "{RVV-BD}", "name": "RVV-BD", "weight": 600}
|
||||
RVV_L = {"clsid": "{RVV-L}", "name": "RVV-L", "weight": 748}
|
||||
RVV_M = {"clsid": "{RVV-M}", "name": "RVV-M", "weight": 190}
|
||||
Su_57_Fuel_Tank = {"clsid": "{SU_57Tank}", "name": "Su-57 Fuel Tank", "weight": 1561.421}
|
||||
Su_57_Fuel_Tank = {
|
||||
"clsid": "{SU_57Tank}",
|
||||
"name": "Su-57 Fuel Tank",
|
||||
"weight": 1561.421,
|
||||
}
|
||||
|
||||
|
||||
class Su_57(PlaneType):
|
||||
@@ -27,10 +31,9 @@ class Su_57(PlaneType):
|
||||
charge_total = 200
|
||||
chaff_charge_size = 1
|
||||
flare_charge_size = 1
|
||||
category = "Interceptor" #{78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
category = "Interceptor" # {78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
|
||||
class Liveries:
|
||||
|
||||
class USSR(Enum):
|
||||
_22 = "22"
|
||||
_20 = "20"
|
||||
@@ -1508,7 +1511,7 @@ class Su_57(PlaneType):
|
||||
_15 = "15"
|
||||
|
||||
class Pylon1:
|
||||
R_73 = (1, Weapons.R_73)
|
||||
R_73__AA_11_Archer____Infra_Red = (1, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
RVV_AE = (1, Su57Weapons.RVV_AE)
|
||||
RVV_M = (1, Su57Weapons.RVV_M)
|
||||
Smoke_Generator___red = (1, Weapons.Smoke_Generator___red)
|
||||
@@ -1519,33 +1522,26 @@ class Su_57(PlaneType):
|
||||
Smoke_Generator___orange = (1, Weapons.Smoke_Generator___orange)
|
||||
|
||||
class Pylon2:
|
||||
R_27R = (2, Weapons.R_27R)
|
||||
R_27ER = (2, Weapons.R_27ER)
|
||||
R_27T = (2, Weapons.R_27T)
|
||||
R_27ET = (2, Weapons.R_27ET)
|
||||
R_77 = (2, Weapons.R_77)
|
||||
R_73 = (2, Weapons.R_73)
|
||||
Kh_31P = (2, Weapons.Kh_31P)
|
||||
Kh_31A = (2, Weapons.Kh_31A)
|
||||
Kh_29L = (2, Weapons.Kh_29L)
|
||||
Kh_29T = (2, Weapons.Kh_29T)
|
||||
Kh_59M = (2, Weapons.Kh_59M)
|
||||
MER_6_FAB_100 = (2, Weapons.MER_6_FAB_100)
|
||||
B_8M1___20_S_8KOM = (2, Weapons.B_8M1___20_S_8KOM)
|
||||
B_13L___5_S_13_OF = (2, Weapons.B_13L___5_S_13_OF)
|
||||
S_25_OFM = (2, Weapons.S_25_OFM)
|
||||
BetAB_500 = (2, Weapons.BetAB_500)
|
||||
KMGU_2___96_AO_2_5RT = (2, Weapons.KMGU_2___96_AO_2_5RT)
|
||||
KMGU_2___96_PTAB_2_5KO = (2, Weapons.KMGU_2___96_PTAB_2_5KO)
|
||||
FAB_250 = (2, Weapons.FAB_250)
|
||||
RBK_250_PTAB_2_5M = (2, Weapons.RBK_250_PTAB_2_5M)
|
||||
FAB_500_M62 = (2, Weapons.FAB_500_M62)
|
||||
RBK_500_255_PTAB_10_5 = (2, Weapons.RBK_500_255_PTAB_10_5)
|
||||
KAB_500L = (2, Weapons.KAB_500L)
|
||||
KAB_500kr = (2, Weapons.KAB_500kr)
|
||||
FAB_1500_M54 = (2, Weapons.FAB_1500_M54)
|
||||
KAB_1500L = (2, Weapons.KAB_1500L)
|
||||
MER_6_FAB_250 = (2, Weapons.MER_6_FAB_250)
|
||||
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
|
||||
2,
|
||||
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
|
||||
)
|
||||
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
|
||||
2,
|
||||
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
|
||||
)
|
||||
R_27T = (2, Weapons.R_27T__AA_10_Alamo_B____Infra_Red)
|
||||
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
|
||||
2,
|
||||
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
|
||||
)
|
||||
R_77__AA_12_Adder____Active_Rdr = (2, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
R_73__AA_11_Archer____Infra_Red = (2, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
Kh_31P = (2, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_31A = (2, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_29L = (2, Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser)
|
||||
Kh_29T = (2, Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided)
|
||||
Kh_59M = (2, Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN)
|
||||
RVV_BD = (2, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (2, Su57Weapons.RVV_AE)
|
||||
RVV_M = (2, Su57Weapons.RVV_M)
|
||||
@@ -1562,7 +1558,7 @@ class Su_57(PlaneType):
|
||||
Smoke_Generator___orange = (2, Weapons.Smoke_Generator___orange)
|
||||
|
||||
class Pylon3:
|
||||
R_73 = (3, Weapons.R_73)
|
||||
R_73__AA_11_Archer____Infra_Red = (3, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
Smoke_Generator___red = (3, Weapons.Smoke_Generator___red)
|
||||
Smoke_Generator___green = (3, Weapons.Smoke_Generator___green)
|
||||
Smoke_Generator___blue = (3, Weapons.Smoke_Generator___blue)
|
||||
@@ -1571,33 +1567,29 @@ class Su_57(PlaneType):
|
||||
Smoke_Generator___orange = (3, Weapons.Smoke_Generator___orange)
|
||||
|
||||
class Pylon4:
|
||||
R_27R = (4, Weapons.R_27R)
|
||||
R_27ER = (4, Weapons.R_27ER)
|
||||
R_27T = (4, Weapons.R_27T)
|
||||
R_27ET = (4, Weapons.R_27ET)
|
||||
R_77 = (4, Weapons.R_77)
|
||||
R_73 = (4, Weapons.R_73)
|
||||
Kh_31P = (4, Weapons.Kh_31P)
|
||||
Kh_31A = (4, Weapons.Kh_31A)
|
||||
Kh_29L = (4, Weapons.Kh_29L)
|
||||
Kh_29T = (4, Weapons.Kh_29T)
|
||||
Kh_59M = (4, Weapons.Kh_59M)
|
||||
MER_6_FAB_100 = (4, Weapons.MER_6_FAB_100)
|
||||
B_8M1___20_S_8KOM = (4, Weapons.B_8M1___20_S_8KOM)
|
||||
B_13L___5_S_13_OF = (4, Weapons.B_13L___5_S_13_OF)
|
||||
S_25_OFM = (4, Weapons.S_25_OFM)
|
||||
BetAB_500 = (4, Weapons.BetAB_500)
|
||||
KMGU_2___96_AO_2_5RT = (4, Weapons.KMGU_2___96_AO_2_5RT)
|
||||
KMGU_2___96_PTAB_2_5KO = (4, Weapons.KMGU_2___96_PTAB_2_5KO)
|
||||
FAB_250 = (4, Weapons.FAB_250)
|
||||
RBK_250_PTAB_2_5M = (4, Weapons.RBK_250_PTAB_2_5M)
|
||||
FAB_500_M62 = (4, Weapons.FAB_500_M62)
|
||||
RBK_500_255_PTAB_10_5 = (4, Weapons.RBK_500_255_PTAB_10_5)
|
||||
KAB_500L = (4, Weapons.KAB_500L)
|
||||
KAB_500kr = (4, Weapons.KAB_500kr)
|
||||
FAB_1500_M54 = (4, Weapons.FAB_1500_M54)
|
||||
KAB_1500L = (4, Weapons.KAB_1500L)
|
||||
MER_6_FAB_250 = (4, Weapons.MER_6_FAB_250)
|
||||
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
|
||||
4,
|
||||
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
|
||||
)
|
||||
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
|
||||
4,
|
||||
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
|
||||
)
|
||||
R_27T__AA_10_Alamo_B____Infra_Red = (
|
||||
4,
|
||||
Weapons.R_27T__AA_10_Alamo_B____Infra_Red,
|
||||
)
|
||||
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
|
||||
4,
|
||||
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
|
||||
)
|
||||
R_77__AA_12_Adder____Active_Rdr = (4, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
R_73__AA_11_Archer____Infra_Red = (4, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
Kh_31P = (4, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_31A = (4, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_29L = (4, Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser)
|
||||
Kh_29T = (4, Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided)
|
||||
Kh_59M = (4, Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN)
|
||||
RVV_BD = (4, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (4, Su57Weapons.RVV_AE)
|
||||
RVV_M = (4, Su57Weapons.RVV_M)
|
||||
@@ -1607,57 +1599,50 @@ class Su_57(PlaneType):
|
||||
Kh_59MK2 = (4, Su57Weapons.Kh_59MK2)
|
||||
|
||||
class Pylon5:
|
||||
R_77 = (5, Weapons.R_77)
|
||||
R_77__AA_12_Adder____Active_Rdr = (5, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
RVV_AE = (5, Su57Weapons.RVV_AE)
|
||||
RVV_M = (5, Su57Weapons.RVV_M)
|
||||
Kh_59MK2 = (5, Su57Weapons.Kh_59MK2)
|
||||
|
||||
class Pylon6:
|
||||
R_77 = (6, Weapons.R_77)
|
||||
R_77__AA_12_Adder____Active_Rdr = (6, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
RVV_AE = (6, Su57Weapons.RVV_AE)
|
||||
RVV_M = (6, Su57Weapons.RVV_M)
|
||||
Kh_59MK2 = (6, Su57Weapons.Kh_59MK2)
|
||||
|
||||
class Pylon7:
|
||||
R_77 = (7, Weapons.R_77)
|
||||
R_77__AA_12_Adder____Active_Rdr = (7, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
RVV_AE = (7, Su57Weapons.RVV_AE)
|
||||
RVV_M = (7, Su57Weapons.RVV_M)
|
||||
Kh_59MK2 = (7, Su57Weapons.Kh_59MK2)
|
||||
|
||||
class Pylon8:
|
||||
R_77 = (8, Weapons.R_77)
|
||||
R_77__AA_12_Adder____Active_Rdr = (8, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
RVV_AE = (8, Su57Weapons.RVV_AE)
|
||||
RVV_M = (8, Su57Weapons.RVV_M)
|
||||
Kh_59MK2 = (8, Su57Weapons.Kh_59MK2)
|
||||
|
||||
class Pylon9:
|
||||
R_27R = (9, Weapons.R_27R)
|
||||
R_27ER = (9, Weapons.R_27ER)
|
||||
R_27T = (9, Weapons.R_27T)
|
||||
R_27ET = (9, Weapons.R_27ET)
|
||||
R_77 = (9, Weapons.R_77)
|
||||
R_73 = (9, Weapons.R_73)
|
||||
Kh_31P = (9, Weapons.Kh_31P)
|
||||
Kh_31A = (9, Weapons.Kh_31A)
|
||||
Kh_29L = (9, Weapons.Kh_29L)
|
||||
Kh_29T = (9, Weapons.Kh_29T)
|
||||
Kh_59M = (9, Weapons.Kh_59M)
|
||||
MER_6_FAB_100 = (9, Weapons.MER_6_FAB_100)
|
||||
B_8M1___20_S_8KOM = (9, Weapons.B_8M1___20_S_8KOM)
|
||||
B_13L___5_S_13_OF = (9, Weapons.B_13L___5_S_13_OF)
|
||||
S_25_OFM = (9, Weapons.S_25_OFM)
|
||||
BetAB_500 = (9, Weapons.BetAB_500)
|
||||
KMGU_2___96_AO_2_5RT = (9, Weapons.KMGU_2___96_AO_2_5RT)
|
||||
KMGU_2___96_PTAB_2_5KO = (9, Weapons.KMGU_2___96_PTAB_2_5KO)
|
||||
FAB_250 = (9, Weapons.FAB_250)
|
||||
RBK_250_PTAB_2_5M = (9, Weapons.RBK_250_PTAB_2_5M)
|
||||
FAB_500_M62 = (9, Weapons.FAB_500_M62)
|
||||
RBK_500_255_PTAB_10_5 = (9, Weapons.RBK_500_255_PTAB_10_5)
|
||||
KAB_500L = (9, Weapons.KAB_500L)
|
||||
KAB_500kr = (9, Weapons.KAB_500kr)
|
||||
FAB_1500_M54 = (9, Weapons.FAB_1500_M54)
|
||||
KAB_1500L = (9, Weapons.KAB_1500L)
|
||||
MER_6_FAB_250 = (9, Weapons.MER_6_FAB_250)
|
||||
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
|
||||
9,
|
||||
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
|
||||
)
|
||||
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
|
||||
9,
|
||||
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
|
||||
)
|
||||
R_27T = (9, Weapons.R_27T__AA_10_Alamo_B____Infra_Red)
|
||||
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
|
||||
9,
|
||||
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
|
||||
)
|
||||
R_77__AA_12_Adder____Active_Rdr = (9, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
R_73__AA_11_Archer____Infra_Red = (9, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
Kh_31P = (9, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_31A = (9, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_29L = (9, Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser)
|
||||
Kh_29T = (9, Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided)
|
||||
Kh_59M = (9, Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN)
|
||||
RVV_BD = (9, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (9, Su57Weapons.RVV_AE)
|
||||
RVV_M = (9, Su57Weapons.RVV_M)
|
||||
@@ -1667,7 +1652,7 @@ class Su_57(PlaneType):
|
||||
Kh_59MK2 = (9, Su57Weapons.Kh_59MK2)
|
||||
|
||||
class Pylon10:
|
||||
R_73 = (10, Weapons.R_73)
|
||||
R_73__AA_11_Archer____Infra_Red = (10, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
Smoke_Generator___red = (10, Weapons.Smoke_Generator___red)
|
||||
Smoke_Generator___green = (10, Weapons.Smoke_Generator___green)
|
||||
Smoke_Generator___blue = (10, Weapons.Smoke_Generator___blue)
|
||||
@@ -1676,35 +1661,28 @@ class Su_57(PlaneType):
|
||||
Smoke_Generator___orange = (10, Weapons.Smoke_Generator___orange)
|
||||
|
||||
class Pylon11:
|
||||
R_27R = (11, Weapons.R_27R)
|
||||
R_27ER = (11, Weapons.R_27ER)
|
||||
R_27T = (11, Weapons.R_27T)
|
||||
R_27ET = (11, Weapons.R_27ET)
|
||||
R_77 = (11, Weapons.R_77)
|
||||
R_73 = (11, Weapons.R_73)
|
||||
Kh_31P = (11, Weapons.Kh_31P)
|
||||
Kh_31A = (11, Weapons.Kh_31A)
|
||||
Kh_29L = (11, Weapons.Kh_29L)
|
||||
Kh_29T = (11, Weapons.Kh_29T)
|
||||
Kh_59M = (11, Weapons.Kh_59M)
|
||||
MER_6_FAB_100 = (11, Weapons.MER_6_FAB_100)
|
||||
B_8M1___20_S_8KOM = (11, Weapons.B_8M1___20_S_8KOM)
|
||||
B_13L___5_S_13_OF = (11, Weapons.B_13L___5_S_13_OF)
|
||||
S_25_OFM = (11, Weapons.S_25_OFM)
|
||||
BetAB_500 = (11, Weapons.BetAB_500)
|
||||
KMGU_2___96_AO_2_5RT = (11, Weapons.KMGU_2___96_AO_2_5RT)
|
||||
KMGU_2___96_PTAB_2_5KO = (11, Weapons.KMGU_2___96_PTAB_2_5KO)
|
||||
FAB_250 = (11, Weapons.FAB_250)
|
||||
RBK_250_PTAB_2_5M = (11, Weapons.RBK_250_PTAB_2_5M)
|
||||
FAB_500_M62 = (11, Weapons.FAB_500_M62)
|
||||
RBK_500_255_PTAB_10_5 = (11, Weapons.RBK_500_255_PTAB_10_5)
|
||||
KAB_500L = (11, Weapons.KAB_500L)
|
||||
KAB_500kr = (11, Weapons.KAB_500kr)
|
||||
FAB_1500_M54 = (11, Weapons.FAB_1500_M54)
|
||||
KAB_1500L = (11, Weapons.KAB_1500L)
|
||||
MER_6_FAB_250 = (11, Weapons.MER_6_FAB_250)
|
||||
#ERRR {R-33}
|
||||
RVV_BD = (11,Su57Weapons.RVV_BD)
|
||||
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
|
||||
11,
|
||||
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
|
||||
)
|
||||
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
|
||||
11,
|
||||
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
|
||||
)
|
||||
R_27T = (11, Weapons.R_27T__AA_10_Alamo_B____Infra_Red)
|
||||
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
|
||||
11,
|
||||
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
|
||||
)
|
||||
R_77__AA_12_Adder____Active_Rdr = (11, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
R_73__AA_11_Archer____Infra_Red = (11, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
Kh_31P = (11, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_31A = (11, Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr)
|
||||
Kh_29L = (11, Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser)
|
||||
Kh_29T = (11, Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided)
|
||||
Kh_59M = (11, Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN)
|
||||
# ERRR {R-33}
|
||||
RVV_BD = (11, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (11, Su57Weapons.RVV_AE)
|
||||
RVV_M = (11, Su57Weapons.RVV_M)
|
||||
RVV_L = (11, Su57Weapons.RVV_L)
|
||||
@@ -1720,7 +1698,7 @@ class Su_57(PlaneType):
|
||||
Kh_59MK2 = (11, Su57Weapons.Kh_59MK2)
|
||||
|
||||
class Pylon12:
|
||||
R_73 = (12, Weapons.R_73)
|
||||
R_73__AA_11_Archer____Infra_Red = (12, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
RVV_AE = (12, Su57Weapons.RVV_AE)
|
||||
RVV_M = (12, Su57Weapons.RVV_M)
|
||||
Smoke_Generator___red = (12, Weapons.Smoke_Generator___red)
|
||||
@@ -1732,5 +1710,15 @@ class Su_57(PlaneType):
|
||||
|
||||
pylons = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
|
||||
|
||||
tasks = [task.CAP, task.Intercept, task.Escort, task.FighterSweep, task.AFAC, task.GroundAttack, task.RunwayAttack, task.AntishipStrike, task.CAS]
|
||||
tasks = [
|
||||
task.CAP,
|
||||
task.Intercept,
|
||||
task.Escort,
|
||||
task.FighterSweep,
|
||||
task.AFAC,
|
||||
task.GroundAttack,
|
||||
task.RunwayAttack,
|
||||
task.AntishipStrike,
|
||||
task.CAS,
|
||||
]
|
||||
task_default = task.CAP
|
||||
|
||||
@@ -147,12 +147,16 @@ def load_icons():
|
||||
"./resources/ui/ground_assets/" + category + "_blue.png"
|
||||
)
|
||||
ICONS["destroyed"] = QPixmap("./resources/ui/ground_assets/destroyed.png")
|
||||
ICONS["EWR"] = QPixmap("./resources/ui/ground_assets/ewr.png")
|
||||
ICONS["EWR_blue"] = QPixmap("./resources/ui/ground_assets/ewr_blue.png")
|
||||
ICONS["ship"] = QPixmap("./resources/ui/ground_assets/ship.png")
|
||||
ICONS["ship_blue"] = QPixmap("./resources/ui/ground_assets/ship_blue.png")
|
||||
ICONS["missile"] = QPixmap("./resources/ui/ground_assets/missile.png")
|
||||
ICONS["missile_blue"] = QPixmap("./resources/ui/ground_assets/missile_blue.png")
|
||||
ICONS["nothreat"] = QPixmap("./resources/ui/ground_assets/nothreat.png")
|
||||
ICONS["nothreat_blue"] = QPixmap("./resources/ui/ground_assets/nothreat_blue.png")
|
||||
ICONS["coastal"] = QPixmap("./resources/ui/ground_assets/coastal.png")
|
||||
ICONS["coastal_blue"] = QPixmap("./resources/ui/ground_assets/coastal_blue.png")
|
||||
|
||||
ICONS["Generator"] = QPixmap(
|
||||
"./resources/ui/misc/" + get_theme_icons() + "/generator.png"
|
||||
|
||||
@@ -7,7 +7,7 @@ from PySide2.QtWidgets import (
|
||||
QLabel,
|
||||
QVBoxLayout,
|
||||
)
|
||||
from dcs.weather import Weather as PydcsWeather
|
||||
from dcs.weather import CloudPreset, Weather as PydcsWeather
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game.utils import mps
|
||||
@@ -162,7 +162,7 @@ class QWeatherWidget(QGroupBox):
|
||||
self.turn = turn
|
||||
self.conditions = conditions
|
||||
|
||||
self.updateForecast()
|
||||
self.update_forecast()
|
||||
self.updateWinds()
|
||||
|
||||
def updateWinds(self):
|
||||
@@ -186,55 +186,76 @@ class QWeatherWidget(QGroupBox):
|
||||
self.windFL26SpeedLabel.setText(f"{int(windFL26Speed.knots)}kts")
|
||||
self.windFL26DirLabel.setText(f"{windFL26Dir}º")
|
||||
|
||||
def updateForecast(self):
|
||||
def update_forecast_from_preset(self, preset: CloudPreset) -> None:
|
||||
self.forecastFog.setText("No fog")
|
||||
if "Rain" in preset.name:
|
||||
self.forecastRain.setText("Rain")
|
||||
self.update_forecast_icons("rain")
|
||||
else:
|
||||
self.forecastRain.setText("No rain")
|
||||
self.update_forecast_icons("partly-cloudy")
|
||||
|
||||
# We get a description like the following for the cloud preset.
|
||||
#
|
||||
# 09 ##Two Layer Broken/Scattered \nMETAR:BKN 7.5/10 SCT 20/22 FEW41
|
||||
#
|
||||
# The second line is probably interesting but doesn't fit into the widget
|
||||
# currently, so for now just extract the first line.
|
||||
self.forecastClouds.setText(preset.description.splitlines()[0].split("##")[1])
|
||||
|
||||
def update_forecast(self):
|
||||
"""Updates the Forecast Text and icon with the current conditions wind info."""
|
||||
icon = []
|
||||
if (
|
||||
self.conditions.weather.clouds
|
||||
and self.conditions.weather.clouds.preset is not None
|
||||
):
|
||||
self.update_forecast_from_preset(self.conditions.weather.clouds.preset)
|
||||
return
|
||||
|
||||
if self.conditions.weather.clouds is None:
|
||||
cloudDensity = 0
|
||||
cloud_density = 0
|
||||
precipitation = None
|
||||
else:
|
||||
cloudDensity = self.conditions.weather.clouds.density
|
||||
cloud_density = self.conditions.weather.clouds.density
|
||||
precipitation = self.conditions.weather.clouds.precipitation
|
||||
|
||||
fog = self.conditions.weather.fog or None
|
||||
is_night = self.conditions.time_of_day == TimeOfDay.Night
|
||||
time = "night" if is_night else "day"
|
||||
|
||||
if cloudDensity <= 0:
|
||||
if not cloud_density:
|
||||
self.forecastClouds.setText("Sunny")
|
||||
icon = [time, "clear"]
|
||||
|
||||
if cloudDensity > 0 and cloudDensity < 3:
|
||||
weather_type = "clear"
|
||||
elif cloud_density < 3:
|
||||
self.forecastClouds.setText("Partly Cloudy")
|
||||
icon = [time, "partly-cloudy"]
|
||||
|
||||
if cloudDensity >= 3 and cloudDensity < 5:
|
||||
weather_type = "partly-cloudy"
|
||||
elif cloud_density < 5:
|
||||
self.forecastClouds.setText("Mostly Cloudy")
|
||||
icon = [time, "partly-cloudy"]
|
||||
|
||||
if cloudDensity >= 5:
|
||||
weather_type = "partly-cloudy"
|
||||
else:
|
||||
self.forecastClouds.setText("Totally Cloudy")
|
||||
icon = [time, "partly-cloudy"]
|
||||
weather_type = "partly-cloudy"
|
||||
|
||||
if precipitation == PydcsWeather.Preceptions.Rain:
|
||||
self.forecastRain.setText("Rain")
|
||||
icon = [time, "rain"]
|
||||
|
||||
weather_type = "rain"
|
||||
elif precipitation == PydcsWeather.Preceptions.Thunderstorm:
|
||||
self.forecastRain.setText("Thunderstorm")
|
||||
icon = [time, "thunderstorm"]
|
||||
|
||||
weather_type = "thunderstorm"
|
||||
else:
|
||||
self.forecastRain.setText("No Rain")
|
||||
self.forecastRain.setText("No rain")
|
||||
|
||||
if not fog:
|
||||
if not self.conditions.weather.fog is not None:
|
||||
self.forecastFog.setText("No fog")
|
||||
else:
|
||||
visibility = round(fog.visibility.nautical_miles, 1)
|
||||
visibility = round(self.conditions.weather.fog.visibility.nautical_miles, 1)
|
||||
self.forecastFog.setText(f"Fog vis: {visibility}nm")
|
||||
icon = [time, ("cloudy" if cloudDensity > 1 else None), "fog"]
|
||||
if cloud_density > 1:
|
||||
weather_type = "cloudy-fog"
|
||||
else:
|
||||
weather_type = "fog"
|
||||
|
||||
icon_key = "Weather_{}".format("-".join(filter(None.__ne__, icon)))
|
||||
self.update_forecast_icons(weather_type)
|
||||
|
||||
def update_forecast_icons(self, weather_type: str) -> None:
|
||||
time = "night" if self.conditions.time_of_day == TimeOfDay.Night else "day"
|
||||
icon_key = f"Weather_{time}-{weather_type}"
|
||||
icon = CONST.ICONS.get(icon_key) or CONST.ICONS["Weather_night-partly-cloudy"]
|
||||
self.weather_icon.setPixmap(icon)
|
||||
|
||||
|
||||
@@ -90,6 +90,12 @@ class QAircraftTypeSelector(QComboBox):
|
||||
f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}",
|
||||
userData=aircraft,
|
||||
)
|
||||
elif mission_type in [FlightType.AEWC]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.AEWC_CAPABLE:
|
||||
self.addItem(
|
||||
f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}",
|
||||
userData=aircraft,
|
||||
)
|
||||
current_aircraft_index = self.findData(current_aircraft)
|
||||
if current_aircraft_index != -1:
|
||||
self.setCurrentIndex(current_aircraft_index)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user