More adaptation for pydcs updates.

This is as much as we can do until pydcs actually adds the py.typed
file. Once that's added there are a few ugly monkey patching corners
that will just need `# type: ignore` for now, but we can't pre-add those
since we have mypy warning us about superfluous ignore comments.

(cherry picked from commit 96c7b87ac7)
This commit is contained in:
Dan Albert
2021-07-09 14:13:20 -07:00
parent 53a1c938c3
commit 1ea13954ec
27 changed files with 238 additions and 207 deletions

View File

@@ -321,7 +321,7 @@ class AircraftConflictGenerator:
@staticmethod
def livery_from_db(flight: Flight) -> Optional[str]:
return db.PLANE_LIVERY_OVERRIDES.get(flight.unit_type)
return db.PLANE_LIVERY_OVERRIDES.get(flight.unit_type.dcs_unit_type)
def livery_from_faction(self, flight: Flight) -> Optional[str]:
faction = self.game.faction_for(player=flight.departure.captured)
@@ -342,7 +342,7 @@ class AircraftConflictGenerator:
return livery
return None
def _setup_livery(self, flight: Flight, group: FlyingGroup) -> None:
def _setup_livery(self, flight: Flight, group: FlyingGroup[Any]) -> None:
livery = self.livery_for(flight)
if livery is None:
return
@@ -458,8 +458,8 @@ class AircraftConflictGenerator:
unit_type: Type[FlyingType],
count: int,
start_type: str,
airport: Optional[Airport] = None,
) -> FlyingGroup:
airport: Airport,
) -> FlyingGroup[Any]:
assert count > 0
logging.info("airgen: {} for {} at {}".format(unit_type, side.id, airport))
@@ -476,7 +476,7 @@ class AircraftConflictGenerator:
def _generate_inflight(
self, name: str, side: Country, flight: Flight, origin: ControlPoint
) -> FlyingGroup:
) -> FlyingGroup[Any]:
assert flight.count > 0
at = origin.position
@@ -521,7 +521,7 @@ class AircraftConflictGenerator:
count: int,
start_type: str,
at: Union[ShipGroup, StaticGroup],
) -> FlyingGroup:
) -> FlyingGroup[Any]:
assert count > 0
logging.info("airgen: {} for {} at unit {}".format(unit_type, side.id, at))
@@ -546,27 +546,6 @@ class AircraftConflictGenerator:
point.alt_type = "RADIO"
return point
def _rtb_for(
self,
group: FlyingGroup[Any],
cp: ControlPoint,
at: Optional[db.StartingPosition] = None,
) -> MovingPoint:
if at is None:
at = cp.at
position = at if isinstance(at, Point) else at.position
last_waypoint = group.points[-1]
if last_waypoint is not None:
heading = position.heading_between_point(last_waypoint.position)
tod_location = position.point_from_heading(heading, RTB_DISTANCE)
self._add_radio_waypoint(group, tod_location, last_waypoint.alt)
destination_waypoint = self._add_radio_waypoint(group, position, RTB_ALTITUDE)
if isinstance(at, Airport):
group.land_at(at)
return destination_waypoint
@staticmethod
def _at_position(at: Union[Point, ShipGroup, Type[Airport]]) -> Point:
if isinstance(at, Point):
@@ -578,7 +557,7 @@ class AircraftConflictGenerator:
else:
assert False
def _setup_payload(self, flight: Flight, group: FlyingGroup) -> None:
def _setup_payload(self, flight: Flight, group: FlyingGroup[Any]) -> None:
for p in group.units:
p.pylons.clear()
@@ -729,7 +708,7 @@ class AircraftConflictGenerator:
def generate_planned_flight(
self, cp: ControlPoint, country: Country, flight: Flight
) -> FlyingGroup:
) -> FlyingGroup[Any]:
name = namegen.next_aircraft_name(country, cp.id, flight)
try:
if flight.start_type == "In Flight":
@@ -738,13 +717,19 @@ class AircraftConflictGenerator:
)
elif isinstance(cp, NavalControlPoint):
group_name = cp.get_carrier_group_name()
carrier_group = self.m.find_group(group_name)
if not isinstance(carrier_group, ShipGroup):
raise RuntimeError(
f"Carrier group {carrier_group} is a "
"{carrier_group.__class__.__name__}, expected a ShipGroup"
)
group = self._generate_at_group(
name=name,
side=country,
unit_type=flight.unit_type.dcs_unit_type,
count=flight.count,
start_type=flight.start_type,
at=self.m.find_group(group_name),
at=carrier_group,
)
else:
if not isinstance(cp, Airfield):
@@ -775,7 +760,7 @@ class AircraftConflictGenerator:
@staticmethod
def set_reduced_fuel(
flight: Flight, group: FlyingGroup[Any], unit_type: Type[PlaneType]
flight: Flight, group: FlyingGroup[Any], unit_type: Type[FlyingType]
) -> None:
if unit_type is Su_33:
for unit in group.units:
@@ -803,7 +788,7 @@ class AircraftConflictGenerator:
flight: Flight,
group: FlyingGroup[Any],
react_on_threat: Optional[OptReactOnThreat.Values] = None,
roe: Optional[OptROE.Values] = None,
roe: Optional[int] = None,
rtb_winchester: Optional[OptRTBOnOutOfAmmo.Values] = None,
restrict_jettison: Optional[bool] = None,
mission_uses_gun: bool = True,
@@ -1438,7 +1423,7 @@ class CasIngressBuilder(PydcsWaypointBuilder):
if isinstance(self.flight.flight_plan, CasFlightPlan):
waypoint.add_task(
EngageTargetsInZone(
position=self.flight.flight_plan.target,
position=self.flight.flight_plan.target.position,
radius=int(self.flight.flight_plan.engagement_distance.meters),
targets=[
Targets.All.GroundUnits.GroundVehicles,

View File

@@ -6,7 +6,7 @@ from datetime import timedelta
from typing import List, Type, Tuple, Optional, TYPE_CHECKING
from dcs.mission import Mission, StartType
from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135
from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135, PlaneType
from dcs.task import (
AWACS,
ActivateBeaconCommand,
@@ -111,6 +111,11 @@ class AirSupportConflictGenerator:
for i, tanker_unit_type in enumerate(
self.game.faction_for(player=True).tankers
):
unit_type = tanker_unit_type.dcs_unit_type
if not issubclass(unit_type, PlaneType):
logging.warning(f"Refueling aircraft {unit_type} must be a plane")
continue
# TODO: Make loiter altitude a property of the unit type.
alt, airspeed = self._get_tanker_params(tanker_unit_type.dcs_unit_type)
freq = self.radio_registry.alloc_uhf()
@@ -130,7 +135,7 @@ class AirSupportConflictGenerator:
self.mission.country(self.game.player_country), tanker_unit_type
),
airport=None,
plane_type=tanker_unit_type.dcs_unit_type,
plane_type=unit_type,
position=tanker_position,
altitude=alt,
race_distance=58000,
@@ -200,12 +205,17 @@ class AirSupportConflictGenerator:
awacs_unit = possible_awacs[0]
freq = self.radio_registry.alloc_uhf()
unit_type = awacs_unit.dcs_unit_type
if not issubclass(unit_type, PlaneType):
logging.warning(f"AWACS aircraft {unit_type} must be a plane")
return
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,
plane_type=unit_type,
altitude=AWACS_ALT,
airport=None,
position=self.conflict.position.random_point_within(

View File

@@ -23,7 +23,7 @@ from dcs.task import (
SetInvisibleCommand,
)
from dcs.triggers import Event, TriggerOnce
from dcs.unit import Vehicle
from dcs.unit import Vehicle, Skill
from dcs.unitgroup import VehicleGroup
from game.data.groundunitclass import GroundUnitClass
@@ -359,7 +359,6 @@ class GroundConflictGenerator:
self.mission.triggerrules.triggers.append(artillery_fallback)
for u in dcs_group.units:
u.initial = True
u.heading = forward_heading + random.randint(-5, 5)
return True
return False
@@ -568,10 +567,10 @@ class GroundConflictGenerator:
)
# Fallback task
fallback = ControlledTask(GoToWaypoint(to_index=len(dcs_group.points)))
fallback.enabled = False
task = ControlledTask(GoToWaypoint(to_index=len(dcs_group.points)))
task.enabled = False
dcs_group.add_trigger_action(Hold())
dcs_group.add_trigger_action(fallback)
dcs_group.add_trigger_action(task)
# Create trigger
fallback = TriggerOnce(Event.NoEvent, "Morale manager #" + str(dcs_group.id))
@@ -632,7 +631,7 @@ class GroundConflictGenerator:
@param enemy_groups Potential enemy groups
@param n number of nearby groups to take
"""
targets = [] # type: List[Optional[VehicleGroup]]
targets = [] # type: List[VehicleGroup]
sorted_list = sorted(
enemy_groups,
key=lambda group: player_group.points[0].position.distance_to_point(
@@ -714,7 +713,7 @@ class GroundConflictGenerator:
distance_from_frontline: int,
heading: int,
spawn_heading: int,
) -> Point:
) -> Optional[Point]:
shifted = conflict_position.point_from_heading(
heading, random.randint(0, combat_width)
)
@@ -764,9 +763,9 @@ class GroundConflictGenerator:
heading=opposite_heading(spawn_heading),
)
if is_player:
g.set_skill(self.game.settings.player_skill)
g.set_skill(Skill(self.game.settings.player_skill))
else:
g.set_skill(self.game.settings.enemy_vehicle_skill)
g.set_skill(Skill(self.game.settings.enemy_vehicle_skill))
positioned_groups.append((g, group))
if group.role in [CombatGroupRole.APC, CombatGroupRole.IFV]:

View File

@@ -1,12 +1,13 @@
"""Support for working with DCS group callsigns."""
import logging
import re
from typing import Any
from dcs.unitgroup import FlyingGroup
from dcs.flyingunit import FlyingUnit
def callsign_for_support_unit(group: FlyingGroup) -> str:
def callsign_for_support_unit(group: FlyingGroup[Any]) -> str:
# Either something like Overlord11 for Western AWACS, or else just a number.
# Convert to either "Overlord" or "Flight 123".
lead = group.units[0]

View File

@@ -63,6 +63,8 @@ class Conflict:
heading_sum(attack_heading, 90),
theater,
)
if position is None:
raise RuntimeError("Could not find front line position")
return position, opposite_heading(attack_heading)
@classmethod

View File

@@ -22,7 +22,7 @@ class EnvironmentGenerator:
def set_fog(self, fog: Optional[Fog]) -> None:
if fog is None:
return
self.mission.weather.fog_visibility = fog.visibility.meters
self.mission.weather.fog_visibility = int(fog.visibility.meters)
self.mission.weather.fog_thickness = fog.thickness
def set_wind(self, wind: WindConditions) -> None:

View File

@@ -1,5 +1,6 @@
import logging
from typing import List, Type
from collections import Sequence
from typing import Type
from dcs.helicopters import (
AH_1W,
@@ -415,7 +416,7 @@ REFUELING_CAPABALE = [
]
def dcs_types_for_task(task: FlightType) -> list[Type[FlyingType]]:
def dcs_types_for_task(task: FlightType) -> Sequence[Type[FlyingType]]:
cap_missions = (FlightType.BARCAP, FlightType.TARCAP, FlightType.SWEEP)
if task in cap_missions:
return CAP_CAPABLE

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from datetime import timedelta
from enum import Enum
from typing import List, Optional, TYPE_CHECKING, Union
from typing import List, Optional, TYPE_CHECKING, Union, Sequence
from dcs.mapping import Point
from dcs.point import MovingPoint, PointAction
@@ -153,7 +153,7 @@ class FlightWaypoint:
# Only used in the waypoint list in the flight edit page. No sense
# having three names. A short and long form is enough.
self.description = ""
self.targets: List[Union[MissionTarget, Unit]] = []
self.targets: Sequence[Union[MissionTarget, Unit]] = []
self.obj_name = ""
self.pretty_name = ""
self.only_for_player = False

View File

@@ -1084,22 +1084,22 @@ class FlightPlanBuilder:
patrol_alt = feet(25000)
builder = WaypointBuilder(flight, self.game, self.is_player)
orbit_location = builder.orbit(orbit_location, patrol_alt)
orbit = builder.orbit(orbit_location, patrol_alt)
return AwacsFlightPlan(
package=self.package,
flight=flight,
takeoff=builder.takeoff(flight.departure),
nav_to=builder.nav_path(
flight.departure.position, orbit_location.position, patrol_alt
flight.departure.position, orbit.position, patrol_alt
),
nav_from=builder.nav_path(
orbit_location.position, flight.arrival.position, patrol_alt
orbit.position, flight.arrival.position, patrol_alt
),
land=builder.land(flight.arrival),
divert=builder.divert(flight.divert),
bullseye=builder.bullseye(),
hold=orbit_location,
hold=orbit,
hold_duration=timedelta(hours=4),
)
@@ -1167,7 +1167,7 @@ class FlightPlanBuilder:
if isinstance(location, FrontLine):
raise InvalidObjectiveLocation(flight.flight_type, location)
start, end = self.racetrack_for_objective(location, barcap=True)
start_pos, end_pos = self.racetrack_for_objective(location, barcap=True)
patrol_alt = meters(
random.randint(
int(self.doctrine.min_patrol_altitude.meters),
@@ -1176,7 +1176,7 @@ class FlightPlanBuilder:
)
builder = WaypointBuilder(flight, self.game, self.is_player)
start, end = builder.race_track(start, end, patrol_alt)
start, end = builder.race_track(start_pos, end_pos, patrol_alt)
return BarCapFlightPlan(
package=self.package,

View File

@@ -15,7 +15,7 @@ from typing import (
from dcs.mapping import Point
from dcs.unit import Unit
from dcs.unitgroup import Group, VehicleGroup
from dcs.unitgroup import Group, VehicleGroup, ShipGroup
if TYPE_CHECKING:
from game import Game
@@ -35,7 +35,7 @@ from .flight import Flight, FlightWaypoint, FlightWaypointType
class StrikeTarget:
name: str
target: Union[
VehicleGroup, TheaterGroundObject[Any], Unit, Group, MultiGroupTransport
VehicleGroup, TheaterGroundObject[Any], Unit, ShipGroup, MultiGroupTransport
]
@@ -444,7 +444,7 @@ class WaypointBuilder:
# description in gen.aircraft.JoinPointBuilder), so instead we give
# the escort flights a flight plan including the ingress point, target
# area, and egress point.
ingress = self.ingress(FlightWaypointType.INGRESS_ESCORT, ingress, target)
ingress_wp = self.ingress(FlightWaypointType.INGRESS_ESCORT, ingress, target)
waypoint = FlightWaypoint(
FlightWaypointType.TARGET_GROUP_LOC,
@@ -458,8 +458,8 @@ class WaypointBuilder:
waypoint.description = "Escort the package"
waypoint.pretty_name = "Target area"
egress = self.egress(egress, target)
return ingress, waypoint, egress
egress_wp = self.egress(egress, target)
return ingress_wp, waypoint, egress_wp
@staticmethod
def pickup(control_point: ControlPoint) -> FlightWaypoint:

View File

@@ -19,12 +19,13 @@ from typing import (
TypeVar,
Any,
Generic,
Union,
)
from dcs import Mission, Point, unitgroup
from dcs.action import SceneryDestructionZone
from dcs.country import Country
from dcs.point import StaticPoint
from dcs.point import StaticPoint, MovingPoint
from dcs.statics import Fortification, fortification_map, warehouse_map
from dcs.task import (
ActivateBeaconCommand,
@@ -36,12 +37,12 @@ from dcs.task import (
from dcs.triggers import TriggerStart, TriggerZone
from dcs.unit import Ship, Unit, Vehicle, SingleHeliPad
from dcs.unitgroup import Group, ShipGroup, StaticGroup, VehicleGroup
from dcs.unittype import StaticType, UnitType
from dcs.unittype import StaticType, UnitType, ShipType, VehicleType
from dcs.vehicles import vehicle_map
from game import db
from game.data.building_data import FORTIFICATION_UNITS, FORTIFICATION_UNITS_ID
from game.db import unit_type_from_name
from game.db import unit_type_from_name, ship_type_from_name, vehicle_type_from_name
from game.theater import ControlPoint, TheaterGroundObject
from game.theater.theatergroundobject import (
BuildingGroundObject,
@@ -102,10 +103,7 @@ class GenericGroundObjectGenerator(Generic[TgoT]):
logging.warning(f"Found empty group in {self.ground_object}")
continue
unit_type = unit_type_from_name(group.units[0].type)
if unit_type is None:
raise RuntimeError(f"Unrecognized unit type: {group.units[0].type}")
unit_type = vehicle_type_from_name(group.units[0].type)
vg = self.m.vehicle_group(
self.country,
group.name,
@@ -129,18 +127,21 @@ class GenericGroundObjectGenerator(Generic[TgoT]):
self._register_unit_group(group, vg)
@staticmethod
def enable_eplrs(group: Group, unit_type: Type[UnitType]) -> None:
if hasattr(unit_type, "eplrs"):
if unit_type.eplrs:
group.points[0].tasks.append(EPLRS(group.id))
def enable_eplrs(group: VehicleGroup, unit_type: Type[VehicleType]) -> None:
if unit_type.eplrs:
group.points[0].tasks.append(EPLRS(group.id))
def set_alarm_state(self, group: Group) -> None:
def set_alarm_state(self, group: Union[ShipGroup, VehicleGroup]) -> None:
if self.game.settings.perf_red_alert_state:
group.points[0].tasks.append(OptAlarmState(2))
else:
group.points[0].tasks.append(OptAlarmState(1))
def _register_unit_group(self, persistence_group: Group, miz_group: Group) -> None:
def _register_unit_group(
self,
persistence_group: Union[ShipGroup, VehicleGroup],
miz_group: Union[ShipGroup, VehicleGroup],
) -> None:
self.unit_map.add_ground_object_units(
self.ground_object, persistence_group, miz_group
)
@@ -161,7 +162,7 @@ class MissileSiteGenerator(GenericGroundObjectGenerator[MissileSiteGroundObject]
for group in self.ground_object.groups:
vg = self.m.find_group(group.name)
if vg is not None:
targets = self.possible_missile_targets(vg)
targets = self.possible_missile_targets()
if targets:
target = random.choice(targets)
real_target = target.point_from_heading(
@@ -178,7 +179,7 @@ class MissileSiteGenerator(GenericGroundObjectGenerator[MissileSiteGroundObject]
"Couldn't setup missile site to fire, group was not generated."
)
def possible_missile_targets(self, vg: Group) -> List[Point]:
def possible_missile_targets(self) -> List[Point]:
"""
Find enemy control points in range
:param vg: Vehicle group we are searching a target for (There is always only oe group right now)
@@ -187,7 +188,7 @@ class MissileSiteGenerator(GenericGroundObjectGenerator[MissileSiteGroundObject]
targets: List[Point] = []
for cp in self.game.theater.controlpoints:
if cp.captured != self.ground_object.control_point.captured:
distance = cp.position.distance_to_point(vg.position)
distance = cp.position.distance_to_point(self.ground_object.position)
if distance < self.missile_site_range:
targets.append(cp.position)
return targets
@@ -238,7 +239,7 @@ class BuildingSiteGenerator(GenericGroundObjectGenerator[BuildingGroundObject]):
f"{self.ground_object.dcs_identifier} not found in static maps"
)
def generate_vehicle_group(self, unit_type: Type[UnitType]) -> None:
def generate_vehicle_group(self, unit_type: Type[VehicleType]) -> None:
if not self.ground_object.is_dead:
group = self.m.vehicle_group(
country=self.country,
@@ -389,13 +390,12 @@ class GenericCarrierGenerator(GenericGroundObjectGenerator[GenericCarrierGroundO
self.add_runway_data(brc or 0, atc, tacan, tacan_callsign, icls)
self._register_unit_group(group, ship_group)
def get_carrier_type(self, group: Group) -> Type[UnitType]:
unit_type = unit_type_from_name(group.units[0].type)
if unit_type is None:
raise RuntimeError(f"Unrecognized carrier name: {group.units[0].type}")
return unit_type
def get_carrier_type(self, group: ShipGroup) -> Type[ShipType]:
return ship_type_from_name(group.units[0].type)
def configure_carrier(self, group: Group, atc_channel: RadioFrequency) -> ShipGroup:
def configure_carrier(
self, group: ShipGroup, atc_channel: RadioFrequency
) -> ShipGroup:
unit_type = self.get_carrier_type(group)
ship_group = self.m.ship_group(
@@ -487,7 +487,7 @@ class GenericCarrierGenerator(GenericGroundObjectGenerator[GenericCarrierGroundO
class CarrierGenerator(GenericCarrierGenerator):
"""Generator for CV(N) groups."""
def get_carrier_type(self, group: Group) -> UnitType:
def get_carrier_type(self, group: ShipGroup) -> Type[ShipType]:
unit_type = super().get_carrier_type(group)
if self.game.settings.supercarrier:
unit_type = db.upgrade_to_supercarrier(unit_type, self.control_point.name)
@@ -542,14 +542,11 @@ class ShipObjectGenerator(GenericGroundObjectGenerator[ShipGroundObject]):
if not group.units:
logging.warning(f"Found empty group in {self.ground_object}")
continue
self.generate_group(group, ship_type_from_name(group.units[0].type))
unit_type = unit_type_from_name(group.units[0].type)
if unit_type is None:
raise RuntimeError(f"Unrecognized unit type: {group.units[0].type}")
self.generate_group(group, unit_type)
def generate_group(self, group_def: Group, first_unit_type: Type[UnitType]) -> None:
def generate_group(
self, group_def: ShipGroup, first_unit_type: Type[ShipType]
) -> None:
group = self.m.ship_group(
self.country,
group_def.name,

View File

@@ -1,9 +1,8 @@
import random
import time
from typing import List
from typing import List, Any
from dcs.country import Country
from dcs.unittype import UnitType as DcsUnitType
from game.dcs.aircrafttype import AircraftType
from game.dcs.unittype import UnitType
@@ -297,7 +296,7 @@ class NameGenerator:
@classmethod
def next_unit_name(
cls, country: Country, parent_base_id: int, unit_type: UnitType[DcsUnitType]
cls, country: Country, parent_base_id: int, unit_type: UnitType[Any]
) -> str:
cls.number += 1
return "unit|{}|{}|{}|{}|".format(
@@ -306,7 +305,7 @@ class NameGenerator:
@classmethod
def next_infantry_name(
cls, country: Country, parent_base_id: int, unit_type: UnitType[DcsUnitType]
cls, country: Country, parent_base_id: int, unit_type: UnitType[Any]
) -> str:
cls.infantry_number += 1
return "infantry|{}|{}|{}|{}|".format(

View File

@@ -157,7 +157,7 @@ class ShipGroupGenerator(
super().__init__(
game,
ground_object,
unitgroup.ShipGroup(self.game.next_group_id(), self.go.group_name),
unitgroup.ShipGroup(game.next_group_id(), ground_object.group_name),
)
self.faction = faction
wp = self.vg.add_waypoint(self.position, 0)

View File

@@ -83,7 +83,12 @@ class TriggersGenerator:
for cp in self.game.theater.controlpoints:
if isinstance(cp, Airfield):
self.mission.terrain.airport_by_id(cp.at.id).set_coalition(
cp_airport = self.mission.terrain.airport_by_id(cp.airport.id)
if cp_airport is None:
raise RuntimeError(
f"Could not find {cp.airport.name} in the mission"
)
cp_airport.set_coalition(
cp.captured and player_coalition or enemy_coalition
)