Compare commits

...

26 Commits

Author SHA1 Message Date
Khopa
a022f9c2e1 Changelog update 2020-06-01 15:27:45 +02:00
Khopa
5adb25a695 Using late activation trigger. Planned flight will not spawn if their home base has been captured or is contested. 2020-06-01 15:11:38 +02:00
Khopa
08c2972cf9 Added map theater : North Caucasus 2020-06-01 14:20:43 +02:00
Khopa
8132c7e676 Fix : CAP aircraft will jettison fuel tanks. 2020-06-01 13:03:35 +02:00
Khopa
8c68c9f703 Fix for payload for release versions. 2020-06-01 12:51:59 +02:00
Khopa
000b6142fd Added Ka-50 to bluefor modern. 2020-06-01 12:42:02 +02:00
Khopa
c203ded1cd Improved Mission Planning flight selection behaviour. 2020-06-01 12:36:10 +02:00
Khopa
64c5c39b2a BARCAP renamed CAP for regular airbases. 2020-06-01 11:14:30 +02:00
Khopa
a8d2a1e371 Removed Ju-88 from CAS (only has torpedo in DCS) 2020-06-01 01:49:20 +02:00
Khopa
9e5846b24a Improved WW2 support. 2020-06-01 01:27:16 +02:00
Khopa
836ff9122c Fix base defense units not being generated when other ground objects were too close. 2020-06-01 00:35:26 +02:00
Khopa
75d836358b Revert an error on sam site generation. (Disabled the wrong code.) 2020-06-01 00:05:32 +02:00
Khopa
bb11e7f90c Removed FARP AA that does not respect the factions config. 2020-05-31 23:58:43 +02:00
Khopa
cf6a71ab86 Fix issue when "no night mission" is enabled. 2020-05-31 23:50:13 +02:00
Khopa
7f7288937d Handle error when there is no AWACS for a faction. 2020-05-31 23:26:03 +02:00
Khopa
a38f9c2183 Added performance settings. 2020-05-31 23:07:54 +02:00
Khopa
7ee880cadc Generate ICLS command for carriers 2020-05-31 20:00:07 +02:00
Khopa
9ae34d474b Added Bluefor modern faction 2020-05-31 19:44:53 +02:00
Khopa
2817e2f2c8 Update for new pyDCS version. Supercarrier support added. 2020-05-31 19:19:03 +02:00
Khopa
02886a09d3 AI Strike flight with user generated STRIKE, will now perform their bombing task correctly. 2020-05-31 18:02:00 +02:00
Khopa
0b9d827ad6 AI Strike flight will bomb all their targets correctly 2020-05-31 15:43:56 +02:00
Khopa
ab3ea84d70 AI flight planner now auto generate STRIKE flights.
Fix CAS point position in predefined wpt selector.
When an airbase is captured, base defenses are re-generated for the new base owner.
2020-05-30 02:32:45 +02:00
Khopa
03a1c44659 README update for QT UI branch 2020-05-30 00:03:42 +02:00
Khopa
53364444fd Possible fix for crash when loading old save files. 2020-05-30 00:03:11 +02:00
Khopa
94040e8551 Fix new campaign wizard crashing and made the campaign generator slightly faster. 2020-05-29 23:47:13 +02:00
Khopa
34d46ee28e Fix objective name error when no more objective name are availables. 2020-05-29 23:43:26 +02:00
52 changed files with 1433 additions and 499 deletions

View File

@@ -1,26 +1,12 @@
![Logo](https://i.imgur.com/c2k18E1.png)
[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
View 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)

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -46,6 +46,7 @@ USA_1990 = {
LHA_1_Tarawa,
], "destroyer": [
Oliver_Hazzard_Perry_class,
USS_Arleigh_Burke_IIa,
], "cruiser": [
Ticonderoga_class,
], "carrier_names": [

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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