Merge remote-tracking branch 'remotes/dcs-retribution/dcs-retribution/dev' into pretense-generator

This commit is contained in:
MetalStormGhost
2024-05-26 22:06:19 +03:00
110 changed files with 2777 additions and 221 deletions

View File

@@ -56,7 +56,7 @@ class MizCampaignLoader:
OFFSHORE_STRIKE_TARGET_UNIT_TYPE = Fortification.Oil_platform.id
SHIP_UNIT_TYPE = USS_Arleigh_Burke_IIa.id
MISSILE_SITE_UNIT_TYPE = MissilesSS.Scud_B.id
COASTAL_DEFENSE_UNIT_TYPE = MissilesSS.Hy_launcher.id
COASTAL_DEFENSE_UNIT_TYPE = MissilesSS.hy_launcher.id
COMMAND_CENTER_UNIT_TYPE = Fortification._Command_Center.id
CONNECTION_NODE_UNIT_TYPE = Fortification.Comms_tower_M.id
@@ -73,23 +73,23 @@ class MizCampaignLoader:
MEDIUM_RANGE_SAM_UNIT_TYPES = {
AirDefence.Hawk_ln.id,
AirDefence.S_75M_Volhov.id,
AirDefence.X_5p73_s_125_ln.id,
AirDefence.x_5p73_s_125_ln.id,
}
SHORT_RANGE_SAM_UNIT_TYPES = {
AirDefence.M1097_Avenger.id,
AirDefence.Rapier_fsa_launcher.id,
AirDefence.X_2S6_Tunguska.id,
AirDefence.rapier_fsa_launcher.id,
AirDefence.x_2S6_Tunguska.id,
AirDefence.Strela_1_9P31.id,
}
AAA_UNIT_TYPES = {
AirDefence.Flak18.id,
AirDefence.flak18.id,
AirDefence.Vulcan.id,
AirDefence.ZSU_23_4_Shilka.id,
}
EWR_UNIT_TYPE = AirDefence.X_1L13_EWR.id
EWR_UNIT_TYPE = AirDefence.x_1L13_EWR.id
ARMOR_GROUP_UNIT_TYPE = Armor.M_1_Abrams.id

View File

