Merge remote-tracking branch 'upstream/develop_2_3_x' into ground_tasking

This commit is contained in:
walterroach 2020-12-12 12:44:47 -06:00
commit 817d6a0e15
27 changed files with 173 additions and 206 deletions

View File

@ -3,9 +3,9 @@ import dcs
DEFAULT_AVAILABLE_BUILDINGS = ['fuel', 'ammo', 'comms', 'oil', 'ware', 'farp', 'fob', 'power', 'factory', 'derrick'] DEFAULT_AVAILABLE_BUILDINGS = ['fuel', 'ammo', 'comms', 'oil', 'ware', 'farp', 'fob', 'power', 'factory', 'derrick']
WW2_FREE = ['fuel', 'factory', 'ware'] WW2_FREE = ['fuel', 'factory', 'ware', 'fob']
WW2_GERMANY_BUILDINGS = ['fuel', 'factory', 'ww2bunker', 'ww2bunker', 'ww2bunker', 'allycamp', 'allycamp'] WW2_GERMANY_BUILDINGS = ['fuel', 'factory', 'ww2bunker', 'ww2bunker', 'ww2bunker', 'allycamp', 'allycamp', 'fob']
WW2_ALLIES_BUILDINGS = ['fuel', 'factory', 'allycamp', 'allycamp', 'allycamp', 'allycamp', 'allycamp'] WW2_ALLIES_BUILDINGS = ['fuel', 'factory', 'allycamp', 'allycamp', 'allycamp', 'allycamp', 'allycamp', 'fob']
FORTIFICATION_BUILDINGS = ['Siegfried Line', 'Concertina wire', 'Concertina Wire', 'Czech hedgehogs 1', 'Czech hedgehogs 2', FORTIFICATION_BUILDINGS = ['Siegfried Line', 'Concertina wire', 'Concertina Wire', 'Czech hedgehogs 1', 'Czech hedgehogs 2',
'Dragonteeth 1', 'Dragonteeth 2', 'Dragonteeth 3', 'Dragonteeth 4', 'Dragonteeth 5', 'Dragonteeth 1', 'Dragonteeth 2', 'Dragonteeth 3', 'Dragonteeth 4', 'Dragonteeth 5',

View File

@ -664,15 +664,14 @@ UNIT_BY_TASK = {
Tu_95MS, Tu_95MS,
UH_1H, UH_1H,
WingLoong_I, WingLoong_I,
Hercules
], ],
Transport: [ Transport: [
IL_76MD, IL_76MD,
An_26B, An_26B,
An_30M, An_30M,
Yak_40, Yak_40,
C_130
C_130,
Hercules,
], ],
Refueling: [ Refueling: [
IL_78M, IL_78M,

View File

@ -2,8 +2,10 @@ import pickle
from typing import Collection, Optional, Tuple from typing import Collection, Optional, Tuple
import logging import logging
from shapely import geometry
Zone = Collection[Tuple[float, float]] Zone = Collection[Tuple[float, float]]
Landmap = Tuple[Collection[Zone], Collection[Zone], Collection[Zone]] Landmap = Tuple[Collection[geometry.Polygon], Collection[geometry.Polygon], Collection[geometry.Polygon]]
def load_landmap(filename: str) -> Optional[Landmap]: def load_landmap(filename: str) -> Optional[Landmap]:
@ -15,22 +17,9 @@ def load_landmap(filename: str) -> Optional[Landmap]:
return None return None
def poly_contains(x, y, poly): def poly_contains(x, y, poly:geometry.Polygon):
n = len(poly) return poly.contains(geometry.Point(x, y))
inside = False
xints = 0.0
p1x, p1y = poly[0]
for i in range(n+1):
p2x, p2y = poly[i % n]
if y > min(p1y, p2y):
if y <= max(p1y, p2y):
if x <= max(p1x, p2x):
if p1y != p2y:
xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xints:
inside = not inside
p1x, p1y = p2x, p2y
return inside
def poly_centroid(poly) -> Tuple[float, float]: def poly_centroid(poly) -> Tuple[float, float]:
x_list = [vertex[0] for vertex in poly] x_list = [vertex[0] for vertex in poly]

View File

@ -37,6 +37,7 @@ def knots_to_kph(value_in_knots: float) -> int:
""" """
return int(value_in_knots * 1.852) return int(value_in_knots * 1.852)
def mps_to_knots(value_in_mps: float) -> int: def mps_to_knots(value_in_mps: float) -> int:
"""Converts Meters Per Second To Knots """Converts Meters Per Second To Knots
@ -44,6 +45,23 @@ def mps_to_knots(value_in_mps: float) -> int:
""" """
return int(value_in_mps * 1.943) return int(value_in_mps * 1.943)
def mps_to_kph(speed: float) -> int:
"""Converts meters per second to kilometers per hour.
:arg speed Speed in m/s.
"""
return int(speed * 3.6)
def kph_to_mps(speed: float) -> int:
"""Converts kilometers per hour to meters per second.
:arg speed Speed in KPH.
"""
return int(speed / 3.6)
def heading_sum(h, a) -> int: def heading_sum(h, a) -> int:
h += a h += a
if h > 360: if h > 360:

View File

@ -34,6 +34,7 @@ from game.theater.theatergroundobject import (
LhaGroundObject, ShipGroundObject, LhaGroundObject, ShipGroundObject,
) )
from game.unitmap import UnitMap from game.unitmap import UnitMap
from game.utils import knots_to_kph, kph_to_mps, mps_to_kph
from .radios import RadioFrequency, RadioRegistry from .radios import RadioFrequency, RadioRegistry
from .runways import RunwayData from .runways import RunwayData
from .tacan import TacanBand, TacanChannel, TacanRegistry from .tacan import TacanBand, TacanChannel, TacanRegistry
@ -204,10 +205,11 @@ class GenericCarrierGenerator(GenericGroundObjectGenerator):
tacan_callsign = self.tacan_callsign() tacan_callsign = self.tacan_callsign()
icls = next(self.icls_alloc) icls = next(self.icls_alloc)
if self.control_point.target_position is not None: # Always steam into the wind, even if the carrier is being moved.
brc = self.steam_to_target_position(ship_group) # There are multiple unsimulated hours between turns, so we can
else: # count those as the time the carrier uses to move and the mission
brc = self.steam_into_wind(ship_group) # time as the recovery window.
brc = self.steam_into_wind(ship_group)
self.activate_beacons(ship_group, tacan, tacan_callsign, icls) self.activate_beacons(ship_group, tacan, tacan_callsign, icls)
self.add_runway_data(brc or 0, atc, tacan, tacan_callsign, icls) self.add_runway_data(brc or 0, atc, tacan, tacan_callsign, icls)
self._register_unit_group(group, ship_group) self._register_unit_group(group, ship_group)
@ -242,19 +244,19 @@ class GenericCarrierGenerator(GenericGroundObjectGenerator):
return ship return ship
def steam_into_wind(self, group: ShipGroup) -> Optional[int]: def steam_into_wind(self, group: ShipGroup) -> Optional[int]:
brc = self.m.weather.wind_at_ground.direction + 180 wind = self.game.conditions.weather.wind.at_0m
brc = wind.direction + 180
# Aim for 25kts over the deck.
carrier_speed = knots_to_kph(25) - mps_to_kph(wind.speed)
for attempt in range(5): for attempt in range(5):
point = group.points[0].position.point_from_heading( point = group.points[0].position.point_from_heading(
brc, 100000 - attempt * 20000) brc, 100000 - attempt * 20000)
if self.game.theater.is_in_sea(point): if self.game.theater.is_in_sea(point):
group.add_waypoint(point) group.points[0].speed = kph_to_mps(carrier_speed)
group.add_waypoint(point, carrier_speed)
return brc return brc
return None return None
def steam_to_target_position(self, group: ShipGroup) -> Optional[int]:
group.add_waypoint(self.control_point.target_position)
return group.position.heading_between_point(self.control_point.target_position)
def tacan_callsign(self) -> str: def tacan_callsign(self) -> str:
raise NotImplementedError raise NotImplementedError

View File

@ -9,4 +9,7 @@ ignore_missing_imports = True
ignore_missing_imports = True ignore_missing_imports = True
[mypy-winreg.*] [mypy-winreg.*]
ignore_missing_imports = True
[mypy-shapely.*]
ignore_missing_imports = True ignore_missing_imports = True

2
pydcs

@ -1 +1 @@
Subproject commit c149afae71dfb534c6f180e2dde9fdc20b4d7d1b Subproject commit f924289c9cbe6e21a01906bdf11c1933110a32de

View File

@ -20,8 +20,9 @@ class DisplayRule:
def value(self, value: bool) -> None: def value(self, value: bool) -> None:
from qt_ui.widgets.map.QLiberationMap import QLiberationMap from qt_ui.widgets.map.QLiberationMap import QLiberationMap
self._value = value self._value = value
QLiberationMap.instance.reload_scene() if QLiberationMap.instance is not None:
QLiberationMap.instance.update() QLiberationMap.instance.reload_scene()
QLiberationMap.instance.update()
def __bool__(self) -> bool: def __bool__(self) -> bool:
return self.value return self.value

View File

@ -270,8 +270,8 @@ class QLiberationMap(QGraphicsView):
culling_distance_point = Point(point.x + culling_distance*1000, point.y + culling_distance*1000) culling_distance_point = Point(point.x + culling_distance*1000, point.y + culling_distance*1000)
distance_point = self._transform_point(culling_distance_point) distance_point = self._transform_point(culling_distance_point)
transformed = self._transform_point(point) transformed = self._transform_point(point)
diameter = distance_point[0] - transformed[0] radius = distance_point[0] - transformed[0]
scene.addEllipse(transformed[0]-diameter/2, transformed[1]-diameter/2, diameter, diameter, CONST.COLORS["transparent"], CONST.COLORS["light_green_transparent"]) scene.addEllipse(transformed[0]-radius, transformed[1]-radius, 2*radius, 2*radius, CONST.COLORS["transparent"], CONST.COLORS["light_green_transparent"])
@staticmethod @staticmethod
def should_display_ground_objects_at(cp: ControlPoint) -> bool: def should_display_ground_objects_at(cp: ControlPoint) -> bool:
@ -744,7 +744,7 @@ class QLiberationMap(QGraphicsView):
for sea_zone in self.game.theater.landmap[2]: for sea_zone in self.game.theater.landmap[2]:
print(sea_zone) print(sea_zone)
poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in sea_zone]) poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in sea_zone.exterior.coords])
if self.reference_point_setup_mode: if self.reference_point_setup_mode:
color = "sea_blue_transparent" color = "sea_blue_transparent"
else: else:
@ -752,14 +752,14 @@ class QLiberationMap(QGraphicsView):
scene.addPolygon(poly, CONST.COLORS[color], CONST.COLORS[color]) scene.addPolygon(poly, CONST.COLORS[color], CONST.COLORS[color])
for inclusion_zone in self.game.theater.landmap[0]: for inclusion_zone in self.game.theater.landmap[0]:
poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in inclusion_zone]) poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in inclusion_zone.exterior.coords])
if self.reference_point_setup_mode: if self.reference_point_setup_mode:
scene.addPolygon(poly, CONST.COLORS["grey_transparent"], CONST.COLORS["dark_grey_transparent"]) scene.addPolygon(poly, CONST.COLORS["grey_transparent"], CONST.COLORS["dark_grey_transparent"])
else: else:
scene.addPolygon(poly, CONST.COLORS["grey"], CONST.COLORS["dark_grey"]) scene.addPolygon(poly, CONST.COLORS["grey"], CONST.COLORS["dark_grey"])
for exclusion_zone in self.game.theater.landmap[1]: for exclusion_zone in self.game.theater.landmap[1]:
poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in exclusion_zone]) poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in exclusion_zone.exterior.coords])
if self.reference_point_setup_mode: if self.reference_point_setup_mode:
scene.addPolygon(poly, CONST.COLORS["grey_transparent"], CONST.COLORS["dark_dark_grey_transparent"]) scene.addPolygon(poly, CONST.COLORS["grey_transparent"], CONST.COLORS["dark_dark_grey_transparent"])
else: else:

