mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Rework frontline vector
Ensures frontline stays outside of exclusion zones by adjusting its position and width Adds a DisplayOption for viewing the frontline vector on the map
This commit is contained in:
parent
b69eb02766
commit
4e12a1cdad
@ -97,42 +97,16 @@ class Conflict:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> Tuple[Point, int, int]:
|
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)
|
Returns a vector for a valid frontline location avoiding exclusion zones.
|
||||||
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y) ])
|
|
||||||
intersection = probe.intersection(theater.land_poly)
|
|
||||||
|
|
||||||
if isinstance(intersection, geometry.LineString):
|
|
||||||
intersection = intersection
|
|
||||||
elif isinstance(intersection, geometry.MultiLineString):
|
|
||||||
intersection = intersection.geoms[0]
|
|
||||||
else:
|
|
||||||
print(intersection)
|
|
||||||
return None
|
|
||||||
|
|
||||||
return Point(*intersection.xy[0]), _heading_sum(heading, 90), intersection.length
|
|
||||||
"""
|
"""
|
||||||
frontline = cls.frontline_position(from_cp, to_cp, theater)
|
center_position, heading = cls.frontline_position(from_cp, to_cp, theater)
|
||||||
center_position, heading = frontline
|
center_position = cls._find_ground_position(center_position, FRONTLINE_LENGTH, _heading_sum(heading, 90), theater)
|
||||||
left_position, right_position = None, None
|
left_heading = _heading_sum(heading, 90)
|
||||||
|
right_heading = _heading_sum(heading, -90)
|
||||||
if not theater.is_on_land(center_position):
|
left_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH / 2), left_heading, theater)
|
||||||
pos = cls._find_ground_position(center_position, FRONTLINE_LENGTH, _heading_sum(heading, -90), theater)
|
right_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH / 2), right_heading, theater)
|
||||||
if pos:
|
distance = int(left_position.distance_to_point(right_position))
|
||||||
right_position = pos
|
return left_position, right_heading, distance
|
||||||
center_position = pos
|
|
||||||
else:
|
|
||||||
pos = cls._find_ground_position(center_position, FRONTLINE_LENGTH, _heading_sum(heading, +90), theater)
|
|
||||||
if pos:
|
|
||||||
left_position = pos
|
|
||||||
center_position = pos
|
|
||||||
|
|
||||||
if left_position is None:
|
|
||||||
left_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH/2), _heading_sum(heading, -90), theater)
|
|
||||||
|
|
||||||
if right_position is None:
|
|
||||||
right_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH/2), _heading_sum(heading, 90), theater)
|
|
||||||
|
|
||||||
return left_position, _heading_sum(heading, 90), int(right_position.distance_to_point(left_position))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def frontline_cas_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
def frontline_cas_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
||||||
@ -154,46 +128,27 @@ class Conflict:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _extend_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point:
|
def _extend_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point:
|
||||||
|
"""Finds a valid ground position in one heading from an initial point"""
|
||||||
pos = initial
|
pos = initial
|
||||||
for offset in range(0, int(max_distance), 500):
|
for distance in range(0, int(max_distance), 100):
|
||||||
new_pos = initial.point_from_heading(heading, offset)
|
if not theater.is_on_land(pos):
|
||||||
if theater.is_on_land(new_pos):
|
|
||||||
pos = new_pos
|
|
||||||
else:
|
|
||||||
return pos
|
return pos
|
||||||
return pos
|
pos = initial.point_from_heading(heading, distance)
|
||||||
|
if theater.is_on_land(pos):
|
||||||
"""
|
return pos
|
||||||
probe_end_point = initial.point_from_heading(heading, max_distance)
|
logging.error("Didn't find ground position ({})!".format(initial))
|
||||||
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y)])
|
return initial
|
||||||
|
|
||||||
intersection = probe.intersection(theater.land_poly)
|
|
||||||
if intersection is geometry.LineString:
|
|
||||||
return Point(*intersection.xy[1])
|
|
||||||
elif intersection is geometry.MultiLineString:
|
|
||||||
return Point(*intersection.geoms[0].xy[1])
|
|
||||||
|
|
||||||
return None
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point:
|
def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point:
|
||||||
|
"""Finds the nearest ground position along a provided heading and it's inverse"""
|
||||||
pos = initial
|
pos = initial
|
||||||
for _ in range(0, int(max_distance), 100):
|
for distance in range(0, int(max_distance), 100):
|
||||||
if theater.is_on_land(pos):
|
if theater.is_on_land(pos):
|
||||||
return pos
|
return pos
|
||||||
|
pos = initial.point_from_heading(heading, distance)
|
||||||
pos = pos.point_from_heading(heading, 500)
|
if theater.is_on_land(pos):
|
||||||
"""
|
return pos
|
||||||
probe_end_point = initial.point_from_heading(heading, max_distance)
|
pos = initial.point_from_heading(_opposite_heading(heading), distance)
|
||||||
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y) ])
|
|
||||||
|
|
||||||
intersection = probe.intersection(theater.land_poly)
|
|
||||||
if isinstance(intersection, geometry.LineString):
|
|
||||||
return Point(*intersection.xy[1])
|
|
||||||
elif isinstance(intersection, geometry.MultiLineString):
|
|
||||||
return Point(*intersection.geoms[0].xy[1])
|
|
||||||
"""
|
|
||||||
|
|
||||||
logging.error("Didn't find ground position ({})!".format(initial))
|
logging.error("Didn't find ground position ({})!".format(initial))
|
||||||
return initial
|
return initial
|
||||||
|
|||||||
@ -58,6 +58,7 @@ class DisplayOptions:
|
|||||||
waypoint_info = DisplayRule("Waypoint Information", True)
|
waypoint_info = DisplayRule("Waypoint Information", True)
|
||||||
culling = DisplayRule("Display Culling Zones", False)
|
culling = DisplayRule("Display Culling Zones", False)
|
||||||
flight_paths = FlightPathOptions()
|
flight_paths = FlightPathOptions()
|
||||||
|
actual_frontline_pos = DisplayRule("Display actual frontline width and location", False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def menu_items(cls) -> Iterator[Union[DisplayGroup, DisplayRule]]:
|
def menu_items(cls) -> Iterator[Union[DisplayGroup, DisplayRule]]:
|
||||||
|
|||||||
@ -476,17 +476,52 @@ class QLiberationMap(QGraphicsView):
|
|||||||
pen.setWidth(6)
|
pen.setWidth(6)
|
||||||
frontline = FrontLine(cp, connected_cp, self.game.theater)
|
frontline = FrontLine(cp, connected_cp, self.game.theater)
|
||||||
if cp.captured and not connected_cp.captured and Conflict.has_frontline_between(cp, connected_cp):
|
if cp.captured and not connected_cp.captured and Conflict.has_frontline_between(cp, connected_cp):
|
||||||
posx = frontline.position
|
if DisplayOptions.actual_frontline_pos:
|
||||||
h = frontline.attack_heading
|
self.draw_actual_frontline(frontline, scene, pen)
|
||||||
pos2 = self._transform_point(posx)
|
else:
|
||||||
self.draw_bezier_frontline(scene, pen, frontline)
|
self.draw_frontline_approximation(frontline, scene, pen)
|
||||||
p1 = point_from_heading(pos2[0], pos2[1], h+180, 25)
|
|
||||||
p2 = point_from_heading(pos2[0], pos2[1], h, 25)
|
|
||||||
scene.addItem(QFrontLine(p1[0], p1[1], p2[0], p2[1],
|
|
||||||
frontline, self.game_model))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.draw_bezier_frontline(scene, pen, frontline)
|
self.draw_bezier_frontline(scene, pen, frontline)
|
||||||
|
|
||||||
|
def draw_frontline_approximation(self, frontline: FrontLine, scene: QGraphicsScene, pen: QPen) -> None:
|
||||||
|
posx = frontline.position
|
||||||
|
h = frontline.attack_heading
|
||||||
|
pos2 = self._transform_point(posx)
|
||||||
|
self.draw_bezier_frontline(scene, pen, frontline)
|
||||||
|
p1 = point_from_heading(pos2[0], pos2[1], h+180, 25)
|
||||||
|
p2 = point_from_heading(pos2[0], pos2[1], h, 25)
|
||||||
|
scene.addItem(
|
||||||
|
QFrontLine(
|
||||||
|
p1[0],
|
||||||
|
p1[1],
|
||||||
|
p2[0],
|
||||||
|
p2[1],
|
||||||
|
frontline,
|
||||||
|
self.game_model
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def draw_actual_frontline(self, frontline: FrontLine, scene: QGraphicsScene, pen: QPen) -> None:
|
||||||
|
self.draw_bezier_frontline(scene, pen, frontline)
|
||||||
|
vector = Conflict.frontline_vector(
|
||||||
|
frontline.control_point_a,
|
||||||
|
frontline.control_point_b,
|
||||||
|
self.game.theater
|
||||||
|
)
|
||||||
|
left_pos = self._transform_point(vector[0])
|
||||||
|
right_pos = self._transform_point(
|
||||||
|
vector[0].point_from_heading(vector[1], vector[2])
|
||||||
|
)
|
||||||
|
scene.addItem(
|
||||||
|
QFrontLine(
|
||||||
|
left_pos[0],
|
||||||
|
left_pos[1],
|
||||||
|
right_pos[0],
|
||||||
|
right_pos[1],
|
||||||
|
frontline,
|
||||||
|
self.game_model
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def wheelEvent(self, event: QWheelEvent):
|
def wheelEvent(self, event: QWheelEvent):
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user