dcs-retribution/theater/controlpoint.py
2020-05-31 20:00:07 +02:00

186 lines
6.7 KiB
Python

import re
import typing
from enum import Enum
from dcs.mapping import *
from dcs.terrain import Airport
from dcs.ships import CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov
from game import db
from gen.ground_forces.combat_stance import CombatStance
from .theatergroundobject import TheaterGroundObject
class ControlPointType(Enum):
AIRBASE = 0 # An airbase with slot for everything
AIRCRAFT_CARRIER_GROUP = 1 # A group with a Stennis type carrier (F/A-18, F-14 compatible)
LHA_GROUP = 2 # A group with a Tarawa carrier (Helicopters & Harrier)
FARP = 4 # A FARP, with slots for helicopters
FOB = 5 # A FOB (ground units only)
class ControlPoint:
id = 0
position = None # type: Point
name = None # type: str
full_name = None # type: str
base = None # type: theater.base.Base
at = None # type: db.StartPosition
icls = 1
connected_points = None # type: typing.List[ControlPoint]
ground_objects = None # type: typing.List[TheaterGroundObject]
captured = False
has_frontline = True
frontline_offset = 0.0
cptype: ControlPointType = None
ICLS_counter = 1
def __init__(self, id: int, name: str, position: Point, at, radials: typing.Collection[int], size: int, importance: float,
has_frontline=True, cptype=ControlPointType.AIRBASE):
import theater.base
self.id = id
self.name = " ".join(re.split(r" |-", name)[:2])
self.full_name = name
self.position = position
self.at = at
self.ground_objects = []
self.ships = []
self.size = size
self.importance = importance
self.captured = False
self.has_frontline = has_frontline
self.radials = radials
self.connected_points = []
self.base = theater.base.Base()
self.cptype = cptype
self.stances = {}
self.tacanY = False
self.tacanN = None
self.tacanI = "TAC"
self.icls = 0
@classmethod
def from_airport(cls, airport: Airport, radials: typing.Collection[int], size: int, importance: float, has_frontline=True):
assert airport
return cls(airport.id, airport.name, airport.position, airport, radials, size, importance, has_frontline, cptype=ControlPointType.AIRBASE)
@classmethod
def carrier(cls, name: str, at: Point, id: int = 1001):
import theater.conflicttheater
cp = cls(id, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1,
has_frontline=False, cptype=ControlPointType.AIRCRAFT_CARRIER_GROUP)
cp.tacanY = random.choice([True, False])
cp.tacanN = random.randint(26, 49)
cp.tacanI = random.choice(["STE", "CVN", "CVH", "CCV", "ACC", "ARC", "GER", "ABR", "LIN", "TRU"])
ControlPoint.ICLS_counter = ControlPoint.ICLS_counter + 1
cp.icls = ControlPoint.ICLS_counter
return cp
@classmethod
def lha(cls, name: str, at: Point, id: int = 1002):
import theater.conflicttheater
cp = cls(id, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1,
has_frontline=False, cptype=ControlPointType.LHA_GROUP)
cp.tacanY = random.choice([True, False])
cp.tacanN = random.randint(1,25)
cp.tacanI = random.choice(["LHD", "LHA", "LHB", "LHC", "LHD", "LDS"])
return cp
def __str__(self):
return self.name
@property
def is_global(self):
return not self.connected_points
@property
def is_carrier(self):
return self.cptype in [ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP]
@property
def is_fleet(self):
return self.cptype in [ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP]
@property
def is_lha(self):
return self.cptype in [ControlPointType.LHA_GROUP]
@property
def sea_radials(self) -> typing.Collection[int]:
# TODO: fix imports
all_radials = [0, 45, 90, 135, 180, 225, 270, 315, ]
result = []
for r in all_radials:
if r not in self.radials:
result.append(r)
return result
def connect(self, to):
self.connected_points.append(to)
self.stances[to.id] = CombatStance.DEFENSIVE
def has_runway(self):
"""
Check whether this control point can have aircraft taking off or landing.
:return:
"""
if self.cptype in [ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP] :
for g in self.ground_objects:
if g.dcs_identifier in ["CARRIER", "LHA"]:
for group in g.groups:
for u in group.units:
if db.unit_type_from_name(u.type) in [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov]:
return True
return False
elif self.cptype in [ControlPointType.AIRBASE, ControlPointType.FARP]:
return True
else:
return True
def get_carrier_group_name(self):
"""
Get the carrier group name if the airbase is a carrier
:return: Carrier group name
"""
if self.cptype in [ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP] :
for g in self.ground_objects:
if g.dcs_identifier == "CARRIER":
for group in g.groups:
for u in group.units:
if db.unit_type_from_name(u.type) in [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov]:
return group.name
elif g.dcs_identifier == "LHA":
for group in g.groups:
for u in group.units:
if db.unit_type_from_name(u.type) in [LHA_1_Tarawa]:
return group.name
return None
def is_connected(self, to) -> bool:
return to in self.connected_points
def find_radial(self, heading: int, ignored_radial: int = None):
closest_radial = 0
closest_radial_delta = 360
for radial in [x for x in self.radials if x != ignored_radial]:
delta = math.fabs(radial - heading)
if delta < closest_radial_delta:
closest_radial = radial
closest_radial_delta = delta
return closest_radial
def find_ground_objects_by_obj_name(self, obj_name):
found = []
for g in self.ground_objects:
if g.obj_name == obj_name:
found.append(g)
return found