This commit is contained in:
Dan Albert
2021-02-12 19:58:30 -08:00
parent 053663bd76
commit a47bef1f13
222 changed files with 8434 additions and 4461 deletions

View File

@@ -27,8 +27,15 @@ class QFrontLine(QGraphicsLineItem):
change the mouse cursor on hover.
"""
def __init__(self, x1: float, y1: float, x2: float, y2: float,
mission_target: FrontLine, game_model: GameModel) -> None:
def __init__(
self,
x1: float,
y1: float,
x2: float,
y2: float,
mission_target: FrontLine,
game_model: GameModel,
) -> None:
super().__init__(x1, y1, x2, y2)
self.mission_target = mission_target
self.game_model = game_model
@@ -98,10 +105,9 @@ class QFrontLine(QGraphicsLineItem):
self.mission_target.control_point_b.base.affect_strength(-0.1)
self.game_model.game.initialize_turn()
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
def cheat_backward(self) -> None:
self.mission_target.control_point_a.base.affect_strength(-0.1)
self.mission_target.control_point_b.base.affect_strength(0.1)
self.game_model.game.initialize_turn()
GameUpdateSignal.get_instance().updateGame(self.game_model.game)

View File

@@ -70,10 +70,10 @@ from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
MAX_SHIP_DISTANCE = nautical_miles(80)
def binomial(i: int, n: int) -> float:
"""Binomial coefficient"""
return math.factorial(n) / float(
math.factorial(i) * math.factorial(n - i))
return math.factorial(n) / float(math.factorial(i) * math.factorial(n - i))
def bernstein(t: float, i: int, n: int) -> float:
@@ -92,7 +92,9 @@ def bezier(t: float, points: Iterable[Tuple[float, float]]) -> Tuple[float, floa
return x, y
def bezier_curve_range(n: int, points: Iterable[Tuple[float, float]]) -> Iterator[Tuple[float, float]]:
def bezier_curve_range(
n: int, points: Iterable[Tuple[float, float]]
) -> Iterator[Tuple[float, float]]:
"""Range of points in a curve bezier"""
for i in range(n):
t = i / float(n - 1)
@@ -133,7 +135,9 @@ class QLiberationMap(QGraphicsView):
self.setGame(game_model.game)
# Object displayed when unit is selected
self.movement_line = QtWidgets.QGraphicsLineItem(QtCore.QLineF(QPointF(0,0),QPointF(0,0)))
self.movement_line = QtWidgets.QGraphicsLineItem(
QtCore.QLineF(QPointF(0, 0), QPointF(0, 0))
)
self.movement_line.setPen(QPen(CONST.COLORS["orange"], width=10.0))
self.selected_cp: QMapControlPoint = None
@@ -162,8 +166,7 @@ class QLiberationMap(QGraphicsView):
# update_flight_selection will be called in when the last
# package is removed. If no flight is selected, it's not a
# problem to also have no package selected.
logging.error(
"Flight was selected with no package selected")
logging.error("Flight was selected with no package selected")
return
# Optional[int] isn't a valid type for a Qt signal. None will be
@@ -183,7 +186,6 @@ class QLiberationMap(QGraphicsView):
self.navmesh_highlight: Optional[QPolygonF] = None
self.shortest_path_segments: List[QLineF] = []
def init_scene(self):
scene = QLiberationScene(self)
self.setScene(scene)
@@ -203,6 +205,7 @@ class QLiberationMap(QGraphicsView):
"""
Uncomment to set up theather reference points"""
def keyPressEvent(self, event):
modifiers = QtWidgets.QApplication.keyboardModifiers()
if not self.reference_point_setup_mode:
@@ -225,40 +228,39 @@ class QLiberationMap(QGraphicsView):
if event.key() == QtCore.Qt.Key_Down:
self.update_reference_point(
self.game.theater.reference_points[0],
Point(0, distance))
self.game.theater.reference_points[0], Point(0, distance)
)
if event.key() == QtCore.Qt.Key_Up:
self.update_reference_point(
self.game.theater.reference_points[0],
Point(0, -distance))
self.game.theater.reference_points[0], Point(0, -distance)
)
if event.key() == QtCore.Qt.Key_Left:
self.update_reference_point(
self.game.theater.reference_points[0],
Point(-distance, 0))
self.game.theater.reference_points[0], Point(-distance, 0)
)
if event.key() == QtCore.Qt.Key_Right:
self.update_reference_point(
self.game.theater.reference_points[0],
Point(distance, 0))
self.game.theater.reference_points[0], Point(distance, 0)
)
if event.key() == QtCore.Qt.Key_S:
self.update_reference_point(
self.game.theater.reference_points[1],
Point(0, distance))
self.game.theater.reference_points[1], Point(0, distance)
)
if event.key() == QtCore.Qt.Key_W:
self.update_reference_point(
self.game.theater.reference_points[1],
Point(0, -distance))
self.game.theater.reference_points[1], Point(0, -distance)
)
if event.key() == QtCore.Qt.Key_A:
self.update_reference_point(
self.game.theater.reference_points[1],
Point(-distance, 0))
self.game.theater.reference_points[1], Point(-distance, 0)
)
if event.key() == QtCore.Qt.Key_D:
self.update_reference_point(
self.game.theater.reference_points[1],
Point(distance, 0))
self.game.theater.reference_points[1], Point(distance, 0)
)
logging.debug(
f"Reference points: {self.game.theater.reference_points}")
logging.debug(f"Reference points: {self.game.theater.reference_points}")
self.reload_scene()
@staticmethod
@@ -275,16 +277,33 @@ class QLiberationMap(QGraphicsView):
distance_point = self._transform_point(culling_distance_point)
transformed = self._transform_point(point)
radius = distance_point[0] - transformed[0]
scene.addEllipse(transformed[0]-radius, transformed[1]-radius, 2*radius, 2*radius, 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"],
)
for zone in culling_zones:
culling_distance_zone = Point(zone.x + culling_distance*1000, zone.y + culling_distance*1000)
culling_distance_zone = Point(
zone.x + culling_distance * 1000, zone.y + culling_distance * 1000
)
distance_zone = self._transform_point(culling_distance_zone)
transformed = self._transform_point(zone)
radius = distance_zone[0] - transformed[0]
scene.addEllipse(transformed[0]-radius, transformed[1]-radius, 2*radius, 2*radius, 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"],
)
def draw_shapely_poly(self, scene: QGraphicsScene, poly: Polygon, pen: QPen,
brush: QBrush) -> Optional[QPolygonF]:
def draw_shapely_poly(
self, scene: QGraphicsScene, poly: Polygon, pen: QPen, brush: QBrush
) -> Optional[QPolygonF]:
if poly.is_empty:
return None
points = []
@@ -293,16 +312,18 @@ class QLiberationMap(QGraphicsView):
points.append(QPointF(x, y))
return scene.addPolygon(QPolygonF(points), pen, brush)
def draw_threat_zone(self, scene: QGraphicsScene, poly: Polygon,
player: bool) -> None:
def draw_threat_zone(
self, scene: QGraphicsScene, poly: Polygon, player: bool
) -> None:
if player:
brush = QColor(0, 132, 255, 100)
else:
brush = QColor(227, 32, 0, 100)
self.draw_shapely_poly(scene, poly, CONST.COLORS["transparent"], brush)
def display_threat_zones(self, scene: QGraphicsScene,
options: ThreatZoneOptions, player: bool) -> None:
def display_threat_zones(
self, scene: QGraphicsScene, options: ThreatZoneOptions, player: bool
) -> None:
"""Draws the threat zones on the map."""
threat_zones = self.game.threat_zone_for(player)
if options.all:
@@ -321,33 +342,44 @@ class QLiberationMap(QGraphicsView):
for poly in polys:
self.draw_threat_zone(scene, poly, player)
def draw_navmesh_neighbor_line(self, scene: QGraphicsScene, poly: Polygon,
begin: ShapelyPoint) -> None:
def draw_navmesh_neighbor_line(
self, scene: QGraphicsScene, poly: Polygon, begin: ShapelyPoint
) -> None:
vertex = Point(begin.x, begin.y)
centroid = poly.centroid
direction = Point(centroid.x, centroid.y)
end = vertex.point_from_heading(vertex.heading_between_point(direction),
nautical_miles(2).meters)
end = vertex.point_from_heading(
vertex.heading_between_point(direction), nautical_miles(2).meters
)
scene.addLine(QLineF(QPointF(*self._transform_point(vertex)),
QPointF(*self._transform_point(end))),
CONST.COLORS["yellow"])
scene.addLine(
QLineF(
QPointF(*self._transform_point(vertex)),
QPointF(*self._transform_point(end)),
),
CONST.COLORS["yellow"],
)
@singledispatchmethod
def draw_navmesh_border(self, intersection, scene: QGraphicsScene,
poly: Polygon) -> None:
raise NotImplementedError("draw_navmesh_border not implemented for %s",
intersection.__class__.__name__)
def draw_navmesh_border(
self, intersection, scene: QGraphicsScene, poly: Polygon
) -> None:
raise NotImplementedError(
"draw_navmesh_border not implemented for %s",
intersection.__class__.__name__,
)
@draw_navmesh_border.register
def draw_navmesh_point_border(self, intersection: ShapelyPoint,
scene: QGraphicsScene, poly: Polygon) -> None:
def draw_navmesh_point_border(
self, intersection: ShapelyPoint, scene: QGraphicsScene, poly: Polygon
) -> None:
# Draw a line from the vertex toward the center of the polygon.
self.draw_navmesh_neighbor_line(scene, poly, intersection)
@draw_navmesh_border.register
def draw_navmesh_edge_border(self, intersection: LineString,
scene: QGraphicsScene, poly: Polygon) -> None:
def draw_navmesh_edge_border(
self, intersection: LineString, scene: QGraphicsScene, poly: Polygon
) -> None:
# Draw a line from the center of the edge toward the center of the
# polygon.
edge_center = intersection.interpolate(0.5, normalized=True)
@@ -355,13 +387,16 @@ class QLiberationMap(QGraphicsView):
def display_navmesh(self, scene: QGraphicsScene, player: bool) -> None:
for navpoly in self.game.navmesh_for(player).polys:
self.draw_shapely_poly(scene, navpoly.poly, CONST.COLORS["black"],
CONST.COLORS["transparent"])
self.draw_shapely_poly(
scene, navpoly.poly, CONST.COLORS["black"], CONST.COLORS["transparent"]
)
position = self._transform_point(
Point(navpoly.poly.centroid.x, navpoly.poly.centroid.y))
text = scene.addSimpleText(f"Navmesh {navpoly.ident}",
self.waypoint_info_font)
Point(navpoly.poly.centroid.x, navpoly.poly.centroid.y)
)
text = scene.addSimpleText(
f"Navmesh {navpoly.ident}", self.waypoint_info_font
)
text.setBrush(QColor(255, 255, 255))
text.setPen(QColor(255, 255, 255))
text.moveBy(position[0] + 8, position[1])
@@ -370,8 +405,9 @@ class QLiberationMap(QGraphicsView):
for border in navpoly.neighbors.values():
self.draw_navmesh_border(border, scene, navpoly.poly)
def highlight_mouse_navmesh(self, scene: QGraphicsScene, navmesh: NavMesh,
mouse_position: Point) -> None:
def highlight_mouse_navmesh(
self, scene: QGraphicsScene, navmesh: NavMesh, mouse_position: Point
) -> None:
if self.navmesh_highlight is not None:
try:
scene.removeItem(self.navmesh_highlight)
@@ -381,11 +417,15 @@ class QLiberationMap(QGraphicsView):
if navpoly is None:
return
self.navmesh_highlight = self.draw_shapely_poly(
scene, navpoly.poly, CONST.COLORS["transparent"],
CONST.COLORS["light_green_transparent"])
scene,
navpoly.poly,
CONST.COLORS["transparent"],
CONST.COLORS["light_green_transparent"],
)
def draw_shortest_path(self, scene: QGraphicsScene, navmesh: NavMesh,
destination: Point, player: bool) -> None:
def draw_shortest_path(
self, scene: QGraphicsScene, navmesh: NavMesh, destination: Point, player: bool
) -> None:
for line in self.shortest_path_segments:
try:
scene.removeItem(line)
@@ -407,21 +447,36 @@ class QLiberationMap(QGraphicsView):
flight_path_pen = self.flight_path_pen(player, selected=True)
# Draw the line to the *middle* of the waypoint.
offset = self.WAYPOINT_SIZE // 2
self.shortest_path_segments.append(scene.addLine(
prev_pos[0] + offset, prev_pos[1] + offset,
new_pos[0] + offset, new_pos[1] + offset,
flight_path_pen
))
self.shortest_path_segments.append(
scene.addLine(
prev_pos[0] + offset,
prev_pos[1] + offset,
new_pos[0] + offset,
new_pos[1] + offset,
flight_path_pen,
)
)
self.shortest_path_segments.append(scene.addEllipse(
new_pos[0], new_pos[1], self.WAYPOINT_SIZE,
self.WAYPOINT_SIZE, flight_path_pen, flight_path_pen
))
self.shortest_path_segments.append(
scene.addEllipse(
new_pos[0],
new_pos[1],
self.WAYPOINT_SIZE,
self.WAYPOINT_SIZE,
flight_path_pen,
flight_path_pen,
)
)
prev_pos = new_pos
def draw_test_flight_plan(self, scene: QGraphicsScene, task: FlightType,
point_near_target: Point, player: bool) -> None:
def draw_test_flight_plan(
self,
scene: QGraphicsScene,
task: FlightType,
point_near_target: Point,
player: bool,
) -> None:
for line in self.shortest_path_segments:
try:
scene.removeItem(line)
@@ -438,8 +493,16 @@ class QLiberationMap(QGraphicsView):
origin = self.game.theater.enemy_points()[0]
package = Package(target)
flight = Flight(package, F_16C_50, 2, task, start_type="Warm",
departure=origin, arrival=origin, divert=None)
flight = Flight(
package,
F_16C_50,
2,
task,
start_type="Warm",
departure=origin,
arrival=origin,
divert=None,
)
package.add_flight(flight)
planner = FlightPlanBuilder(self.game, package, is_player=player)
try:
@@ -452,31 +515,49 @@ class QLiberationMap(QGraphicsView):
@staticmethod
def should_display_ground_objects_at(cp: ControlPoint) -> bool:
return ((DisplayOptions.sam_ranges and cp.captured) or
(DisplayOptions.enemy_sam_ranges and not cp.captured))
return (DisplayOptions.sam_ranges and cp.captured) or (
DisplayOptions.enemy_sam_ranges and not cp.captured
)
def draw_threat_range(self, scene: QGraphicsScene, group: Group, ground_object: TheaterGroundObject, cp: ControlPoint) -> None:
def draw_threat_range(
self,
scene: QGraphicsScene,
group: Group,
ground_object: TheaterGroundObject,
cp: ControlPoint,
) -> None:
go_pos = self._transform_point(ground_object.position)
detection_range = ground_object.detection_range(group)
threat_range = ground_object.threat_range(group)
if threat_range:
threat_pos = self._transform_point(
ground_object.position + Point(threat_range.meters,
threat_range.meters))
ground_object.position + Point(threat_range.meters, threat_range.meters)
)
threat_radius = Point(*go_pos).distance_to_point(Point(*threat_pos))
# Add threat range circle
scene.addEllipse(go_pos[0] - threat_radius / 2 + 7, go_pos[1] - threat_radius / 2 + 6,
threat_radius, threat_radius, self.threat_pen(cp.captured))
scene.addEllipse(
go_pos[0] - threat_radius / 2 + 7,
go_pos[1] - threat_radius / 2 + 6,
threat_radius,
threat_radius,
self.threat_pen(cp.captured),
)
if detection_range and DisplayOptions.detection_range:
# Add detection range circle
detection_pos = self._transform_point(
ground_object.position + Point(detection_range.meters,
detection_range.meters))
ground_object.position
+ Point(detection_range.meters, detection_range.meters)
)
detection_radius = Point(*go_pos).distance_to_point(Point(*detection_pos))
scene.addEllipse(go_pos[0] - detection_radius/2 + 7, go_pos[1] - detection_radius/2 + 6,
detection_radius, detection_radius, self.detection_pen(cp.captured))
scene.addEllipse(
go_pos[0] - detection_radius / 2 + 7,
go_pos[1] - detection_radius / 2 + 6,
detection_radius,
detection_radius,
self.detection_pen(cp.captured),
)
def draw_ground_objects(self, scene: QGraphicsScene, cp: ControlPoint) -> None:
added_objects = []
@@ -486,8 +567,22 @@ class QLiberationMap(QGraphicsView):
go_pos = self._transform_point(ground_object.position)
if not ground_object.airbase_group:
buildings = self.game.theater.find_ground_objects_by_obj_name(ground_object.obj_name)
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 14, 12, cp, ground_object, self.game, buildings))
buildings = self.game.theater.find_ground_objects_by_obj_name(
ground_object.obj_name
)
scene.addItem(
QMapGroundObject(
self,
go_pos[0],
go_pos[1],
14,
12,
cp,
ground_object,
self.game,
buildings,
)
)
should_display = self.should_display_ground_objects_at(cp)
if ground_object.might_have_aa and should_display:
@@ -508,10 +603,8 @@ class QLiberationMap(QGraphicsView):
if DisplayOptions.culling and self.game.settings.perf_culling:
self.display_culling(scene)
self.display_threat_zones(scene, DisplayOptions.blue_threat_zones,
player=True)
self.display_threat_zones(scene, DisplayOptions.red_threat_zones,
player=False)
self.display_threat_zones(scene, DisplayOptions.blue_threat_zones, player=True)
self.display_threat_zones(scene, DisplayOptions.red_threat_zones, player=False)
if DisplayOptions.navmeshes.blue_navmesh:
self.display_navmesh(scene, player=True)
@@ -522,24 +615,33 @@ class QLiberationMap(QGraphicsView):
pos = self._transform_point(cp.position)
scene.addItem(QMapControlPoint(self, pos[0] - CONST.CP_SIZE / 2,
pos[1] - CONST.CP_SIZE / 2,
CONST.CP_SIZE,
CONST.CP_SIZE, cp, self.game_model))
scene.addItem(
QMapControlPoint(
self,
pos[0] - CONST.CP_SIZE / 2,
pos[1] - CONST.CP_SIZE / 2,
CONST.CP_SIZE,
CONST.CP_SIZE,
cp,
self.game_model,
)
)
if cp.captured:
pen = QPen(brush=CONST.COLORS[playerColor])
brush = CONST.COLORS[playerColor+"_transparent"]
brush = CONST.COLORS[playerColor + "_transparent"]
else:
pen = QPen(brush=CONST.COLORS[enemyColor])
brush = CONST.COLORS[enemyColor+"_transparent"]
brush = CONST.COLORS[enemyColor + "_transparent"]
self.draw_ground_objects(scene, cp)
if cp.target_position is not None:
proj = self._transform_point(cp.target_position)
scene.addLine(QLineF(QPointF(pos[0], pos[1]), QPointF(proj[0], proj[1])),
QPen(CONST.COLORS["green"], width=10, s=Qt.DashDotLine))
scene.addLine(
QLineF(QPointF(pos[0], pos[1]), QPointF(proj[0], proj[1])),
QPen(CONST.COLORS["green"], width=10, s=Qt.DashDotLine),
)
for cp in self.game.theater.enemy_points():
if DisplayOptions.lines:
@@ -585,8 +687,9 @@ class QLiberationMap(QGraphicsView):
continue
self.draw_flight_plan(scene, flight, selected)
def draw_flight_plan(self, scene: QGraphicsScene, flight: Flight,
selected: bool) -> None:
def draw_flight_plan(
self, scene: QGraphicsScene, flight: Flight, selected: bool
) -> None:
is_player = flight.from_cp.captured
pos = self._transform_point(flight.from_cp.position)
@@ -604,8 +707,7 @@ class QLiberationMap(QGraphicsView):
continue
new_pos = self._transform_point(Point(point.x, point.y))
self.draw_flight_path(scene, prev_pos, new_pos, is_player,
selected)
self.draw_flight_path(scene, prev_pos, new_pos, is_player, selected)
self.draw_waypoint(scene, new_pos, is_player, selected)
if selected and DisplayOptions.waypoint_info:
if point.waypoint_type in target_types:
@@ -613,44 +715,63 @@ class QLiberationMap(QGraphicsView):
# Don't draw dozens of targets over each other.
continue
drew_target = True
self.draw_waypoint_info(scene, idx + 1, point, new_pos,
flight.flight_plan)
self.draw_waypoint_info(
scene, idx + 1, point, new_pos, flight.flight_plan
)
prev_pos = tuple(new_pos)
if selected and DisplayOptions.barcap_commit_range:
self.draw_barcap_commit_range(scene, flight)
def draw_barcap_commit_range(self, scene: QGraphicsScene,
flight: Flight) -> None:
def draw_barcap_commit_range(self, scene: QGraphicsScene, flight: Flight) -> None:
if flight.flight_type is not FlightType.BARCAP:
return
if not isinstance(flight.flight_plan, BarCapFlightPlan):
return
start = flight.flight_plan.patrol_start
end = flight.flight_plan.patrol_end
line = LineString([
ShapelyPoint(start.x, start.y),
ShapelyPoint(end.x, end.y),
])
line = LineString(
[
ShapelyPoint(start.x, start.y),
ShapelyPoint(end.x, end.y),
]
)
doctrine = self.game.faction_for(flight.departure.captured).doctrine
bubble = line.buffer(doctrine.cap_engagement_range.meters)
self.flight_path_items.append(self.draw_shapely_poly(
scene, bubble, CONST.COLORS["yellow"], CONST.COLORS["transparent"]
))
self.flight_path_items.append(
self.draw_shapely_poly(
scene, bubble, CONST.COLORS["yellow"], CONST.COLORS["transparent"]
)
)
def draw_waypoint(self, scene: QGraphicsScene,
position: Tuple[float, float], player: bool,
selected: bool) -> None:
def draw_waypoint(
self,
scene: QGraphicsScene,
position: Tuple[float, float],
player: bool,
selected: bool,
) -> None:
waypoint_pen = self.waypoint_pen(player, selected)
waypoint_brush = self.waypoint_brush(player, selected)
self.flight_path_items.append(scene.addEllipse(
position[0], position[1], self.WAYPOINT_SIZE,
self.WAYPOINT_SIZE, waypoint_pen, waypoint_brush
))
self.flight_path_items.append(
scene.addEllipse(
position[0],
position[1],
self.WAYPOINT_SIZE,
self.WAYPOINT_SIZE,
waypoint_pen,
waypoint_brush,
)
)
def draw_waypoint_info(self, scene: QGraphicsScene, number: int,
waypoint: FlightWaypoint, position: Tuple[int, int],
flight_plan: FlightPlan) -> None:
def draw_waypoint_info(
self,
scene: QGraphicsScene,
number: int,
waypoint: FlightWaypoint,
position: Tuple[int, int],
flight_plan: FlightPlan,
) -> None:
altitude = int(waypoint.alt.feet)
altitude_type = "AGL" if waypoint.alt_type == "RADIO" else "MSL"
@@ -669,11 +790,13 @@ class QLiberationMap(QGraphicsView):
pen = QPen(QColor("black"), 0.3)
brush = QColor("white")
text = "\n".join([
f"{number} {waypoint.name}",
f"{altitude} ft {altitude_type}",
tot,
])
text = "\n".join(
[
f"{number} {waypoint.name}",
f"{altitude} ft {altitude_type}",
tot,
]
)
item = scene.addSimpleText(text, self.waypoint_info_font)
item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
@@ -683,19 +806,30 @@ class QLiberationMap(QGraphicsView):
item.setZValue(2)
self.flight_path_items.append(item)
def draw_flight_path(self, scene: QGraphicsScene, pos0: Tuple[float, float],
pos1: Tuple[float, float], player: bool,
selected: bool) -> None:
def draw_flight_path(
self,
scene: QGraphicsScene,
pos0: Tuple[float, float],
pos1: Tuple[float, float],
player: bool,
selected: bool,
) -> None:
flight_path_pen = self.flight_path_pen(player, selected)
# Draw the line to the *middle* of the waypoint.
offset = self.WAYPOINT_SIZE // 2
self.flight_path_items.append(scene.addLine(
pos0[0] + offset, pos0[1] + offset,
pos1[0] + offset, pos1[1] + offset,
flight_path_pen
))
self.flight_path_items.append(
scene.addLine(
pos0[0] + offset,
pos0[1] + offset,
pos1[0] + offset,
pos1[1] + offset,
flight_path_pen,
)
)
def draw_bezier_frontline(self, scene: QGraphicsScene, pen:QPen, frontline: FrontLine) -> None:
def draw_bezier_frontline(
self, scene: QGraphicsScene, pen: QPen, frontline: FrontLine
) -> None:
"""
Thanks to Alquimista for sharing a python implementation of the bezier algorithm this is adapted from.
https://gist.github.com/Alquimista/1274149#file-bezdraw-py
@@ -706,7 +840,9 @@ class QLiberationMap(QGraphicsView):
bezier_fixed_points.append(self._transform_point(segment.point_b))
old_point = bezier_fixed_points[0]
for point in bezier_curve_range(int(len(bezier_fixed_points) * 2), bezier_fixed_points):
for point in bezier_curve_range(
int(len(bezier_fixed_points) * 2), bezier_fixed_points
):
scene.addLine(old_point[0], old_point[1], point[0], point[1], pen=pen)
old_point = point
@@ -715,14 +851,18 @@ class QLiberationMap(QGraphicsView):
for connected_cp in cp.connected_points:
pos2 = self._transform_point(connected_cp.position)
if not cp.captured:
color = CONST.COLORS["dark_"+enemyColor]
color = CONST.COLORS["dark_" + enemyColor]
else:
color = CONST.COLORS["dark_"+playerColor]
color = CONST.COLORS["dark_" + playerColor]
pen = QPen(brush=color)
pen.setColor(color)
pen.setWidth(6)
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)
):
if DisplayOptions.actual_frontline_pos:
self.draw_actual_frontline(frontline, scene, pen)
else:
@@ -730,35 +870,30 @@ class QLiberationMap(QGraphicsView):
else:
self.draw_bezier_frontline(scene, pen, frontline)
def draw_frontline_approximation(self, frontline: FrontLine, scene: QGraphicsScene, pen: QPen) -> None:
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)
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
)
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:
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
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])
)
vector[0].point_from_heading(vector[1], vector[2])
)
scene.addItem(
QFrontLine(
left_pos[0],
@@ -766,7 +901,7 @@ class QLiberationMap(QGraphicsView):
right_pos[0],
right_pos[1],
frontline,
self.game_model
self.game_model,
)
)
@@ -779,26 +914,48 @@ class QLiberationMap(QGraphicsView):
SMALL_LINE = 2
dist = self.distance_to_pixels(nautical_miles(scale_distance_nm))
self.scene().addRect(POS_X, POS_Y-PADDING, PADDING*2 + dist, BIG_LINE*2+3*PADDING, pen=CONST.COLORS["black"], brush=CONST.COLORS["black"])
l = self.scene().addLine(POS_X + PADDING, POS_Y + BIG_LINE*2, POS_X + PADDING + dist, POS_Y + BIG_LINE*2)
self.scene().addRect(
POS_X,
POS_Y - PADDING,
PADDING * 2 + dist,
BIG_LINE * 2 + 3 * PADDING,
pen=CONST.COLORS["black"],
brush=CONST.COLORS["black"],
)
l = self.scene().addLine(
POS_X + PADDING,
POS_Y + BIG_LINE * 2,
POS_X + PADDING + dist,
POS_Y + BIG_LINE * 2,
)
text = self.scene().addText("0nm", font=QFont("Trebuchet MS", 6, weight=5, italic=False))
text.setPos(POS_X, POS_Y + BIG_LINE*2)
text = self.scene().addText(
"0nm", font=QFont("Trebuchet MS", 6, weight=5, italic=False)
)
text.setPos(POS_X, POS_Y + BIG_LINE * 2)
text.setDefaultTextColor(Qt.white)
text2 = self.scene().addText(str(scale_distance_nm) + "nm", font=QFont("Trebuchet MS", 6, weight=5, italic=False))
text2 = self.scene().addText(
str(scale_distance_nm) + "nm",
font=QFont("Trebuchet MS", 6, weight=5, italic=False),
)
text2.setPos(POS_X + dist, POS_Y + BIG_LINE * 2)
text2.setDefaultTextColor(Qt.white)
l.setPen(CONST.COLORS["white"])
for i in range(number_of_points+1):
d = float(i)/float(number_of_points)
for i in range(number_of_points + 1):
d = float(i) / float(number_of_points)
if i == 0 or i == number_of_points:
h = BIG_LINE
else:
h = SMALL_LINE
l = self.scene().addLine(POS_X + PADDING + d * dist, POS_Y + BIG_LINE*2, POS_X + PADDING + d * dist, POS_Y + BIG_LINE - h)
l = self.scene().addLine(
POS_X + PADDING + d * dist,
POS_Y + BIG_LINE * 2,
POS_X + PADDING + d * dist,
POS_Y + BIG_LINE - h,
)
l.setPen(CONST.COLORS["white"])
def wheelEvent(self, event: QWheelEvent):
@@ -828,7 +985,8 @@ class QLiberationMap(QGraphicsView):
point_b = self.game.theater.reference_points[1]
world_distance = self._transpose_point(
point_b.world_coordinates - point_a.world_coordinates)
point_b.world_coordinates - point_a.world_coordinates
)
image_distance = point_b.image_coordinates - point_a.image_coordinates
x_scale = image_distance.x / world_distance.x
@@ -870,8 +1028,7 @@ class QLiberationMap(QGraphicsView):
scale = self._scaling_factor()
offset = point_a.image_coordinates - scene_point
scaled = self._transpose_point(
Point(offset.x / scale.x, offset.y / scale.y))
scaled = self._transpose_point(Point(offset.x / scale.x, offset.y / scale.y))
return point_a.world_coordinates - scaled
def distance_to_pixels(self, distance: Distance) -> int:
@@ -955,7 +1112,12 @@ class QLiberationMap(QGraphicsView):
for sea_zone in self.game.theater.landmap.sea_zones:
print(sea_zone)
poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in sea_zone.exterior.coords])
poly = QPolygonF(
[
QPointF(*self._transform_point(Point(point[0], point[1])))
for point in sea_zone.exterior.coords
]
)
if self.reference_point_setup_mode:
color = "sea_blue_transparent"
else:
@@ -963,18 +1125,40 @@ class QLiberationMap(QGraphicsView):
scene.addPolygon(poly, CONST.COLORS[color], CONST.COLORS[color])
for inclusion_zone in self.game.theater.landmap.inclusion_zones:
poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in inclusion_zone.exterior.coords])
poly = QPolygonF(
[
QPointF(*self._transform_point(Point(point[0], point[1])))
for point in inclusion_zone.exterior.coords
]
)
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:
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.exclusion_zones:
poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in exclusion_zone.exterior.coords])
poly = QPolygonF(
[
QPointF(*self._transform_point(Point(point[0], point[1])))
for point in exclusion_zone.exterior.coords
]
)
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:
scene.addPolygon(poly, CONST.COLORS["grey"], CONST.COLORS["dark_dark_grey"])
scene.addPolygon(
poly, CONST.COLORS["grey"], CONST.COLORS["dark_dark_grey"]
)
# Uncomment to display plan projection test
# self.projection_test()
@@ -983,15 +1167,18 @@ class QLiberationMap(QGraphicsView):
if self.reference_point_setup_mode:
for i, point in enumerate(self.game.theater.reference_points):
self.scene().addRect(
QRectF(point.image_coordinates.x, point.image_coordinates.y,
25, 25), pen=CONST.COLORS["red"],
brush=CONST.COLORS["red"])
QRectF(
point.image_coordinates.x, point.image_coordinates.y, 25, 25
),
pen=CONST.COLORS["red"],
brush=CONST.COLORS["red"],
)
text = self.scene().addText(
f"P{i} = {point.image_coordinates}",
font=QFont("Trebuchet MS", 14, weight=8, italic=False))
font=QFont("Trebuchet MS", 14, weight=8, italic=False),
)
text.setDefaultTextColor(CONST.COLORS["red"])
text.setPos(point.image_coordinates.x + 26,
point.image_coordinates.y)
text.setPos(point.image_coordinates.x + 26, point.image_coordinates.y)
# Set to True to visually debug _transform_point.
draw_transformed = False
@@ -1000,10 +1187,12 @@ class QLiberationMap(QGraphicsView):
self.scene().addRect(
QRectF(x, y, 25, 25),
pen=CONST.COLORS["red"],
brush=CONST.COLORS["red"])
brush=CONST.COLORS["red"],
)
text = self.scene().addText(
f"P{i}' = {x}, {y}",
font=QFont("Trebuchet MS", 14, weight=8, italic=False))
font=QFont("Trebuchet MS", 14, weight=8, italic=False),
)
text.setDefaultTextColor(CONST.COLORS["red"])
text.setPos(x + 26, y)
@@ -1023,7 +1212,9 @@ class QLiberationMap(QGraphicsView):
self.state = QLiberationMapState.MOVING_UNIT
self.selected_cp = selected_cp
position = self._transform_point(selected_cp.control_point.position)
self.movement_line = QtWidgets.QGraphicsLineItem(QLineF(QPointF(*position), QPointF(*position)))
self.movement_line = QtWidgets.QGraphicsLineItem(
QLineF(QPointF(*position), QPointF(*position))
)
self.scene().addItem(self.movement_line)
def is_valid_ship_pos(self, scene_position: Point) -> bool:
@@ -1043,7 +1234,8 @@ class QLiberationMap(QGraphicsView):
if self.state == QLiberationMapState.MOVING_UNIT:
self.setCursor(Qt.PointingHandCursor)
self.movement_line.setLine(
QLineF(self.movement_line.line().p1(), event.scenePos()))
QLineF(self.movement_line.line().p1(), event.scenePos())
)
if self.is_valid_ship_pos(mouse_position):
self.movement_line.setPen(CONST.COLORS["green"])
@@ -1053,21 +1245,28 @@ class QLiberationMap(QGraphicsView):
mouse_world_pos = self._scene_to_dcs_coords(mouse_position)
if DisplayOptions.navmeshes.blue_navmesh:
self.highlight_mouse_navmesh(
self.scene(), self.game.blue_navmesh,
self._scene_to_dcs_coords(mouse_position))
self.scene(),
self.game.blue_navmesh,
self._scene_to_dcs_coords(mouse_position),
)
if DisplayOptions.path_debug.shortest_path:
self.draw_shortest_path(self.scene(), self.game.blue_navmesh,
mouse_world_pos, player=True)
self.draw_shortest_path(
self.scene(), self.game.blue_navmesh, mouse_world_pos, player=True
)
if DisplayOptions.navmeshes.red_navmesh:
self.highlight_mouse_navmesh(
self.scene(), self.game.red_navmesh, mouse_world_pos)
self.scene(), self.game.red_navmesh, mouse_world_pos
)
debug_blue = DisplayOptions.path_debug_faction.blue
if DisplayOptions.path_debug.shortest_path:
self.draw_shortest_path(
self.scene(), self.game.navmesh_for(player=debug_blue),
mouse_world_pos, player=False)
self.scene(),
self.game.navmesh_for(player=debug_blue),
mouse_world_pos,
player=False,
)
elif not DisplayOptions.path_debug.hide:
if DisplayOptions.path_debug.barcap:
task = FlightType.BARCAP
@@ -1080,10 +1279,10 @@ class QLiberationMap(QGraphicsView):
elif DisplayOptions.path_debug.tarcap:
task = FlightType.TARCAP
else:
raise ValueError(
"Unexpected value for DisplayOptions.path_debug")
self.draw_test_flight_plan(self.scene(), task, mouse_world_pos,
player=debug_blue)
raise ValueError("Unexpected value for DisplayOptions.path_debug")
self.draw_test_flight_plan(
self.scene(), task, mouse_world_pos, player=debug_blue
)
def sceneMousePressEvent(self, event: QGraphicsSceneMouseEvent):
if self.state == QLiberationMapState.MOVING_UNIT:
@@ -1109,4 +1308,4 @@ class QLiberationMap(QGraphicsView):
self.scene().removeItem(self.movement_line)
except:
pass
self.selected_cp = None
self.selected_cp = None

