mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a022f9c2e1 | ||
|
|
5adb25a695 | ||
|
|
08c2972cf9 | ||
|
|
8132c7e676 | ||
|
|
8c68c9f703 | ||
|
|
000b6142fd | ||
|
|
c203ded1cd | ||
|
|
64c5c39b2a | ||
|
|
a8d2a1e371 | ||
|
|
9e5846b24a | ||
|
|
836ff9122c | ||
|
|
75d836358b | ||
|
|
bb11e7f90c | ||
|
|
cf6a71ab86 | ||
|
|
7f7288937d | ||
|
|
a38f9c2183 | ||
|
|
7ee880cadc | ||
|
|
9ae34d474b | ||
|
|
2817e2f2c8 | ||
|
|
02886a09d3 | ||
|
|
0b9d827ad6 | ||
|
|
ab3ea84d70 | ||
|
|
03a1c44659 | ||
|
|
53364444fd | ||
|
|
94040e8551 | ||
|
|
34d46ee28e |
26
README.md
26
README.md
@@ -1,26 +1,12 @@
|
||||

|
||||
|
||||
[DCS World](https://www.digitalcombatsimulator.com/en/products/world/) single-player dynamic campaign.
|
||||
[DCS World](https://www.digitalcombatsimulator.com/en/products/world/) single-player semi dynamic campaign.
|
||||
|
||||
Uses [pydcs](http://github.com/pydcs/dcs) for mission generation.
|
||||
DCS Liberation uses [pydcs](http://github.com/pydcs/dcs) for mission generation
|
||||
and [Mist](https://github.com/mrSkortch/MissionScriptingTools) for mission scripting
|
||||
|
||||
## Tutorials
|
||||
* [Manual](https://github.com/shdwp/dcs_liberation/wiki/Manual)
|
||||
## Resources
|
||||
|
||||
You should start with the manual, it covers everything you need to know before playing the campaign.
|
||||
* [Getting Started](https://github.com/Khopa/dcs_liberation/wiki/Getting-started)
|
||||
|
||||
* [Strike objectives reference images](https://imgur.com/a/vCSHa9f)
|
||||
|
||||
If you can't find the strike objective you can see here how it's supposed to look.
|
||||
|
||||
* [Troubleshooting](https://github.com/shdwp/dcs_liberation/wiki/Troubleshooting)
|
||||
|
||||
You could also briefly check the troubleshooting page to get familiar with the known issues that you could probably fix by yourself.
|
||||
|
||||
* [Modding tutorial](https://github.com/shdwp/dcs_liberation/wiki/Modding-tutorial)
|
||||
|
||||
Modding tutorial will cover how to change default loadouts, configure which planes are present in the campaign (or add new altogether) and more. Check this out if you find that something is not going for your liking, there could be a tutorial for changing that. Although be aware that it would require changing source files and could easily result in non functioning application.
|
||||
|
||||
* [Development guide](https://github.com/shdwp/dcs_liberation/wiki/Development-guide)
|
||||
|
||||
If you want to contribute to the project, this will give you a brief overview and on how to actually run it from source files.
|
||||
* [Tutorials](https://github.com/Khopa/dcs_liberation/wiki/Tutorial-01-:-UI)
|
||||
|
||||
29
changelog.md
Normal file
29
changelog.md
Normal file
@@ -0,0 +1,29 @@
|
||||
#2.0 RC 6
|
||||
|
||||
Saves file from RC5 are not compatible with the new version.
|
||||
Sorry :(
|
||||
|
||||
##Features/Improvements :
|
||||
|
||||
* **[Units/Factions]** Supercarrier support (You have to go to settings to enable it, if you have the supercarrier module)
|
||||
* **[Units/Factions]** Added 'Modern Bluefor' factions, containing all most popular DCS flyable units
|
||||
* **[Units/Factions]** Factions US 2005 / 1990 will now sometimes have Arleigh Burke class ships instead of Perry as carrier escorts
|
||||
* **[Units/Factions]** Added support for newest WW2 Units
|
||||
* **[Campaign logic]** When a base is captured, refill the "base defenses" group with units for the new owner.
|
||||
* **[Mission Generator]** Carrier ICLS channel will now be configured (check your briefing)
|
||||
* **[Mission Generator]** SAM units will spawn on RED Alarm state
|
||||
* **[Mission Generator]** AI Flight planner now creates its own STRIKE flights
|
||||
* **[Mission Generator]** AI units assigned to Strike flight will now actually engage the buildings they have been assigned.
|
||||
* **[Mission Generator]** Added performance settings to allow disabling : smoke, artillery strike, moving units, infantry, SAM Red alert mode.
|
||||
* **[Mission Generator]** Using Late Activation & Trigger in attempt to improve performance & reduce stutter (Previously they were spawned through 'ETA' feature)
|
||||
* **[UX]** : Improved flight selection behaviour in the Mission Planning Window
|
||||
|
||||
##Fixed issues :
|
||||
|
||||
* **[Mission Generator]** Payloads were not correctly assigned in the release version.
|
||||
* **[Mission Generator]** Game generation does not work when "no night mission" settings was selected and the current time was "day"
|
||||
* **[Mission Generator]** Game generation does not work when the player selected faction has no AWACS
|
||||
* **[Mission Generator]** Planned flights will spawn even if their home base has been captured or is being contested by enemy ground units.
|
||||
* **[Campaign Generator]** Base defenses would not be generated on Normandy map and in some rare cases on others maps as well
|
||||
* **[Mission Planning]** CAS waypoints created from the "Predefined waypoint selector" would not be at the exact location of the frontline
|
||||
* **[Naming]** CAP mission flown from airbase are not named BARCAP anymore (CAP from carrier is still named BARCAP)
|
||||
130
game/db.py
130
game/db.py
@@ -44,6 +44,7 @@ from game.factions.usa_1960 import USA_1960
|
||||
from game.factions.usa_1965 import USA_1965
|
||||
from game.factions.usa_1990 import USA_1990
|
||||
from game.factions.usa_2005 import USA_2005
|
||||
from game.factions.bluefor_modern import BLUEFOR_MODERN
|
||||
|
||||
"""
|
||||
---------- BEGINNING OF CONFIGURATION SECTION
|
||||
@@ -83,11 +84,14 @@ PRICES = {
|
||||
J_11A: 26,
|
||||
JF_17: 20,
|
||||
Su_30: 24,
|
||||
SpitfireLFMkIX:3,
|
||||
SpitfireLFMkIXCW:3,
|
||||
Bf_109K_4:3,
|
||||
FW_190D9:3,
|
||||
FW_190A8:3,
|
||||
|
||||
SpitfireLFMkIX: 8,
|
||||
SpitfireLFMkIXCW: 8,
|
||||
Bf_109K_4: 8,
|
||||
FW_190D9: 8,
|
||||
FW_190A8: 8,
|
||||
A_20G: 12,
|
||||
Ju_88A4: 12,
|
||||
|
||||
F_5E_3: 8,
|
||||
MiG_15bis: 4,
|
||||
@@ -152,12 +156,12 @@ PRICES = {
|
||||
C_130: 8,
|
||||
|
||||
# WW2
|
||||
P_51D_30_NA: 3,
|
||||
P_51D: 3,
|
||||
P_51D_30_NA: 6,
|
||||
P_51D: 6,
|
||||
|
||||
# armor
|
||||
Armor.APC_MTLB: 4,
|
||||
Armor.ARV_MTLB_U_BOMAN: 5,
|
||||
Armor.FDDM_Grad: 5,
|
||||
Armor.ARV_BRDM_2: 6,
|
||||
Armor.ARV_BTR_RD: 8,
|
||||
Armor.APC_BTR_80: 8,
|
||||
@@ -227,22 +231,31 @@ PRICES = {
|
||||
AirDefence.SAM_Chaparral_M48: 10,
|
||||
|
||||
# WW2
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G:7,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H:4,
|
||||
Armor.HT_Pz_Kpfw_VI_Tiger_I:10,
|
||||
Armor.HT_Pz_Kpfw_VI_Ausf__B__Tiger_II:12,
|
||||
Armor.APC_Sd_Kfz_251:3,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma:4,
|
||||
Armor.MT_M4_Sherman:4,
|
||||
Armor.MT_M4A4_Sherman_Firefly:6,
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G:18,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H:8,
|
||||
Armor.HT_Pz_Kpfw_VI_Tiger_I:22,
|
||||
Armor.HT_Pz_Kpfw_VI_Ausf__B__Tiger_II:26,
|
||||
Armor.TD_Jagdpanther_G1: 16,
|
||||
Armor.TD_Jagdpanzer_IV: 10,
|
||||
Armor.Sd_Kfz_184_Elefant: 18,
|
||||
Armor.APC_Sd_Kfz_251:2,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma:6,
|
||||
Armor.MT_M4_Sherman:5,
|
||||
Armor.MT_M4A4_Sherman_Firefly:8,
|
||||
Armor.CT_Cromwell_IV:8,
|
||||
Armor.M30_Cargo_Carrier:2,
|
||||
Armor.APC_M2A1:2,
|
||||
AirDefence.AAA_Bofors_40mm:4,
|
||||
AirDefence.AAA_Flak_36:6,
|
||||
AirDefence.AAA_Flak_18:4,
|
||||
Artillery.M12_GMC:2,
|
||||
Artillery.Sturmpanzer_IV_Brummbär:2,
|
||||
Armor.ST_Centaur_IV: 8,
|
||||
Armor.HIT_Churchill_VII: 12,
|
||||
Armor.LAC_M8_Greyhound: 4,
|
||||
Armor.TD_M10_GMC: 8,
|
||||
Armor.StuG_III_Ausf__G: 6,
|
||||
AirDefence.AAA_Bofors_40mm: 4,
|
||||
AirDefence.AAA_8_8cm_Flak_36: 6,
|
||||
AirDefence.AAA_8_8cm_Flak_18: 4,
|
||||
Artillery.M12_GMC: 2,
|
||||
Artillery.Sturmpanzer_IV_Brummbär: 2,
|
||||
|
||||
|
||||
# ship
|
||||
CV_1143_5_Admiral_Kuznetsov: 100,
|
||||
@@ -299,7 +312,7 @@ UNIT_BY_TASK = {
|
||||
FW_190D9,
|
||||
FW_190A8,
|
||||
SpitfireLFMkIXCW,
|
||||
SpitfireLFMkIX
|
||||
SpitfireLFMkIX,
|
||||
],
|
||||
CAS: [
|
||||
F_86F_Sabre,
|
||||
@@ -330,6 +343,8 @@ UNIT_BY_TASK = {
|
||||
Mi_28N,
|
||||
Mi_24V,
|
||||
MiG_27K,
|
||||
A_20G,
|
||||
Ju_88A4,
|
||||
],
|
||||
Transport: [
|
||||
IL_76MD,
|
||||
@@ -351,11 +366,11 @@ UNIT_BY_TASK = {
|
||||
Armor.APC_MTLB,
|
||||
Armor.APC_MTLB,
|
||||
Armor.APC_MTLB,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.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,
|
||||
@@ -450,6 +465,33 @@ UNIT_BY_TASK = {
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_M2A1,
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H,
|
||||
Armor.HT_Pz_Kpfw_VI_Tiger_I,
|
||||
Armor.HT_Pz_Kpfw_VI_Ausf__B__Tiger_II,
|
||||
Armor.TD_Jagdpanther_G1,
|
||||
Armor.TD_Jagdpanzer_IV,
|
||||
Armor.Sd_Kfz_184_Elefant,
|
||||
Armor.APC_Sd_Kfz_251,
|
||||
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,
|
||||
Armor.ST_Centaur_IV,
|
||||
Armor.ST_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,
|
||||
Artillery.M12_GMC,
|
||||
Artillery.Sturmpanzer_IV_Brummbär,
|
||||
|
||||
Artillery.MLRS_M270,
|
||||
Artillery.SPH_M109_Paladin,
|
||||
@@ -534,6 +576,7 @@ SAM_CONVERT = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
Units that will always be spawned in the air
|
||||
"""
|
||||
@@ -568,9 +611,10 @@ FACTIONS = {
|
||||
"USA 1965": USA_1965,
|
||||
"USA 1960": USA_1960,
|
||||
"USA 1955 (Require WW2 Pack)": USA_1955,
|
||||
"USA 1944 (Require WW2 Pack)": USA_1944,
|
||||
"France 1995": France_1995,
|
||||
"Allies 1944 (Require WW2 Pack)": USA_1944,
|
||||
"Bluefor Modern": BLUEFOR_MODERN,
|
||||
"France 2005": France_2005,
|
||||
"France 1995": France_1995,
|
||||
"Germany 1990": Germany_1990,
|
||||
"Netherlands 1990": Netherlands_1990,
|
||||
"United Kingdown 1990": UnitedKingdom_1990,
|
||||
@@ -637,7 +681,15 @@ PLANE_PAYLOAD_OVERRIDES = {
|
||||
AntishipStrike: "ANTISHIP",
|
||||
GroundAttack: "STRIKE"
|
||||
},
|
||||
|
||||
F_A_18C: {
|
||||
CAP: "CAP HEAVY",
|
||||
Intercept: "CAP HEAVY",
|
||||
CAS: "CAS MAVERICK F",
|
||||
PinpointStrike: "STRIKE",
|
||||
SEAD: "SEAD",
|
||||
AntishipStrike: "ANTISHIP",
|
||||
GroundAttack: "STRIKE"
|
||||
},
|
||||
A_10A: COMMON_OVERRIDE,
|
||||
A_10C: COMMON_OVERRIDE,
|
||||
AV8BNA: COMMON_OVERRIDE,
|
||||
@@ -797,6 +849,21 @@ TaskForceDict = typing.Dict[typing.Type[Task], AssignedUnitsDict]
|
||||
StartingPosition = typing.Optional[typing.Union[ShipGroup, StaticGroup, Airport, Point]]
|
||||
|
||||
|
||||
def upgrade_to_supercarrier(unit, name: str):
|
||||
if unit == CVN_74_John_C__Stennis:
|
||||
if name == "CVN-71 Theodore Roosevelt":
|
||||
return CVN_71_Theodore_Roosevelt
|
||||
elif name == "CVN-72 Abraham Lincoln":
|
||||
return CVN_72_Abraham_Lincoln
|
||||
elif name == "CVN-73 George Washington":
|
||||
return CVN_73_George_Washington
|
||||
else:
|
||||
return CVN_71_Theodore_Roosevelt
|
||||
elif unit == CV_1143_5_Admiral_Kuznetsov:
|
||||
return CV_1143_5_Admiral_Kuznetsov_2017
|
||||
else:
|
||||
return unit
|
||||
|
||||
def unit_task(unit: UnitType) -> Task:
|
||||
for task, units in UNIT_BY_TASK.items():
|
||||
if unit in units:
|
||||
@@ -982,4 +1049,5 @@ class DefaultLiveries:
|
||||
|
||||
OH_58D.Liveries = DefaultLiveries
|
||||
F_16C_50.Liveries = DefaultLiveries
|
||||
P_51D_30_NA.Liveries = DefaultLiveries
|
||||
P_51D_30_NA.Liveries = DefaultLiveries
|
||||
Ju_88A4.Liveries = DefaultLiveries
|
||||
@@ -13,6 +13,7 @@ from theater import *
|
||||
from gen.environmentgen import EnvironmentSettings
|
||||
from gen.conflictgen import Conflict
|
||||
from game.db import assigned_units_from, unitdict_from
|
||||
from theater.start_generator import generate_airbase_defense_group
|
||||
|
||||
from userdata.debriefing import Debriefing
|
||||
from userdata import persistency
|
||||
@@ -214,28 +215,35 @@ class Event:
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.id == id:
|
||||
|
||||
pname = ""
|
||||
if cp.captured and new_owner_coalition != coalition:
|
||||
cp.captured = False
|
||||
cp.base.aircraft = {}
|
||||
cp.base.armor = {}
|
||||
cp.base.aa = {}
|
||||
for g in cp.ground_objects:
|
||||
g.groups = []
|
||||
info = Information(cp.name + " lost !",
|
||||
"The ennemy took control of " + cp.name + "\nShame on us !",
|
||||
self.game.turn)
|
||||
self.game.informations.append(info)
|
||||
pname = self.game.enemy_name
|
||||
elif not(cp.captured) and new_owner_coalition == coalition:
|
||||
cp.captured = True
|
||||
cp.base.aircraft = {}
|
||||
cp.base.armor = {}
|
||||
cp.base.aa = {}
|
||||
for g in cp.ground_objects:
|
||||
g.groups = []
|
||||
info = Information(cp.name + " captured !",
|
||||
"The ennemy took control of " + cp.name + "\nShame on us !",
|
||||
self.game.turn)
|
||||
info = Information(cp.name + " captured !", "The ennemy took control of " + cp.name + "\nShame on us !", self.game.turn)
|
||||
self.game.informations.append(info)
|
||||
pname = self.game.player_name
|
||||
else:
|
||||
continue
|
||||
|
||||
cp.base.aircraft = {}
|
||||
cp.base.armor = {}
|
||||
cp.base.aa = {}
|
||||
|
||||
airbase_def_id = 0
|
||||
for g in cp.ground_objects:
|
||||
g.groups = []
|
||||
if g.airbase_group and pname != "":
|
||||
generate_airbase_defense_group(airbase_def_id, g, pname, self.game, cp)
|
||||
airbase_def_id = airbase_def_id + 1
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
78
game/factions/bluefor_modern.py
Normal file
78
game/factions/bluefor_modern.py
Normal file
@@ -0,0 +1,78 @@
|
||||
from dcs.vehicles import *
|
||||
from dcs.ships import *
|
||||
from dcs.planes import *
|
||||
from dcs.helicopters import *
|
||||
|
||||
BLUEFOR_MODERN = {
|
||||
"country": "USA",
|
||||
"side": "blue",
|
||||
"units": [
|
||||
|
||||
F_15C,
|
||||
F_14B,
|
||||
FA_18C_hornet,
|
||||
F_16C_50,
|
||||
JF_17,
|
||||
M_2000C,
|
||||
F_5E_3,
|
||||
Su_27,
|
||||
|
||||
Su_25T,
|
||||
A_10A,
|
||||
A_10C,
|
||||
AV8BNA,
|
||||
AJS37,
|
||||
|
||||
KC_135,
|
||||
S_3B_Tanker,
|
||||
C_130,
|
||||
E_3A,
|
||||
|
||||
UH_1H,
|
||||
AH_64D,
|
||||
Ka_50,
|
||||
|
||||
Armor.MBT_M1A2_Abrams,
|
||||
Armor.MBT_Leopard_2,
|
||||
Armor.ATGM_M1134_Stryker,
|
||||
Armor.IFV_M2A2_Bradley,
|
||||
Armor.IFV_Marder,
|
||||
Armor.APC_M1043_HMMWV_Armament,
|
||||
|
||||
Artillery.MLRS_M270,
|
||||
Artillery.SPH_M109_Paladin,
|
||||
|
||||
Unarmed.Transport_M818,
|
||||
Infantry.Infantry_M4,
|
||||
Infantry.Soldier_M249,
|
||||
|
||||
AirDefence.SAM_Hawk_PCP,
|
||||
AirDefence.SAM_Patriot_EPP_III,
|
||||
|
||||
CVN_74_John_C__Stennis,
|
||||
LHA_1_Tarawa,
|
||||
Armed_speedboat,
|
||||
], "shorad": [
|
||||
AirDefence.SAM_Avenger_M1097,
|
||||
], "aircraft_carrier": [
|
||||
CVN_74_John_C__Stennis,
|
||||
], "helicopter_carrier": [
|
||||
LHA_1_Tarawa,
|
||||
], "destroyer": [
|
||||
Oliver_Hazzard_Perry_class,
|
||||
USS_Arleigh_Burke_IIa,
|
||||
], "cruiser": [
|
||||
Ticonderoga_class,
|
||||
], "carrier_names": [
|
||||
"CVN-71 Theodore Roosevelt",
|
||||
"CVN-72 Abraham Lincoln",
|
||||
"CVN-73 George Washington",
|
||||
"CVN-74 John C. Stennis",
|
||||
], "lhanames": [
|
||||
"LHA-1 Tarawa",
|
||||
"LHA-2 Saipan",
|
||||
"LHA-3 Belleau Wood",
|
||||
"LHA-4 Nassau",
|
||||
"LHA-5 Peleliu"
|
||||
]
|
||||
}
|
||||
@@ -9,6 +9,7 @@ Germany_1944 = {
|
||||
FW_190A8,
|
||||
FW_190D9,
|
||||
Bf_109K_4,
|
||||
Ju_88A4,
|
||||
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H,
|
||||
@@ -16,13 +17,20 @@ Germany_1944 = {
|
||||
Armor.HT_Pz_Kpfw_VI_Ausf__B__Tiger_II,
|
||||
Armor.APC_Sd_Kfz_251,
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma,
|
||||
Armor.Sd_Kfz_184_Elefant,
|
||||
Armor.TD_Jagdpanther_G1,
|
||||
Armor.TD_Jagdpanzer_IV,
|
||||
|
||||
Artillery.Sturmpanzer_IV_Brummbär,
|
||||
|
||||
Unarmed.Sd_Kfz_2,
|
||||
Unarmed.Sd_Kfz_7,
|
||||
Unarmed.Kübelwagen_82,
|
||||
|
||||
Infantry.Infantry_Mauser_98,
|
||||
|
||||
AirDefence.AAA_Flak_36,
|
||||
AirDefence.AAA_8_8cm_Flak_36,
|
||||
],
|
||||
"shorad":[
|
||||
AirDefence.AAA_8_8cm_Flak_36,
|
||||
]
|
||||
}
|
||||
@@ -28,7 +28,7 @@ Lybia_2011 = {
|
||||
AirDefence.HQ_7_Self_Propelled_LN,
|
||||
|
||||
Armor.IFV_BMP_1,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.FDDM_Grad,
|
||||
Armor.ARV_BRDM_2,
|
||||
Armor.MBT_T_55,
|
||||
Armor.MBT_T_72B,
|
||||
|
||||
@@ -17,7 +17,7 @@ Russia_1955 = {
|
||||
AirDefence.AAA_ZU_23_Closed,
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
Armor.ARV_BRDM_2,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.FDDM_Grad,
|
||||
Armor.APC_MTLB,
|
||||
Armor.MBT_T_55,
|
||||
Artillery.MLRS_BM_21_Grad,
|
||||
|
||||
@@ -10,15 +10,22 @@ USA_1944 = {
|
||||
P_51D_30_NA,
|
||||
SpitfireLFMkIX,
|
||||
SpitfireLFMkIXCW,
|
||||
A_20G,
|
||||
|
||||
Armor.MT_M4_Sherman,
|
||||
Armor.MT_M4A4_Sherman_Firefly,
|
||||
Armor.CT_Cromwell_IV,
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.APC_M2A1,
|
||||
Armor.CT_Cromwell_IV,
|
||||
Armor.ST_Centaur_IV,
|
||||
Armor.HIT_Churchill_VII,
|
||||
Armor.LAC_M8_Greyhound,
|
||||
Armor.TD_M10_GMC,
|
||||
Artillery.M12_GMC,
|
||||
|
||||
Infantry.Infantry_M1_Garand,
|
||||
Infantry.Infantry_SMLE_No_4_Mk_1,
|
||||
|
||||
LS_Samuel_Chase,
|
||||
LST_Mk_II,
|
||||
@@ -26,5 +33,7 @@ USA_1944 = {
|
||||
|
||||
Unarmed.CCKW_353,
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
], "shorad":[
|
||||
AirDefence.AAA_Bofors_40mm,
|
||||
]
|
||||
}
|
||||
@@ -46,6 +46,7 @@ USA_1990 = {
|
||||
LHA_1_Tarawa,
|
||||
], "destroyer": [
|
||||
Oliver_Hazzard_Perry_class,
|
||||
USS_Arleigh_Burke_IIa,
|
||||
], "cruiser": [
|
||||
Ticonderoga_class,
|
||||
], "carrier_names": [
|
||||
|
||||
@@ -53,11 +53,13 @@ USA_2005 = {
|
||||
LHA_1_Tarawa,
|
||||
], "destroyer": [
|
||||
Oliver_Hazzard_Perry_class,
|
||||
USS_Arleigh_Burke_IIa,
|
||||
], "cruiser": [
|
||||
Ticonderoga_class,
|
||||
], "carrier_names": [
|
||||
"CVN-71 Theodore Roosevelt",
|
||||
"CVN-72 Abraham Lincoln",
|
||||
"CVN-73 Georges Washington",
|
||||
"CVN-73 George Washington",
|
||||
"CVN-74 John C. Stennis",
|
||||
], "lhanames": [
|
||||
"LHA-1 Tarawa",
|
||||
|
||||
21
game/game.py
21
game/game.py
@@ -1,24 +1,11 @@
|
||||
import logging
|
||||
import typing
|
||||
import random
|
||||
import math
|
||||
|
||||
from dcs.task import *
|
||||
from dcs.vehicles import *
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from game.db import REWARDS, PLAYER_BUDGET_BASE
|
||||
from game.game_stats import GameStats
|
||||
from game.infos.information import Information
|
||||
from gen.conflictgen import Conflict
|
||||
from gen.flights.ai_flight_planner import FlightPlanner
|
||||
from gen.ground_forces.ai_ground_planner import GroundPlanner
|
||||
from userdata.debriefing import Debriefing
|
||||
from theater import *
|
||||
|
||||
from . import db
|
||||
from .settings import Settings
|
||||
from .event import *
|
||||
from datetime import datetime, timedelta
|
||||
from .settings import Settings
|
||||
|
||||
COMMISION_UNIT_VARIETY = 4
|
||||
COMMISION_LIMITS_SCALE = 1.5
|
||||
@@ -230,6 +217,10 @@ class Game:
|
||||
self.ground_planners[cp.id] = gplanner
|
||||
|
||||
def _enemy_reinforcement(self):
|
||||
"""
|
||||
Compute and commision reinforcement for enemy bases
|
||||
"""
|
||||
|
||||
MAX_ARMOR = 30 * self.settings.multiplier
|
||||
MAX_AIRCRAFT = 25 * self.settings.multiplier
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class Operation:
|
||||
def initialize(self, mission: Mission, conflict: Conflict):
|
||||
self.current_mission = mission
|
||||
self.conflict = conflict
|
||||
self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings)
|
||||
self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings, self.game)
|
||||
self.shipgen = ShipGenerator(mission, conflict)
|
||||
self.airsupportgen = AirSupportConflictGenerator(mission, conflict, self.game)
|
||||
self.triggersgen = TriggersGenerator(mission, conflict, self.game)
|
||||
@@ -172,7 +172,8 @@ class Operation:
|
||||
self.forcedoptionsgen.generate()
|
||||
|
||||
# Generate Visuals Smoke Effects
|
||||
self.visualgen.generate()
|
||||
if self.game.settings.perf_smoke_gen:
|
||||
self.visualgen.generate()
|
||||
|
||||
# Inject Lua Scripts
|
||||
load_mist = TriggerStart(comment="Load Mist Lua Framework")
|
||||
@@ -198,8 +199,6 @@ class Operation:
|
||||
self.briefinggen.append_frequency("AWACS", "133 MHz AM")
|
||||
|
||||
self.briefinggen.append_frequency("Flight", "251 MHz AM")
|
||||
if self.departure_cp.is_global or self.conflict.to_cp.is_global:
|
||||
self.briefinggen.append_frequency("Carrier", "20X/ICLS CHAN1")
|
||||
|
||||
# Generate the briefing
|
||||
self.briefinggen.generate()
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
|
||||
class Settings:
|
||||
|
||||
# Difficulty settings
|
||||
player_skill = "Good"
|
||||
enemy_skill = "Average"
|
||||
enemy_vehicle_skill = "Average"
|
||||
map_coalition_visibility = "All Units"
|
||||
labels = "Full"
|
||||
only_player_takeoff = True
|
||||
only_player_takeoff = True # Legacy parameter do not use
|
||||
night_disabled = False
|
||||
supercarrier = False
|
||||
multiplier = 1
|
||||
sams = True
|
||||
cold_start = False
|
||||
sams = True # Legacy parameter do not use
|
||||
cold_start = False # Legacy parameter do not use
|
||||
version = None
|
||||
|
||||
# Performance oriented
|
||||
perf_red_alert_state = True
|
||||
perf_smoke_gen = True
|
||||
perf_artillery = True
|
||||
perf_moving_units = True
|
||||
perf_infantry = True
|
||||
|
||||
|
||||
|
||||
320
gen/aircraft.py
320
gen/aircraft.py
@@ -1,8 +1,9 @@
|
||||
import logging
|
||||
|
||||
from dcs.action import ActivateGroup
|
||||
from dcs.condition import TimeAfter, CoalitionHasAirdrome
|
||||
from dcs.helicopters import UH_1H
|
||||
from dcs.terrain.terrain import NoParkingSlotError
|
||||
from dcs.triggers import TriggerOnce, Event
|
||||
|
||||
from game import db
|
||||
from game.settings import Settings
|
||||
from gen.flights.ai_flight_planner import FlightPlanner
|
||||
from gen.flights.flight import Flight, FlightType
|
||||
@@ -10,12 +11,6 @@ from .conflictgen import *
|
||||
from .naming import *
|
||||
from .triggergen import TRIGGER_WAYPOINT_OFFSET
|
||||
|
||||
from dcs.mission import *
|
||||
from dcs.unitgroup import *
|
||||
from dcs.unittype import *
|
||||
from dcs.task import *
|
||||
from dcs.terrain.terrain import NoParkingSlotError, RunwayOccupiedError
|
||||
|
||||
SPREAD_DISTANCE_FACTOR = 1, 2
|
||||
ESCORT_ENGAGEMENT_MAX_DIST = 100000
|
||||
WORKAROUND_WAYP_DIST = 1000
|
||||
@@ -46,8 +41,9 @@ INTERCEPT_MAX_DISTANCE = 200000
|
||||
class AircraftConflictGenerator:
|
||||
escort_targets = [] # type: typing.List[typing.Tuple[FlyingGroup, int]]
|
||||
|
||||
def __init__(self, mission: Mission, conflict: Conflict, settings: Settings):
|
||||
def __init__(self, mission: Mission, conflict: Conflict, settings: Settings, game):
|
||||
self.m = mission
|
||||
self.game = game
|
||||
self.settings = settings
|
||||
self.conflict = conflict
|
||||
self.escort_targets = []
|
||||
@@ -311,21 +307,31 @@ class AircraftConflictGenerator:
|
||||
group = self.generate_planned_flight(cp, country, flight)
|
||||
self.setup_group_as_intercept_flight(group, flight)
|
||||
self._setup_custom_payload(flight, group)
|
||||
self.setup_group_activation_trigger(flight, group)
|
||||
|
||||
for flight in flight_planner.cap_flights:
|
||||
group = self.generate_planned_flight(cp, country, flight)
|
||||
self.setup_group_as_cap_flight(group, flight)
|
||||
self._setup_custom_payload(flight, group)
|
||||
self.setup_group_activation_trigger(flight, group)
|
||||
|
||||
for flight in flight_planner.cas_flights:
|
||||
group = self.generate_planned_flight(cp, country, flight)
|
||||
self.setup_group_as_cas_flight(group, flight)
|
||||
self._setup_custom_payload(flight, group)
|
||||
self.setup_group_activation_trigger(flight, group)
|
||||
|
||||
for flight in flight_planner.sead_flights:
|
||||
group = self.generate_planned_flight(cp, country, flight)
|
||||
self.setup_group_as_sead_flight(group, flight)
|
||||
self._setup_custom_payload(flight, group)
|
||||
self.setup_group_activation_trigger(flight, group)
|
||||
|
||||
for flight in flight_planner.strike_flights:
|
||||
group = self.generate_planned_flight(cp, country, flight)
|
||||
self.setup_group_as_strike_flight(group, flight)
|
||||
self._setup_custom_payload(flight, group)
|
||||
self.setup_group_activation_trigger(flight, group)
|
||||
|
||||
for flight in flight_planner.custom_flights:
|
||||
group = self.generate_planned_flight(cp, country, flight)
|
||||
@@ -344,6 +350,23 @@ class AircraftConflictGenerator:
|
||||
else:
|
||||
self.setup_group_as_cap_flight(group, flight)
|
||||
self._setup_custom_payload(flight, group)
|
||||
self.setup_group_activation_trigger(flight, group)
|
||||
|
||||
def setup_group_activation_trigger(self, flight, group):
|
||||
if flight.scheduled_in > 0:
|
||||
group.late_activation = True
|
||||
activation_trigger = TriggerOnce(Event.NoEvent, "LiberationActivationTriggerForGroup" + str(group.id))
|
||||
activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in*60))
|
||||
|
||||
if(flight.from_cp.cptype == ControlPointType.AIRBASE):
|
||||
if not flight.from_cp.captured:
|
||||
activation_trigger.add_condition(CoalitionHasAirdrome(1, flight.from_cp.id))
|
||||
else:
|
||||
activation_trigger.add_condition(CoalitionHasAirdrome(2, flight.from_cp.id))
|
||||
|
||||
|
||||
activation_trigger.add_action(ActivateGroup(group.id))
|
||||
self.m.triggerrules.triggers.append(activation_trigger)
|
||||
|
||||
def generate_planned_flight(self, cp, country, flight:Flight):
|
||||
try:
|
||||
@@ -391,7 +414,6 @@ class AircraftConflictGenerator:
|
||||
client_count=0,
|
||||
at=cp.position)
|
||||
group.points[0].alt = 1500
|
||||
group.points[0].ETA = flight.scheduled_in * 60
|
||||
|
||||
return group
|
||||
|
||||
@@ -416,7 +438,7 @@ class AircraftConflictGenerator:
|
||||
group.points[0].tasks.append(CASTaskAction())
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFireWeaponFree))
|
||||
group.points[0].tasks.append(OptRestrictJettison(True))
|
||||
#group.points[0].tasks.append(OptRestrictJettison(True))
|
||||
|
||||
for point in flight.points:
|
||||
group.add_waypoint(Point(point.x,point.y), point.alt)
|
||||
@@ -445,11 +467,24 @@ class AircraftConflictGenerator:
|
||||
group.points[0].tasks.clear()
|
||||
group.points[0].tasks.append(CASTaskAction())
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFireWeaponFree))
|
||||
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire))
|
||||
group.points[0].tasks.append(OptRestrictJettison(True))
|
||||
|
||||
i = 1
|
||||
bombing_point_found = False
|
||||
for point in flight.points:
|
||||
group.add_waypoint(Point(point.x,point.y), point.alt)
|
||||
if not bombing_point_found:
|
||||
for t in point.targets:
|
||||
if hasattr(t, "obj_name"):
|
||||
buildings = self.game.theater.find_ground_objects_by_obj_name(t.obj_name)
|
||||
for building in buildings:
|
||||
group.points[i].tasks.append(Bombing(building.position))
|
||||
else:
|
||||
group.points[i].tasks.append(Bombing(t.position))
|
||||
bombing_point_found = True
|
||||
i = i + 1
|
||||
|
||||
|
||||
def setup_group_as_antiship_flight(self, group, flight):
|
||||
group.task = AntishipStrike.name
|
||||
@@ -464,263 +499,4 @@ class AircraftConflictGenerator:
|
||||
for point in flight.points:
|
||||
group.add_waypoint(Point(point.x,point.y), point.alt)
|
||||
|
||||
def generate_cas_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.attackers_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||
|
||||
waypoint = self._add_radio_waypoint(group, self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
if self.conflict.is_vector:
|
||||
self._add_radio_waypoint(group, self.conflict.tail, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
|
||||
group.task = CAS.name
|
||||
self._setup_group(group, CAS, client_count)
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_ground_attack_strikegroup(self, strikegroup: db.PlaneDict, clients: db.PlaneDict, targets: typing.List[typing.Tuple[str, Point]], at: db.StartingPosition = None, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.attackers_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||
|
||||
escort_until_waypoint = None
|
||||
|
||||
for name, pos in targets:
|
||||
waypoint = group.add_waypoint(pos, 0, WARM_START_AIRSPEED, self.m.translation.create_string(name))
|
||||
waypoint.tasks.append(Bombing(pos, attack_qty=2))
|
||||
if escort_until_waypoint is None:
|
||||
escort_until_waypoint = waypoint
|
||||
|
||||
group.task = GroundAttack.name
|
||||
self._setup_group(group, GroundAttack, client_count)
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(escort_until_waypoint)))
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_sead_strikegroup(self, strikegroup: db.PlaneDict, clients: db.PlaneDict, targets: typing.List[typing.Tuple[str, Point]], at: db.StartingPosition, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.attackers_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||
|
||||
escort_until_waypoint = None
|
||||
|
||||
for name, pos in targets:
|
||||
waypoint = group.add_waypoint(pos, 0, WARM_START_AIRSPEED, self.m.translation.create_string(name))
|
||||
if escort_until_waypoint is None:
|
||||
escort_until_waypoint = waypoint
|
||||
|
||||
group.task = SEAD.name
|
||||
self._setup_group(group, SEAD, client_count)
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(escort_until_waypoint)))
|
||||
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_defenders_cas(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.defenders_country, self.conflict.to_cp.id, flying_type),
|
||||
side=self.conflict.defenders_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_defenders_location))
|
||||
|
||||
location = self._group_point(self.conflict.air_defenders_location)
|
||||
insertion_point = self.conflict.find_insertion_point(location)
|
||||
waypoint = self._add_radio_waypoint(group, insertion_point, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
|
||||
if self.conflict.is_vector:
|
||||
destination_tail = self.conflict.tail.distance_to_point(insertion_point) > self.conflict.position.distance_to_point(insertion_point)
|
||||
self._add_radio_waypoint(group, destination_tail and self.conflict.tail or self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
|
||||
group.task = CAS.name
|
||||
self._setup_group(group, CAS, client_count)
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
self._rtb_for(group, self.conflict.to_cp, at)
|
||||
|
||||
def generate_ship_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, target_groups: typing.Collection[ShipGroup], at: db.StartingPosition = None, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.attackers_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||
|
||||
wayp = self._add_radio_waypoint(group, self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
for target_group in target_groups:
|
||||
wayp.tasks.append(AttackGroup(target_group.id))
|
||||
|
||||
group.task = AntishipStrike.name
|
||||
self._setup_group(group, AntishipStrike, client_count)
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(wayp)))
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_attackers_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
for g in self._generate_escort(
|
||||
side=self.conflict.attackers_country,
|
||||
units=attackers,
|
||||
clients=clients,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location),
|
||||
is_quick=at is None,
|
||||
cp=self.conflict.from_cp,
|
||||
should_orbit=True):
|
||||
self._rtb_for(g, self.conflict.from_cp, at)
|
||||
|
||||
def generate_defenders_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
for g in self._generate_escort(
|
||||
side=self.conflict.defenders_country,
|
||||
units=escort,
|
||||
clients=clients,
|
||||
at=at and at or self._group_point(self.conflict.air_defenders_location),
|
||||
is_quick=at is None,
|
||||
cp=self.conflict.to_cp,
|
||||
should_orbit=False):
|
||||
self._rtb_for(g, self.conflict.to_cp, at)
|
||||
|
||||
def generate_defense(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.to_cp.id, flying_type),
|
||||
side=self.conflict.defenders_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_defenders_location))
|
||||
|
||||
group.task = CAP.name
|
||||
wayp = self._add_radio_waypoint(group, self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
wayp.tasks.append(dcs.task.EngageTargets(max_distance=DEFENCE_ENGAGEMENT_MAX_DISTANCE))
|
||||
wayp.tasks.append(dcs.task.OrbitAction(ATTACK_CIRCLE_ALT, pattern=OrbitAction.OrbitPattern.Circle))
|
||||
self._setup_group(group, CAP, client_count)
|
||||
self._rtb_for(group, self.conflict.to_cp, at)
|
||||
|
||||
def generate_migcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
for flying_type, count, client_count in self._split_to_groups(patrol, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.attackers_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||
|
||||
waypoint = self._add_radio_waypoint(group, self.conflict.position, WARM_START_ALTITUDE, WARM_START_AIRSPEED)
|
||||
if self.conflict.is_vector:
|
||||
self._add_radio_waypoint(group, self.conflict.tail, WARM_START_ALTITUDE, WARM_START_AIRSPEED)
|
||||
|
||||
group.task = CAP.name
|
||||
self._setup_group(group, CAP, client_count)
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_barcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
for flying_type, count, client_count in self._split_to_groups(patrol, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.defenders_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_defenders_location))
|
||||
|
||||
waypoint = self._add_radio_waypoint(group, self.conflict.position, WARM_START_ALTITUDE, WARM_START_AIRSPEED)
|
||||
if self.conflict.is_vector:
|
||||
self._add_radio_waypoint(group, self.conflict.tail, WARM_START_ALTITUDE, WARM_START_AIRSPEED)
|
||||
else:
|
||||
heading = group.position.heading_between_point(self.conflict.position)
|
||||
waypoint = self._add_radio_waypoint(group, self.conflict.position.point_from_heading(heading, BARCAP_RACETRACK_DISTANCE),
|
||||
WARM_START_ALTITUDE,
|
||||
WARM_START_AIRSPEED)
|
||||
waypoint.tasks.append(OrbitAction(WARM_START_ALTITUDE, WARM_START_AIRSPEED))
|
||||
|
||||
group.task = CAP.name
|
||||
self._setup_group(group, CAP, client_count)
|
||||
self._rtb_for(group, self.conflict.to_cp, at)
|
||||
|
||||
def generate_transport(self, transport: db.PlaneDict, destination: Airport, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(transport):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.defenders_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=self._group_point(self.conflict.air_defenders_location))
|
||||
|
||||
waypoint = self._rtb_for(group, self.conflict.to_cp)
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
|
||||
self._add_radio_waypoint(group, destination.position, RTB_ALTITUDE)
|
||||
group.task = Transport.name
|
||||
group.land_at(destination)
|
||||
|
||||
def generate_interception(self, interceptors: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
for flying_type, count, client_count in self._split_to_groups(interceptors, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
|
||||
side=self.conflict.attackers_country,
|
||||
unit_type=flying_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||
|
||||
group.task = CAP.name
|
||||
group.points[0].tasks.append(EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE))
|
||||
|
||||
wayp = self._add_radio_waypoint(group, self.conflict.position, WARM_START_ALTITUDE, INTERCEPTION_AIRSPEED)
|
||||
wayp.tasks.append(EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE))
|
||||
|
||||
if self.conflict.is_vector:
|
||||
self._add_radio_waypoint(group, self.conflict.tail, CAS_ALTITUDE, WARM_START_ALTITUDE)
|
||||
|
||||
self._setup_group(group, CAP, client_count)
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_passenger_transport(self, helis: db.HeliDict, clients: db.HeliDict, at: db.StartingPosition):
|
||||
for heli_type, count, client_count in self._split_to_groups(helis, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, heli_type),
|
||||
side=self.conflict.attackers_country,
|
||||
unit_type=heli_type,
|
||||
count=count,
|
||||
client_count=client_count,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location)
|
||||
)
|
||||
|
||||
self._add_radio_waypoint(group, self.conflict.position, HELI_ALT)
|
||||
self._setup_group(group, Transport, client_count)
|
||||
|
||||
|
||||
|
||||
@@ -53,17 +53,20 @@ class AirSupportConflictGenerator:
|
||||
tanker_group.points[0].tasks.append(SetImmortalCommand(True))
|
||||
|
||||
if is_awacs_enabled:
|
||||
awacs_unit = db.find_unittype(AWACS, self.conflict.attackers_side)[0]
|
||||
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=133,
|
||||
start_type=StartType.Warm,
|
||||
)
|
||||
try:
|
||||
awacs_unit = db.find_unittype(AWACS, self.conflict.attackers_side)[0]
|
||||
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=133,
|
||||
start_type=StartType.Warm,
|
||||
)
|
||||
awacs_flight.points[0].tasks.append(SetInvisibleCommand(True))
|
||||
awacs_flight.points[0].tasks.append(SetImmortalCommand(True))
|
||||
except:
|
||||
print("No AWACS for faction")
|
||||
|
||||
awacs_flight.points[0].tasks.append(SetInvisibleCommand(True))
|
||||
awacs_flight.points[0].tasks.append(SetImmortalCommand(True))
|
||||
|
||||
15
gen/armor.py
15
gen/armor.py
@@ -96,6 +96,11 @@ class GroundConflictGenerator:
|
||||
|
||||
|
||||
def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading):
|
||||
|
||||
# Disable infantry unit gen if disabled
|
||||
if not self.game.settings.perf_infantry:
|
||||
return
|
||||
|
||||
infantry_position = group.points[0].position.random_point_within(250, 50)
|
||||
|
||||
if side == self.conflict.attackers_country:
|
||||
@@ -135,12 +140,16 @@ class GroundConflictGenerator:
|
||||
|
||||
def plan_action_for_groups(self, stance, ally_groups, enemy_groups, forward_heading, from_cp, to_cp):
|
||||
|
||||
if not self.game.settings.perf_moving_units:
|
||||
return
|
||||
|
||||
for dcs_group, group in ally_groups:
|
||||
if group.role == CombatGroupRole.ARTILLERY:
|
||||
# Fire on any ennemy in range
|
||||
target = self.get_artillery_target_in_range(dcs_group, group, enemy_groups)
|
||||
if target is not None:
|
||||
dcs_group.points[0].tasks.append(FireAtPoint(target, len(group.units) * 10, 100))
|
||||
if self.game.settings.perf_artillery:
|
||||
target = self.get_artillery_target_in_range(dcs_group, group, enemy_groups)
|
||||
if target is not None:
|
||||
dcs_group.points[0].tasks.append(FireAtPoint(target, len(group.units) * 10, 100))
|
||||
elif group.role in [CombatGroupRole.TANK, CombatGroupRole.IFV]:
|
||||
if stance == CombatStance.AGGRESIVE:
|
||||
# Attack nearest enemy if any
|
||||
|
||||
@@ -57,11 +57,7 @@ class BriefingGenerator:
|
||||
self.description += "-"*50 + "\n"
|
||||
|
||||
for planner in self.game.planners.values():
|
||||
for flight in planner.cap_flights:
|
||||
self.add_flight_description(flight)
|
||||
for flight in planner.cas_flights:
|
||||
self.add_flight_description(flight)
|
||||
for flight in planner.sead_flights:
|
||||
for flight in planner.flights:
|
||||
self.add_flight_description(flight)
|
||||
|
||||
if self.freqs:
|
||||
@@ -69,10 +65,9 @@ class BriefingGenerator:
|
||||
self.description += "-" * 50 + "\n"
|
||||
for name, freq in self.freqs:
|
||||
self.description += "\n{}: {}".format(name, freq)
|
||||
|
||||
self.description += "\n" + ("-" * 50) + "\n"
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.captured and cp.cptype in [ControlPointType.LHA_GROUP, ControlPointType.AIRCRAFT_CARRIER_GROUP]:
|
||||
self.description += "\n"
|
||||
self.description += cp.name + " TACAN : "
|
||||
|
||||
self.description += str(cp.tacanN)
|
||||
@@ -82,6 +77,9 @@ class BriefingGenerator:
|
||||
self.description += "X"
|
||||
self.description += " " + str(cp.tacanI) + "\n"
|
||||
|
||||
if cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP and hasattr(cp, "icls"):
|
||||
self.description += "ICLS Channel : " + str(cp.icls) + "\n"
|
||||
self.description += "-" * 50 + "\n"
|
||||
|
||||
self.m.set_description_text(self.description)
|
||||
|
||||
|
||||
@@ -172,13 +172,6 @@ class Conflict:
|
||||
position = middle_point.point_from_heading(attack_heading, strength_delta * attack_distance / 2 - FRONTLINE_MIN_CP_DISTANCE)
|
||||
return position, _opposite_heading(attack_heading)
|
||||
|
||||
ground_position = cls._find_ground_position(position, attack_distance / 2 - FRONTLINE_MIN_CP_DISTANCE, attack_heading, theater)
|
||||
if ground_position:
|
||||
return ground_position, _opposite_heading(attack_heading)
|
||||
else:
|
||||
logging.warning("Coudn't find frontline position between {} and {}!".format(from_cp, to_cp))
|
||||
return position, _opposite_heading(attack_heading)
|
||||
|
||||
|
||||
@classmethod
|
||||
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> typing.Optional[typing.Tuple[Point, int, int]]:
|
||||
|
||||
@@ -61,12 +61,14 @@ class EnviromentGenerator:
|
||||
logging.info("Skip Night mission due to user settings")
|
||||
if daytime == "dawn":
|
||||
time_range = (8, 9)
|
||||
elif daytime == "noon":
|
||||
elif daytime == "day":
|
||||
time_range = (10, 12)
|
||||
elif daytime == "dusk":
|
||||
time_range = (12, 14)
|
||||
elif daytime == "night":
|
||||
time_range = (14, 17)
|
||||
else:
|
||||
time_range = (10, 12)
|
||||
else:
|
||||
time_range = self.game.theater.daytime_map[daytime]
|
||||
|
||||
|
||||
@@ -17,7 +17,13 @@ MISSION_DURATION = 120 # in minutes
|
||||
CAP_EVERY_X_MINUTES = 20
|
||||
CAS_EVERY_X_MINUTES = 30
|
||||
SEAD_EVERY_X_MINUTES = 40
|
||||
STRIKE_EVERY_X_MINUTES = 40
|
||||
|
||||
INGRESS_EGRESS_DISTANCE = 45000
|
||||
INGRESS_ALT = 6096 # 20k feet
|
||||
EGRESS_ALT = 6096 # 20k feet
|
||||
PATROL_ALT_RANGE = (3600, 9200)
|
||||
NAV_ALT = 9144
|
||||
|
||||
class FlightPlanner:
|
||||
|
||||
@@ -53,7 +59,7 @@ class FlightPlanner:
|
||||
#self.commision_interceptors()
|
||||
|
||||
# Then some CAP patrol for the next 2 hours
|
||||
self.commision_barcap()
|
||||
self.commision_cap()
|
||||
|
||||
# Then setup cas
|
||||
self.commision_cas()
|
||||
@@ -61,6 +67,8 @@ class FlightPlanner:
|
||||
# Then prepare some sead flights if required
|
||||
self.commision_sead()
|
||||
|
||||
self.commision_strike()
|
||||
|
||||
# TODO : commision STRIKE / ANTISHIP
|
||||
|
||||
def remove_flight(self, index):
|
||||
@@ -107,7 +115,7 @@ class FlightPlanner:
|
||||
for k, v in inventory.items():
|
||||
self.aircraft_inventory[k] = v
|
||||
|
||||
def commision_barcap(self):
|
||||
def commision_cap(self):
|
||||
"""
|
||||
Pick some aircraft to assign them to defensive CAP roles (BARCAP)
|
||||
"""
|
||||
@@ -124,13 +132,14 @@ class FlightPlanner:
|
||||
break
|
||||
|
||||
inventory[unit] = inventory[unit] - 2
|
||||
flight = Flight(unit, 2, self.from_cp, FlightType.BARCAP)
|
||||
ftype = FlightType.BARCAP if self.from_cp.is_carrier else FlightType.CAP
|
||||
flight = Flight(unit, 2, self.from_cp, ftype)
|
||||
|
||||
# Flight path : fly over each ground object (TODO : improve)
|
||||
flight.points = []
|
||||
flight.scheduled_in = offset + i*random.randint(CAP_EVERY_X_MINUTES-5, CAP_EVERY_X_MINUTES+5)
|
||||
|
||||
patrol_alt = random.randint(3600, 7000)
|
||||
patrol_alt = random.randint(PATROL_ALT_RANGE[0], PATROL_ALT_RANGE[1])
|
||||
|
||||
patrolled = []
|
||||
for ground_object in self.from_cp.ground_objects:
|
||||
@@ -144,7 +153,7 @@ class FlightPlanner:
|
||||
|
||||
if len(flight.points) == 0:
|
||||
for i in range(3):
|
||||
pos = self.from_cp.position.point_from_heading(random.randint(0,360), random.randint(30000, 80000))
|
||||
pos = self.from_cp.position.point_from_heading(random.randint(0, 360), random.randint(30000, 80000))
|
||||
point = FlightWaypoint(pos.x, pos.y, patrol_alt)
|
||||
point.name = "Patrol point"
|
||||
point.description = "Patrol #" + str(len(flight.points))
|
||||
@@ -245,12 +254,33 @@ class FlightPlanner:
|
||||
location = self.potential_sead_targets[0][0]
|
||||
self.potential_sead_targets.pop(0)
|
||||
|
||||
heading = self.from_cp.position.heading_between_point(location.position)
|
||||
ingress_heading = heading - 180 + 25
|
||||
egress_heading = heading - 180 - 25
|
||||
|
||||
ingress_pos = location.position.point_from_heading(ingress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
ingress_point = FlightWaypoint(ingress_pos.x, ingress_pos.y, INGRESS_ALT)
|
||||
ingress_point.pretty_name = "INGRESS on " + location.obj_name
|
||||
ingress_point.description = "INGRESS on " + location.obj_name
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
point = FlightWaypoint(location.position.x, location.position.y, 1000)
|
||||
point.description = "SEAD"
|
||||
point.pretty_name = "SEAD"
|
||||
if flight.flight_type == FlightType.DEAD:
|
||||
point.description = "SEAD on " + location.obj_name
|
||||
point.pretty_name = "SEAD on " + location.obj_name
|
||||
else:
|
||||
point.description = "DEAD on " + location.obj_name
|
||||
point.pretty_name = "DEAD on " + location.obj_name
|
||||
|
||||
point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
|
||||
egress_pos = location.position.point_from_heading(egress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
egress_point = FlightWaypoint(egress_pos.x, egress_pos.y, EGRESS_ALT)
|
||||
egress_point.pretty_name = "EGRESS on " + location.obj_name
|
||||
egress_point.description = "EGRESS on " + location.obj_name
|
||||
flight.points.append(egress_point)
|
||||
|
||||
self.sead_flights.append(flight)
|
||||
self.flights.append(flight)
|
||||
|
||||
@@ -258,6 +288,74 @@ class FlightPlanner:
|
||||
for k, v in inventory.items():
|
||||
self.aircraft_inventory[k] = v
|
||||
|
||||
|
||||
def commision_strike(self):
|
||||
"""
|
||||
Pick some aircraft to assign them to STRIKE tasks
|
||||
"""
|
||||
possible_aircraft = [k for k, v in self.aircraft_inventory.items() if k in CAS_CAPABLE and v >= 2]
|
||||
inventory = dict({k: v for k, v in self.aircraft_inventory.items() if k in possible_aircraft})
|
||||
|
||||
if len(self.potential_strike_targets) > 0:
|
||||
|
||||
offset = random.randint(0,5)
|
||||
for i in range(int(MISSION_DURATION/STRIKE_EVERY_X_MINUTES)):
|
||||
|
||||
if len(self.potential_strike_targets) <= 0:
|
||||
break
|
||||
|
||||
try:
|
||||
unit = random.choice([k for k, v in inventory.items() if v >= 2])
|
||||
except IndexError:
|
||||
break
|
||||
|
||||
inventory[unit] = inventory[unit] - 2
|
||||
flight = Flight(unit, 2, self.from_cp, FlightType.STRIKE)
|
||||
|
||||
flight.points = []
|
||||
flight.scheduled_in = offset + i*random.randint(SEAD_EVERY_X_MINUTES-5, SEAD_EVERY_X_MINUTES+5)
|
||||
|
||||
location = self.potential_strike_targets[0][0]
|
||||
self.potential_strike_targets.pop(0)
|
||||
|
||||
heading = self.from_cp.position.heading_between_point(location.position)
|
||||
ingress_heading = heading - 180 + 25
|
||||
egress_heading = heading - 180 - 25
|
||||
|
||||
ingress_pos = location.position.point_from_heading(ingress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
ingress_point = FlightWaypoint(ingress_pos.x, ingress_pos.y, INGRESS_ALT)
|
||||
ingress_point.pretty_name = "INGRESS on " + location.obj_name
|
||||
ingress_point.description = "INGRESS on " + location.obj_name
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
if len(location.groups) > 0:
|
||||
for g in location.groups:
|
||||
for j, u in enumerate(g.units):
|
||||
point = FlightWaypoint(u.position.x, u.position.y, 0)
|
||||
point.description = "STRIKE " + "[" + str(location.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
point.pretty_name = "STRIKE " + "[" + str(location.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
else:
|
||||
point = FlightWaypoint(location.position.x, location.position.y, 0)
|
||||
point.description = "STRIKE on " + location.obj_name + " " + str(location.category)
|
||||
point.pretty_name = "STRIKE on " + location.obj_name + " " + str(location.category)
|
||||
point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
|
||||
egress_pos = location.position.point_from_heading(egress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
egress_point = FlightWaypoint(egress_pos.x, egress_pos.y, EGRESS_ALT)
|
||||
egress_point.pretty_name = "EGRESS on " + location.obj_name
|
||||
egress_point.description = "EGRESS on " + location.obj_name
|
||||
flight.points.append(egress_point)
|
||||
|
||||
self.strike_flights.append(flight)
|
||||
self.flights.append(flight)
|
||||
|
||||
# Update inventory
|
||||
for k, v in inventory.items():
|
||||
self.aircraft_inventory[k] = v
|
||||
|
||||
def _get_cas_locations(self):
|
||||
cas_locations = []
|
||||
for cp in self.from_cp.connected_points:
|
||||
@@ -285,7 +383,7 @@ class FlightPlanner:
|
||||
|
||||
added_group = []
|
||||
for g in cp.ground_objects:
|
||||
if g.group_id in added_group: continue
|
||||
if g.group_id in added_group or g.is_dead: continue
|
||||
|
||||
# Compute distance to current cp
|
||||
distance = math.hypot(cp.position.x - self.from_cp.position.x,
|
||||
|
||||
@@ -106,6 +106,7 @@ CAS_CAPABLE = [
|
||||
|
||||
P_51D_30_NA,
|
||||
P_51D,
|
||||
A_20G,
|
||||
|
||||
SpitfireLFMkIXCW,
|
||||
SpitfireLFMkIX,
|
||||
@@ -119,7 +120,7 @@ CAS_CAPABLE = [
|
||||
SEAD_CAPABLE = [
|
||||
F_4E,
|
||||
FA_18C_hornet,
|
||||
F_16C_50,
|
||||
# F_16C_50, Not yet
|
||||
AV8BNA,
|
||||
JF_17,
|
||||
|
||||
@@ -168,6 +169,7 @@ STRIKE_CAPABLE = [
|
||||
|
||||
P_51D_30_NA,
|
||||
P_51D,
|
||||
A_20G,
|
||||
|
||||
SpitfireLFMkIXCW,
|
||||
SpitfireLFMkIX,
|
||||
@@ -175,11 +177,18 @@ STRIKE_CAPABLE = [
|
||||
Bf_109K_4,
|
||||
FW_190D9,
|
||||
FW_190A8,
|
||||
|
||||
]
|
||||
|
||||
ANTISHIP_CAPABLE = [
|
||||
Su_24M,
|
||||
Su_17M4,
|
||||
F_A_18C,
|
||||
AV8BNA,
|
||||
JF_17
|
||||
JF_17,
|
||||
F_16C_50,
|
||||
A_10C,
|
||||
A_10A,
|
||||
|
||||
Ju_88A4,
|
||||
]
|
||||
@@ -19,6 +19,9 @@ TYPE_TANKS = [
|
||||
Armor.MBT_M1A2_Abrams,
|
||||
Armor.MBT_M60A3_Patton,
|
||||
Armor.MBT_Merkava_Mk__4,
|
||||
Armor.ZTZ_96B,
|
||||
|
||||
# WW2
|
||||
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G,
|
||||
Armor.MT_Pz_Kpfw_IV_Ausf_H,
|
||||
Armor.HT_Pz_Kpfw_VI_Tiger_I,
|
||||
@@ -26,13 +29,21 @@ TYPE_TANKS = [
|
||||
Armor.MT_M4_Sherman,
|
||||
Armor.MT_M4A4_Sherman_Firefly,
|
||||
Armor.StuG_IV,
|
||||
Armor.ZTZ_96B
|
||||
Armor.ST_Centaur_IV,
|
||||
Armor.CT_Cromwell_IV,
|
||||
Armor.HIT_Churchill_VII,
|
||||
]
|
||||
|
||||
TYPE_ATGM = [
|
||||
Armor.ATGM_M1045_HMMWV_TOW,
|
||||
Armor.ATGM_M1134_Stryker,
|
||||
Armor.IFV_BMP_2,
|
||||
|
||||
# WW2 (Tank Destroyers)
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.TD_Jagdpanzer_IV,
|
||||
Armor.TD_Jagdpanther_G1,
|
||||
Armor.TD_M10_GMC,
|
||||
]
|
||||
|
||||
TYPE_IFV = [
|
||||
@@ -46,8 +57,10 @@ TYPE_IFV = [
|
||||
Armor.IFV_M2A2_Bradley,
|
||||
Armor.IFV_BMD_1,
|
||||
Armor.ZBD_04A,
|
||||
Armor.APC_Sd_Kfz_251,
|
||||
|
||||
# WW2
|
||||
Armor.IFV_Sd_Kfz_234_2_Puma,
|
||||
Armor.LAC_M8_Greyhound,
|
||||
]
|
||||
|
||||
TYPE_APC = [
|
||||
@@ -63,9 +76,11 @@ TYPE_APC = [
|
||||
Armor.TPz_Fuchs,
|
||||
Armor.ARV_BRDM_2,
|
||||
Armor.ARV_BTR_RD,
|
||||
Armor.ARV_MTLB_U_BOMAN,
|
||||
Armor.M30_Cargo_Carrier,
|
||||
Armor.FDDM_Grad,
|
||||
|
||||
# WW2
|
||||
Armor.APC_M2A1,
|
||||
Armor.APC_Sd_Kfz_251,
|
||||
]
|
||||
|
||||
TYPE_ARTILLERY = [
|
||||
@@ -79,9 +94,11 @@ TYPE_ARTILLERY = [
|
||||
Artillery.SPH_2S9_Nona,
|
||||
Artillery.SpGH_Dana,
|
||||
Artillery.SPH_2S19_Msta,
|
||||
Artillery.M12_GMC,
|
||||
Artillery.MLRS_FDDM,
|
||||
Artillery.Sturmpanzer_IV_Brummbär
|
||||
|
||||
# WW2
|
||||
Artillery.Sturmpanzer_IV_Brummbär,
|
||||
Artillery.M12_GMC
|
||||
]
|
||||
|
||||
TYPE_LOGI = [
|
||||
|
||||
@@ -77,14 +77,23 @@ class GroundObjectsGenerator:
|
||||
vehicle.position.y = u.position.y
|
||||
vehicle.heading = u.heading
|
||||
vg.add_unit(vehicle)
|
||||
|
||||
if self.game.settings.perf_red_alert_state:
|
||||
vg.points[0].tasks.append(OptAlarmState(2))
|
||||
else:
|
||||
vg.points[0].tasks.append(OptAlarmState(1))
|
||||
|
||||
elif ground_object.dcs_identifier in ["CARRIER", "LHA"]:
|
||||
for g in ground_object.groups:
|
||||
if len(g.units) > 0:
|
||||
|
||||
utype = unit_type_from_name(g.units[0].type)
|
||||
sg = self.m.ship_group(side, g.name, utype, position=g.position, heading=g.units[0].heading)
|
||||
if ground_object.dcs_identifier == "CARRIER" and self.game.settings.supercarrier == True:
|
||||
utype = db.upgrade_to_supercarrier(utype, cp.name)
|
||||
|
||||
sg = self.m.ship_group(side, g.name, utype, position=g.position, heading=g.units[0].heading)
|
||||
sg.units[0].name = self.m.string(g.units[0].name)
|
||||
|
||||
for i, u in enumerate(g.units):
|
||||
if i > 0:
|
||||
ship = Ship(self.m.next_unit_id(), self.m.string(u.name), unit_type_from_name(u.type))
|
||||
@@ -100,6 +109,9 @@ class GroundObjectsGenerator:
|
||||
modeChannel = "X" if not cp.tacanY else "Y"
|
||||
sg.points[0].tasks.append(ActivateBeaconCommand(channel=cp.tacanN, modechannel=modeChannel, callsign=cp.tacanI, unit_id=sg.units[0].id))
|
||||
|
||||
if ground_object.dcs_identifier == "CARRIER" and hasattr(cp, "icls"):
|
||||
sg.points[0].tasks.append(ActivateICLSCommand(cp.icls, unit_id=sg.units[0].id))
|
||||
|
||||
else:
|
||||
if ground_object.dcs_identifier in warehouse_map:
|
||||
static_type = warehouse_map[ground_object.dcs_identifier]
|
||||
@@ -110,16 +122,6 @@ class GroundObjectsGenerator:
|
||||
print("Didn't find {} in static _map(s)!".format(ground_object.dcs_identifier))
|
||||
continue
|
||||
|
||||
if ground_object.group_id not in consumed_farps:
|
||||
consumed_farps.add(ground_object.group_id)
|
||||
if random.randint(0, 100) > 50:
|
||||
farp_aa(
|
||||
self.m,
|
||||
side,
|
||||
ground_object.string_identifier,
|
||||
ground_object.position,
|
||||
)
|
||||
|
||||
group = self.m.static_group(
|
||||
country=side,
|
||||
name=ground_object.string_identifier,
|
||||
|
||||
@@ -68,7 +68,7 @@ class NameGenerator:
|
||||
|
||||
def random_objective_name(self):
|
||||
if len(self.ANIMALS) == 0:
|
||||
random.choice(ALPHA_MILITARY).upper() + " #" + str(random.randint(0, 100))
|
||||
return random.choice(ALPHA_MILITARY).upper() + "#" + str(random.randint(0, 100))
|
||||
else:
|
||||
animal = random.choice(self.ANIMALS)
|
||||
self.ANIMALS.remove(animal)
|
||||
|
||||
@@ -4,7 +4,7 @@ from dcs.vehicles import AirDefence, Unarmed
|
||||
|
||||
from gen.sam.group_generator import GroupGenerator
|
||||
|
||||
GFLAK = [AirDefence.AAA_Flak_Vierling_38, AirDefence.AAA_Flak_Vierling_38, AirDefence.AAA_Flak_18, AirDefence.AAA_Flak_36, AirDefence.AAA_Flak_37, AirDefence.AAA_Flak_38]
|
||||
GFLAK = [AirDefence.AAA_Flak_Vierling_38, 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]
|
||||
|
||||
class FlakGenerator(GroupGenerator):
|
||||
"""
|
||||
@@ -31,7 +31,7 @@ class FlakGenerator(GroupGenerator):
|
||||
if(mixed):
|
||||
unit_type = random.choice(GFLAK)
|
||||
|
||||
# Enough Opel truck to transport the guns
|
||||
# Enough Opel Blitz truck to transport the guns
|
||||
for i in range(grid_x):
|
||||
for j in range(grid_y):
|
||||
self.add_unit(Unarmed.Blitz_3_6_6700A, "AAA#" + str(index),
|
||||
|
||||
@@ -50,7 +50,7 @@ SAM_MAP = {
|
||||
AirDefence.SAM_Patriot_EPP_III: PatriotGenerator,
|
||||
AirDefence.SAM_Chaparral_M48: ChaparralGenerator,
|
||||
AirDefence.AAA_Bofors_40mm: BoforsGenerator,
|
||||
AirDefence.AAA_Flak_36: FlakGenerator,
|
||||
AirDefence.AAA_8_8cm_Flak_36: FlakGenerator,
|
||||
AirDefence.SAM_SA_2_LN_SM_90: SA2Generator,
|
||||
AirDefence.SAM_SA_3_S_125_LN_5P73: SA3Generator,
|
||||
AirDefence.SAM_SA_6_Kub_LN_2P25: SA6Generator,
|
||||
|
||||
@@ -20,8 +20,14 @@ if __name__ == "__main__":
|
||||
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads")
|
||||
if os.path.exists(custom_payloads):
|
||||
dcs.planes.FlyingType.payload_dirs.append(custom_payloads)
|
||||
else:
|
||||
# For release version the path is different.
|
||||
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
||||
"resources\\customized_payloads")
|
||||
if os.path.exists(custom_payloads):
|
||||
dcs.planes.FlyingType.payload_dirs.append(custom_payloads)
|
||||
|
||||
VERSION_STRING = "2.0"
|
||||
VERSION_STRING = "2.0RC6"
|
||||
logging_module.setup_version_string(VERSION_STRING)
|
||||
logging.info("Using {} as userdata folder".format(persistency.base_path()))
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from PySide2.QtCore import QSortFilterProxyModel, Qt, QModelIndex
|
||||
from PySide2.QtGui import QStandardItem, QStandardItemModel
|
||||
from PySide2.QtWidgets import QComboBox, QCompleter
|
||||
from game import Game
|
||||
from gen import Conflict
|
||||
from gen.flights.flight import FlightWaypoint
|
||||
from theater import ControlPointType
|
||||
|
||||
@@ -89,7 +90,8 @@ class QPredefinedWaypointSelectionComboBox(QComboBox):
|
||||
if cp.captured:
|
||||
enemy_cp = [ecp for ecp in cp.connected_points if ecp.captured != cp.captured]
|
||||
for ecp in enemy_cp:
|
||||
wpt = FlightWaypoint((cp.position.x + ecp.position.x)/2, (cp.position.y + ecp.position.y)/2, 800)
|
||||
pos = Conflict.frontline_position(self.game.theater, cp, ecp)[0]
|
||||
wpt = FlightWaypoint(pos.x, pos.y, 800)
|
||||
wpt.name = "Frontline " + cp.name + "/" + ecp.name + " [CAS]"
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.description = "Frontline"
|
||||
@@ -103,6 +105,7 @@ class QPredefinedWaypointSelectionComboBox(QComboBox):
|
||||
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + ground_object.category + " #" + str(ground_object.object_id)
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.obj_name = ground_object.obj_name
|
||||
wpt.targets.append(ground_object)
|
||||
if cp.captured:
|
||||
wpt.description = "Friendly Building"
|
||||
else:
|
||||
@@ -118,6 +121,7 @@ class QPredefinedWaypointSelectionComboBox(QComboBox):
|
||||
wpt = FlightWaypoint(u.position.x, u.position.y, 0)
|
||||
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.targets.append(u)
|
||||
wpt.obj_name = ground_object.obj_name
|
||||
if cp.captured:
|
||||
wpt.description = "Friendly unit : " + u.type
|
||||
|
||||
@@ -7,6 +7,7 @@ from dcs.task import CAP, CAS
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game import db, Game
|
||||
from gen import namegen
|
||||
from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy
|
||||
from userdata.logging import version_string
|
||||
|
||||
@@ -29,6 +30,7 @@ class NewGameWizard(QtWidgets.QWizard):
|
||||
self.generatedGame = None
|
||||
|
||||
def accept(self):
|
||||
|
||||
blueFaction = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "blue"][self.field("blueFaction")]
|
||||
redFaction = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "red"][self.field("redFaction")]
|
||||
playerIsBlue = self.field("playerIsBlue")
|
||||
@@ -36,11 +38,11 @@ class NewGameWizard(QtWidgets.QWizard):
|
||||
isTerrainNttr = self.field("isTerrainNttr")
|
||||
isTerrainCaucasusSmall = self.field("isTerrainCaucasusSmall")
|
||||
isTerrainCaucasusSmallInverted = self.field("isTerrainCaucasusSmallInverted")
|
||||
isTerrainCaucasusNorth= self.field("isTerrainCaucasusNorth")
|
||||
isIranianCampaignTheater = self.field("isIranianCampaignTheater")
|
||||
isTerrainNormandy = self.field("isTerrainNormandy")
|
||||
isTerrainEmirates = self.field("isTerrainEmirates")
|
||||
timePeriod = db.TIME_PERIODS[list(db.TIME_PERIODS.keys())[self.field("timePeriod")]]
|
||||
sams = self.field("sams")
|
||||
midGame = self.field("midGame")
|
||||
multiplier = self.field("multiplier")
|
||||
|
||||
@@ -55,6 +57,8 @@ class NewGameWizard(QtWidgets.QWizard):
|
||||
conflicttheater = caucasus.WesternGeorgia()
|
||||
elif isTerrainCaucasusSmallInverted:
|
||||
conflicttheater = caucasus.WesternGeorgiaInverted()
|
||||
elif isTerrainCaucasusNorth:
|
||||
conflicttheater = caucasus.NorthCaucasus()
|
||||
elif isIranianCampaignTheater:
|
||||
conflicttheater = persiangulf.IranianCampaign()
|
||||
elif isTerrainEmirates:
|
||||
@@ -64,27 +68,38 @@ class NewGameWizard(QtWidgets.QWizard):
|
||||
else:
|
||||
conflicttheater = caucasus.CaucasusTheater()
|
||||
|
||||
self.generatedGame = self.start_new_game(player_name, enemy_name, conflicttheater, sams, midGame, multiplier,
|
||||
self.generatedGame = self.start_new_game(player_name, enemy_name, conflicttheater, midGame, multiplier,
|
||||
timePeriod)
|
||||
|
||||
super(NewGameWizard, self).accept()
|
||||
|
||||
def start_new_game(self, player_name: str, enemy_name: str, conflicttheater: ConflictTheater, sams: bool,
|
||||
def start_new_game(self, player_name: str, enemy_name: str, conflicttheater: ConflictTheater,
|
||||
midgame: bool, multiplier: float, period: datetime):
|
||||
|
||||
if midgame:
|
||||
for i in range(0, int(len(conflicttheater.controlpoints) / 2)):
|
||||
conflicttheater.controlpoints[i].captured = True
|
||||
|
||||
start_generator.generate_inital_units(conflicttheater, enemy_name, sams, multiplier)
|
||||
# Reset name generator
|
||||
namegen.reset()
|
||||
|
||||
print("-- Starting New Game Generator")
|
||||
print("Enemy name : " + enemy_name)
|
||||
print("Player name : " + player_name)
|
||||
print("Midgame : " + str(midgame))
|
||||
start_generator.generate_inital_units(conflicttheater, enemy_name, True, multiplier)
|
||||
|
||||
print("-- Initial units generated")
|
||||
game = Game(player_name=player_name,
|
||||
enemy_name=enemy_name,
|
||||
theater=conflicttheater,
|
||||
start_date=period)
|
||||
|
||||
print("-- Game Object generated")
|
||||
start_generator.generate_groundobjects(conflicttheater, game)
|
||||
game.budget = int(game.budget * multiplier)
|
||||
game.settings.multiplier = multiplier
|
||||
game.settings.sams = sams
|
||||
game.settings.sams = True
|
||||
game.settings.version = version_string()
|
||||
|
||||
if midgame:
|
||||
@@ -206,12 +221,14 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
|
||||
|
||||
# Terrain selection
|
||||
terrainGroup = QtWidgets.QGroupBox("Terrain")
|
||||
terrainCaucasusSmall = QtWidgets.QRadioButton("Caucasus - Western Georgia [RECOMMENDED]")
|
||||
terrainCaucasusSmall = QtWidgets.QRadioButton("Caucasus - Western Georgia [RECOMMENDED - Early Cold War Era]")
|
||||
terrainCaucasusSmall.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"]))
|
||||
terrainCaucasusSmallInverted = QtWidgets.QRadioButton("Caucasus - Western Georgia Inverted [RECOMMENDED]")
|
||||
terrainCaucasusSmallInverted = QtWidgets.QRadioButton("Caucasus - Western Georgia Inverted [RECOMMENDED - Early Cold War Era]")
|
||||
terrainCaucasusSmallInverted.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"]))
|
||||
terrainCaucasus = QtWidgets.QRadioButton("Caucasus - Full map [NOT TESTED]")
|
||||
terrainCaucasus.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"]))
|
||||
terrainCaucasusNorth = QtWidgets.QRadioButton("Caucasus - North - [RECOMMENDED - Modern Era]")
|
||||
terrainCaucasusNorth.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Caucasus"]))
|
||||
|
||||
terrainPg = QtWidgets.QRadioButton("Persian Gulf - Full Map [NOT TESTED]")
|
||||
terrainPg.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Persian_Gulf"]))
|
||||
@@ -238,6 +255,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
|
||||
self.registerField('isTerrainCaucasus', terrainCaucasus)
|
||||
self.registerField('isTerrainCaucasusSmall', terrainCaucasusSmall)
|
||||
self.registerField('isTerrainCaucasusSmallInverted', terrainCaucasusSmallInverted)
|
||||
self.registerField('isTerrainCaucasusNorth', terrainCaucasusNorth)
|
||||
self.registerField('isTerrainPg', terrainPg)
|
||||
self.registerField('isIranianCampaignTheater', terrainIran)
|
||||
self.registerField('isTerrainEmirates', terrainEmirates)
|
||||
@@ -249,6 +267,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
|
||||
terrainGroupLayout = QtWidgets.QVBoxLayout()
|
||||
terrainGroupLayout.addWidget(terrainCaucasusSmall)
|
||||
terrainGroupLayout.addWidget(terrainCaucasusSmallInverted)
|
||||
terrainGroupLayout.addWidget(terrainCaucasusNorth)
|
||||
terrainGroupLayout.addWidget(terrainCaucasus)
|
||||
terrainGroupLayout.addWidget(terrainIran)
|
||||
terrainGroupLayout.addWidget(terrainEmirates)
|
||||
@@ -278,21 +297,16 @@ class MiscOptions(QtWidgets.QWizardPage):
|
||||
self.setPixmap(QtWidgets.QWizard.LogoPixmap,
|
||||
QtGui.QPixmap('./resources/ui/wizard/logo1.png'))
|
||||
|
||||
sams = QtWidgets.QCheckBox()
|
||||
sams.setChecked(True)
|
||||
midGame = QtWidgets.QCheckBox()
|
||||
multiplier = QtWidgets.QSpinBox()
|
||||
multiplier.setEnabled(False)
|
||||
multiplier.setMinimum(1)
|
||||
multiplier.setMaximum(5)
|
||||
|
||||
self.registerField('sams', sams)
|
||||
self.registerField('midGame', midGame)
|
||||
self.registerField('multiplier', multiplier)
|
||||
|
||||
layout = QtWidgets.QGridLayout()
|
||||
#layout.addWidget(QtWidgets.QLabel("With SAM Systems :"), 0, 0)
|
||||
#layout.addWidget(sams, 0, 1)
|
||||
layout.addWidget(QtWidgets.QLabel("Start at mid game"), 1, 0)
|
||||
layout.addWidget(midGame, 1, 1)
|
||||
layout.addWidget(QtWidgets.QLabel("Ennemy forces multiplier [Disabled for Now]"), 2, 0)
|
||||
|
||||
@@ -38,7 +38,7 @@ class QMissionPlanning(QDialog):
|
||||
self.planned_flight_view.set_flight_planner(self.planner)
|
||||
self.selected_cp = self.captured_cp[0]
|
||||
|
||||
self.planned_flight_view.selectionModel().setCurrentIndex(self.planned_flight_view.indexAt(QPoint(1, 1)), QItemSelectionModel.Select)
|
||||
self.planned_flight_view.selectionModel().setCurrentIndex(self.planned_flight_view.indexAt(QPoint(1, 1)), QItemSelectionModel.Rows)
|
||||
self.planned_flight_view.selectionModel().selectionChanged.connect(self.on_flight_selection_change)
|
||||
|
||||
if len(self.planned_flight_view.flight_planner.flights) > 0:
|
||||
@@ -83,15 +83,24 @@ class QMissionPlanning(QDialog):
|
||||
else:
|
||||
self.planned_flight_view.set_flight_planner(None)
|
||||
|
||||
print(self.selected_cp.id)
|
||||
|
||||
def on_flight_selection_change(self):
|
||||
index = self.planned_flight_view.selectionModel().currentIndex().row()
|
||||
flight = self.planner.flights[index]
|
||||
|
||||
print("On flight selection change")
|
||||
|
||||
index = self.planned_flight_view.selectionModel().currentIndex().row()
|
||||
self.planned_flight_view.repaint();
|
||||
|
||||
if self.flight_planner is not None:
|
||||
self.flight_planner.clearTabs()
|
||||
|
||||
try:
|
||||
flight = self.planner.flights[index]
|
||||
except IndexError:
|
||||
flight = None
|
||||
self.flight_planner = QFlightPlanner(flight, self.game, self.planner)
|
||||
self.layout.addWidget(self.flight_planner, 0, 1)
|
||||
|
||||
|
||||
def on_add_flight(self):
|
||||
possible_aircraft_type = list(self.selected_cp.base.aircraft.keys())
|
||||
|
||||
@@ -110,7 +119,8 @@ class QMissionPlanning(QDialog):
|
||||
def on_delete_flight(self):
|
||||
index = self.planned_flight_view.selectionModel().currentIndex().row()
|
||||
self.planner.remove_flight(index)
|
||||
self.planned_flight_view.set_flight_planner(self.planner)
|
||||
self.planned_flight_view.set_flight_planner(self.planner, index)
|
||||
|
||||
|
||||
def on_start(self):
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from PySide2.QtCore import QSize
|
||||
from PySide2.QtCore import QSize, QItemSelectionModel, QPoint
|
||||
from PySide2.QtGui import QStandardItemModel
|
||||
from PySide2.QtWidgets import QListView
|
||||
from PySide2.QtWidgets import QListView, QAbstractItemView
|
||||
|
||||
from gen.flights.ai_flight_planner import FlightPlanner
|
||||
from qt_ui.windows.mission.QFlightItem import QFlightItem
|
||||
@@ -13,18 +13,29 @@ class QPlannedFlightsView(QListView):
|
||||
self.model = QStandardItemModel(self)
|
||||
self.setModel(self.model)
|
||||
self.setIconSize(QSize(91, 24))
|
||||
self.setSelectionBehavior(QAbstractItemView.SelectItems)
|
||||
if flight_planner:
|
||||
self.set_flight_planner(flight_planner)
|
||||
|
||||
def update_content(self):
|
||||
def update_content(self, row=0):
|
||||
for i, f in enumerate(self.flight_planner.flights):
|
||||
self.model.appendRow(QFlightItem(f))
|
||||
self.setSelectedFlight(row)
|
||||
self.repaint()
|
||||
|
||||
def setSelectedFlight(self, row):
|
||||
self.selectionModel().clearSelection()
|
||||
index = self.model.index(row, 0)
|
||||
if not index.isValid():
|
||||
index = self.model.index(0, 0)
|
||||
self.selectionModel().setCurrentIndex(index, QItemSelectionModel.Select)
|
||||
self.repaint()
|
||||
|
||||
def clear_layout(self):
|
||||
self.model.removeRows(0, self.model.rowCount())
|
||||
|
||||
def set_flight_planner(self, flight_planner: FlightPlanner):
|
||||
def set_flight_planner(self, flight_planner: FlightPlanner, row=0):
|
||||
self.clear_layout()
|
||||
self.flight_planner = flight_planner
|
||||
if self.flight_planner:
|
||||
self.update_content()
|
||||
self.update_content(row)
|
||||
|
||||
@@ -111,6 +111,6 @@ class QFlightCreator(QDialog):
|
||||
self.planner.flights.append(flight)
|
||||
self.planner.custom_flights.append(flight)
|
||||
if self.flight_view is not None:
|
||||
self.flight_view.set_flight_planner(self.planner)
|
||||
self.flight_view.set_flight_planner(self.planner, len(self.planner.flights)-1)
|
||||
self.close()
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ class QFlightPlanner(QTabWidget):
|
||||
|
||||
def __init__(self, flight: Flight, game: Game, planner):
|
||||
super(QFlightPlanner, self).__init__()
|
||||
self.tabCount = 0
|
||||
if flight:
|
||||
self.general_settings_tab = QGeneralFlightSettingsTab(flight, game, planner)
|
||||
self.payload_tab = QFlightPayloadTab(flight, game)
|
||||
@@ -18,9 +19,15 @@ class QFlightPlanner(QTabWidget):
|
||||
self.addTab(self.general_settings_tab, "General Flight settings")
|
||||
self.addTab(self.payload_tab, "Payload")
|
||||
self.addTab(self.waypoint_tab, "Waypoints")
|
||||
self.tabCount = 3
|
||||
else:
|
||||
tabError = QFrame()
|
||||
l = QGridLayout()
|
||||
l.addWidget(QLabel("No flight selected"))
|
||||
tabError.setLayout(l)
|
||||
self.addTab(tabError, "No flight")
|
||||
self.addTab(tabError, "No flight")
|
||||
self.tabCount = 1
|
||||
|
||||
def clearTabs(self):
|
||||
for i in range(self.tabCount):
|
||||
self.removeTab(i)
|
||||
@@ -1,7 +1,7 @@
|
||||
from PySide2.QtCore import QSize, Qt, QItemSelectionModel, QPoint
|
||||
from PySide2.QtGui import QStandardItemModel, QStandardItem
|
||||
from PySide2.QtWidgets import QLabel, QDialog, QGridLayout, QListView, QStackedLayout, QComboBox, QWidget, \
|
||||
QAbstractItemView, QPushButton, QGroupBox, QCheckBox
|
||||
QAbstractItemView, QPushButton, QGroupBox, QCheckBox, QVBoxLayout
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game.game import Game
|
||||
@@ -121,32 +121,61 @@ class QSettingsWindow(QDialog):
|
||||
|
||||
def initGeneratorLayout(self):
|
||||
self.generatorPage = QWidget()
|
||||
self.generatorLayout = QGridLayout()
|
||||
self.generatorLayout = QVBoxLayout()
|
||||
self.generatorLayout.setAlignment(Qt.AlignTop)
|
||||
self.generatorPage.setLayout(self.generatorLayout)
|
||||
|
||||
self.coldStart = QCheckBox()
|
||||
self.coldStart.setChecked(self.game.settings.cold_start)
|
||||
self.coldStart.toggled.connect(self.applySettings)
|
||||
self.takeOffOnlyForPlayerGroup = QCheckBox()
|
||||
self.takeOffOnlyForPlayerGroup.setChecked(self.game.settings.only_player_takeoff)
|
||||
self.takeOffOnlyForPlayerGroup.toggled.connect(self.applySettings)
|
||||
|
||||
self.coldStart = QCheckBox()
|
||||
self.coldStart.setChecked(self.game.settings.cold_start)
|
||||
self.coldStart.toggled.connect(self.applySettings)
|
||||
self.gameplay = QGroupBox("Gameplay")
|
||||
self.gameplayLayout = QGridLayout();
|
||||
self.gameplayLayout.setAlignment(Qt.AlignTop)
|
||||
self.gameplay.setLayout(self.gameplayLayout)
|
||||
|
||||
self.supercarrier = QCheckBox()
|
||||
self.supercarrier.setChecked(self.game.settings.supercarrier)
|
||||
self.supercarrier.toggled.connect(self.applySettings)
|
||||
|
||||
# Settings not used anymore
|
||||
# self.generatorLayout.addWidget(QLabel("Aircraft cold start"), 0, 0)
|
||||
# self.generatorLayout.addWidget(self.coldStart, 0, 1)
|
||||
# self.generatorLayout.addWidget(QLabel("Takeoff only for player group"), 1, 0)
|
||||
# self.generatorLayout.addWidget(self.takeOffOnlyForPlayerGroup, 1, 1)
|
||||
self.generatorLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
|
||||
self.generatorLayout.addWidget(self.supercarrier, 0, 1)
|
||||
self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
|
||||
self.gameplayLayout.addWidget(self.supercarrier, 0, 1)
|
||||
|
||||
self.performance = QGroupBox("Performance")
|
||||
self.performanceLayout = QGridLayout();
|
||||
self.performanceLayout.setAlignment(Qt.AlignTop)
|
||||
self.performance.setLayout(self.performanceLayout)
|
||||
|
||||
self.smoke = QCheckBox()
|
||||
self.smoke.setChecked(self.game.settings.perf_smoke_gen)
|
||||
self.smoke.toggled.connect(self.applySettings)
|
||||
|
||||
self.red_alert = QCheckBox()
|
||||
self.red_alert.setChecked(self.game.settings.perf_red_alert_state)
|
||||
self.red_alert.toggled.connect(self.applySettings)
|
||||
|
||||
self.arti = QCheckBox()
|
||||
self.arti.setChecked(self.game.settings.perf_artillery)
|
||||
self.arti.toggled.connect(self.applySettings)
|
||||
|
||||
self.moving_units = QCheckBox()
|
||||
self.moving_units.setChecked(self.game.settings.perf_moving_units)
|
||||
self.moving_units.toggled.connect(self.applySettings)
|
||||
|
||||
self.infantry = QCheckBox()
|
||||
self.infantry.setChecked(self.game.settings.perf_infantry)
|
||||
self.infantry.toggled.connect(self.applySettings)
|
||||
|
||||
self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0)
|
||||
self.performanceLayout.addWidget(self.smoke, 0, 1)
|
||||
self.performanceLayout.addWidget(QLabel("SAM starts in RED alert mode"), 1, 0)
|
||||
self.performanceLayout.addWidget(self.red_alert, 1, 1)
|
||||
self.performanceLayout.addWidget(QLabel("Artillery strikes"), 2, 0)
|
||||
self.performanceLayout.addWidget(self.arti, 2, 1)
|
||||
self.performanceLayout.addWidget(QLabel("Moving ground units"), 3, 0)
|
||||
self.performanceLayout.addWidget(self.moving_units, 3, 1)
|
||||
self.performanceLayout.addWidget(QLabel("Generate infantry squads along vehicles"), 4, 0)
|
||||
self.performanceLayout.addWidget(self.infantry, 4, 1)
|
||||
|
||||
self.generatorLayout.addWidget(self.gameplay)
|
||||
self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience."))
|
||||
self.generatorLayout.addWidget(self.performance)
|
||||
|
||||
|
||||
def initCheatLayout(self):
|
||||
@@ -194,10 +223,14 @@ class QSettingsWindow(QDialog):
|
||||
self.game.settings.enemy_vehicle_skill = CONST.SKILL_OPTIONS[self.enemyAASkill.currentIndex()]
|
||||
self.game.settings.labels = CONST.LABELS_OPTIONS[self.difficultyLabel.currentIndex()]
|
||||
self.game.settings.night_disabled = self.noNightMission.isChecked()
|
||||
self.game.settings.only_player_takeoff = self.takeOffOnlyForPlayerGroup.isChecked()
|
||||
self.game.settings.cold_start = self.coldStart.isChecked()
|
||||
self.game.settings.supercarrier = self.supercarrier.isChecked()
|
||||
|
||||
self.game.settings.perf_red_alert_state = self.red_alert.isChecked()
|
||||
self.game.settings.perf_smoke_gen = self.smoke.isChecked()
|
||||
self.game.settings.perf_artillery = self.arti.isChecked()
|
||||
self.game.settings.perf_moving_units = self.moving_units.isChecked()
|
||||
self.game.settings.perf_infantry = self.infantry.isChecked()
|
||||
|
||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||
|
||||
def onSelectionChanged(self):
|
||||
|
||||
Binary file not shown.
62
resources/customized_payloads/Bf-109K-4.lua
Normal file
62
resources/customized_payloads/Bf-109K-4.lua
Normal file
@@ -0,0 +1,62 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "Bf-109K-4",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "SC_501_SC500",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 34,
|
||||
[2] = 31,
|
||||
[3] = 30,
|
||||
[4] = 32,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "SC_501_SC250",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 34,
|
||||
[2] = 31,
|
||||
[3] = 30,
|
||||
[4] = 32,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "CAP",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "SC_501_SC500",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 34,
|
||||
[2] = 31,
|
||||
[3] = 30,
|
||||
[4] = 32,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
["unitType"] = "Bf-109K-4",
|
||||
}
|
||||
return unitPayloads
|
||||
61
resources/customized_payloads/FW-190A8.lua
Normal file
61
resources/customized_payloads/FW-190A8.lua
Normal file
@@ -0,0 +1,61 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "FW-190A8",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{WGr21}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{WGr21}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{SC_250_T1_L2}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{SD_500_A}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{SD_500_A}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
["name"] = "CAP",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
["unitType"] = "FW-190A8",
|
||||
}
|
||||
return unitPayloads
|
||||
70
resources/customized_payloads/FW-190D9.lua
Normal file
70
resources/customized_payloads/FW-190D9.lua
Normal file
@@ -0,0 +1,70 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "FW-190D9",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{WGr21}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{WGr21}",
|
||||
["num"] = 2,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 11,
|
||||
[2] = 10,
|
||||
[3] = 32,
|
||||
[4] = 31,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "SC_501_SC500",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 34,
|
||||
[2] = 31,
|
||||
[3] = 30,
|
||||
[4] = 32,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{WGr21}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{WGr21}",
|
||||
["num"] = 2,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 11,
|
||||
[2] = 10,
|
||||
[3] = 32,
|
||||
[4] = 31,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
["name"] = "CAP",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
["unitType"] = "FW-190D9",
|
||||
}
|
||||
return unitPayloads
|
||||
49
resources/customized_payloads/Ju-88A4.lua
Normal file
49
resources/customized_payloads/Ju-88A4.lua
Normal file
@@ -0,0 +1,49 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "Ju-88A4",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{LTF_5B}",
|
||||
["num"] = 1,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{LTF_5B}",
|
||||
["num"] = 3,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 32,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 32,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 32,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
["name"] = "CAP",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 32,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
["unitType"] = "Ju-88A4",
|
||||
}
|
||||
return unitPayloads
|
||||
141
resources/customized_payloads/P-51D-30-NA.lua
Normal file
141
resources/customized_payloads/P-51D-30-NA.lua
Normal file
@@ -0,0 +1,141 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "P-51D-30-NA",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 10,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 8,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
[2] = 32,
|
||||
[3] = 30,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 10,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 8,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
[2] = 32,
|
||||
[3] = 30,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "CAP",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 10,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 8,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
[2] = 32,
|
||||
[3] = 30,
|
||||
},
|
||||
},
|
||||
},
|
||||
["unitType"] = "P-51D-30-NA",
|
||||
}
|
||||
return unitPayloads
|
||||
133
resources/customized_payloads/P-51D.lua
Normal file
133
resources/customized_payloads/P-51D.lua
Normal file
@@ -0,0 +1,133 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "P-51D",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 10,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 8,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
[2] = 32,
|
||||
[3] = 30,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 10,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 8,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
[2] = 32,
|
||||
[3] = 30,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 10,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 8,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{AN-M64}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{HVAR}",
|
||||
["num"] = 1,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
[2] = 32,
|
||||
[3] = 30,
|
||||
},
|
||||
},
|
||||
},
|
||||
["unitType"] = "P-51D",
|
||||
}
|
||||
return unitPayloads
|
||||
77
resources/customized_payloads/SpitfireLFMkIX.lua
Normal file
77
resources/customized_payloads/SpitfireLFMkIX.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "SpitfireLFMkIX",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "CAP",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "British_GP_500LBS_Bomb_MK4_on_British_UniversalBC_MK3",
|
||||
["num"] = 2,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_LH_Spitfire_Wing_Carrier",
|
||||
["num"] = 1,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_RH_Spitfire_Wing_Carrier",
|
||||
["num"] = 3,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "British_GP_500LBS_Bomb_MK4_on_British_UniversalBC_MK3",
|
||||
["num"] = 2,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_LH_Spitfire_Wing_Carrier",
|
||||
["num"] = 1,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_RH_Spitfire_Wing_Carrier",
|
||||
["num"] = 3,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "British_GP_500LBS_Bomb_MK4_on_British_UniversalBC_MK3",
|
||||
["num"] = 2,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_LH_Spitfire_Wing_Carrier",
|
||||
["num"] = 1,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_RH_Spitfire_Wing_Carrier",
|
||||
["num"] = 3,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
["unitType"] = "SpitfireLFMkIX",
|
||||
}
|
||||
return unitPayloads
|
||||
77
resources/customized_payloads/SpitfireLFMkIXCW.lua
Normal file
77
resources/customized_payloads/SpitfireLFMkIXCW.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
local unitPayloads = {
|
||||
["name"] = "SpitfireLFMkIXCW",
|
||||
["payloads"] = {
|
||||
[1] = {
|
||||
["name"] = "CAP",
|
||||
["pylons"] = {
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
["name"] = "CAS",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_RH_Spitfire_Wing_Carrier",
|
||||
["num"] = 3,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_LH_Spitfire_Wing_Carrier",
|
||||
["num"] = 1,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "British_GP_500LBS_Bomb_MK4_on_British_UniversalBC_MK3",
|
||||
["num"] = 2,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
["name"] = "STRIKE",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_RH_Spitfire_Wing_Carrier",
|
||||
["num"] = 3,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_LH_Spitfire_Wing_Carrier",
|
||||
["num"] = 1,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "British_GP_500LBS_Bomb_MK4_on_British_UniversalBC_MK3",
|
||||
["num"] = 2,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
["name"] = "ANTISHIP",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_RH_Spitfire_Wing_Carrier",
|
||||
["num"] = 3,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "British_GP_250LBS_Bomb_MK4_on_LH_Spitfire_Wing_Carrier",
|
||||
["num"] = 1,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "British_GP_500LBS_Bomb_MK4_on_British_UniversalBC_MK3",
|
||||
["num"] = 2,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 31,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
["unitType"] = "SpitfireLFMkIXCW",
|
||||
}
|
||||
return unitPayloads
|
||||
Binary file not shown.
@@ -9,7 +9,7 @@ dcs.planes.FlyingType.payload_dirs = [os.path.join(os.path.dirname(os.path.realp
|
||||
|
||||
mis = dcs.Mission(dcs.terrain.PersianGulf())
|
||||
pos = dcs.terrain.PersianGulf().khasab().position
|
||||
airgen = AircraftConflictGenerator(mis, None, None)
|
||||
airgen = AircraftConflictGenerator(mis, None, None, None)
|
||||
|
||||
for t, uts in db.UNIT_BY_TASK.items():
|
||||
if t != dcs.task.CAP and t != dcs.task.CAS:
|
||||
|
||||
@@ -73,11 +73,6 @@ class CaucasusTheater(ConflictTheater):
|
||||
self.carrier_1.captured = True
|
||||
self.batumi.captured = True
|
||||
|
||||
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
|
||||
point.name = " ".join(re.split(r"[ -]", point.name)[:1])
|
||||
|
||||
super(CaucasusTheater, self).add_controlpoint(point, connected_to=connected_to)
|
||||
|
||||
|
||||
"""
|
||||
A smaller version of the caucasus map in western georgia.
|
||||
@@ -160,4 +155,51 @@ class WesternGeorgiaInverted(ConflictTheater):
|
||||
self.add_controlpoint(self.carrier_1)
|
||||
|
||||
self.carrier_1.captured = True
|
||||
self.sochi.captured = True
|
||||
self.sochi.captured = True
|
||||
|
||||
|
||||
|
||||
|
||||
class NorthCaucasus(ConflictTheater):
|
||||
terrain = caucasus.Caucasus()
|
||||
overview_image = "caumap.gif"
|
||||
reference_points = {(-317948.32727306, 635639.37385346): (278.5*4, 319*4),
|
||||
(-355692.3067714, 617269.96285781): (263*4, 352*4), }
|
||||
|
||||
landmap = load_landmap("resources\\caulandmap.p")
|
||||
daytime_map = {
|
||||
"dawn": (6, 9),
|
||||
"day": (9, 18),
|
||||
"dusk": (18, 20),
|
||||
"night": (0, 5),
|
||||
}
|
||||
|
||||
carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-305810.6875, 406399.1875))
|
||||
|
||||
def __init__(self, load_ground_objects=True):
|
||||
super(NorthCaucasus, self).__init__()
|
||||
|
||||
self.kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, LAND, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
self.soganlug = ControlPoint.from_airport(caucasus.Soganlug, LAND, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
self.maykop = ControlPoint.from_airport(caucasus.Maykop_Khanskaya, LAND, SIZE_LARGE, IMPORTANCE_HIGH)
|
||||
self.beslan = ControlPoint.from_airport(caucasus.Beslan, LAND, SIZE_REGULAR, IMPORTANCE_LOW)
|
||||
self.nalchik = ControlPoint.from_airport(caucasus.Nalchik, LAND, SIZE_REGULAR, 1.1)
|
||||
self.mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, LAND, SIZE_BIG, 1.3)
|
||||
self.mozdok = ControlPoint.from_airport(caucasus.Mozdok, LAND, SIZE_BIG, 1.1)
|
||||
self.carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-285810.6875, 496399.1875))
|
||||
|
||||
self.soganlug.frontline_offset = 0.5
|
||||
self.soganlug.base.strength = 1
|
||||
|
||||
self.add_controlpoint(self.kutaisi, connected_to=[self.soganlug])
|
||||
self.add_controlpoint(self.soganlug, connected_to=[self.beslan, self.kutaisi])
|
||||
self.add_controlpoint(self.beslan, connected_to=[self.soganlug, self.mozdok, self.nalchik])
|
||||
self.add_controlpoint(self.nalchik, connected_to=[self.beslan, self.mozdok, self.mineralnye])
|
||||
self.add_controlpoint(self.mozdok, connected_to=[self.nalchik, self.beslan, self.mineralnye])
|
||||
self.add_controlpoint(self.mineralnye, connected_to=[self.nalchik, self.mozdok, self.maykop])
|
||||
self.add_controlpoint(self.maykop, connected_to=[self.mineralnye])
|
||||
self.add_controlpoint(self.carrier_1, connected_to=[])
|
||||
|
||||
self.carrier_1.captured = True
|
||||
self.soganlug.captured = True
|
||||
self.kutaisi.captured = True
|
||||
|
||||
@@ -72,6 +72,14 @@ class ConflictTheater:
|
||||
|
||||
self.controlpoints.append(point)
|
||||
|
||||
def find_ground_objects_by_obj_name(self, obj_name):
|
||||
found = []
|
||||
for cp in self.controlpoints:
|
||||
for g in cp.ground_objects:
|
||||
if g.obj_name == obj_name:
|
||||
found.append(g)
|
||||
return found
|
||||
|
||||
def is_in_sea(self, point: Point) -> bool:
|
||||
if not self.landmap:
|
||||
return False
|
||||
|
||||
@@ -27,6 +27,7 @@ class ControlPoint:
|
||||
full_name = None # type: str
|
||||
base = None # type: theater.base.Base
|
||||
at = None # type: db.StartPosition
|
||||
icls = 1
|
||||
|
||||
connected_points = None # type: typing.List[ControlPoint]
|
||||
ground_objects = None # type: typing.List[TheaterGroundObject]
|
||||
@@ -36,6 +37,8 @@ class ControlPoint:
|
||||
frontline_offset = 0.0
|
||||
cptype: ControlPointType = None
|
||||
|
||||
ICLS_counter = 1
|
||||
|
||||
def __init__(self, id: int, name: str, position: Point, at, radials: typing.Collection[int], size: int, importance: float,
|
||||
has_frontline=True, cptype=ControlPointType.AIRBASE):
|
||||
import theater.base
|
||||
@@ -60,6 +63,7 @@ class ControlPoint:
|
||||
self.tacanY = False
|
||||
self.tacanN = None
|
||||
self.tacanI = "TAC"
|
||||
self.icls = 0
|
||||
|
||||
@classmethod
|
||||
def from_airport(cls, airport: Airport, radials: typing.Collection[int], size: int, importance: float, has_frontline=True):
|
||||
@@ -74,6 +78,8 @@ class ControlPoint:
|
||||
cp.tacanY = random.choice([True, False])
|
||||
cp.tacanN = random.randint(26, 49)
|
||||
cp.tacanI = random.choice(["STE", "CVN", "CVH", "CCV", "ACC", "ARC", "GER", "ABR", "LIN", "TRU"])
|
||||
ControlPoint.ICLS_counter = ControlPoint.ICLS_counter + 1
|
||||
cp.icls = ControlPoint.ICLS_counter
|
||||
return cp
|
||||
|
||||
@classmethod
|
||||
@@ -170,3 +176,10 @@ class ControlPoint:
|
||||
|
||||
return closest_radial
|
||||
|
||||
def find_ground_objects_by_obj_name(self, obj_name):
|
||||
found = []
|
||||
for g in self.ground_objects:
|
||||
if g.obj_name == obj_name:
|
||||
found.append(g)
|
||||
return found
|
||||
|
||||
|
||||
@@ -112,11 +112,15 @@ def generate_groundobjects(theater: ConflictTheater, game):
|
||||
if "lhanames" in db.FACTIONS[faction]:
|
||||
cp.name = random.choice(db.FACTIONS[faction]["lhanames"])
|
||||
else:
|
||||
|
||||
for i in range(random.randint(2,6)):
|
||||
point = find_location(True, cp.position, theater, 1000, 2800, [])
|
||||
|
||||
print("GENERATE BASE DEFENSE")
|
||||
point = find_location(True, cp.position, theater, 1000, 2800, [], True)
|
||||
print(point)
|
||||
|
||||
if point is None:
|
||||
print("Couldn't find point for {}".format(cp))
|
||||
print("Couldn't find point for {} base defense".format(cp))
|
||||
continue
|
||||
|
||||
group_id = group_id + 1
|
||||
@@ -131,18 +135,7 @@ def generate_groundobjects(theater: ConflictTheater, game):
|
||||
g.heading = 0
|
||||
g.position = Point(point.x, point.y)
|
||||
|
||||
if i == 0:
|
||||
group = generate_armor_group(faction, game, g)
|
||||
elif i == 1 and random.randint(0,1) == 0:
|
||||
group = generate_anti_air_group(game, cp, g, faction)
|
||||
elif random.randint(0, 2) == 1:
|
||||
group = generate_shorad_group(game, cp, g, faction)
|
||||
else:
|
||||
group = generate_armor_group(faction, game, g)
|
||||
|
||||
g.groups = []
|
||||
if group is not None:
|
||||
g.groups.append(group)
|
||||
generate_airbase_defense_group(i, g, faction, game, cp)
|
||||
cp.ground_objects.append(g)
|
||||
|
||||
print("---------------------------")
|
||||
@@ -151,7 +144,27 @@ def generate_groundobjects(theater: ConflictTheater, game):
|
||||
print(ground_object.groups)
|
||||
|
||||
|
||||
def find_location(on_ground, near, theater, min, max, others) -> typing.Optional[Point]:
|
||||
def generate_airbase_defense_group(airbase_defense_group_id, ground_obj:TheaterGroundObject, faction, game, cp):
|
||||
|
||||
print("GENERATE AIR DEFENSE GROUP")
|
||||
print(faction)
|
||||
print(airbase_defense_group_id)
|
||||
|
||||
if airbase_defense_group_id == 0:
|
||||
group = generate_armor_group(faction, game, ground_obj)
|
||||
elif airbase_defense_group_id == 1 and random.randint(0, 1) == 0:
|
||||
group = generate_anti_air_group(game, cp, ground_obj, faction)
|
||||
elif random.randint(0, 2) == 1:
|
||||
group = generate_shorad_group(game, cp, ground_obj, faction)
|
||||
else:
|
||||
group = generate_armor_group(faction, game, ground_obj)
|
||||
|
||||
ground_obj.groups = []
|
||||
if group is not None:
|
||||
ground_obj.groups.append(group)
|
||||
|
||||
|
||||
def find_location(on_ground, near, theater, min, max, others, is_base_defense=False) -> typing.Optional[Point]:
|
||||
"""
|
||||
Find a valid ground object location
|
||||
:param on_ground: Whether it should be on ground or on sea (True = on ground)
|
||||
@@ -163,7 +176,7 @@ def find_location(on_ground, near, theater, min, max, others) -> typing.Optional
|
||||
:return:
|
||||
"""
|
||||
point = None
|
||||
for _ in range(1000):
|
||||
for _ in range(300):
|
||||
|
||||
# Check if on land or sea
|
||||
p = near.random_point_within(max, min)
|
||||
@@ -189,6 +202,7 @@ def find_location(on_ground, near, theater, min, max, others) -> typing.Optional
|
||||
|
||||
if point:
|
||||
for other in theater.controlpoints:
|
||||
if is_base_defense: break
|
||||
if other.position != near:
|
||||
if point is None:
|
||||
break
|
||||
@@ -254,7 +268,7 @@ def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templat
|
||||
g.group_id = group_id
|
||||
g.object_id = object_id
|
||||
g.cp_id = cp.id
|
||||
g.airbase_gorup = False
|
||||
g.airbase_group = False
|
||||
g.obj_name = obj_name
|
||||
|
||||
g.dcs_identifier = object["type"]
|
||||
|
||||
@@ -46,4 +46,4 @@ else:
|
||||
logging.basicConfig(stream=log_stream, level=logging.INFO)
|
||||
Tk.report_callback_exception = _handle_exception
|
||||
|
||||
logging.info("DCS Libration {}".format(_version_string))
|
||||
logging.info("DCS Liberation {}".format(_version_string))
|
||||
|
||||
@@ -46,7 +46,12 @@ def restore_game():
|
||||
return None
|
||||
|
||||
with open(_save_file(), "rb") as f:
|
||||
return pickle.load(f)
|
||||
try:
|
||||
save = pickle.load(f)
|
||||
return save
|
||||
except:
|
||||
print("Invalid Save game")
|
||||
return None
|
||||
|
||||
|
||||
def save_game(game) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user