View File

@ -363,7 +363,7 @@ class QSettingsWindow(QDialog):
self.culling.toggled.connect(self.applySettings) self.culling.toggled.connect(self.applySettings)
self.culling_distance = QSpinBox() self.culling_distance = QSpinBox()
self.culling_distance.setMinimum(50) self.culling_distance.setMinimum(10)
self.culling_distance.setMaximum(10000) self.culling_distance.setMaximum(10000)
self.culling_distance.setValue(self.game.settings.perf_culling_distance) self.culling_distance.setValue(self.game.settings.perf_culling_distance)
self.culling_distance.valueChanged.connect(self.applySettings) self.culling_distance.valueChanged.connect(self.applySettings)

View File

@ -8,3 +8,4 @@ tabulate~=0.8.7
mypy==0.782 mypy==0.782
mypy-extensions==0.4.3 mypy-extensions==0.4.3
jinja2>=2.11.2 jinja2>=2.11.2
shapely==1.7.1

View File

@ -3,85 +3,5 @@
"theater": "Syria", "theater": "Syria",
"authors": "Khopa", "authors": "Khopa",
"description": "<p>In this scenario, you start from Turkey and have to invade territories in northern Syria.</p>", "description": "<p>In this scenario, you start from Turkey and have to invade territories in northern Syria.</p>",
"player_points": [ "miz": "invasion_from_turkey.miz"
{
"type": "airbase",
"id": "Incirlik",
"size": 1000,
"importance": 1.4
},
{
"type": "airbase",
"id": "Hatay",
"size": 1000,
"importance": 1.4
},
{
"type": "carrier",
"id": 1001,
"x": 133000,
"y": -54000
},
{
"type": "lha",
"id": 1002,
"x": 155000,
"y": -19000
}
],
"enemy_points": [
{
"type": "airbase",
"id": "Minakh",
"size": 1000,
"importance": 1
},
{
"type": "airbase",
"id": "Aleppo",
"size": 1000,
"importance": 1.2
},
{
"type": "airbase",
"id": "Kuweires",
"size": 1000,
"importance": 1
},
{
"type": "airbase",
"id": "Jirah",
"size": 1000,
"importance": 1
},
{
"type": "airbase",
"id": "Tabqa",
"size": 1000,
"importance": 1,
"captured_invert": true
}
],
"links": [
[
"Hatay",
"Minakh"
],
[
"Aleppo",
"Minakh"
],
[
"Aleppo",
"Kuweires"
],
[
"Jirah",
"Kuweires"
],
[
"Jirah",
"Tabqa"
]
]
} }

