Fix mypy issues in all modules except qt_ui.

This commit is contained in:
Dan Albert
2020-10-03 14:58:44 -07:00
parent 1808e5bccf
commit db6b660270
88 changed files with 1990 additions and 661 deletions

View File

@@ -1,4 +1,3 @@
from .aaa import *
from .aircraft import *
from .armor import *
from .airsupportgen import *
@@ -12,4 +11,3 @@ from .forcedoptionsgen import *
from .kneeboard import *
from . import naming

View File

@@ -1,51 +0,0 @@
from .conflictgen import *
from .naming import *
from dcs.mission import *
from dcs.mission import *
from .conflictgen import *
from .naming import *
DISTANCE_FACTOR = 0.5, 1
EXTRA_AA_MIN_DISTANCE = 50000
EXTRA_AA_MAX_DISTANCE = 150000
EXTRA_AA_POSITION_FROM_CP = 550
class ExtraAAConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict, game, player_country: Country, enemy_country: Country):
self.mission = mission
self.game = game
self.conflict = conflict
self.player_country = player_country
self.enemy_country = enemy_country
def generate(self):
for cp in self.game.theater.controlpoints:
if cp.is_global:
continue
if cp.position.distance_to_point(self.conflict.position) < EXTRA_AA_MIN_DISTANCE:
continue
if cp.position.distance_to_point(self.conflict.from_cp.position) < EXTRA_AA_MIN_DISTANCE:
continue
if cp.position.distance_to_point(self.conflict.to_cp.position) < EXTRA_AA_MIN_DISTANCE:
continue
if cp.position.distance_to_point(self.conflict.position) > EXTRA_AA_MAX_DISTANCE:
continue
country_name = cp.captured and self.player_country or self.enemy_country
position = cp.position.point_from_heading(0, EXTRA_AA_POSITION_FROM_CP)
self.mission.vehicle_group(
country=self.mission.country(country_name),
name=namegen.next_basedefense_name(),
_type=db.EXTRA_AA[country_name],
position=position,
group_size=1
)

View File

