Restored compatibility of the Pretense generator after the timedelta -> datetime change and other changes caused by the Liberation merge/sync.

This commit is contained in:
MetalStormGhost 2023-10-09 20:17:31 +03:00
parent 04c32073aa
commit a3575995bd
5 changed files with 102 additions and 49 deletions

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import random import random
from collections.abc import Iterator from collections.abc import Iterator
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta from datetime import datetime
from typing import TYPE_CHECKING, Type from typing import TYPE_CHECKING, Type
from game.utils import feet from game.utils import feet
@ -31,16 +31,20 @@ class PretenseCargoFlightPlan(StandardFlightPlan[FerryLayout]):
def tot_waypoint(self) -> FlightWaypoint: def tot_waypoint(self) -> FlightWaypoint:
return self.layout.arrival return self.layout.arrival
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: def tot_for_waypoint(self, waypoint: FlightWaypoint) -> datetime | None:
# TOT planning isn't really useful for ferries. They're behind the front # TOT planning isn't really useful for ferries. They're behind the front
# lines so no need to wait for escorts or for other missions to complete. # lines so no need to wait for escorts or for other missions to complete.
return None return None
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> datetime | None:
return None return None
@property @property
def mission_departure_time(self) -> timedelta: def mission_begin_on_station_time(self) -> datetime | None:
return None
@property
def mission_departure_time(self) -> datetime:
return self.package.time_over_target return self.package.time_over_target
@ -77,14 +81,14 @@ class Builder(IBuilder[PretenseCargoFlightPlan, FerryLayout]):
offmap_heading, PRETENSE_CARGO_FLIGHT_DISTANCE offmap_heading, PRETENSE_CARGO_FLIGHT_DISTANCE
) )
altitude_is_agl = self.flight.unit_type.dcs_unit_type.helicopter altitude_is_agl = self.flight.is_helo
altitude = ( altitude = (
feet(1500) feet(self.coalition.game.settings.heli_cruise_alt_agl)
if altitude_is_agl if altitude_is_agl
else self.flight.unit_type.preferred_patrol_altitude else self.flight.unit_type.preferred_patrol_altitude
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
ferry_layout = FerryLayout( ferry_layout = FerryLayout(
departure=builder.join(offmap_transport_spawn), departure=builder.join(offmap_transport_spawn),
nav_to=builder.nav_path( nav_to=builder.nav_path(
@ -101,8 +105,7 @@ class Builder(IBuilder[PretenseCargoFlightPlan, FerryLayout]):
ferry_layout.departure = builder.join(offmap_transport_spawn) ferry_layout.departure = builder.join(offmap_transport_spawn)
ferry_layout.nav_to.append(builder.join(offmap_transport_spawn)) ferry_layout.nav_to.append(builder.join(offmap_transport_spawn))
ferry_layout.nav_from.append(builder.join(offmap_transport_spawn)) ferry_layout.nav_from.append(builder.join(offmap_transport_spawn))
print(ferry_layout)
return ferry_layout return ferry_layout
def build(self) -> PretenseCargoFlightPlan: def build(self, dump_debug_info: bool = False) -> PretenseCargoFlightPlan:
return PretenseCargoFlightPlan(self.flight, self.layout()) return PretenseCargoFlightPlan(self.flight, self.layout())

View File

@ -395,7 +395,7 @@ class PretenseAircraftGenerator:
) )
print( print(
f"Generated flight for {flight_type} flying {squadron.aircraft.name} at {squadron.location.name}" f"Generated flight for {flight_type} flying {squadron.aircraft.display_name} at {squadron.location.name}"
) )
ato.add_package(package) ato.add_package(package)
return return
@ -442,7 +442,7 @@ class PretenseAircraftGenerator:
divert=cp, divert=cp,
) )
print( print(
f"Generated flight for {flight_type} flying {squadron.aircraft.name} at {squadron.location.name}" f"Generated flight for {flight_type} flying {squadron.aircraft.display_name} at {squadron.location.name}"
) )
package.add_flight(flight) package.add_flight(flight)
@ -483,7 +483,7 @@ class PretenseAircraftGenerator:
divert=cp, divert=cp,
) )
print( print(
f"Generated flight for {flight_type} flying {squadron.aircraft.name} at {squadron.location.name}" f"Generated flight for {flight_type} flying {squadron.aircraft.display_name} at {squadron.location.name}"
) )
package.add_flight(flight) package.add_flight(flight)
@ -524,7 +524,7 @@ class PretenseAircraftGenerator:
divert=cp, divert=cp,
) )
print( print(
f"Generated flight for {flight_type} flying {squadron.aircraft.name} at {squadron.location.name}" f"Generated flight for {flight_type} flying {squadron.aircraft.display_name} at {squadron.location.name}"
) )
package.add_flight(flight) package.add_flight(flight)
@ -582,11 +582,11 @@ class PretenseAircraftGenerator:
StartType.COLD, StartType.COLD,
divert=cp, divert=cp,
) )
for roster_pilot in flight.roster.pilots: for roster_pilot in flight.roster.members:
if roster_pilot is not None: if roster_pilot.pilot is not None:
roster_pilot.player = True roster_pilot.pilot.player = True
print( print(
f"Generated flight for {squadron.primary_task} flying {squadron.aircraft.name} at {squadron.location.name}. Pilot client count: {flight.client_count}" f"Generated flight for {squadron.primary_task} flying {squadron.aircraft.display_name} at {squadron.location.name}. Pilot client count: {flight.client_count}"
) )
package.add_flight(flight) package.add_flight(flight)
@ -720,7 +720,9 @@ class PretenseAircraftGenerator:
flight.departure, flight flight.departure, flight
) )
logging.info( logging.info(
f"Generating flight in {flight.coalition.faction.name} package {flight.squadron.aircraft} {flight.flight_type} for target: {package.target.name}, departure: {flight.from_cp.name}" f"Generating flight in {flight.coalition.faction.name} package"
f" {flight.squadron.aircraft} {flight.flight_type} for target: {package.target.name},"
f" departure: {flight.departure.name}"
) )
if flight.alive: if flight.alive:
@ -761,45 +763,81 @@ class PretenseAircraftGenerator:
self.ground_spawns, self.ground_spawns,
self.mission_data, self.mission_data,
).create_flight_group() ).create_flight_group()
if flight.flight_type == FlightType.CAS:
control_points_to_scan = (
list(self.game.theater.closest_opposing_control_points())
+ self.game.theater.controlpoints
)
if (
flight.flight_type == FlightType.CAS
or flight.flight_type == FlightType.TARCAP
):
for conflict in self.game.theater.conflicts(): for conflict in self.game.theater.conflicts():
flight.package.target = conflict flight.package.target = conflict
break break
elif flight.flight_type == FlightType.BARCAP:
for cp in control_points_to_scan:
if cp.coalition != flight.coalition or cp == flight.departure:
continue
if flight.package.target != flight.departure:
break
for mission_target in cp.ground_objects:
flight.package.target = mission_target
break
elif ( elif (
flight.flight_type == FlightType.STRIKE flight.flight_type == FlightType.STRIKE
or flight.flight_type == FlightType.BAI or flight.flight_type == FlightType.BAI
): ):
for cp in self.game.theater.closest_opposing_control_points(): for cp in control_points_to_scan:
if cp.coalition == flight.coalition: if cp.coalition == flight.coalition or cp == flight.departure:
continue continue
if flight.package.target != flight.departure:
break
for mission_target in cp.ground_objects: for mission_target in cp.ground_objects:
flight.package.target = mission_target flight.package.target = mission_target
break
elif ( elif (
flight.flight_type == FlightType.OCA_RUNWAY flight.flight_type == FlightType.OCA_RUNWAY
or flight.flight_type == FlightType.OCA_AIRCRAFT or flight.flight_type == FlightType.OCA_AIRCRAFT
): ):
for cp in self.game.theater.controlpoints: for cp in control_points_to_scan:
if cp.coalition == flight.coalition or not isinstance(cp, Airfield): if (
cp.coalition == flight.coalition
or not isinstance(cp, Airfield)
or cp == flight.departure
):
continue continue
flight.package.target = cp flight.package.target = cp
elif flight.flight_type == FlightType.DEAD: break
for cp in self.game.theater.controlpoints: elif (
if cp.coalition == flight.coalition: flight.flight_type == FlightType.DEAD
or flight.flight_type == FlightType.SEAD
):
for cp in control_points_to_scan:
if cp.coalition == flight.coalition or cp == flight.departure:
continue continue
if flight.package.target != flight.departure:
break
for ground_object in cp.ground_objects: for ground_object in cp.ground_objects:
is_ewr = isinstance(ground_object, EwrGroundObject) is_ewr = isinstance(ground_object, EwrGroundObject)
is_sam = isinstance(ground_object, SamGroundObject) is_sam = isinstance(ground_object, SamGroundObject)
if is_ewr or is_sam: if is_ewr or is_sam:
flight.package.target = ground_object flight.package.target = ground_object
break
elif flight.flight_type == FlightType.AIR_ASSAULT: elif flight.flight_type == FlightType.AIR_ASSAULT:
for cp in self.game.theater.closest_opposing_control_points(): for cp in control_points_to_scan:
if cp.coalition == flight.coalition: if cp.coalition == flight.coalition or cp == flight.departure:
continue continue
if flight.is_hercules: if flight.is_hercules:
if cp.coalition == flight.coalition or not isinstance(cp, Airfield): if cp.coalition == flight.coalition or not isinstance(cp, Airfield):
continue continue
flight.package.target = cp flight.package.target = cp
break
now = self.game.conditions.start_time
flight.package.set_tot_asap(now)
logging.info( logging.info(
f"Configuring flight {group.name} {flight.squadron.aircraft} {flight.flight_type}, number of players: {flight.client_count}" f"Configuring flight {group.name} {flight.squadron.aircraft} {flight.flight_type}, number of players: {flight.client_count}"
@ -812,7 +850,6 @@ class PretenseAircraftGenerator:
self.time, self.time,
self.radio_registry, self.radio_registry,
self.tacan_registy, self.tacan_registy,
self.laser_code_registry,
self.mission_data, self.mission_data,
dynamic_runways, dynamic_runways,
self.use_client, self.use_client,
@ -832,7 +869,7 @@ class PretenseAircraftGenerator:
or flight.client_count or flight.client_count
and ( and (
not self.need_ecm not self.need_ecm
or flight.loadout.has_weapon_of_type(WeaponType.JAMMER) or flight.any_member_has_weapon_of_type(WeaponType.JAMMER)
) )
): ):
self.ewrj_package_dict[id(flight.package)].append(group) self.ewrj_package_dict[id(flight.package)].append(group)