View File

@@ -4,17 +4,18 @@ import qt_ui.uiconstants as CONST
class QLiberationScene(QGraphicsScene):
def __init__(self, parent):
super().__init__(parent)
item = self.addText("Go to \"File/New Game\" to setup a new campaign or go to \"File/Open\" to load an existing save game.",
CONST.FONT_PRIMARY)
item = self.addText(
'Go to "File/New Game" to setup a new campaign or go to "File/Open" to load an existing save game.',
CONST.FONT_PRIMARY,
)
item.setDefaultTextColor(CONST.COLORS["white"])
def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
super(QLiberationScene, self).mouseMoveEvent(event)
self.parent().sceneMouseMovedEvent(event)
def mousePressEvent(self, event:QGraphicsSceneMouseEvent):
def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
super(QLiberationScene, self).mousePressEvent(event)
self.parent().sceneMousePressEvent(event)

View File

@@ -13,8 +13,16 @@ from ...windows.GameUpdateSignal import GameUpdateSignal
class QMapControlPoint(QMapObject):
def __init__(self, parent, x: float, y: float, w: float, h: float,
control_point: ControlPoint, game_model: GameModel) -> None:
def __init__(
self,
parent,
x: float,
y: float,
w: float,
h: float,
control_point: ControlPoint,
game_model: GameModel,
) -> None:
super().__init__(x, y, w, h, mission_target=control_point)
self.game_model = game_model
self.control_point = control_point
@@ -22,8 +30,7 @@ class QMapControlPoint(QMapObject):
self.setZValue(1)
self.setToolTip(self.control_point.name)
self.base_details_dialog: Optional[QBaseMenu2] = None
self.capture_action = QAction(
f"CHEAT: Capture {self.control_point.name}")
self.capture_action = QAction(f"CHEAT: Capture {self.control_point.name}")
self.capture_action.triggered.connect(self.cheat_capture)
self.move_action = QAction("Move")
@@ -69,9 +76,7 @@ class QMapControlPoint(QMapObject):
def on_click(self) -> None:
self.base_details_dialog = QBaseMenu2(
self.window(),
self.control_point,
self.game_model
self.window(), self.control_point, self.game_model
)
self.base_details_dialog.show()
@@ -89,7 +94,10 @@ class QMapControlPoint(QMapObject):
return
for connected in self.control_point.connected_points:
if connected.captured and self.game_model.game.settings.enable_base_capture_cheat:
if (
connected.captured
and self.game_model.game.settings.enable_base_capture_cheat
):
menu.addAction(self.capture_action)
break
@@ -105,7 +113,7 @@ class QMapControlPoint(QMapObject):
def cancel_move(self):
self.control_point.target_position = None
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
def open_new_package_dialog(self) -> None:
"""Extends the default packagedialog to redirect to base menu for red air base."""
is_navy = isinstance(self.control_point, NavalControlPoint)