@@ -1,14 +1,67 @@
import logging
import random
from dataclasses import dataclass
from typing import Type
from typing import Dict, List, Optional, Tuple, Type, Union
from dcs import helicopters
from dcs.action import ActivateGroup, AITaskPush, MessageToAll
from dcs.condition import TimeAfter, CoalitionHasAirdrome, PartOfCoalitionInZone
from dcs.action import AITaskPush, ActivateGroup, MessageToAll
from dcs.condition import CoalitionHasAirdrome, PartOfCoalitionInZone, TimeAfter
from dcs.country import Country
from dcs.flyingunit import FlyingUnit
from dcs.helicopters import helicopter_map, UH_1H
from dcs.helicopters import UH_1H, helicopter_map
from dcs.mapping import Point
from dcs.mission import Mission, StartType
from dcs.planes import (
AJS37,
B_17G,
Bf_109K_4,
FW_190A8,
FW_190D9,
F_14B,
I_16,
JF_17,
Ju_88A4,
P_47D_30,
P_51D,
P_51D_30_NA,
SpitfireLFMkIX,
SpitfireLFMkIXCW,
Su_33,
)
from dcs.point import PointAction
from dcs.task import (
AntishipStrike,
AttackGroup,
Bombing,
CAP,
CAS,
ControlledTask,
EPLRS,
EngageTargets,
Escort,
GroundAttack,
MainTask,
NoTask,
OptROE,
OptRTBOnBingoFuel,
OptRTBOnOutOfAmmo,
OptReactOnThreat,
OptRestrictAfterburner,
OptRestrictJettison,
OrbitAction,
PinpointStrike,
SEAD,
StartCommand,
Targets,
Task,
)
from dcs.terrain.terrain import Airport, NoParkingSlotError
from dcs.triggers import TriggerOnce, Event
from dcs.translation import String
from dcs.triggers import Event, TriggerOnce
from dcs.unitgroup import FlyingGroup, Group, ShipGroup, StaticGroup
from dcs.unittype import FlyingType, UnitType
from game import db
from game.data.cap_capabilities_db import GUNFIGHTERS
from game.settings import Settings
from game.utils import nm_to_meter
@@ -22,9 +75,10 @@ from gen.flights.flight import (
FlightWaypoint,
FlightWaypointType,
)
from gen.radios import get_radio, MHz, Radio, RadioFrequency, RadioRegistry
from .conflictgen import *
from .naming import *
from gen.radios import MHz, Radio, RadioFrequency, RadioRegistry, get_radio
from theater.controlpoint import ControlPoint, ControlPointType
from .naming import namegen
from .conflictgen import Conflict
WARM_START_HELI_AIRSPEED = 120
WARM_START_HELI_ALT = 500
@@ -264,8 +318,12 @@ class CommonRadioChannelAllocator(RadioChannelAllocator):
def assign_channels_for_flight(self, flight: FlightData,
air_support: AirSupport) -> None:
flight.assign_channel(
self.intra_flight_radio_index, 1, flight.intra_flight_channel)
if self.intra_flight_radio_index is not None:
flight.assign_channel(
self.intra_flight_radio_index, 1, flight.intra_flight_channel)
if self.inter_flight_radio_index is None:
return
# For cases where the inter-flight and intra-flight radios share presets
# (the JF-17 only has one set of channels, even though it can use two
@@ -335,8 +393,10 @@ class ViggenRadioChannelAllocator(RadioChannelAllocator):
# the guard channel.
radio_id = 1
flight.assign_channel(radio_id, 1, flight.intra_flight_channel)
flight.assign_channel(radio_id, 4, flight.departure.atc)
flight.assign_channel(radio_id, 5, flight.arrival.atc)
if flight.departure.atc is not None:
flight.assign_channel(radio_id, 4, flight.departure.atc)
if flight.arrival.atc is not None:
flight.assign_channel(radio_id, 5, flight.arrival.atc)
# TODO: Assign divert to 6 when we support divert airfields.
@@ -348,8 +408,10 @@ class SCR522RadioChannelAllocator(RadioChannelAllocator):
air_support: AirSupport) -> None:
radio_id = 1
flight.assign_channel(radio_id, 1, flight.intra_flight_channel)
flight.assign_channel(radio_id, 2, flight.departure.atc)
flight.assign_channel(radio_id, 3, flight.arrival.atc)
if flight.departure.atc is not None:
flight.assign_channel(radio_id, 2, flight.departure.atc)
if flight.arrival.atc is not None:
flight.assign_channel(radio_id, 3, flight.arrival.atc)
# TODO : Some GCI on Channel 4 ?
@@ -471,8 +533,6 @@ AIRCRAFT_DATA["P-47D-30"] = AIRCRAFT_DATA["P-51D"]
class AircraftConflictGenerator:
escort_targets = [] # type: typing.List[typing.Tuple[FlyingGroup, int]]
def __init__(self, mission: Mission, conflict: Conflict, settings: Settings,
game, radio_registry: RadioRegistry):
self.m = mission
@@ -480,7 +540,7 @@ class AircraftConflictGenerator:
self.settings = settings
self.conflict = conflict
self.radio_registry = radio_registry
self.escort_targets = []
self.escort_targets: List[Tuple[FlyingGroup, int]] = []
self.flights: List[FlightData] = []
def get_intra_flight_channel(self, airframe: UnitType) -> RadioFrequency:
@@ -502,33 +562,23 @@ class AircraftConflictGenerator:
def _start_type(self) -> StartType:
return self.settings.cold_start and StartType.Cold or StartType.Warm
def _setup_group(self, group: FlyingGroup, for_task: typing.Type[Task],
def _setup_group(self, group: FlyingGroup, for_task: Type[Task],
flight: Flight, dynamic_runways: Dict[str, RunwayData]):
did_load_loadout = False
unit_type = group.units[0].unit_type
if unit_type in db.PLANE_PAYLOAD_OVERRIDES:
override_loadout = db.PLANE_PAYLOAD_OVERRIDES[unit_type]
if type(override_loadout) == dict:
# Clear pylons
for p in group.units:
p.pylons.clear()
# Clear pylons
for p in group.units:
p.pylons.clear()
# Now load loadout
if for_task in db.PLANE_PAYLOAD_OVERRIDES[unit_type]:
payload_name = db.PLANE_PAYLOAD_OVERRIDES[unit_type][for_task]
group.load_loadout(payload_name)
did_load_loadout = True
logging.info("Loaded overridden payload for {} - {} for task {}".format(unit_type, payload_name, for_task))
elif "*" in db.PLANE_PAYLOAD_OVERRIDES[unit_type]:
payload_name = db.PLANE_PAYLOAD_OVERRIDES[unit_type]["*"]
group.load_loadout(payload_name)
did_load_loadout = True
logging.info("Loaded overridden payload for {} - {} for task {}".format(unit_type, payload_name, for_task))
elif issubclass(override_loadout, MainTask):
group.load_task_default_loadout(override_loadout)
# Now load loadout
if for_task in db.PLANE_PAYLOAD_OVERRIDES[unit_type]:
payload_name = db.PLANE_PAYLOAD_OVERRIDES[unit_type][for_task]
group.load_loadout(payload_name)
did_load_loadout = True
logging.info("Loaded overridden payload for {} - {} for task {}".format(unit_type, payload_name, for_task))
if not did_load_loadout:
group.load_task_default_loadout(for_task)
@@ -590,7 +640,7 @@ class AircraftConflictGenerator:
# Special case so Su 33 carrier take off
if unit_type is Su_33:
if task is not CAP:
if flight.flight_type is not CAP:
for unit in group.units:
unit.fuel = Su_33.fuel_max / 2.2
else:
@@ -613,9 +663,12 @@ class AircraftConflictGenerator:
# so just use the first runway.
return runways[0]
def _generate_at_airport(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, airport: Airport = None, start_type = None) -> FlyingGroup:
def _generate_at_airport(self, name: str, side: Country,
unit_type: FlyingType, count: int,
client_count: int,
airport: Optional[Airport] = None,
start_type=None) -> FlyingGroup:
assert count > 0
assert unit is not None
if start_type is None:
start_type = self._start_type()
@@ -633,7 +686,6 @@ class AircraftConflictGenerator:
def _generate_inflight(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: Point) -> FlyingGroup:
assert count > 0
assert unit is not None
if unit_type in helicopters.helicopter_map.values():
alt = WARM_START_HELI_ALT
@@ -660,9 +712,11 @@ class AircraftConflictGenerator:
group.points[0].alt_type = "RADIO"
return group
def _generate_at_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: typing.Union[ShipGroup, StaticGroup], start_type=None) -> FlyingGroup:
def _generate_at_group(self, name: str, side: Country,
unit_type: FlyingType, count: int, client_count: int,
at: Union[ShipGroup, StaticGroup],
start_type=None) -> FlyingGroup:
assert count > 0
assert unit is not None
if start_type is None:
start_type = self._start_type()
@@ -688,7 +742,7 @@ class AircraftConflictGenerator:
return self._generate_at_group(name, side, unit_type, count, client_count, at)
else:
return self._generate_inflight(name, side, unit_type, count, client_count, at.position)
elif issubclass(at, Airport):
elif isinstance(at, Airport):
takeoff_ban = unit_type in db.TAKEOFF_BAN
ai_ban = client_count == 0 and self.settings.only_player_takeoff
@@ -707,8 +761,9 @@ class AircraftConflictGenerator:
point.alt_type = "RADIO"
return point
def _rtb_for(self, group: FlyingGroup, cp: ControlPoint, at: db.StartingPosition = None):
if not at:
def _rtb_for(self, group: FlyingGroup, cp: ControlPoint,
at: Optional[db.StartingPosition] = None):
if at is None:
at = cp.at
position = at if isinstance(at, Point) else at.position