Binary file not shown.

View File

@ -3,83 +3,5 @@
"theater": "Normandy", "theater": "Normandy",
"authors": "Khopa", "authors": "Khopa",
"description": "<p>Normandy 1944 D-Day scenario.</p>", "description": "<p>Normandy 1944 D-Day scenario.</p>",
"player_points": [ "miz":"normandy.miz"
{
"type": "airbase",
"id": "Chailey",
"size": 600,
"importance": 1
},
{
"type": "airbase",
"id": "Needs Oar Point",
"size": 600,
"importance": 1
},
{
"type": "airbase",
"id": "Deux Jumeaux",
"size": 600,
"importance": 1
}
],
"enemy_points": [
{
"type": "airbase",
"id": "Lignerolles",
"size": 600,
"importance": 1
},
{
"type": "airbase",
"id": "Lessay",
"size": 600,
"importance": 1
},
{
"type": "airbase",
"id": "Carpiquet",
"size": 600,
"importance": 1
},
{
"type": "airbase",
"id": "Maupertus",
"size": 600,
"importance": 1
},
{
"type": "airbase",
"id": "Evreux",
"size": 600,
"importance": 1,
"captured_invert": true
}
],
"links": [
[
"Chailey",
"Needs Oar Point"
],
[
"Deux Jumeaux",
"Lignerolles"
],
[
"Lessay",
"Lignerolles"
],
[
"Carpiquet",
"Lignerolles"
],
[
"Lessay",
"Maupertus"
],
[
"Carpiquet",
"Evreux"
]
]
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,111 @@
{
"country": "USA",
"name": "USA 2005",
"authors": "Khopa",
"description": "<p>USA in the 2000s.</p>",
"aircrafts": [
"F_15C",
"F_15E",
"F_14B",
"FA_18C_hornet",
"F_16C_50",
"A_10C",
"A_10C_2",
"AV8BNA",
"UH_1H",
"AH_64D",
"B_52H",
"B_1B",
"F_117A",
"Hercules"
],
"awacs": [
"E_3A"
],
"tankers": [
"KC_135",
"KC130"
],
"frontline_units": [
"MBT_M1A2_Abrams",
"ATGM_M1134_Stryker",
"APC_M1126_Stryker_ICV",
"IFV_M2A2_Bradley",
"IFV_LAV_25",
"APC_M1043_HMMWV_Armament",
"ATGM_M1045_HMMWV_TOW"
],
"artillery_units": [
"MLRS_M270",
"SPH_M109_Paladin"
],
"logistics_units": [
"Transport_M818"
],
"infantry_units": [
"Infantry_M4",
"Soldier_M249",
"Stinger_MANPADS"
],
"air_defenses": [
"AvengerGenerator",
"LinebackerGenerator",
"PatriotGenerator"
],
"ewrs": [
"PatriotEwrGenerator"
],
"aircraft_carrier": [
"CVN_74_John_C__Stennis"
],
"helicopter_carrier": [
"LHA_1_Tarawa"
],
"destroyers": [
"USS_Arleigh_Burke_IIa"
],
"cruisers": [
"Ticonderoga_class"
],
"requirements": {},
"carrier_names": [
"CVN-71 Theodore Roosevelt",
"CVN-72 Abraham Lincoln",
"CVN-73 George Washington",
"CVN-74 John C. Stennis",
"CVN-75 Harry S. Truman"
],
"helicopter_carrier_names": [
"LHA-1 Tarawa",
"LHA-2 Saipan",
"LHA-3 Belleau Wood",
"LHA-4 Nassau",
"LHA-5 Peleliu"
],
"navy_generators": [
"ArleighBurkeGroupGenerator",
"OliverHazardPerryGroupGenerator"
],
"has_jtac": true,
"jtac_unit": "MQ_9_Reaper",
"liveries_overrides": {
"FA_18C_hornet": [
"VFA-37",
"VFA-106",
"VFA-113",
"VFA-122",
"VFA-131",
"VFA-192",
"VFA-34",
"VFA-83",
"VFA-87",
"VFA-97",
"VMFA-122",
"VMFA-132",
"VMFA-251",
"VMFA-312",
"VMFA-314",
"VMFA-323"
]
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,7 @@
import pickle import pickle
from dcs.mission import Mission from dcs.mission import Mission
from shapely import geometry
for terrain in ["cau", "nev", "syria", "channel", "normandy", "gulf"]: for terrain in ["cau", "nev", "syria", "channel", "normandy", "gulf"]:
print("Terrain " + terrain) print("Terrain " + terrain)
@ -15,16 +16,16 @@ for terrain in ["cau", "nev", "syria", "channel", "normandy", "gulf"]:
if terrain == "cau" and inclusion_zones: if terrain == "cau" and inclusion_zones:
# legacy # legacy
exclusion_zones.append(zone) exclusion_zones.append(geometry.Polygon(zone))
else: else:
if plane_group.units[0].type == "F-15C": if plane_group.units[0].type == "F-15C":
exclusion_zones.append(zone) exclusion_zones.append(geometry.Polygon(zone))
else: else:
inclusion_zones.append(zone) inclusion_zones.append(geometry.Polygon(zone))
for ship_group in m.country("USA").ship_group: for ship_group in m.country("USA").ship_group:
zone = [(x.position.x, x.position.y) for x in ship_group.points] zone = [(x.position.x, x.position.y) for x in ship_group.points]
seas_zones.append(zone) seas_zones.append(geometry.Polygon(zone))
with open("../{}landmap.p".format(terrain), "wb") as f: with open("../{}landmap.p".format(terrain), "wb") as f:
print(len(inclusion_zones), len(exclusion_zones), len(seas_zones)) print(len(inclusion_zones), len(exclusion_zones), len(seas_zones))

Binary file not shown.