mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Logging before we've made it to the logging setup was causing the root logger to be permanently configured to the default (warning) log level, so we weren't getting any info or debug logs any more. Defer the campaign data load until it is needed rather than doing it at import time. I've also cleaned up a bit so we only load each campaign once, rather than re-loading the campaign to create the theater again after the wizard is finished.
284 lines
8.4 KiB
Python
284 lines
8.4 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any, Dict, Iterator, List, Optional, Tuple
|
|
|
|
from dcs.mapping import Point
|
|
from dcs.terrain import (
|
|
caucasus,
|
|
nevada,
|
|
normandy,
|
|
persiangulf,
|
|
syria,
|
|
thechannel,
|
|
)
|
|
from dcs.terrain.terrain import Terrain
|
|
|
|
from .controlpoint import ControlPoint
|
|
from .landmap import Landmap, load_landmap, poly_contains
|
|
|
|
SIZE_TINY = 150
|
|
SIZE_SMALL = 600
|
|
SIZE_REGULAR = 1000
|
|
SIZE_BIG = 2000
|
|
SIZE_LARGE = 3000
|
|
|
|
IMPORTANCE_LOW = 1
|
|
IMPORTANCE_MEDIUM = 1.2
|
|
IMPORTANCE_HIGH = 1.4
|
|
|
|
"""
|
|
ALL_RADIALS = [0, 45, 90, 135, 180, 225, 270, 315, ]
|
|
COAST_NS_E = [45, 90, 135, ]
|
|
COAST_EW_N = [315, 0, 45, ]
|
|
COAST_NSEW_E = [225, 270, 315, ]
|
|
COAST_NSEW_W = [45, 90, 135, ]
|
|
|
|
COAST_NS_W = [225, 270, 315, ]
|
|
COAST_EW_S = [135, 180, 225, ]
|
|
"""
|
|
|
|
LAND = [0, 45, 90, 135, 180, 225, 270, 315, ]
|
|
|
|
COAST_V_E = [0, 45, 90, 135, 180]
|
|
COAST_V_W = [180, 225, 270, 315, 0]
|
|
|
|
COAST_A_W = [315, 0, 45, 135, 180, 225, 270]
|
|
COAST_A_E = [0, 45, 90, 135, 180, 225, 315]
|
|
|
|
COAST_H_N = [270, 315, 0, 45, 90]
|
|
COAST_H_S = [90, 135, 180, 225, 270]
|
|
|
|
COAST_DL_E = [45, 90, 135, 180, 225]
|
|
COAST_DL_W = [225, 270, 315, 0, 45]
|
|
COAST_DR_E = [315, 0, 45, 90, 135]
|
|
COAST_DR_W = [135, 180, 225, 315]
|
|
|
|
|
|
class ConflictTheater:
|
|
terrain: Terrain
|
|
|
|
reference_points: Dict[Tuple[float, float], Tuple[float, float]]
|
|
overview_image: str
|
|
landmap: Optional[Landmap]
|
|
"""
|
|
land_poly = None # type: Polygon
|
|
"""
|
|
daytime_map: Dict[str, Tuple[int, int]]
|
|
|
|
def __init__(self):
|
|
self.controlpoints: List[ControlPoint] = []
|
|
"""
|
|
self.land_poly = geometry.Polygon(self.landmap[0][0])
|
|
for x in self.landmap[1]:
|
|
self.land_poly = self.land_poly.difference(geometry.Polygon(x))
|
|
"""
|
|
|
|
def add_controlpoint(self, point: ControlPoint,
|
|
connected_to: Optional[List[ControlPoint]] = None):
|
|
if connected_to is None:
|
|
connected_to = []
|
|
for connected_point in connected_to:
|
|
point.connect(to=connected_point)
|
|
|
|
self.controlpoints.append(point)
|
|
|
|
def find_ground_objects_by_obj_name(self, obj_name):
|
|
found = []
|
|
for cp in self.controlpoints:
|
|
for g in cp.ground_objects:
|
|
if g.obj_name == obj_name:
|
|
found.append(g)
|
|
return found
|
|
|
|
def is_in_sea(self, point: Point) -> bool:
|
|
if not self.landmap:
|
|
return False
|
|
|
|
for inclusion_zone in self.landmap[0]:
|
|
if poly_contains(point.x, point.y, inclusion_zone):
|
|
return False
|
|
|
|
return True
|
|
|
|
def is_on_land(self, point: Point) -> bool:
|
|
if not self.landmap:
|
|
return True
|
|
|
|
is_point_included = False
|
|
for inclusion_zone in self.landmap[0]:
|
|
if poly_contains(point.x, point.y, inclusion_zone):
|
|
is_point_included = True
|
|
|
|
if not is_point_included:
|
|
return False
|
|
|
|
for exclusion_zone in self.landmap[1]:
|
|
if poly_contains(point.x, point.y, exclusion_zone):
|
|
return False
|
|
|
|
return True
|
|
|
|
def player_points(self) -> List[ControlPoint]:
|
|
return [point for point in self.controlpoints if point.captured]
|
|
|
|
def conflicts(self, from_player=True) -> Iterator[Tuple[ControlPoint, ControlPoint]]:
|
|
for cp in [x for x in self.controlpoints if x.captured == from_player]:
|
|
for connected_point in [x for x in cp.connected_points if x.captured != from_player]:
|
|
yield cp, connected_point
|
|
|
|
def enemy_points(self) -> List[ControlPoint]:
|
|
return [point for point in self.controlpoints if not point.captured]
|
|
|
|
def add_json_cp(self, theater, p: dict) -> ControlPoint:
|
|
|
|
if p["type"] == "airbase":
|
|
|
|
airbase = theater.terrain.airports[p["id"]].__class__
|
|
|
|
if "radials" in p.keys():
|
|
radials = p["radials"]
|
|
else:
|
|
radials = LAND
|
|
|
|
if "size" in p.keys():
|
|
size = p["size"]
|
|
else:
|
|
size = SIZE_REGULAR
|
|
|
|
if "importance" in p.keys():
|
|
importance = p["importance"]
|
|
else:
|
|
importance = IMPORTANCE_MEDIUM
|
|
|
|
cp = ControlPoint.from_airport(airbase, radials, size, importance)
|
|
elif p["type"] == "carrier":
|
|
cp = ControlPoint.carrier("carrier", Point(p["x"], p["y"]), p["id"])
|
|
else:
|
|
cp = ControlPoint.lha("lha", Point(p["x"], p["y"]), p["id"])
|
|
|
|
if "captured_invert" in p.keys():
|
|
cp.captured_invert = p["captured_invert"]
|
|
else:
|
|
cp.captured_invert = False
|
|
|
|
return cp
|
|
|
|
@staticmethod
|
|
def from_json(data: Dict[str, Any]) -> ConflictTheater:
|
|
theaters = {
|
|
"Caucasus": CaucasusTheater,
|
|
"Nevada": NevadaTheater,
|
|
"Persian Gulf": PersianGulfTheater,
|
|
"Normandy": NormandyTheater,
|
|
"The Channel": TheChannelTheater,
|
|
"Syria": SyriaTheater,
|
|
}
|
|
theater = theaters[data["theater"]]
|
|
t = theater()
|
|
cps = {}
|
|
|
|
for p in data["player_points"]:
|
|
cp = t.add_json_cp(theater, p)
|
|
cp.captured = True
|
|
cps[p["id"]] = cp
|
|
t.add_controlpoint(cp)
|
|
|
|
for p in data["enemy_points"]:
|
|
cp = t.add_json_cp(theater, p)
|
|
cps[p["id"]] = cp
|
|
t.add_controlpoint(cp)
|
|
|
|
for l in data["links"]:
|
|
cps[l[0]].connect(cps[l[1]])
|
|
cps[l[1]].connect(cps[l[0]])
|
|
|
|
return t
|
|
|
|
|
|
class CaucasusTheater(ConflictTheater):
|
|
terrain = caucasus.Caucasus()
|
|
overview_image = "caumap.gif"
|
|
reference_points = {(-317948.32727306, 635639.37385346): (278.5 * 4, 319 * 4),
|
|
(-355692.3067714, 617269.96285781): (263 * 4, 352 * 4), }
|
|
|
|
landmap = load_landmap("resources\\caulandmap.p")
|
|
daytime_map = {
|
|
"dawn": (6, 9),
|
|
"day": (9, 18),
|
|
"dusk": (18, 20),
|
|
"night": (0, 5),
|
|
}
|
|
|
|
|
|
class PersianGulfTheater(ConflictTheater):
|
|
terrain = persiangulf.PersianGulf()
|
|
overview_image = "persiangulf.gif"
|
|
reference_points = {
|
|
(persiangulf.Shiraz_International_Airport.position.x, persiangulf.Shiraz_International_Airport.position.y): (
|
|
772, -1970),
|
|
(persiangulf.Liwa_Airbase.position.x, persiangulf.Liwa_Airbase.position.y): (1188, 78), }
|
|
landmap = load_landmap("resources\\gulflandmap.p")
|
|
daytime_map = {
|
|
"dawn": (6, 8),
|
|
"day": (8, 16),
|
|
"dusk": (16, 18),
|
|
"night": (0, 5),
|
|
}
|
|
|
|
|
|
class NevadaTheater(ConflictTheater):
|
|
terrain = nevada.Nevada()
|
|
overview_image = "nevada.gif"
|
|
reference_points = {(nevada.Mina_Airport_3Q0.position.x, nevada.Mina_Airport_3Q0.position.y): (45 * 2, -360 * 2),
|
|
(nevada.Laughlin_Airport.position.x, nevada.Laughlin_Airport.position.y): (440 * 2, 80 * 2), }
|
|
landmap = load_landmap("resources\\nev_landmap.p")
|
|
daytime_map = {
|
|
"dawn": (4, 6),
|
|
"day": (6, 17),
|
|
"dusk": (17, 18),
|
|
"night": (0, 5),
|
|
}
|
|
|
|
|
|
class NormandyTheater(ConflictTheater):
|
|
terrain = normandy.Normandy()
|
|
overview_image = "normandy.gif"
|
|
reference_points = {(normandy.Needs_Oar_Point.position.x, normandy.Needs_Oar_Point.position.y): (-170, -1000),
|
|
(normandy.Evreux.position.x, normandy.Evreux.position.y): (2020, 500)}
|
|
landmap = load_landmap("resources\\normandylandmap.p")
|
|
daytime_map = {
|
|
"dawn": (6, 8),
|
|
"day": (10, 17),
|
|
"dusk": (17, 18),
|
|
"night": (0, 5),
|
|
}
|
|
|
|
|
|
class TheChannelTheater(ConflictTheater):
|
|
terrain = thechannel.TheChannel()
|
|
overview_image = "thechannel.gif"
|
|
reference_points = {(thechannel.Abbeville_Drucat.position.x, thechannel.Abbeville_Drucat.position.y): (2400, 4100),
|
|
(thechannel.Detling.position.x, thechannel.Detling.position.y): (1100, 2000)}
|
|
landmap = load_landmap("resources\\channellandmap.p")
|
|
daytime_map = {
|
|
"dawn": (6, 8),
|
|
"day": (10, 17),
|
|
"dusk": (17, 18),
|
|
"night": (0, 5),
|
|
}
|
|
|
|
|
|
class SyriaTheater(ConflictTheater):
|
|
terrain = syria.Syria()
|
|
overview_image = "syria.gif"
|
|
reference_points = {(syria.Eyn_Shemer.position.x, syria.Eyn_Shemer.position.y): (1300, 1380),
|
|
(syria.Tabqa.position.x, syria.Tabqa.position.y): (2060, 570)}
|
|
landmap = load_landmap("resources\\syrialandmap.p")
|
|
daytime_map = {
|
|
"dawn": (6, 8),
|
|
"day": (8, 16),
|
|
"dusk": (16, 18),
|
|
"night": (0, 5),
|
|
}
|