View File

@@ -195,10 +195,12 @@ AIRFIELD_DATA = {
runway_length=8623,
atc=AtcData(MHz(3, 750), MHz(121, 0), MHz(38, 400), MHz(250, 0)),
outer_ndb={
"22": ("AP", MHz(443, 0)), "4": "443.00 (AN)"
"22": ("AP", MHz(443, 0)),
"04": ("AN", MHz(443)),
},
inner_ndb={
"22": ("P", MHz(215, 0)), "4": "215.00 (N)"
"22": ("P", MHz(215, 0)),
"04": ("N", MHz(215)),
},
),

View File

@@ -1,8 +1,21 @@
from dataclasses import dataclass, field
from typing import List, Type
from dcs.mission import Mission, StartType
from dcs.planes import IL_78M
from dcs.task import (
AWACS,
ActivateBeaconCommand,
MainTask,
Refueling,
SetImmortalCommand,
SetInvisibleCommand,
)
from game import db
from .naming import namegen
from .callsigns import callsign_for_support_unit
from .conflictgen import *
from .naming import *
from .conflictgen import Conflict
from .radios import RadioFrequency, RadioRegistry
from .tacan import TacanBand, TacanChannel, TacanRegistry
@@ -49,7 +62,7 @@ class AirSupportConflictGenerator:
self.tacan_registry = tacan_registry
@classmethod
def support_tasks(cls) -> typing.Collection[typing.Type[MainTask]]:
def support_tasks(cls) -> List[Type[MainTask]]:
return [Refueling, AWACS]
def generate(self, is_awacs_enabled):

View File