View File

@@ -9,17 +9,28 @@ from game import Game
from game.data.building_data import FORTIFICATION_BUILDINGS
from game.db import REWARDS
from game.theater import ControlPoint, TheaterGroundObject
from game.theater.theatergroundobject import MissileSiteGroundObject, CoastalSiteGroundObject
from game.theater.theatergroundobject import (
MissileSiteGroundObject,
CoastalSiteGroundObject,
)
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
from .QMapObject import QMapObject
from ...displayoptions import DisplayOptions
class QMapGroundObject(QMapObject):
def __init__(self, parent, x: float, y: float, w: float, h: float,
control_point: ControlPoint,
ground_object: TheaterGroundObject, game: Game,
buildings: Optional[List[TheaterGroundObject]] = None) -> None:
def __init__(
self,
parent,
x: float,
y: float,
w: float,
h: float,
control_point: ControlPoint,
ground_object: TheaterGroundObject,
game: Game,
buildings: Optional[List[TheaterGroundObject]] = None,
) -> None:
super().__init__(x, y, w, h, mission_target=ground_object)
self.ground_object = ground_object
self.control_point = control_point
@@ -42,7 +53,7 @@ class QMapGroundObject(QMapObject):
for g in self.ground_object.groups:
for u in g.units:
if u.type in units:
units[u.type] = units[u.type]+1
units[u.type] = units[u.type] + 1
else:
units[u.type] = 1
@@ -80,8 +91,12 @@ class QMapGroundObject(QMapObject):
if isinstance(self.ground_object, CoastalSiteGroundObject):
cat = "coastal"
rect = QRect(option.rect.x() + 2, option.rect.y(),
option.rect.width() - 2, option.rect.height())
rect = QRect(
option.rect.x() + 2,
option.rect.y(),
option.rect.width() - 2,
option.rect.height(),
)
is_dead = self.ground_object.is_dead
for building in self.buildings:
@@ -98,7 +113,7 @@ class QMapGroundObject(QMapObject):
if not is_dead and not self.control_point.captured:
if cat == "aa" and not has_threat:
painter.drawPixmap(rect, const.ICONS["nothreat" + enemy_icons])
else:
else:
painter.drawPixmap(rect, const.ICONS[cat + enemy_icons])
elif not is_dead:
if cat == "aa" and not has_threat:
@@ -130,13 +145,22 @@ class QMapGroundObject(QMapObject):
units_dead += len(g.units_losts)
if units_dead + units_alive > 0:
ratio = float(units_alive)/(float(units_dead) + float(units_alive))
ratio = float(units_alive) / (float(units_dead) + float(units_alive))
bar_height = ratio * option.rect.height()
painter.fillRect(option.rect.x(), option.rect.y(), 2,
option.rect.height(),
QBrush(const.COLORS["dark_red"]))
painter.fillRect(option.rect.x(), option.rect.y(), 2, bar_height,
QBrush(const.COLORS["green"]))
painter.fillRect(
option.rect.x(),
option.rect.y(),
2,
option.rect.height(),
QBrush(const.COLORS["dark_red"]),
)
painter.fillRect(
option.rect.x(),
option.rect.y(),
2,
bar_height,
QBrush(const.COLORS["green"]),
)
def on_click(self) -> None:
self.ground_object_dialog = QGroundObjectMenu(
@@ -144,6 +168,6 @@ class QMapGroundObject(QMapObject):
self.ground_object,
self.buildings,
self.control_point,
self.game
self.game,
)
self.ground_object_dialog.show()

View File

@@ -23,8 +23,9 @@ class QMapObject(QGraphicsRectItem):
change the mouse cursor on hover.
"""
def __init__(self, x: float, y: float, w: float, h: float,
mission_target: MissionTarget) -> None:
def __init__(
self, x: float, y: float, w: float, h: float, mission_target: MissionTarget
) -> None:
super().__init__(x, y, w, h)
self.mission_target = mission_target
self.new_package_dialog: Optional[QNewPackageDialog] = None