View File

@ -3,14 +3,17 @@ from __future__ import annotations
from datetime import datetime from datetime import datetime
from typing import Any, Optional, TYPE_CHECKING from typing import Any, Optional, TYPE_CHECKING
from dcs import Mission from dcs import Mission, Point
from dcs.flyingunit import FlyingUnit
from dcs.unitgroup import FlyingGroup from dcs.unitgroup import FlyingGroup
from game.ato import Flight, FlightType from game.ato import Flight, FlightType
from game.ato.flightmember import FlightMember
from game.data.weapons import Pylon from game.data.weapons import Pylon
from game.lasercodes.lasercoderegistry import LaserCodeRegistry from game.lasercodes.lasercoderegistry import LaserCodeRegistry
from game.missiongenerator.aircraft.aircraftbehavior import AircraftBehavior from game.missiongenerator.aircraft.aircraftbehavior import AircraftBehavior
from game.missiongenerator.aircraft.aircraftpainter import AircraftPainter from game.missiongenerator.aircraft.aircraftpainter import AircraftPainter
from game.missiongenerator.aircraft.bingoestimator import BingoEstimator
from game.missiongenerator.aircraft.flightdata import FlightData from game.missiongenerator.aircraft.flightdata import FlightData
from game.missiongenerator.aircraft.flightgroupconfigurator import ( from game.missiongenerator.aircraft.flightgroupconfigurator import (
FlightGroupConfigurator, FlightGroupConfigurator,
@ -37,7 +40,6 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
time: datetime, time: datetime,
radio_registry: RadioRegistry, radio_registry: RadioRegistry,
tacan_registry: TacanRegistry, tacan_registry: TacanRegistry,
laser_code_registry: LaserCodeRegistry,
mission_data: MissionData, mission_data: MissionData,
dynamic_runways: dict[str, RunwayData], dynamic_runways: dict[str, RunwayData],
use_client: bool, use_client: bool,
@ -50,7 +52,6 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
time, time,
radio_registry, radio_registry,
tacan_registry, tacan_registry,
laser_code_registry,
mission_data, mission_data,
dynamic_runways, dynamic_runways,
use_client, use_client,
@ -63,7 +64,6 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
self.time = time self.time = time
self.radio_registry = radio_registry self.radio_registry = radio_registry
self.tacan_registry = tacan_registry self.tacan_registry = tacan_registry
self.laser_code_registry = laser_code_registry
self.mission_data = mission_data self.mission_data = mission_data
self.dynamic_runways = dynamic_runways self.dynamic_runways = dynamic_runways
self.use_client = use_client self.use_client = use_client
@ -72,12 +72,12 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
AircraftBehavior(self.flight.flight_type).apply_to(self.flight, self.group) AircraftBehavior(self.flight.flight_type).apply_to(self.flight, self.group)
AircraftPainter(self.flight, self.group).apply_livery() AircraftPainter(self.flight, self.group).apply_livery()
self.setup_props() self.setup_props()
self.setup_payload() self.setup_payloads()
self.setup_fuel() self.setup_fuel()
flight_channel = self.setup_radios() flight_channel = self.setup_radios()
laser_codes: list[Optional[int]] = [] laser_codes: list[Optional[int]] = []
for unit, pilot in zip(self.group.units, self.flight.roster.pilots): for unit, pilot in zip(self.group.units, self.flight.roster.members):
self.configure_flight_member(unit, pilot, laser_codes) self.configure_flight_member(unit, pilot, laser_codes)
divert = None divert = None
@ -90,12 +90,21 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
self.flight, self.flight,
self.group, self.group,
self.mission, self.mission,
self.game.conditions.start_time,
self.time, self.time,
self.game.settings, self.game.settings,
self.mission_data, self.mission_data,
).create_waypoints() ).create_waypoints()
divert_position: Point | None = None
if self.flight.divert is not None:
divert_position = self.flight.divert.position
bingo_estimator = BingoEstimator(
self.flight.unit_type.fuel_consumption,
self.flight.arrival.position,
divert_position,
self.flight.flight_plan.waypoints,
)
self.group.uncontrolled = False self.group.uncontrolled = False
return FlightData( return FlightData(
@ -105,7 +114,7 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
flight_type=self.flight.flight_type, flight_type=self.flight.flight_type,
units=self.group.units, units=self.group.units,
size=len(self.group.units), size=len(self.group.units),
friendly=self.flight.from_cp.captured, friendly=self.flight.departure.captured,
departure_delay=mission_start_time, departure_delay=mission_start_time,
departure=self.flight.departure.active_runway( departure=self.flight.departure.active_runway(
self.game.theater, self.game.conditions, self.dynamic_runways self.game.theater, self.game.conditions, self.dynamic_runways
@ -116,21 +125,26 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
divert=divert, divert=divert,
waypoints=waypoints, waypoints=waypoints,
intra_flight_channel=flight_channel, intra_flight_channel=flight_channel,
bingo_fuel=self.flight.flight_plan.bingo_fuel, bingo_fuel=bingo_estimator.estimate_bingo(),
joker_fuel=self.flight.flight_plan.joker_fuel, joker_fuel=bingo_estimator.estimate_joker(),
custom_name=self.flight.custom_name, custom_name=self.flight.custom_name,
laser_codes=laser_codes, laser_codes=laser_codes,
) )
def setup_payload(self) -> None: def setup_payloads(self) -> None:
for p in self.group.units: for unit, member in zip(self.group.units, self.flight.iter_members()):
p.pylons.clear() self.setup_payload(unit, member)
def setup_payload(self, unit: FlyingUnit, member: FlightMember) -> None:
unit.pylons.clear()
loadout = member.loadout
if self.flight.flight_type == FlightType.SEAD: if self.flight.flight_type == FlightType.SEAD:
self.flight.loadout = self.flight.loadout.default_for_task_and_aircraft( loadout = member.loadout.default_for_task_and_aircraft(
FlightType.SEAD_SWEEP, self.flight.unit_type.dcs_unit_type FlightType.SEAD_SWEEP, self.flight.unit_type.dcs_unit_type
) )
loadout = self.flight.loadout
if self.game.settings.restrict_weapons_by_date: if self.game.settings.restrict_weapons_by_date:
loadout = loadout.degrade_for_date(self.flight.unit_type, self.game.date) loadout = loadout.degrade_for_date(self.flight.unit_type, self.game.date)
@ -138,4 +152,4 @@ class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
if weapon is None: if weapon is None:
continue continue
pylon = Pylon.for_aircraft(self.flight.unit_type, pylon_number) pylon = Pylon.for_aircraft(self.flight.unit_type, pylon_number)
pylon.equip(self.group, weapon) pylon.equip(unit, weapon)

View File

@ -118,7 +118,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
raise RuntimeError( raise RuntimeError(
f"Cannot spawn fixed-wing aircraft at {cp} because of insufficient ground spawn slots." f"Cannot spawn fixed-wing aircraft at {cp} because of insufficient ground spawn slots."
) )
pilot_count = len(self.flight.roster.pilots) pilot_count = len(self.flight.roster.members)
if ( if (
not is_heli not is_heli
and self.flight.roster.player_count != pilot_count and self.flight.roster.player_count != pilot_count

View File

@ -148,7 +148,7 @@ class PretenseMissionGenerator(MissionGenerator):
player_cp = front_line.blue_cp player_cp = front_line.blue_cp
enemy_cp = front_line.red_cp enemy_cp = front_line.red_cp
conflict = FrontLineConflictDescription.frontline_cas_conflict( conflict = FrontLineConflictDescription.frontline_cas_conflict(
front_line, self.game.theater, self.game.settings front_line, self.game.theater
) )
# Generate frontline ops # Generate frontline ops
player_gp = self.game.ground_planners[player_cp.id].units_per_cp[ player_gp = self.game.ground_planners[player_cp.id].units_per_cp[
@ -166,7 +166,6 @@ class PretenseMissionGenerator(MissionGenerator):
self.unit_map, self.unit_map,
self.radio_registry, self.radio_registry,
self.mission_data, self.mission_data,
self.laser_code_registry,
) )
ground_conflict_gen.generate() ground_conflict_gen.generate()