@@ -1,13 +1,39 @@
import logging
import random
from dataclasses import dataclass
from typing import List
from dcs import Mission
from dcs.action import AITaskPush
from dcs.condition import TimeAfter, UnitDamaged, Or, GroupLifeLess
from dcs.triggers import TriggerOnce, Event
from dcs.condition import GroupLifeLess, Or, TimeAfter, UnitDamaged
from dcs.country import Country
from dcs.mapping import Point
from dcs.planes import MQ_9_Reaper
from dcs.point import PointAction
from dcs.task import (
AttackGroup,
ControlledTask,
EPLRS,
FireAtPoint,
GoToWaypoint,
Hold,
OrbitAction,
SetImmortalCommand,
SetInvisibleCommand,
)
from dcs.triggers import Event, TriggerOnce
from dcs.unit import Vehicle
from dcs.unittype import VehicleType
from gen import namegen
from gen.ground_forces.ai_ground_planner import CombatGroupRole, DISTANCE_FROM_FRONTLINE
from game import db
from .naming import namegen
from gen.ground_forces.ai_ground_planner import (
CombatGroupRole,
DISTANCE_FROM_FRONTLINE,
)
from .callsigns import callsign_for_support_unit
from .conflictgen import *
from .conflictgen import Conflict
from .ground_forces.combat_stance import CombatStance
SPREAD_DISTANCE_FACTOR = 0.1, 0.3
SPREAD_DISTANCE_SIZE_FACTOR = 0.1
@@ -48,7 +74,7 @@ class GroundConflictGenerator:
self.jtacs: List[JtacInfo] = []
def _group_point(self, point) -> Point:
distance = randint(
distance = random.randint(
int(self.conflict.size * SPREAD_DISTANCE_FACTOR[0]),
int(self.conflict.size * SPREAD_DISTANCE_FACTOR[1]),
)
@@ -165,7 +191,7 @@ class GroundConflictGenerator:
heading=forward_heading,
move_formation=PointAction.OffRoad)
for i in range(randint(3, 10)):
for i in range(random.randint(3, 10)):
u = random.choice(possible_infantry_units)
position = infantry_position.random_point_within(55, 5)
self.mission.vehicle_group(

View File

@@ -1,21 +1,11 @@
import logging
import typing
import pdb
import dcs
import random
from typing import Tuple
from random import randint
from dcs import Mission
from dcs.country import Country
from dcs.mapping import Point
from dcs.mission import *
from dcs.vehicles import *
from dcs.unitgroup import *
from dcs.unittype import *
from dcs.mapping import *
from dcs.point import *
from dcs.task import *
from dcs.country import *
from theater import *
from theater import ConflictTheater, ControlPoint
AIR_DISTANCE = 40000
@@ -65,24 +55,6 @@ def _heading_sum(h, a) -> int:
class Conflict:
attackers_side = None # type: str
defenders_side = None # type: str
attackers_country = None # type: Country
defenders_country = None # type: Country
from_cp = None # type: ControlPoint
to_cp = None # type: ControlPoint
position = None # type: Point
size = None # type: int
radials = None # type: typing.List[int]
heading = None # type: int
distance = None # type: int
ground_attackers_location = None # type: Point
ground_defenders_location = None # type: Point
air_attackers_location = None # type: Point
air_defenders_location = None # type: Point
def __init__(self,
theater: ConflictTheater,
from_cp: ControlPoint,
@@ -155,7 +127,7 @@ class Conflict:
else:
return self.position
def find_ground_position(self, at: Point, heading: int, max_distance: int = 40000) -> typing.Optional[Point]:
def find_ground_position(self, at: Point, heading: int, max_distance: int = 40000) -> Point:
return Conflict._find_ground_position(at, max_distance, heading, self.theater)
@classmethod
@@ -163,7 +135,7 @@ class Conflict:
return from_cp.has_frontline and to_cp.has_frontline
@classmethod
def frontline_position(cls, theater: ConflictTheater, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Optional[typing.Tuple[Point, int]]:
def frontline_position(cls, theater: ConflictTheater, from_cp: ControlPoint, to_cp: ControlPoint) -> Tuple[Point, int]:
attack_heading = from_cp.position.heading_between_point(to_cp.position)
attack_distance = from_cp.position.distance_to_point(to_cp.position)
middle_point = from_cp.position.point_from_heading(attack_heading, attack_distance / 2)
@@ -174,9 +146,7 @@ class Conflict:
@classmethod
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> typing.Optional[typing.Tuple[Point, int, int]]:
initial, heading = cls.frontline_position(theater, from_cp, to_cp)
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> Tuple[Point, int, int]:
"""
probe_end_point = initial.point_from_heading(heading, FRONTLINE_LENGTH)
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y) ])
@@ -193,9 +163,6 @@ class Conflict:
return Point(*intersection.xy[0]), _heading_sum(heading, 90), intersection.length
"""
frontline = cls.frontline_position(theater, from_cp, to_cp)
if not frontline:
return None
center_position, heading = frontline
left_position, right_position = None, None
@@ -243,7 +210,7 @@ class Conflict:
"""
@classmethod
def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> typing.Optional[Point]:
def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point:
pos = initial
for _ in range(0, int(max_distance), 500):
if theater.is_on_land(pos):
@@ -302,10 +269,14 @@ class Conflict:
distance = to_cp.size * GROUND_DISTANCE_FACTOR
attackers_location = position.point_from_heading(attack_heading, distance)
attackers_location = Conflict._find_ground_position(attackers_location, distance * 2, _heading_sum(attack_heading, 180), theater)
attackers_location = Conflict._find_ground_position(
attackers_location, int(distance * 2),
_heading_sum(attack_heading, 180), theater)
defenders_location = position.point_from_heading(defense_heading, distance)
defenders_location = Conflict._find_ground_position(defenders_location, distance * 2, _heading_sum(defense_heading, 180), theater)
defenders_location = Conflict._find_ground_position(
defenders_location, int(distance * 2),
_heading_sum(defense_heading, 180), theater)
return cls(
position=position,
@@ -429,7 +400,7 @@ class Conflict:
assert cls.has_frontline_between(from_cp, to_cp)
position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater)
attack_position = position.point_from_heading(heading, randint(0, int(distance)))
attack_position = position.point_from_heading(heading, random.randint(0, int(distance)))
attackers_position = attack_position.point_from_heading(heading - 90, AIR_DISTANCE)
defenders_position = attack_position.point_from_heading(heading + 90, random.randint(*CAP_CAS_DISTANCE))
@@ -456,7 +427,9 @@ class Conflict:
distance = to_cp.size * GROUND_DISTANCE_FACTOR
defenders_location = position.point_from_heading(defense_heading, distance)
defenders_location = Conflict._find_ground_position(defenders_location, distance * 2, _heading_sum(defense_heading, 180), theater)
defenders_location = Conflict._find_ground_position(
defenders_location, int(distance * 2),
_heading_sum(defense_heading, 180), theater)
return cls(
position=position,

View File

@@ -1,20 +1,11 @@
import logging
import typing
import random
from datetime import datetime, timedelta, time
from datetime import timedelta
from dcs.mission import Mission
from dcs.triggers import *
from dcs.condition import *
from dcs.action import *
from dcs.unit import Skill
from dcs.point import MovingPoint, PointProperties
from dcs.action import *
from dcs.weather import *
from dcs.weather import Weather, Wind
from game import db
from theater import *
from gen import *
from .conflictgen import Conflict
WEATHER_CLOUD_BASE = 2000, 3000
WEATHER_CLOUD_DENSITY = 1, 8

View File

@@ -28,13 +28,13 @@ SHIP_MAP = {
}
def generate_ship_group(game, ground_object, faction:str):
def generate_ship_group(game, ground_object, faction_name: str):
"""
This generate a ship group
:return: Nothing, but put the group reference inside the ground object
"""
faction = db.FACTIONS[faction]
if "boat" in faction.keys():
faction = db.FACTIONS[faction_name]
if "boat" in faction:
generators = faction["boat"]
if len(generators) > 0:
gen = random.choice(generators)

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
import logging
import operator
from dataclasses import dataclass
from typing import Dict, Iterator, List, Optional, Set, TYPE_CHECKING, Tuple
from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple
from dcs.unittype import UnitType
@@ -406,17 +406,18 @@ class CoalitionMissionPlanner:
self.game.aircraft_inventory,
self.is_player
)
for flight in mission.flights:
if not builder.plan_flight(flight):
for proposed_flight in mission.flights:
if not builder.plan_flight(proposed_flight):
builder.release_planned_aircraft()
self.message("Insufficient aircraft",
f"Not enough aircraft in range for {mission}")
return
package = builder.build()
builder = FlightPlanBuilder(self.game, package, self.is_player)
flight_plan_builder = FlightPlanBuilder(self.game, package,
self.is_player)
for flight in package.flights:
builder.populate_flight_plan(flight)
flight_plan_builder.populate_flight_plan(flight)
self.ato.add_package(package)
def message(self, title, text) -> None:

View File

@@ -1,5 +1,78 @@
from dcs.planes import *
from dcs.helicopters import *
from dcs.helicopters import (
AH_1W,
AH_64A,
AH_64D,
Ka_50,
Mi_24V,
Mi_28N,
Mi_8MT,
OH_58D,
SA342L,
SA342M,
UH_1H,
)
from dcs.planes import (
AJS37,
AV8BNA,
A_10A,
A_10C,
A_10C_2,
A_20G,
B_17G,
Bf_109K_4,
C_101CC,
FA_18C_hornet,
FW_190A8,
FW_190D9,
F_14B,
F_15C,
F_15E,
F_16A,
F_16C_50,
F_4E,
F_5E_3,
F_86F_Sabre,
F_A_18C,
JF_17,
J_11A,
Ju_88A4,
L_39ZA,
MQ_9_Reaper,
M_2000C,
MiG_15bis,
MiG_19P,
MiG_21Bis,
MiG_23MLD,
MiG_25PD,
MiG_27K,
MiG_29A,
MiG_29G,
MiG_29K,
MiG_29S,
MiG_31,
Mirage_2000_5,
P_47D_30,
P_47D_30bl1,
P_47D_40,
P_51D,
P_51D_30_NA,
RQ_1A_Predator,
SpitfireLFMkIX,
SpitfireLFMkIXCW,
Su_17M4,
Su_24M,
Su_24MR,
Su_25,
Su_25T,
Su_25TM,
Su_27,
Su_30,
Su_33,
Su_34,
Tornado_GR4,
Tornado_IDS,
WingLoong_I,
)
# Interceptor are the aircraft prioritized for interception tasks
# If none is available, the AI will use regular CAP-capable aircraft instead

View File

@@ -1,10 +1,10 @@
from enum import Enum
from typing import List
from typing import Dict, Optional
from game import db
from dcs.unittype import UnitType
from dcs.point import MovingPoint, PointAction
from theater.controlpoint import ControlPoint
from theater.controlpoint import ControlPoint, MissionTarget
class FlightType(Enum):
@@ -73,8 +73,8 @@ class FlightWaypoint:
self.alt_type = "BARO"
self.name = ""
self.description = ""
self.targets = []
self.targetGroup = None
self.targets: List[MissionTarget] = []
self.targetGroup: Optional[MissionTarget] = None
self.obj_name = ""
self.pretty_name = ""
self.category: PredefinedWaypointCategory = PredefinedWaypointCategory.NOT_PREDEFINED
@@ -110,15 +110,9 @@ class FlightWaypoint:
class Flight:
unit_type: UnitType = None
from_cp = None
points: List[FlightWaypoint] = []
flight_type: FlightType = None
count: int = 0
client_count: int = 0
targets = []
use_custom_loadout = False
loadout = {}
preset_loadout_name = ""
start_type = "Runway"
group = False # Contains DCS Mission group data after mission has been generated
@@ -126,14 +120,14 @@ class Flight:
# How long before this flight should take off
scheduled_in = 0
def __init__(self, unit_type: UnitType, count: int, from_cp, flight_type: FlightType):
def __init__(self, unit_type: UnitType, count: int, from_cp: ControlPoint, flight_type: FlightType):
self.unit_type = unit_type
self.count = count
self.from_cp = from_cp
self.flight_type = flight_type
self.points = []
self.targets = []
self.loadout = {}
self.points: List[FlightWaypoint] = []
self.targets: List[MissionTarget] = []
self.loadout: Dict[str, str] = {}
self.start_type = "Runway"
def __repr__(self):
@@ -143,10 +137,10 @@ class Flight:
# Test
if __name__ == '__main__':
from pydcs.dcs.planes import A_10C
from dcs.planes import A_10C
from theater import ControlPoint, Point, List
from_cp = ControlPoint(0, "AA", Point(0, 0), None, [], 0, 0)
from_cp = ControlPoint(0, "AA", Point(0, 0), Point(0, 0), [], 0, 0)
f = Flight(A_10C(), 4, from_cp, FlightType.CAS)
f.scheduled_in = 50
print(f)

View File

@@ -388,12 +388,14 @@ class FlightPlanBuilder:
def _join_point(self) -> Point:
ingress_point = self.package.ingress_point
assert ingress_point is not None
heading = self._heading_to_package_airfield(ingress_point)
return ingress_point.point_from_heading(heading,
-self.doctrine.join_distance)
def _split_point(self) -> Point:
egress_point = self.package.egress_point
assert egress_point is not None
heading = self._heading_to_package_airfield(egress_point)
return egress_point.point_from_heading(heading,
-self.doctrine.split_distance)

View File

@@ -153,14 +153,16 @@ class WaypointBuilder:
self._target_point(target, name, f"STRIKE [{location.name}]: {name}",
location)
# TODO: Seems fishy.
self.ingress_point.targetGroup = location
if self.ingress_point is not None:
self.ingress_point.targetGroup = location
def sead_point(self, target: Union[TheaterGroundObject, Unit], name: str,
location: MissionTarget) -> None:
self._target_point(target, name, f"STRIKE [{location.name}]: {name}",
location)
# TODO: Seems fishy.
self.ingress_point.targetGroup = location
if self.ingress_point is not None:
self.ingress_point.targetGroup = location
def strike_point(self, target: Union[TheaterGroundObject, Unit], name: str,
location: MissionTarget) -> None:
@@ -191,12 +193,14 @@ class WaypointBuilder:
def sead_area(self, target: MissionTarget) -> None:
self._target_area(f"SEAD on {target.name}", target)
# TODO: Seems fishy.
self.ingress_point.targetGroup = target
if self.ingress_point is not None:
self.ingress_point.targetGroup = target
def dead_area(self, target: MissionTarget) -> None:
self._target_area(f"DEAD on {target.name}", target)
# TODO: Seems fishy.
self.ingress_point.targetGroup = target
if self.ingress_point is not None:
self.ingress_point.targetGroup = target
def _target_area(self, name: str, location: MissionTarget) -> None:
if self.ingress_point is None:

View File

@@ -1,13 +1,13 @@
import random
from enum import Enum
from typing import Dict, List
from dcs.vehicles import *
from gen import Conflict
from gen.ground_forces.combat_stance import CombatStance
from theater import ControlPoint
from dcs.vehicles import Armor, Artillery, Infantry, Unarmed
from dcs.unittype import VehicleType
import pydcs_extensions.frenchpack.frenchpack as frenchpack
from gen.ground_forces.combat_stance import CombatStance
from theater import ControlPoint
TYPE_TANKS = [
Armor.MBT_T_55,
@@ -207,8 +207,8 @@ GROUP_SIZES_BY_COMBAT_STANCE = {
class CombatGroup:
def __init__(self, role:CombatGroupRole):
self.units = []
def __init__(self, role: CombatGroupRole):
self.units: List[VehicleType] = []
self.role = role
self.assigned_enemy_cp = None
self.start_position = None
@@ -222,33 +222,22 @@ class CombatGroup:
class GroundPlanner:
cp = None
combat_groups_dict = {}
connected_enemy_cp = []
tank_groups = []
apc_group = []
ifv_group = []
art_group = []
shorad_groups = []
logi_groups = []
def __init__(self, cp:ControlPoint, game):
self.cp = cp
self.game = game
self.connected_enemy_cp = [cp for cp in self.cp.connected_points if cp.captured != self.cp.captured]
self.tank_groups = []
self.apc_group = []
self.ifv_group = []
self.art_group = []
self.atgm_group = []
self.logi_groups = []
self.shorad_groups = []
self.tank_groups: List[CombatGroup] = []
self.apc_group: List[CombatGroup] = []
self.ifv_group: List[CombatGroup] = []
self.art_group: List[CombatGroup] = []
self.atgm_group: List[CombatGroup] = []
self.logi_groups: List[CombatGroup] = []
self.shorad_groups: List[CombatGroup] = []
self.units_per_cp = {}
self.units_per_cp: Dict[int, List[CombatGroup]] = {}
for cp in self.connected_enemy_cp:
self.units_per_cp[cp.id] = []
self.reserve = []
self.reserve: List[CombatGroup] = []
def plan_groundwar(self):

View File

@@ -1,11 +1,23 @@
from dcs.statics import *
from dcs.unit import Ship, Vehicle
import logging
import random
from typing import Dict, Iterator
from game.data.building_data import FORTIFICATION_UNITS_ID, FORTIFICATION_UNITS
from dcs import Mission
from dcs.statics import fortification_map, warehouse_map
from dcs.task import (
ActivateBeaconCommand,
ActivateICLSCommand,
EPLRS,
OptAlarmState,
)
from dcs.unit import Ship, Vehicle
from dcs.unitgroup import StaticGroup
from game import db
from game.data.building_data import FORTIFICATION_UNITS, FORTIFICATION_UNITS_ID
from game.db import unit_type_from_name
from .airfields import RunwayData
from .conflictgen import *
from .naming import *
from .conflictgen import Conflict
from .radios import RadioRegistry
from .tacan import TacanBand, TacanRegistry
@@ -26,7 +38,7 @@ class GroundObjectsGenerator:
self.icls_alloc = iter(range(1, 21))
self.runways: Dict[str, RunwayData] = {}
def generate_farps(self, number_of_units=1) -> typing.Collection[StaticGroup]:
def generate_farps(self, number_of_units=1) -> Iterator[StaticGroup]:
if self.conflict.is_vector:
center = self.conflict.center
heading = self.conflict.heading - 90

View File

@@ -82,6 +82,8 @@ class KneeboardPageWriter:
def table(self, cells: List[List[str]],
headers: Optional[List[str]] = None) -> None:
if headers is None:
headers = []
table = tabulate(cells, headers=headers, numalign="right")
self.text(table, font=self.table_font)
@@ -136,7 +138,7 @@ class FlightPlanBuilder:
def add_waypoint_row(self, waypoint: NumberedWaypoint) -> None:
self.rows.append([
waypoint.number,
str(waypoint.number),
waypoint.waypoint.pretty_name,
str(int(units.meters_to_feet(waypoint.waypoint.alt)))
])
@@ -194,7 +196,7 @@ class BriefingPage(KneeboardPage):
tankers.append([
tanker.callsign,
tanker.variant,
tanker.tacan,
str(tanker.tacan),
self.format_frequency(tanker.freq),
])
writer.table(tankers, headers=["Callsign", "Type", "TACAN", "UHF"])
@@ -225,12 +227,22 @@ class BriefingPage(KneeboardPage):
atc = ""
if runway.atc is not None:
atc = self.format_frequency(runway.atc)
if runway.tacan is None:
tacan = ""
else:
tacan = str(runway.tacan)
if runway.ils is not None:
ils = str(runway.ils)
elif runway.icls is not None:
ils = str(runway.icls)
else:
ils = ""
return [
row_title,
runway.airfield_name,
atc,
runway.tacan or "",
runway.ils or runway.icls or "",
tacan,
ils,
runway.runway_name,
]

View File

@@ -8,13 +8,13 @@ MISSILES_MAP = {
}
def generate_missile_group(game, ground_object, faction:str):
def generate_missile_group(game, ground_object, faction_name: str):
"""
This generate a ship group
:return: Nothing, but put the group reference inside the ground object
"""
faction = db.FACTIONS[faction]
if "missiles" in faction.keys():
faction = db.FACTIONS[faction_name]
if "missiles" in faction:
generators = faction["missiles"]
if len(generators) > 0:
gen = random.choice(generators)

View File

@@ -1,19 +1,12 @@
import typing
import random
from datetime import datetime, timedelta, time
from dcs.action import MarkToAll
from dcs.condition import TimeAfter
from dcs.mission import Mission
from dcs.triggers import *
from dcs.condition import *
from dcs.action import *
from dcs.task import Option
from dcs.translation import String
from dcs.triggers import Event, TriggerOnce
from dcs.unit import Skill
from dcs.point import MovingPoint, PointProperties
from dcs.action import *
from game import db
from theater import *
from gen.airsupportgen import AirSupportConflictGenerator
from gen import *
from .conflictgen import Conflict
PUSH_TRIGGER_SIZE = 3000
PUSH_TRIGGER_ACTIVATION_AGL = 25

View File

@@ -1,18 +1,20 @@
import typing
from __future__ import annotations
import random
from datetime import datetime, timedelta
from typing import TYPE_CHECKING
from dcs.mapping import Point
from dcs.mission import Mission
from dcs.statics import *
from dcs.unit import Static
from dcs.unittype import StaticType
from theater import *
from .conflictgen import *
#from game.game import Game
from game import db
if TYPE_CHECKING:
from game import Game
from .conflictgen import Conflict, FRONTLINE_LENGTH
class MarkerSmoke(unittype.StaticType):
class MarkerSmoke(StaticType):
id = "big_smoke"
category = "Effects"
name = "big_smoke"
@@ -20,7 +22,7 @@ class MarkerSmoke(unittype.StaticType):
rate = 0.1
class Smoke(unittype.StaticType):
class Smoke(StaticType):
id = "big_smoke"
category = "Effects"
name = "big_smoke"
@@ -28,7 +30,7 @@ class Smoke(unittype.StaticType):
rate = 1
class BigSmoke(unittype.StaticType):
class BigSmoke(StaticType):
id = "big_smoke"
category = "Effects"
name = "big_smoke"
@@ -36,7 +38,7 @@ class BigSmoke(unittype.StaticType):
rate = 1
class MassiveSmoke(unittype.StaticType):
class MassiveSmoke(StaticType):
id = "big_smoke"
category = "Effects"
name = "big_smoke"
@@ -44,7 +46,7 @@ class MassiveSmoke(unittype.StaticType):
rate = 1
class Outpost(unittype.StaticType):
class Outpost(StaticType):
id = "outpost"
name = "outpost"
category = "Fortifications"
@@ -90,9 +92,7 @@ def turn_heading(heading, fac):
class VisualGenerator:
game = None # type: Game
def __init__(self, mission: Mission, conflict: Conflict, game):
def __init__(self, mission: Mission, conflict: Conflict, game: Game):
self.mission = mission
self.conflict = conflict
self.game = game