mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
new weather, strike objectives placement fixes & tarawa for av8b
This commit is contained in:
parent
6d0f488672
commit
e2306ba0f3
@ -43,7 +43,7 @@ def is_version_compatible(save_version):
|
||||
if current_version_components == save_version_components:
|
||||
return True
|
||||
|
||||
if save_version in ["1.4_rc1", "1.4_rc2", "1.4_rc3", "1.4_rc4", "1.4_rc5"]:
|
||||
if save_version in ["1.4_rc1", "1.4_rc2", "1.4_rc3", "1.4_rc4", "1.4_rc5", "1.4_rc6"]:
|
||||
return False
|
||||
|
||||
if current_version_components[:2] == save_version_components[:2]:
|
||||
|
||||
31
game/db.py
31
game/db.py
@ -76,7 +76,6 @@ PRICES = {
|
||||
S_3B_Tanker: 13,
|
||||
IL_78M: 13,
|
||||
KC_135: 13,
|
||||
KC130: 13,
|
||||
|
||||
A_50: 8,
|
||||
E_3A: 8,
|
||||
@ -110,9 +109,10 @@ PRICES = {
|
||||
# ship
|
||||
CV_1143_5_Admiral_Kuznetsov: 100,
|
||||
CVN_74_John_C__Stennis: 100,
|
||||
LHA_1_Tarawa: 50,
|
||||
|
||||
LHA_1_Tarawa: 30,
|
||||
Bulk_cargo_ship_Yakushev: 10,
|
||||
Armed_speedboat: 10,
|
||||
Dry_cargo_ship_Ivanov: 10,
|
||||
Tanker_Elnya_160: 10,
|
||||
}
|
||||
@ -166,14 +166,13 @@ UNIT_BY_TASK = {
|
||||
An_30M,
|
||||
Yak_40,
|
||||
|
||||
S_3B_Tanker,
|
||||
C_130,
|
||||
],
|
||||
|
||||
Refueling: [
|
||||
IL_78M,
|
||||
KC_135,
|
||||
KC130,
|
||||
S_3B_Tanker,
|
||||
],
|
||||
|
||||
AWACS: [E_3A, A_50, ],
|
||||
@ -198,8 +197,8 @@ UNIT_BY_TASK = {
|
||||
Nothing: [Infantry.Infantry_M4, Infantry.Soldier_AK, ],
|
||||
Embarking: [UH_1H, Mi_8MT, ],
|
||||
|
||||
Carriage: [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov, ],
|
||||
CargoTransportation: [Dry_cargo_ship_Ivanov, Bulk_cargo_ship_Yakushev, Tanker_Elnya_160, LHA_1_Tarawa],
|
||||
Carriage: [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov, ],
|
||||
CargoTransportation: [Dry_cargo_ship_Ivanov, Bulk_cargo_ship_Yakushev, Tanker_Elnya_160, Armed_speedboat, ],
|
||||
}
|
||||
|
||||
"""
|
||||
@ -299,7 +298,6 @@ UNIT_BY_COUNTRY = {
|
||||
AV8BNA,
|
||||
|
||||
KC_135,
|
||||
KC130,
|
||||
S_3B_Tanker,
|
||||
C_130,
|
||||
E_3A,
|
||||
@ -319,9 +317,18 @@ UNIT_BY_COUNTRY = {
|
||||
|
||||
CVN_74_John_C__Stennis,
|
||||
LHA_1_Tarawa,
|
||||
Armed_speedboat,
|
||||
],
|
||||
}
|
||||
|
||||
CARRIER_TYPE_BY_PLANE = {
|
||||
FA_18C_hornet: CVN_74_John_C__Stennis,
|
||||
Ka_50: LHA_1_Tarawa,
|
||||
UH_1H: LHA_1_Tarawa,
|
||||
Mi_8MT: LHA_1_Tarawa,
|
||||
AV8BNA: LHA_1_Tarawa,
|
||||
}
|
||||
|
||||
"""
|
||||
Aircraft payload overrides. Usually default loadout for the task is loaded during the mission generation.
|
||||
Syntax goes as follows:
|
||||
@ -341,6 +348,8 @@ Payload will be used for operation of following type, "*" category will be used
|
||||
PLANE_PAYLOAD_OVERRIDES = {
|
||||
FA_18C_hornet: {
|
||||
CAP: "AIM-120*4,AIM-9*2,AIM-7*2,Fuel",
|
||||
PinpointStrike: "MK-82*8,AIM-9*2,AIM-7,FLIR Pod,Fuel",
|
||||
AntishipStrike: "MK-82*8,AIM-9*2,AIM-7,FLIR Pod,Fuel",
|
||||
},
|
||||
|
||||
Su_25T: {
|
||||
@ -460,6 +469,14 @@ def unitdict_append(unit_dict: UnitsDict, unit_type: UnitType, count: int):
|
||||
unit_dict[unit_type] = unit_dict.get(unit_type, 0) + 1
|
||||
|
||||
|
||||
def unitdict_merge(a: UnitsDict, b: UnitsDict) -> UnitsDict:
|
||||
b = b.copy()
|
||||
for k, v in a.items():
|
||||
b[k] = b.get(k, 0) + v
|
||||
|
||||
return b
|
||||
|
||||
|
||||
def unitdict_split(unit_dict: UnitsDict, count: int):
|
||||
buffer_dict = {}
|
||||
for unit_type, unit_count in unit_dict.items():
|
||||
|
||||
@ -11,7 +11,7 @@ class NavalInterceptEvent(Event):
|
||||
|
||||
def _targets_count(self) -> int:
|
||||
from gen.conflictgen import IMPORTANCE_LOW
|
||||
factor = (self.to_cp.importance - IMPORTANCE_LOW) * 10
|
||||
factor = (self.to_cp.importance - IMPORTANCE_LOW + 0.1) * 20
|
||||
return max(int(factor), 1)
|
||||
|
||||
def __str__(self) -> str:
|
||||
|
||||
@ -39,16 +39,7 @@ class InterceptOperation(Operation):
|
||||
conflict=conflict)
|
||||
|
||||
def generate(self):
|
||||
for global_cp in self.game.theater.controlpoints:
|
||||
if not global_cp.is_global:
|
||||
continue
|
||||
|
||||
ship = self.shipgen.generate_carrier(type=db.find_unittype(Carriage, self.game.player)[0],
|
||||
country=self.game.player,
|
||||
at=global_cp.at)
|
||||
|
||||
if global_cp == self.from_cp and not self.is_quick:
|
||||
self.attackers_starting_position = ship
|
||||
self.prepare_carriers(self.interceptors.keys())
|
||||
|
||||
self.airgen.generate_transport(self.transport, self.to_cp.at)
|
||||
self.airgen.generate_defenders_escort(*assigned_units_split(self.escort), at=self.defenders_starting_position)
|
||||
|
||||
@ -33,6 +33,8 @@ class NavalInterceptionOperation(Operation):
|
||||
self.initialize(self.mission, conflict)
|
||||
|
||||
def generate(self):
|
||||
self.prepare_carriers(db.unitdict_from(self.strikegroup))
|
||||
|
||||
target_groups = self.shipgen.generate_cargo(units=self.targets)
|
||||
|
||||
self.airgen.generate_ship_strikegroup(
|
||||
|
||||
@ -83,6 +83,18 @@ class Operation:
|
||||
self.attackers_starting_position = self.from_cp.at
|
||||
self.defenders_starting_position = self.to_cp.at
|
||||
|
||||
def prepare_carriers(self, for_units: db.UnitsDict):
|
||||
for global_cp in self.game.theater.controlpoints:
|
||||
if not global_cp.is_global:
|
||||
continue
|
||||
|
||||
ship = self.shipgen.generate_carrier(for_units=for_units,
|
||||
country=self.game.player,
|
||||
at=global_cp.at)
|
||||
|
||||
if global_cp == self.from_cp and not self.is_quick:
|
||||
self.attackers_starting_position = ship
|
||||
|
||||
def generate(self):
|
||||
self.visualgen.generate()
|
||||
|
||||
|
||||
@ -35,16 +35,7 @@ class StrikeOperation(Operation):
|
||||
conflict=conflict)
|
||||
|
||||
def generate(self):
|
||||
for global_cp in self.game.theater.controlpoints:
|
||||
if not global_cp.is_global:
|
||||
continue
|
||||
|
||||
ship = self.shipgen.generate_carrier(type=db.find_unittype(Carriage, self.game.player)[0],
|
||||
country=self.game.player,
|
||||
at=global_cp.at)
|
||||
|
||||
if global_cp == self.from_cp and not self.is_quick:
|
||||
self.attackers_starting_position = ship
|
||||
self.prepare_carriers(db.unitdict_merge(db.unitdict_from(self.strikegroup), db.unitdict_from(self.escort)))
|
||||
|
||||
targets = [] # type: typing.List[typing.Tuple[str, str, Point]]
|
||||
category_counters = {} # type: typing.Dict[str, int]
|
||||
|
||||
@ -5,6 +5,7 @@ class Settings:
|
||||
enemy_vehicle_skill = "Average"
|
||||
only_player_takeoff = True
|
||||
night_disabled = False
|
||||
|
||||
multiplier = 1
|
||||
sams = True
|
||||
cold_start = False
|
||||
|
||||
@ -9,11 +9,11 @@ from dcs.task import *
|
||||
from dcs.terrain.terrain import NoParkingSlotError
|
||||
|
||||
TANKER_DISTANCE = 15000
|
||||
TANKER_ALT = 6000
|
||||
TANKER_ALT = 4572
|
||||
TANKER_HEADING_OFFSET = 45
|
||||
|
||||
AWACS_DISTANCE = 150000
|
||||
AWACS_ALT = 15000
|
||||
AWACS_ALT = 13000
|
||||
|
||||
|
||||
class AirSupportConflictGenerator:
|
||||
|
||||
@ -21,6 +21,10 @@ WEATHER_CLOUD_DENSITY = 1, 8
|
||||
WEATHER_CLOUD_THICKNESS = 100, 400
|
||||
WEATHER_CLOUD_BASE_MIN = 1600
|
||||
|
||||
WEATHER_FOG_CHANCE = 20
|
||||
WEATHER_FOG_VISIBILITY = 2500, 5000
|
||||
WEATHER_FOG_THICKNESS = 100, 500
|
||||
|
||||
RANDOM_TIME = {
|
||||
"night": 5,
|
||||
"dusk": 30,
|
||||
@ -29,11 +33,10 @@ RANDOM_TIME = {
|
||||
}
|
||||
|
||||
RANDOM_WEATHER = {
|
||||
1: 0, # heavy rain
|
||||
2: 5, # rain
|
||||
3: 15, # dynamic
|
||||
4: 40, # clear
|
||||
5: 100, # random
|
||||
1: 0, # thunderstorm
|
||||
2: 20, # rain
|
||||
3: 80, # clouds
|
||||
4: 100, # clear
|
||||
}
|
||||
|
||||
|
||||
@ -68,6 +71,29 @@ class EnviromentGenerator:
|
||||
|
||||
self.mission.start_time = start_time
|
||||
|
||||
def _generate_wind(self, wind_speed, wind_direction=None):
|
||||
# wind
|
||||
if not wind_direction:
|
||||
wind_direction = random.randint(0, 360)
|
||||
|
||||
self.mission.weather.wind_at_ground = Wind(wind_direction, wind_speed)
|
||||
self.mission.weather.wind_at_2000 = Wind(wind_direction, wind_speed * 2)
|
||||
self.mission.weather.wind_at_8000 = Wind(wind_direction, wind_speed * 3)
|
||||
|
||||
def _generate_base_weather(self):
|
||||
# clouds
|
||||
self.mission.weather.clouds_base = random.randint(*WEATHER_CLOUD_BASE)
|
||||
self.mission.weather.clouds_density = random.randint(*WEATHER_CLOUD_DENSITY)
|
||||
self.mission.weather.clouds_thickness = random.randint(*WEATHER_CLOUD_THICKNESS)
|
||||
|
||||
# wind
|
||||
self._generate_wind(random.randint(0, 4))
|
||||
|
||||
# fog
|
||||
if random.randint(0, 100) < WEATHER_FOG_CHANCE:
|
||||
self.mission.weather.fog_visibility = random.randint(*WEATHER_FOG_VISIBILITY)
|
||||
self.mission.weather.fog_thickness = random.randint(*WEATHER_FOG_THICKNESS)
|
||||
|
||||
def _gen_random_weather(self):
|
||||
weather_type = None
|
||||
for k, v in RANDOM_WEATHER.items():
|
||||
@ -77,24 +103,25 @@ class EnviromentGenerator:
|
||||
|
||||
logging.info("generated weather {}".format(weather_type))
|
||||
if weather_type == 1:
|
||||
self.mission.weather.heavy_rain()
|
||||
elif weather_type == 2:
|
||||
self.mission.weather.heavy_rain()
|
||||
self.mission.weather.enable_fog = False
|
||||
elif weather_type == 3:
|
||||
self.mission.weather.random(self.mission.start_time, self.conflict.theater.terrain)
|
||||
elif weather_type == 4:
|
||||
pass
|
||||
elif weather_type == 5:
|
||||
self.mission.weather.clouds_base = random.randint(*WEATHER_CLOUD_BASE)
|
||||
self.mission.weather.clouds_density = random.randint(*WEATHER_CLOUD_DENSITY)
|
||||
self.mission.weather.clouds_thickness = random.randint(*WEATHER_CLOUD_THICKNESS)
|
||||
# thunderstorm
|
||||
self._generate_base_weather()
|
||||
self._generate_wind(random.randint(8, 12))
|
||||
|
||||
wind_direction = random.randint(0, 360)
|
||||
wind_speed = random.randint(0, 4)
|
||||
self.mission.weather.wind_at_ground = Wind(wind_direction, wind_speed)
|
||||
self.mission.weather.wind_at_2000 = Wind(wind_direction, wind_speed * 2)
|
||||
self.mission.weather.wind_at_8000 = Wind(wind_direction, wind_speed * 3)
|
||||
self.mission.weather.clouds_density = random.randint(9, 10)
|
||||
self.mission.weather.clouds_iprecptns = Weather.Preceptions.Thunderstorm
|
||||
elif weather_type == 2:
|
||||
# rain
|
||||
self._generate_base_weather()
|
||||
self.mission.weather.clouds_density = random.randint(5, 8)
|
||||
self.mission.weather.clouds_iprecptns = Weather.Preceptions.Rain
|
||||
|
||||
self._generate_wind(random.randint(4, 8))
|
||||
elif weather_type == 3:
|
||||
# clouds
|
||||
self._generate_base_weather()
|
||||
elif weather_type == 4:
|
||||
# clear
|
||||
pass
|
||||
|
||||
if self.mission.weather.clouds_density > 0:
|
||||
# sometimes clouds are randomized way too low and need to be fixed
|
||||
|
||||
@ -16,7 +16,17 @@ class ShipGenerator:
|
||||
self.m = mission
|
||||
self.conflict = conflict
|
||||
|
||||
def generate_carrier(self, type: ShipType, country: str, at: Point) -> ShipGroup:
|
||||
def generate_carrier(self, for_units: db.UnitsDict, country: str, at: Point) -> ShipGroup:
|
||||
type = db.find_unittype(Carriage, country)[0]
|
||||
print(for_units)
|
||||
for unit_type, unit_count in for_units.items():
|
||||
if unit_count == 0:
|
||||
continue
|
||||
|
||||
if unit_type in db.CARRIER_TYPE_BY_PLANE:
|
||||
type = db.CARRIER_TYPE_BY_PLANE[unit_type]
|
||||
break
|
||||
|
||||
group = self.m.ship_group(
|
||||
country=self.m.country(country),
|
||||
name=namegen.next_carrier_name(self.m.country(country)),
|
||||
|
||||
@ -10,9 +10,9 @@ from dcs.task import *
|
||||
from game import db
|
||||
|
||||
STRENGTH_AA_ASSEMBLE_MIN = 0.2
|
||||
PLANES_SCRAMBLE_MIN_BASE = 4
|
||||
PLANES_SCRAMBLE_MIN_BASE = 2
|
||||
PLANES_SCRAMBLE_MAX_BASE = 8
|
||||
PLANES_SCRAMBLE_FACTOR = 0.6
|
||||
PLANES_SCRAMBLE_FACTOR = 0.3
|
||||
|
||||
BASE_MAX_STRENGTH = 1
|
||||
BASE_MIN_STRENGTH = 0
|
||||
|
||||
@ -72,8 +72,8 @@ class PersianGulfTheater(ConflictTheater):
|
||||
self.add_controlpoint(self.havadarya, connected_to=[self.lar, self.qeshm, self.bandar_abbas])
|
||||
self.add_controlpoint(self.bandar_abbas, connected_to=[self.havadarya])
|
||||
|
||||
self.add_controlpoint(self.east_carrier)
|
||||
self.add_controlpoint(self.west_carrier)
|
||||
self.add_controlpoint(self.east_carrier)
|
||||
|
||||
self.west_carrier.captured = True
|
||||
self.east_carrier.captured = True
|
||||
|
||||
@ -2,6 +2,7 @@ import math
|
||||
import pickle
|
||||
import random
|
||||
import typing
|
||||
import logging
|
||||
|
||||
from theater.base import *
|
||||
from theater.conflicttheater import *
|
||||
@ -72,8 +73,8 @@ def generate_groundobjects(theater: ConflictTheater):
|
||||
|
||||
group_id = 0
|
||||
for cp in theater.enemy_points():
|
||||
for _ in range(0, random.randrange(3, 6)):
|
||||
available_categories = list(tpls) + ["aa", "aa", "aa"]
|
||||
for _ in range(0, random.randrange(2, 4)):
|
||||
available_categories = list(tpls) + ["aa", "aa"]
|
||||
tpl_category = random.choice(available_categories)
|
||||
|
||||
tpl = random.choice(list(tpls[tpl_category].values()))
|
||||
@ -84,14 +85,17 @@ def generate_groundobjects(theater: ConflictTheater):
|
||||
print("Couldn't find point for {}".format(cp))
|
||||
continue
|
||||
|
||||
dist = point.distance_to_point(cp.position)
|
||||
"""
|
||||
dist = point.distance_to_point(cp.position) - 15000
|
||||
for another_cp in theater.enemy_points():
|
||||
if another_cp.position.distance_to_point(point) < dist:
|
||||
cp = another_cp
|
||||
"""
|
||||
|
||||
group_id += 1
|
||||
object_id = 0
|
||||
|
||||
logging.info("generated {} for {}".format(tpl_category, cp))
|
||||
for object in tpl:
|
||||
object_id += 1
|
||||
|
||||
|
||||
@ -79,10 +79,14 @@ class ConfigurationMenu(Menu):
|
||||
Label(body, text="Takeoff only for player group", **STYLES["widget"]).grid(row=row, column=0, sticky=W)
|
||||
Checkbutton(body, variable=self.takeoff_var, **STYLES["radiobutton"]).grid(row=row, column=1, sticky=E)
|
||||
row += 1
|
||||
Label(body, text="Only player group will start on the ground. AI units will be circling in the air until player takes off.", **STYLES["widget"]).grid(row=row, column=0, columnspan=2)
|
||||
row += 1
|
||||
|
||||
Label(body, text="Disable night missions", **STYLES["widget"]).grid(row=row, column=0, sticky=W)
|
||||
Checkbutton(body, variable=self.night_var, **STYLES["radiobutton"]).grid(row=row, column=1, sticky=E)
|
||||
row += 1
|
||||
Label(body, text="No night missions. Dawns and dusks will still be present.", **STYLES["widget"]).grid(row=row, column=0, columnspan=2)
|
||||
row += 1
|
||||
|
||||
Button(body, text="Display logs", command=self.display_logs, **STYLES["btn-primary"]).grid(row=row, column=1, sticky=E, pady=30)
|
||||
row += 1
|
||||
|
||||
@ -98,9 +98,6 @@ class NewGameMenu(Menu):
|
||||
Label(terrain, text="Persian Gulf", **STYLES["widget"]).grid(row=2, column=1, sticky=W)
|
||||
self.create_label_image(terrain, "terrain_pg.gif").grid(row=2, column=2, padx=5)
|
||||
|
||||
Label(terrain, text="Currently strike missions are only\navailable for a number of airports only in Caucasus", **STYLES["widget"]) \
|
||||
.grid(row=3, column=0, columnspan=3, sticky=W)
|
||||
|
||||
# Misc Options
|
||||
options = LabelFrame(body, text="Misc Options", **STYLES["label-frame"])
|
||||
options.grid(row=0, column=2, sticky=NE, padx=5)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user