@@ -5,8 +5,8 @@ from game.theater.theatergroup import TheaterUnit
class AlicCodes:
CODES = {
AirDefence.X_1L13_EWR.id: 101,
AirDefence.X_55G6_EWR.id: 102,
AirDefence.x_1L13_EWR.id: 101,
AirDefence.x_55G6_EWR.id: 102,
AirDefence.S_300PS_40B6MD_sr.id: 103,
AirDefence.S_300PS_64H6E_sr.id: 104,
AirDefence.SA_11_Buk_SR_9S18M1.id: 107,
@@ -17,12 +17,12 @@ class AlicCodes:
AirDefence.Osa_9A33_ln.id: 117,
AirDefence.Strela_10M3.id: 118,
AirDefence.Tor_9A331.id: 119,
AirDefence.X_2S6_Tunguska.id: 120,
AirDefence.x_2S6_Tunguska.id: 120,
AirDefence.ZSU_23_4_Shilka.id: 121,
AirDefence.P_19_s_125_sr.id: 122,
AirDefence.Snr_s_125_tr.id: 123,
AirDefence.Rapier_fsa_blindfire_radar.id: 124,
AirDefence.Rapier_fsa_launcher.id: 125,
AirDefence.p_19_s_125_sr.id: 122,
AirDefence.snr_s_125_tr.id: 123,
AirDefence.rapier_fsa_blindfire_radar.id: 124,
AirDefence.rapier_fsa_launcher.id: 125,
AirDefence.SNR_75V.id: 126,
AirDefence.HQ_7_LN_SP.id: 127,
AirDefence.HQ_7_STR_SP.id: 128,

View File

@@ -26,7 +26,7 @@ from dcs.vehicles import AirDefence
from pydcs_extensions import highdigitsams as hds
TELARS = {
AirDefence.X_2S6_Tunguska,
AirDefence.x_2S6_Tunguska,
AirDefence.SA_11_Buk_LN_9A310M1,
AirDefence.Osa_9A33_ln,
AirDefence.Tor_9A331,
@@ -36,14 +36,14 @@ TELARS = {
TRACK_RADARS = {
AirDefence.Kub_1S91_str,
AirDefence.Snr_s_125_tr,
AirDefence.snr_s_125_tr,
AirDefence.S_300PS_40B6M_tr,
AirDefence.S_300PS_5H63C_30H6_tr,
AirDefence.Hawk_tr,
AirDefence.Patriot_str,
AirDefence.SNR_75V,
AirDefence.RPC_5N62V,
AirDefence.Rapier_fsa_blindfire_radar,
AirDefence.rapier_fsa_blindfire_radar,
AirDefence.HQ_7_STR_SP,
AirDefence.NASAMS_Radar_MPQ64F1,
hds.SAM_SA_10B_S_300PS_30N6_TR,
@@ -55,7 +55,7 @@ TRACK_RADARS = {
LAUNCHER_TRACKER_PAIRS = {
AirDefence.Kub_2P25_ln: (AirDefence.Kub_1S91_str,),
AirDefence.X_5p73_s_125_ln: (AirDefence.Snr_s_125_tr,),
AirDefence.x_5p73_s_125_ln: (AirDefence.snr_s_125_tr,),
AirDefence.S_300PS_5P85C_ln: (
AirDefence.S_300PS_40B6M_tr,
AirDefence.S_300PS_5H63C_30H6_tr,
@@ -67,14 +67,14 @@ LAUNCHER_TRACKER_PAIRS = {
AirDefence.Hawk_ln: (AirDefence.Hawk_tr,),
AirDefence.Patriot_ln: (AirDefence.Patriot_str,),
AirDefence.S_75M_Volhov: (AirDefence.SNR_75V,),
AirDefence.Rapier_fsa_launcher: (AirDefence.Rapier_fsa_blindfire_radar,),
AirDefence.rapier_fsa_launcher: (AirDefence.rapier_fsa_blindfire_radar,),
AirDefence.HQ_7_LN_SP: (AirDefence.HQ_7_STR_SP,),
AirDefence.S_200_Launcher: (AirDefence.RPC_5N62V,),
AirDefence.NASAMS_LN_B: (AirDefence.NASAMS_Radar_MPQ64F1,),
AirDefence.NASAMS_LN_C: (AirDefence.NASAMS_Radar_MPQ64F1,),
hds.SAM_SA_2__V759__LN_SM_90: (AirDefence.SNR_75V,),
hds.SAM_HQ_2_LN_SM_90: (AirDefence.SNR_75V,),
hds.SAM_SA_3__V_601P__LN_5P73: (AirDefence.Snr_s_125_tr,),
hds.SAM_SA_3__V_601P__LN_5P73: (AirDefence.snr_s_125_tr,),
hds.SAM_SA_10B_S_300PS_5P85SE_LN: (hds.SAM_SA_10B_S_300PS_30N6_TR,),
hds.SAM_SA_10B_S_300PS_5P85SU_LN: (hds.SAM_SA_10B_S_300PS_30N6_TR,),
hds.SAM_SA_12_S_300V_9A82_LN: (hds.SAM_SA_12_S_300V_9S32_TR,),
@@ -88,7 +88,7 @@ LAUNCHER_TRACKER_PAIRS = {
UNITS_WITH_RADAR = {
# Radars
AirDefence.X_2S6_Tunguska,
AirDefence.x_2S6_Tunguska,
AirDefence.SA_11_Buk_LN_9A310M1,
AirDefence.Osa_9A33_ln,
AirDefence.Tor_9A331,
@@ -96,11 +96,11 @@ UNITS_WITH_RADAR = {
AirDefence.Vulcan,
AirDefence.Roland_ADS,
AirDefence.ZSU_23_4_Shilka,
AirDefence.X_1L13_EWR,
AirDefence.x_1L13_EWR,
AirDefence.Kub_1S91_str,
AirDefence.S_300PS_40B6M_tr,
AirDefence.S_300PS_40B6MD_sr,
AirDefence.X_55G6_EWR,
AirDefence.x_55G6_EWR,
AirDefence.S_300PS_64H6E_sr,
AirDefence.SA_11_Buk_SR_9S18M1,
AirDefence.Dog_Ear_radar,
@@ -108,13 +108,13 @@ UNITS_WITH_RADAR = {
AirDefence.Hawk_sr,
AirDefence.Patriot_str,
AirDefence.Hawk_cwar,
AirDefence.P_19_s_125_sr,
AirDefence.p_19_s_125_sr,
AirDefence.Roland_Radar,
AirDefence.Snr_s_125_tr,
AirDefence.snr_s_125_tr,
AirDefence.SNR_75V,
AirDefence.RLS_19J6,
AirDefence.RPC_5N62V,
AirDefence.Rapier_fsa_blindfire_radar,
AirDefence.rapier_fsa_blindfire_radar,
AirDefence.HQ_7_LN_SP,
AirDefence.HQ_7_STR_SP,
AirDefence.FuMG_401,

View File

@@ -397,6 +397,9 @@ class Faction:
if not mod_settings.f105_thunderchief:
self.remove_aircraft("VSN_F105D")
self.remove_aircraft("VSN_F105G")
if not mod_settings.f106_deltadart:
self.remove_aircraft("VSN_F106A")
self.remove_aircraft("VSN_F106B")
if not mod_settings.a6a_intruder:
self.remove_aircraft("VSN_A6A")
if not mod_settings.jas39_gripen:

View File

@@ -33,7 +33,7 @@ from typing import Dict, Iterator, List, Optional, TYPE_CHECKING, Tuple
from PIL import Image, ImageDraw, ImageFont
from dcs.mission import Mission
from dcs.planes import F_15ESE
from suntime import Sun # type: ignore
from suntime import Sun, SunTimeException # type: ignore
from tabulate import tabulate
from game.ato.flighttype import FlightType
@@ -445,14 +445,23 @@ class BriefingPage(KneeboardPage):
tz = fl.squadron.coalition.game.theater.timezone
# Get today's sunrise and sunset in UTC
sr_utc = sun.get_sunrise_time(dt)
ss_utc = sun.get_sunset_time(dt)
sr = sr_utc + tz.utcoffset(sun.get_sunrise_time(dt))
ss = ss_utc + tz.utcoffset(sun.get_sunset_time(dt))
try:
rise_utc = sun.get_sunrise_time(dt)
rise = rise_utc + tz.utcoffset(sun.get_sunrise_time(dt))
except SunTimeException:
rise_utc = None
rise = None
try:
set_utc = sun.get_sunset_time(dt)
sunset = set_utc + tz.utcoffset(sun.get_sunset_time(dt))
except SunTimeException:
set_utc = None
sunset = None
writer.text(
f"Sunrise - Sunset: {sr.strftime('%H:%M')} - {ss.strftime('%H:%M')}"
f" ({sr_utc.strftime('%H:%M')} - {ss_utc.strftime('%H:%M')} UTC)"
f"Sunrise - Sunset: {rise.strftime('%H:%M') if rise else 'N/A'} - {sunset.strftime('%H:%M') if sunset else 'N/A'}"
f" ({rise_utc.strftime('%H:%M') if rise_utc else 'N/A'} - {set_utc.strftime('%H:%M') if set_utc else 'N/A'} UTC)"
)
if fl.bingo_fuel and fl.joker_fuel:

View File

@@ -74,6 +74,26 @@ class MigrationUnpickler(pickle.Unpickler):
return ELM2084_MMR_AD_RT
elif name == "IRON_DOME_CP":
return Iron_Dome_David_Sling_CP
if module == "dcs.terrain.kola.airports":
if name == "Lakselv":
from dcs.terrain.kola.airports import Banak
return Banak
elif name == "Severomorsk1":
from dcs.terrain.kola.airports import Severomorsk_1
return Severomorsk_1
elif name == "Severomorsk3":
from dcs.terrain.kola.airports import Severomorsk_3
return Severomorsk_3
elif name == "Olenegorsk":
from dcs.terrain.kola.airports import Olenya
return Olenya
if module in ["dcs.vehicles", "dcs.ships"]:
try:
return super().find_class(module, name)
except AttributeError:
alternate = name.split('.')[:-1] + [name.split('.')[-1][0].lower() + name.split('.')[-1][1:]]
name = '.'.join(alternate)
print(name)
return super().find_class(module, name)
# fmt: on

View File

@@ -305,7 +305,7 @@ class Settings:
section=GENERAL_SECTION,
default=True,
detail=(
"Automatically swaps ATFLIR to LITENING pod for newly generated land-based F-18 flights "
"Automatically swaps ATFLIR to LITENING pod for newly generated land-based F/A-18 flights "
"without having to change the payload. <u>Takes effect after current turn!</u>"
),
)
@@ -327,7 +327,7 @@ class Settings:
)
# Doctrine Distances Section
airbase_threat_range: int = bounded_int_option(
"Airbase threat range (nmi)",
"Airbase threat range (NM)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=DOCTRINE_DISTANCES_SECTION,
default=100,
@@ -339,7 +339,7 @@ class Settings:
),
)
cas_engagement_range_distance: int = bounded_int_option(
"CAS engagement range (nmi)",
"CAS engagement range (NM)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=DOCTRINE_DISTANCES_SECTION,
default=10,
@@ -347,7 +347,7 @@ class Settings:
max=100,
)
sead_sweep_engagement_range_distance: int = bounded_int_option(
"SEAD Sweep engagement range (nmi)",
"SEAD Sweep engagement range (NM)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=DOCTRINE_DISTANCES_SECTION,
default=30,
@@ -355,7 +355,7 @@ class Settings:
max=100,
)
sead_threat_buffer_min_distance: int = bounded_int_option(
"SEAD Escort/Sweep threat buffer distance (nmi)",
"SEAD Escort/Sweep threat buffer distance (NM)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=DOCTRINE_DISTANCES_SECTION,
default=5,
@@ -366,7 +366,7 @@ class Settings:
),
)
tarcap_threat_buffer_min_distance: int = bounded_int_option(
"TARCAP threat buffer distance (nmi)",
"TARCAP threat buffer distance (NM)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=DOCTRINE_DISTANCES_SECTION,
default=20,
@@ -375,7 +375,7 @@ class Settings:
detail=("How close to known threats will the TARCAP racetrack extend."),
)
aewc_threat_buffer_min_distance: int = bounded_int_option(
"AEW&C threat buffer distance (nmi)",
"AEW&C threat buffer distance (NM)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=DOCTRINE_DISTANCES_SECTION,
default=80,
@@ -387,7 +387,7 @@ class Settings:
),
)
tanker_threat_buffer_min_distance: int = bounded_int_option(
"Theater tanker threat buffer distance (nmi)",
"Theater tanker threat buffer distance (NM)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=DOCTRINE_DISTANCES_SECTION,
default=70,
@@ -547,7 +547,7 @@ class Settings:
default=True,
)
auto_procurement_balance: int = bounded_int_option(
"AI ground unit procurement budget ratio (%) for BLUE",
"AI ground unit procurement budget ratio (%) for OWNFOR",
CAMPAIGN_MANAGEMENT_PAGE,
HQ_AUTOMATION_SECTION,
min=0,
@@ -560,7 +560,7 @@ class Settings:
),
)
frontline_reserves_factor: int = bounded_int_option(
"AI ground unit front-line reserves factor (%) for BLUE",
"AI ground unit front-line reserves factor (%) for OWNFOR",
CAMPAIGN_MANAGEMENT_PAGE,
HQ_AUTOMATION_SECTION,
min=0,
@@ -572,18 +572,18 @@ class Settings:
),
)
reserves_procurement_target: int = bounded_int_option(
"AI ground unit reserves procurement target for BLUE",
"AI ground unit reserves procurement target for OWNFOR",
CAMPAIGN_MANAGEMENT_PAGE,
HQ_AUTOMATION_SECTION,
min=0,
max=1000,
default=10,
detail=(
"The number of units that will be bought as reserves for applicable control points"
"The number of units that will be bought as reserves for applicable control points."
),
)
auto_procurement_balance_red: int = bounded_int_option(
"AI ground unit procurement budget ratio (%) for RED",
"AI ground unit procurement budget ratio (%) for OPFOR",
CAMPAIGN_MANAGEMENT_PAGE,
HQ_AUTOMATION_SECTION,
min=0,
@@ -596,7 +596,7 @@ class Settings:
),
)
frontline_reserves_factor_red: int = bounded_int_option(
"AI ground unit front-line reserves factor (%) for RED",
"AI ground unit front-line reserves factor (%) for OPFOR",
CAMPAIGN_MANAGEMENT_PAGE,
HQ_AUTOMATION_SECTION,
min=0,
@@ -608,14 +608,14 @@ class Settings:
),
)
reserves_procurement_target_red: int = bounded_int_option(
"AI ground unit reserves procurement target for RED",
"AI ground unit reserves procurement target for OPFOR",
CAMPAIGN_MANAGEMENT_PAGE,
HQ_AUTOMATION_SECTION,
min=0,
max=1000,
default=10,
detail=(
"The number of units that will be bought as reserves for applicable control points"
"The number of units that will be bought as reserves for applicable control points."
),
)
@@ -1011,7 +1011,7 @@ class Settings:
default=True,
)
perf_disable_untasked_blufor_aircraft: bool = boolean_option(
"Disable untasked BLUFOR aircraft at airfields",
"Disable untasked OWNFOR aircraft at airfields",
page=MISSION_GENERATOR_PAGE,
section=PERFORMANCE_SECTION,
default=False,

View File

@@ -28,7 +28,7 @@ from uuid import UUID
from dcs.mapping import Point
from dcs.ships import (
Ara_vdm,
ara_vdm,
CVN_71,
CVN_72,
CVN_73,
@@ -39,7 +39,7 @@ from dcs.ships import (
LHA_Tarawa,
Stennis,
Type_071,
Hms_invincible,
hms_invincible,
)
from dcs.terrain.terrain import Airport, ParkingSlot
from dcs.unitgroup import ShipGroup, StaticGroup
@@ -1385,13 +1385,13 @@ class NavalControlPoint(
for group in self.find_main_tgo().groups:
for u in group.units:
if u.alive and u.type in [
Ara_vdm,
ara_vdm,
Forrestal,
Stennis,
LHA_Tarawa,
KUZNECOW,
Type_071,
Hms_invincible,
hms_invincible,
L02,
L52,
L61,

View File

@@ -80,6 +80,7 @@ class ModSettings:
f100_supersabre: bool = False
f104_starfighter: bool = False
f105_thunderchief: bool = False
f106_deltadart: bool = False
hercules: bool = False
irondome: bool = False
uh_60l: bool = False

View File

@@ -4,6 +4,7 @@ import datetime
import logging
import random
from dataclasses import dataclass
from typing import Tuple
from game.settings import Settings, NightMissions
from game.theater import ConflictTheater, SeasonalConditions
@@ -74,11 +75,25 @@ class Conditions:
# time constrained to that. DaytimeMap enforces that we have only whole hour
# ranges for now, so we don't need to worry about accidentally changing the time
# of day by truncating sub-hours.
time = datetime.time(
hour=random.randint(time_range[0].hour, time_range[1].hour)
)
day, hours = Conditions.random_time_progression(day, time_range)
time = datetime.time(hour=hours)
return datetime.datetime.combine(day, time)
@staticmethod
def random_time_progression(
day: datetime.date, time_range: Tuple[datetime.time, datetime.time]
) -> Tuple[datetime.date, int]:
start, end = time_range[0].hour, time_range[1].hour
if start > end:
end += 24
hours = random.randint(start, end)
if hours > 23:
day += datetime.timedelta(days=1.0)
hours %= 24
else:
hours = random.randint(start, end)
return day, hours
@classmethod
def generate_weather(
cls,