Show runway status on the new map.

Fixes https://github.com/dcs-liberation/dcs_liberation/issues/1105
This commit is contained in:
Dan Albert 2021-05-31 14:17:57 -07:00
parent 355e6e1d15
commit 284f2bc323
3 changed files with 67 additions and 15 deletions

View File

@ -6,7 +6,7 @@ import logging
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum, unique, auto, IntEnum
from functools import total_ordering, cached_property from functools import total_ordering, cached_property
from typing import ( from typing import (
Any, Any,
@ -219,6 +219,13 @@ class GroundUnitDestination:
return self.total_value < other.total_value return self.total_value < other.total_value
@unique
class ControlPointStatus(IntEnum):
Functional = auto()
Damaged = auto()
Destroyed = auto()
class ControlPoint(MissionTarget, ABC): class ControlPoint(MissionTarget, ABC):
position = None # type: Point position = None # type: Point
@ -710,6 +717,11 @@ class ControlPoint(MissionTarget, ABC):
def category(self) -> str: def category(self) -> str:
... ...
@property
@abstractmethod
def status(self) -> ControlPointStatus:
...
class Airfield(ControlPoint): class Airfield(ControlPoint):
def __init__( def __init__(
@ -794,6 +806,15 @@ class Airfield(ControlPoint):
def category(self) -> str: def category(self) -> str:
return "airfield" return "airfield"
@property
def status(self) -> ControlPointStatus:
runway_staus = self.runway_status
if runway_staus.needs_repair:
return ControlPointStatus.Destroyed
elif runway_staus.damaged:
return ControlPointStatus.Damaged
return ControlPointStatus.Functional
class NavalControlPoint(ControlPoint, ABC): class NavalControlPoint(ControlPoint, ABC):
@property @property
@ -818,20 +839,24 @@ class NavalControlPoint(ControlPoint, ABC):
def heading(self) -> int: def heading(self) -> int:
return 0 # TODO compute heading return 0 # TODO compute heading
def find_main_tgo(self) -> TheaterGroundObject:
for g in self.ground_objects:
if g.dcs_identifier in ["CARRIER", "LHA"]:
return g
raise RuntimeError(f"Found no carrier/LHA group for {self.name}")
def runway_is_operational(self) -> bool: def runway_is_operational(self) -> bool:
# Necessary because it's possible for the carrier itself to have sunk # Necessary because it's possible for the carrier itself to have sunk
# while its escorts are still alive. # while its escorts are still alive.
for g in self.ground_objects: for group in self.find_main_tgo().groups:
if g.dcs_identifier in ["CARRIER", "LHA"]: for u in group.units:
for group in g.groups: if db.unit_type_from_name(u.type) in [
for u in group.units: CVN_74_John_C__Stennis,
if db.unit_type_from_name(u.type) in [ LHA_1_Tarawa,
CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov,
LHA_1_Tarawa, Type_071_Amphibious_Transport_Dock,
CV_1143_5_Admiral_Kuznetsov, ]:
Type_071_Amphibious_Transport_Dock, return True
]:
return True
return False return False
def active_runway( def active_runway(
@ -857,6 +882,14 @@ class NavalControlPoint(ControlPoint, ABC):
def can_deploy_ground_units(self) -> bool: def can_deploy_ground_units(self) -> bool:
return False return False
@property
def status(self) -> ControlPointStatus:
if not self.runway_is_operational():
return ControlPointStatus.Destroyed
if self.find_main_tgo().dead_units:
return ControlPointStatus.Damaged
return ControlPointStatus.Functional
class Carrier(NavalControlPoint): class Carrier(NavalControlPoint):
def __init__(self, name: str, at: Point, cp_id: int): def __init__(self, name: str, at: Point, cp_id: int):
@ -986,6 +1019,10 @@ class OffMapSpawn(ControlPoint):
def category(self) -> str: def category(self) -> str:
return "offmap" return "offmap"
@property
def status(self) -> ControlPointStatus:
return ControlPointStatus.Functional
class Fob(ControlPoint): class Fob(ControlPoint):
def __init__(self, name: str, at: Point, cp_id: int): def __init__(self, name: str, at: Point, cp_id: int):
@ -1046,3 +1083,7 @@ class Fob(ControlPoint):
@property @property
def category(self) -> str: def category(self) -> str:
return "fob" return "fob"
@property
def status(self) -> ControlPointStatus:
return ControlPointStatus.Functional

View File

@ -20,6 +20,7 @@ from game.theater import (
TheaterGroundObject, TheaterGroundObject,
FrontLine, FrontLine,
LatLon, LatLon,
ControlPointStatus,
) )
from game.threatzones import ThreatZones from game.threatzones import ThreatZones
from game.transfers import MultiGroupTransport, TransportMap from game.transfers import MultiGroupTransport, TransportMap
@ -79,6 +80,7 @@ class ControlPointJs(QObject):
mobileChanged = Signal() mobileChanged = Signal()
destinationChanged = Signal(list) destinationChanged = Signal(list)
categoryChanged = Signal() categoryChanged = Signal()
statusChanged = Signal()
def __init__( def __init__(
self, self,
@ -104,6 +106,17 @@ class ControlPointJs(QObject):
def category(self) -> str: def category(self) -> str:
return self.control_point.category return self.control_point.category
@Property(str, notify=statusChanged)
def status(self) -> str:
status = self.control_point.status
if status is ControlPointStatus.Functional:
return "alive"
elif status is ControlPointStatus.Damaged:
return "damaged"
elif status is ControlPointStatus.Destroyed:
return "destroyed"
raise ValueError(f"Unhandled ControlPointStatus: {status.name}")
@Property(list, notify=positionChanged) @Property(list, notify=positionChanged)
def position(self) -> LeafletLatLon: def position(self) -> LeafletLatLon:
ll = self.theater.point_to_ll(self.control_point.position) ll = self.theater.point_to_ll(self.control_point.position)

View File

@ -290,12 +290,10 @@ class ControlPoint {
} }
icon() { icon() {
// TODO: Runway status.
// https://github.com/dcs-liberation/dcs_liberation/issues/1105
return Icons.ControlPoints.icon( return Icons.ControlPoints.icon(
this.cp.category, this.cp.category,
this.cp.blue, this.cp.blue,
UnitState.Alive this.cp.status
); );
} }