mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Added missions generators in flight planner. + refactoring
This commit is contained in:
parent
397164e667
commit
fde3a988b7
@ -320,7 +320,7 @@ class Event:
|
||||
enemy_cp.base.affect_strength(delta)
|
||||
cp.base.affect_strength(-delta)
|
||||
info = Information("Frontline Report",
|
||||
"Our ground forces from " + cp.name + " are losing ground against the enemy forces from" + enemy_cp.name,
|
||||
"Our ground forces from " + cp.name + " are losing ground against the enemy forces from " + enemy_cp.name,
|
||||
self.game.turn)
|
||||
self.game.informations.append(info)
|
||||
|
||||
|
||||
@ -258,7 +258,7 @@ class AircraftConflictGenerator:
|
||||
def setup_group_activation_trigger(self, flight, group):
|
||||
if flight.scheduled_in > 0 and flight.client_count == 0:
|
||||
|
||||
if flight.start_type != "In Flight":
|
||||
if flight.start_type != "In Flight" and flight.from_cp.cptype not in [ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP]:
|
||||
group.late_activation = False
|
||||
group.uncontrolled = True
|
||||
|
||||
@ -402,8 +402,6 @@ class AircraftConflictGenerator:
|
||||
elif point.waypoint_type == FlightWaypointType.LANDING_POINT:
|
||||
pt.type = "Land"
|
||||
elif point.waypoint_type == FlightWaypointType.INGRESS_STRIKE:
|
||||
print("TGTS :")
|
||||
print(point.targets)
|
||||
for j, t in enumerate(point.targets):
|
||||
print(t.position)
|
||||
pt.tasks.append(Bombing(t.position))
|
||||
@ -411,6 +409,12 @@ class AircraftConflictGenerator:
|
||||
group.add_nav_target_point(t.position, "PP" + str(j + 1))
|
||||
if group.units[0].unit_type == F_14B and j == 0:
|
||||
group.add_nav_target_point(t.position, "ST")
|
||||
elif point.waypoint_type == FlightWaypointType.INGRESS_SEAD:
|
||||
for j, t in enumerate(point.targets):
|
||||
if group.units[0].unit_type == JF_17 and j < 4:
|
||||
group.add_nav_target_point(t.position, "PP" + str(j + 1))
|
||||
if group.units[0].unit_type == F_14B and j == 0:
|
||||
group.add_nav_target_point(t.position, "ST")
|
||||
|
||||
if pt is not None:
|
||||
pt.alt_type = point.alt_type
|
||||
|
||||
@ -153,67 +153,16 @@ class FlightPlanner:
|
||||
break
|
||||
|
||||
inventory[unit] = inventory[unit] - 2
|
||||
ftype = FlightType.BARCAP if self.from_cp.is_carrier else FlightType.CAP
|
||||
flight = Flight(unit, 2, self.from_cp, ftype)
|
||||
flight = Flight(unit, 2, self.from_cp, FlightType.CAP)
|
||||
|
||||
flight.points = []
|
||||
flight.scheduled_in = offset + i*random.randint(CAP_EVERY_X_MINUTES-5, CAP_EVERY_X_MINUTES+5)
|
||||
|
||||
patrol_alt = random.randint(PATROL_ALT_RANGE[0], PATROL_ALT_RANGE[1])
|
||||
|
||||
# Choose a location for CAP patrols (Either behind frontline if there is one, or to protect ground objects)
|
||||
if len(self._get_cas_locations()) > 0:
|
||||
loc = random.choice(self._get_cas_locations())
|
||||
ingress, heading, distance = Conflict.frontline_vector(self.from_cp, loc, self.game.theater)
|
||||
center = ingress.point_from_heading(heading, distance / 2)
|
||||
orbit_center = center.point_from_heading(heading - 90, random.randint(nm_to_meter(6), nm_to_meter(15)))
|
||||
radius = distance * 2
|
||||
orbit0p = orbit_center.point_from_heading(heading, radius)
|
||||
orbit1p = orbit_center.point_from_heading(heading + 180, radius)
|
||||
elif len(self.from_cp.ground_objects) > 0:
|
||||
loc = random.choice(self.from_cp.ground_objects)
|
||||
hdg = self.from_cp.position.heading_between_point(loc.position)
|
||||
radius = random.randint(nm_to_meter(5), nm_to_meter(10))
|
||||
orbit0p = loc.position.point_from_heading(hdg - 90, radius)
|
||||
orbit1p = loc.position.point_from_heading(hdg + 90, radius)
|
||||
enemy_cp = random.choice(self._get_cas_locations())
|
||||
self.generate_frontline_cap(flight, flight.from_cp, enemy_cp)
|
||||
else:
|
||||
loc = self.from_cp.position.point_from_heading(random.randint(0, 360), random.randint(nm_to_meter(5), nm_to_meter(40)))
|
||||
hdg = self.from_cp.position.heading_between_point(loc.position)
|
||||
radius = random.randint(nm_to_meter(40), nm_to_meter(120))
|
||||
orbit0p = loc.position.point_from_heading(hdg - 90, radius)
|
||||
orbit1p = loc.position.point_from_heading(hdg + 90, radius)
|
||||
|
||||
|
||||
# Create points
|
||||
ascend = self.generate_ascend_point(self.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
orbit0 = FlightWaypoint(orbit0p.x, orbit0p.y, patrol_alt)
|
||||
orbit0.name = "ORBIT 0"
|
||||
orbit0.description = "Standby between this point and the next one"
|
||||
orbit0.pretty_name = "Orbit race-track start"
|
||||
orbit0.waypoint_type = FlightWaypointType.PATROL_TRACK
|
||||
flight.points.append(orbit0)
|
||||
|
||||
orbit1 = FlightWaypoint(orbit1p.x, orbit1p.y, patrol_alt)
|
||||
orbit1.name = "ORBIT 1"
|
||||
orbit1.description = "Standby between this point and the previous one"
|
||||
orbit1.pretty_name = "Orbit race-track end"
|
||||
orbit1.waypoint_type = FlightWaypointType.PATROL
|
||||
flight.points.append(orbit1)
|
||||
|
||||
orbit0.targets.append(self.from_cp)
|
||||
obj_added = []
|
||||
for ground_object in self.from_cp.ground_objects:
|
||||
if ground_object.obj_name not in obj_added and not ground_object.airbase_group:
|
||||
orbit0.targets.append(ground_object)
|
||||
obj_added.append(ground_object.obj_name)
|
||||
|
||||
descend = self.generate_descend_point(self.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(self.from_cp)
|
||||
flight.points.append(rtb)
|
||||
self.generate_barcap(flight, flight.from_cp)
|
||||
|
||||
self.cap_flights.append(flight)
|
||||
self.flights.append(flight)
|
||||
@ -243,47 +192,11 @@ class FlightPlanner:
|
||||
|
||||
inventory[unit] = inventory[unit] - 2
|
||||
flight = Flight(unit, 2, self.from_cp, FlightType.CAS)
|
||||
|
||||
flight.points = []
|
||||
flight.scheduled_in = offset + i*random.randint(CAS_EVERY_X_MINUTES-5, CAS_EVERY_X_MINUTES+5)
|
||||
|
||||
flight.scheduled_in = offset + i * random.randint(CAS_EVERY_X_MINUTES - 5, CAS_EVERY_X_MINUTES + 5)
|
||||
location = random.choice(cas_location)
|
||||
ingress, heading, distance = Conflict.frontline_vector(self.from_cp, location, self.game.theater)
|
||||
center = ingress.point_from_heading(heading, distance/2)
|
||||
egress = ingress.point_from_heading(heading, distance)
|
||||
|
||||
ascend = self.generate_ascend_point(self.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
ingress_point = FlightWaypoint(ingress.x, ingress.y, 1000)
|
||||
ingress_point.alt_type = "RADIO"
|
||||
ingress_point.name = "INGRESS"
|
||||
ingress_point.pretty_name = "INGRESS"
|
||||
ingress_point.description = "Ingress into CAS area"
|
||||
ingress_point.waypoint_type = FlightWaypointType.INGRESS_CAS
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
center_point = FlightWaypoint(center.x, center.y, 1000)
|
||||
center_point.alt_type = "RADIO"
|
||||
center_point.description = "Provide CAS"
|
||||
center_point.name = "CAS"
|
||||
center_point.pretty_name = "CAS"
|
||||
center_point.waypoint_type = FlightWaypointType.CAS
|
||||
flight.points.append(center_point)
|
||||
|
||||
egress_point = FlightWaypoint(egress.x, egress.y, 1000)
|
||||
egress_point.alt_type = "RADIO"
|
||||
egress_point.description = "Egress from CAS area"
|
||||
egress_point.name = "EGRESS"
|
||||
egress_point.pretty_name = "EGRESS"
|
||||
egress_point.waypoint_type = FlightWaypointType.EGRESS
|
||||
flight.points.append(egress_point)
|
||||
|
||||
descend = self.generate_descend_point(self.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(self.from_cp)
|
||||
flight.points.append(rtb)
|
||||
self.generate_cas(flight, flight.from_cp, location)
|
||||
|
||||
self.cas_flights.append(flight)
|
||||
self.flights.append(flight)
|
||||
@ -319,49 +232,10 @@ class FlightPlanner:
|
||||
flight.points = []
|
||||
flight.scheduled_in = offset + i*random.randint(SEAD_EVERY_X_MINUTES-5, SEAD_EVERY_X_MINUTES+5)
|
||||
|
||||
ascend = self.generate_ascend_point(self.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
location = self.potential_sead_targets[0][0]
|
||||
self.potential_sead_targets.pop(0)
|
||||
|
||||
heading = self.from_cp.position.heading_between_point(location.position)
|
||||
ingress_heading = heading - 180 + 25
|
||||
egress_heading = heading - 180 - 25
|
||||
|
||||
ingress_pos = location.position.point_from_heading(ingress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
ingress_point = FlightWaypoint(ingress_pos.x, ingress_pos.y, INGRESS_ALT)
|
||||
ingress_point.pretty_name = "INGRESS on " + location.obj_name
|
||||
ingress_point.description = "INGRESS on " + location.obj_name
|
||||
ingress_point.waypoint_type = FlightWaypointType.INGRESS_SEAD
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
point = FlightWaypoint(location.position.x, location.position.y, 0)
|
||||
point.alt_type = "RADIO"
|
||||
if flight.flight_type == FlightType.DEAD:
|
||||
point.description = "SEAD on " + location.obj_name
|
||||
point.pretty_name = "SEAD on " + location.obj_name
|
||||
point.only_for_player = True
|
||||
else:
|
||||
point.description = "DEAD on " + location.obj_name
|
||||
point.pretty_name = "DEAD on " + location.obj_name
|
||||
point.only_for_player = True
|
||||
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
|
||||
egress_pos = location.position.point_from_heading(egress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
egress_point = FlightWaypoint(egress_pos.x, egress_pos.y, EGRESS_ALT)
|
||||
egress_point.pretty_name = "EGRESS from " + location.obj_name
|
||||
egress_point.description = "EGRESS from " + location.obj_name
|
||||
egress_point.waypoint_type = FlightWaypointType.EGRESS
|
||||
flight.points.append(egress_point)
|
||||
|
||||
descend = self.generate_descend_point(self.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(self.from_cp)
|
||||
flight.points.append(rtb)
|
||||
self.generate_sead(flight, location, [])
|
||||
|
||||
self.sead_flights.append(flight)
|
||||
self.flights.append(flight)
|
||||
@ -397,75 +271,10 @@ class FlightPlanner:
|
||||
flight.points = []
|
||||
flight.scheduled_in = offset + i*random.randint(SEAD_EVERY_X_MINUTES-5, SEAD_EVERY_X_MINUTES+5)
|
||||
|
||||
ascend = self.generate_ascend_point(self.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
location = self.potential_strike_targets[0][0]
|
||||
self.potential_strike_targets.pop(0)
|
||||
|
||||
heading = self.from_cp.position.heading_between_point(location.position)
|
||||
ingress_heading = heading - 180 + 25
|
||||
egress_heading = heading - 180 - 25
|
||||
|
||||
ingress_pos = location.position.point_from_heading(ingress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
ingress_point = FlightWaypoint(ingress_pos.x, ingress_pos.y, INGRESS_ALT)
|
||||
ingress_point.pretty_name = "INGRESS on " + location.obj_name
|
||||
ingress_point.description = "INGRESS on " + location.obj_name
|
||||
ingress_point.name = "INGRESS"
|
||||
ingress_point.waypoint_type = FlightWaypointType.INGRESS_STRIKE
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
if len(location.groups) > 0 and location.dcs_identifier == "AA":
|
||||
for g in location.groups:
|
||||
for j, u in enumerate(g.units):
|
||||
point = FlightWaypoint(u.position.x, u.position.y, 0)
|
||||
point.description = "STRIKE " + "[" + str(location.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
point.pretty_name = "STRIKE " + "[" + str(location.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
point.name = location.obj_name + "#" + str(j)
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
else:
|
||||
if hasattr(location, "obj_name"):
|
||||
buildings = self.game.theater.find_ground_objects_by_obj_name(location.obj_name)
|
||||
print(buildings)
|
||||
for building in buildings:
|
||||
print("BUILDING " + str(building.is_dead) + " " + str(building.dcs_identifier))
|
||||
if building.is_dead:
|
||||
continue
|
||||
|
||||
point = FlightWaypoint(building.position.x, building.position.y, 0)
|
||||
point.description = "STRIKE on " + building.obj_name + " " + str(building.category)
|
||||
point.pretty_name = "STRIKE on " + building.obj_name + " " + str(building.category)
|
||||
point.name = building.obj_name
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(building)
|
||||
flight.points.append(point)
|
||||
else:
|
||||
point = FlightWaypoint(location.position.x, location.position.y, 0)
|
||||
point.description = "STRIKE on " + location.obj_name + " " + str(location.category)
|
||||
point.pretty_name = "STRIKE on " + location.obj_name + " " + str(location.category)
|
||||
point.name = location.obj_name
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
|
||||
|
||||
|
||||
|
||||
egress_pos = location.position.point_from_heading(egress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
egress_point = FlightWaypoint(egress_pos.x, egress_pos.y, EGRESS_ALT)
|
||||
egress_point.name = "EGRESS"
|
||||
egress_point.pretty_name = "EGRESS from " + location.obj_name
|
||||
egress_point.description = "EGRESS from " + location.obj_name
|
||||
egress_point.waypoint_type = FlightWaypointType.EGRESS
|
||||
flight.points.append(egress_point)
|
||||
|
||||
descend = self.generate_descend_point(self.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(self.from_cp)
|
||||
flight.points.append(rtb)
|
||||
self.generate_strike(flight, location)
|
||||
|
||||
self.strike_flights.append(flight)
|
||||
self.flights.append(flight)
|
||||
@ -475,9 +284,12 @@ class FlightPlanner:
|
||||
self.aircraft_inventory[k] = v
|
||||
|
||||
def _get_cas_locations(self):
|
||||
return self._get_cas_locations_for_cp(self.from_cp)
|
||||
|
||||
def _get_cas_locations_for_cp(self, for_cp):
|
||||
cas_locations = []
|
||||
for cp in self.from_cp.connected_points:
|
||||
if cp.captured != self.from_cp.captured:
|
||||
for cp in for_cp.connected_points:
|
||||
if cp.captured != for_cp.captured:
|
||||
cas_locations.append(cp)
|
||||
return cas_locations
|
||||
|
||||
@ -563,7 +375,300 @@ class FlightPlanner:
|
||||
del base_aircraft_inventory[f.unit_type]
|
||||
return base_aircraft_inventory
|
||||
|
||||
|
||||
def generate_strike(self, flight, location):
|
||||
|
||||
flight.flight_type = FlightType.STRIKE
|
||||
ascend = self.generate_ascend_point(flight.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
heading = flight.from_cp.position.heading_between_point(location.position)
|
||||
ingress_heading = heading - 180 + 25
|
||||
egress_heading = heading - 180 - 25
|
||||
|
||||
ingress_pos = location.position.point_from_heading(ingress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
ingress_point = FlightWaypoint(ingress_pos.x, ingress_pos.y, INGRESS_ALT)
|
||||
ingress_point.pretty_name = "INGRESS on " + location.obj_name
|
||||
ingress_point.description = "INGRESS on " + location.obj_name
|
||||
ingress_point.name = "INGRESS"
|
||||
ingress_point.waypoint_type = FlightWaypointType.INGRESS_STRIKE
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
if len(location.groups) > 0 and location.dcs_identifier == "AA":
|
||||
for g in location.groups:
|
||||
for j, u in enumerate(g.units):
|
||||
point = FlightWaypoint(u.position.x, u.position.y, 0)
|
||||
point.description = "STRIKE " + "[" + str(location.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
point.pretty_name = "STRIKE " + "[" + str(location.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
point.name = location.obj_name + "#" + str(j)
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
else:
|
||||
if hasattr(location, "obj_name"):
|
||||
buildings = self.game.theater.find_ground_objects_by_obj_name(location.obj_name)
|
||||
print(buildings)
|
||||
for building in buildings:
|
||||
print("BUILDING " + str(building.is_dead) + " " + str(building.dcs_identifier))
|
||||
if building.is_dead:
|
||||
continue
|
||||
|
||||
point = FlightWaypoint(building.position.x, building.position.y, 0)
|
||||
point.description = "STRIKE on " + building.obj_name + " " + str(building.category)
|
||||
point.pretty_name = "STRIKE on " + building.obj_name + " " + str(building.category)
|
||||
point.name = building.obj_name
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(building)
|
||||
flight.points.append(point)
|
||||
else:
|
||||
point = FlightWaypoint(location.position.x, location.position.y, 0)
|
||||
point.description = "STRIKE on " + location.obj_name
|
||||
point.pretty_name = "STRIKE on " + location.obj_name
|
||||
point.name = location.obj_name
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
|
||||
egress_pos = location.position.point_from_heading(egress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
egress_point = FlightWaypoint(egress_pos.x, egress_pos.y, EGRESS_ALT)
|
||||
egress_point.name = "EGRESS"
|
||||
egress_point.pretty_name = "EGRESS from " + location.obj_name
|
||||
egress_point.description = "EGRESS from " + location.obj_name
|
||||
egress_point.waypoint_type = FlightWaypointType.EGRESS
|
||||
flight.points.append(egress_point)
|
||||
|
||||
descend = self.generate_descend_point(flight.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(flight.from_cp)
|
||||
flight.points.append(rtb)
|
||||
|
||||
def generate_barcap(self, flight, for_cp):
|
||||
"""
|
||||
Generate a barcap flight at a given location
|
||||
:param flight: Flight to setup
|
||||
:param for_cp: CP to protect
|
||||
:param location: Location to protect in priority
|
||||
:param location: Is the location to protect a frontline
|
||||
"""
|
||||
flight.flight_type = FlightType.BARCAP if for_cp.is_carrier else FlightType.CAP
|
||||
patrol_alt = random.randint(PATROL_ALT_RANGE[0], PATROL_ALT_RANGE[1])
|
||||
|
||||
if len(for_cp.ground_objects) > 0:
|
||||
loc = random.choice(for_cp.ground_objects)
|
||||
hdg = for_cp.position.heading_between_point(loc.position)
|
||||
radius = nm_to_meter(random.randint(15, 40))
|
||||
orbit0p = loc.position.point_from_heading(hdg - 90, radius)
|
||||
orbit1p = loc.position.point_from_heading(hdg + 90, radius)
|
||||
else:
|
||||
loc = for_cp.position.point_from_heading(random.randint(0, 360),random.randint(nm_to_meter(10), nm_to_meter(40)))
|
||||
hdg = for_cp.position.heading_between_point(loc.position)
|
||||
radius = nm_to_meter(random.randint(15, 40))
|
||||
orbit0p = loc.position.point_from_heading(hdg - 90, radius)
|
||||
orbit1p = loc.position.point_from_heading(hdg + 90, radius)
|
||||
|
||||
# Create points
|
||||
ascend = self.generate_ascend_point(flight.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
orbit0 = FlightWaypoint(orbit0p.x, orbit0p.y, patrol_alt)
|
||||
orbit0.name = "ORBIT 0"
|
||||
orbit0.description = "Standby between this point and the next one"
|
||||
orbit0.pretty_name = "Race-track start"
|
||||
orbit0.waypoint_type = FlightWaypointType.PATROL_TRACK
|
||||
flight.points.append(orbit0)
|
||||
|
||||
orbit1 = FlightWaypoint(orbit1p.x, orbit1p.y, patrol_alt)
|
||||
orbit1.name = "ORBIT 1"
|
||||
orbit1.description = "Standby between this point and the previous one"
|
||||
orbit1.pretty_name = "Race-track end"
|
||||
orbit1.waypoint_type = FlightWaypointType.PATROL
|
||||
flight.points.append(orbit1)
|
||||
|
||||
orbit0.targets.append(for_cp)
|
||||
obj_added = []
|
||||
for ground_object in for_cp.ground_objects:
|
||||
if ground_object.obj_name not in obj_added and not ground_object.airbase_group:
|
||||
orbit0.targets.append(ground_object)
|
||||
obj_added.append(ground_object.obj_name)
|
||||
|
||||
descend = self.generate_descend_point(flight.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(flight.from_cp)
|
||||
flight.points.append(rtb)
|
||||
|
||||
|
||||
def generate_frontline_cap(self, flight, ally_cp, enemy_cp):
|
||||
"""
|
||||
Generate a cap flight for the frontline between ally_cp and enemy cp in order to ensure air superiority and
|
||||
protect friendly CAP airbase
|
||||
:param flight: Flight to setup
|
||||
:param ally_cp: CP to protect
|
||||
:param enemy_cp: Enemy connected cp
|
||||
"""
|
||||
flight.flight_type = FlightType.CAP
|
||||
patrol_alt = random.randint(PATROL_ALT_RANGE[0], PATROL_ALT_RANGE[1])
|
||||
|
||||
# Find targets waypoints
|
||||
ingress, heading, distance = Conflict.frontline_vector(ally_cp, enemy_cp, self.game.theater)
|
||||
center = ingress.point_from_heading(heading, distance / 2)
|
||||
orbit_center = center.point_from_heading(heading - 90, random.randint(nm_to_meter(6), nm_to_meter(15)))
|
||||
radius = distance * 2
|
||||
orbit0p = orbit_center.point_from_heading(heading, radius)
|
||||
orbit1p = orbit_center.point_from_heading(heading + 180, radius)
|
||||
|
||||
# Create points
|
||||
ascend = self.generate_ascend_point(flight.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
orbit0 = FlightWaypoint(orbit0p.x, orbit0p.y, patrol_alt)
|
||||
orbit0.name = "ORBIT 0"
|
||||
orbit0.description = "Standby between this point and the next one"
|
||||
orbit0.pretty_name = "Race-track start"
|
||||
orbit0.waypoint_type = FlightWaypointType.PATROL_TRACK
|
||||
flight.points.append(orbit0)
|
||||
|
||||
orbit1 = FlightWaypoint(orbit1p.x, orbit1p.y, patrol_alt)
|
||||
orbit1.name = "ORBIT 1"
|
||||
orbit1.description = "Standby between this point and the previous one"
|
||||
orbit1.pretty_name = "Race-track end"
|
||||
orbit1.waypoint_type = FlightWaypointType.PATROL
|
||||
flight.points.append(orbit1)
|
||||
|
||||
# Note : Targets of a PATROL TRACK waypoints are the points to be defended
|
||||
orbit0.targets.append(flight.from_cp)
|
||||
orbit0.targets.append(center)
|
||||
|
||||
descend = self.generate_descend_point(flight.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(flight.from_cp)
|
||||
flight.points.append(rtb)
|
||||
|
||||
|
||||
def generate_sead(self, flight, location, custom_targets = []):
|
||||
"""
|
||||
Generate a sead flight at a given location
|
||||
:param flight: Flight to setup
|
||||
:param location: Location of the SEAD target
|
||||
:param custom_targets: Custom targets if any
|
||||
"""
|
||||
flight.points = []
|
||||
flight.flight_type = random.choice([FlightType.SEAD, FlightType.DEAD])
|
||||
|
||||
ascend = self.generate_ascend_point(flight.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
heading = flight.from_cp.position.heading_between_point(location.position)
|
||||
ingress_heading = heading - 180 + 25
|
||||
egress_heading = heading - 180 - 25
|
||||
|
||||
ingress_pos = location.position.point_from_heading(ingress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
ingress_point = FlightWaypoint(ingress_pos.x, ingress_pos.y, INGRESS_ALT)
|
||||
ingress_point.name = "INGRESS"
|
||||
ingress_point.pretty_name = "INGRESS on " + location.obj_name
|
||||
ingress_point.description = "INGRESS on " + location.obj_name
|
||||
ingress_point.waypoint_type = FlightWaypointType.INGRESS_SEAD
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
if len(custom_targets) > 0:
|
||||
for target in custom_targets:
|
||||
point = FlightWaypoint(target.position.x, target.position.y, 0)
|
||||
point.alt_type = "RADIO"
|
||||
if flight.flight_type == FlightType.DEAD:
|
||||
point.description = "SEAD on " + target.type
|
||||
point.pretty_name = "SEAD on " + location.obj_name
|
||||
point.only_for_player = True
|
||||
else:
|
||||
point.description = "DEAD on " + location.obj_name
|
||||
point.pretty_name = "DEAD on " + location.obj_name
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
else:
|
||||
point = FlightWaypoint(location.position.x, location.position.y, 0)
|
||||
point.alt_type = "RADIO"
|
||||
if flight.flight_type == FlightType.DEAD:
|
||||
point.description = "SEAD on " + location.obj_name
|
||||
point.pretty_name = "SEAD on " + location.obj_name
|
||||
point.only_for_player = True
|
||||
else:
|
||||
point.description = "DEAD on " + location.obj_name
|
||||
point.pretty_name = "DEAD on " + location.obj_name
|
||||
point.only_for_player = True
|
||||
ingress_point.targets.append(location)
|
||||
flight.points.append(point)
|
||||
|
||||
egress_pos = location.position.point_from_heading(egress_heading, INGRESS_EGRESS_DISTANCE)
|
||||
egress_point = FlightWaypoint(egress_pos.x, egress_pos.y, EGRESS_ALT)
|
||||
egress_point.name = "INGRESS"
|
||||
egress_point.pretty_name = "EGRESS from " + location.obj_name
|
||||
egress_point.description = "EGRESS from " + location.obj_name
|
||||
egress_point.waypoint_type = FlightWaypointType.EGRESS
|
||||
flight.points.append(egress_point)
|
||||
|
||||
descend = self.generate_descend_point(flight.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(flight.from_cp)
|
||||
flight.points.append(rtb)
|
||||
|
||||
|
||||
def generate_cas(self, flight, from_cp, location):
|
||||
"""
|
||||
Generate a CAS flight at a given location
|
||||
:param flight: Flight to setup
|
||||
:param location: Location of the CAS targets
|
||||
"""
|
||||
|
||||
flight.points = []
|
||||
flight.flight_type = FlightType.CAS
|
||||
|
||||
ingress, heading, distance = Conflict.frontline_vector(from_cp, location, self.game.theater)
|
||||
center = ingress.point_from_heading(heading, distance / 2)
|
||||
egress = ingress.point_from_heading(heading, distance)
|
||||
|
||||
ascend = self.generate_ascend_point(flight.from_cp)
|
||||
flight.points.append(ascend)
|
||||
|
||||
ingress_point = FlightWaypoint(ingress.x, ingress.y, 1000)
|
||||
ingress_point.alt_type = "RADIO"
|
||||
ingress_point.name = "INGRESS"
|
||||
ingress_point.pretty_name = "INGRESS"
|
||||
ingress_point.description = "Ingress into CAS area"
|
||||
ingress_point.waypoint_type = FlightWaypointType.INGRESS_CAS
|
||||
flight.points.append(ingress_point)
|
||||
|
||||
center_point = FlightWaypoint(center.x, center.y, 1000)
|
||||
center_point.alt_type = "RADIO"
|
||||
center_point.description = "Provide CAS"
|
||||
center_point.name = "CAS"
|
||||
center_point.pretty_name = "CAS"
|
||||
center_point.waypoint_type = FlightWaypointType.CAS
|
||||
flight.points.append(center_point)
|
||||
|
||||
egress_point = FlightWaypoint(egress.x, egress.y, 1000)
|
||||
egress_point.alt_type = "RADIO"
|
||||
egress_point.description = "Egress from CAS area"
|
||||
egress_point.name = "EGRESS"
|
||||
egress_point.pretty_name = "EGRESS"
|
||||
egress_point.waypoint_type = FlightWaypointType.EGRESS
|
||||
flight.points.append(egress_point)
|
||||
|
||||
descend = self.generate_descend_point(flight.from_cp)
|
||||
flight.points.append(descend)
|
||||
|
||||
rtb = self.generate_rtb_waypoint(flight.from_cp)
|
||||
flight.points.append(rtb)
|
||||
|
||||
|
||||
def generate_ascend_point(self, from_cp):
|
||||
"""
|
||||
Generate ascend point
|
||||
:param from_cp: Airport you're taking off from
|
||||
:return:
|
||||
"""
|
||||
ascend_heading = from_cp.heading
|
||||
pos_ascend = from_cp.position.point_from_heading(ascend_heading, 10000)
|
||||
ascend = FlightWaypoint(pos_ascend.x, pos_ascend.y, PATTERN_ALTITUDE)
|
||||
@ -574,9 +679,15 @@ class FlightPlanner:
|
||||
ascend.waypoint_type = FlightWaypointType.ASCEND_POINT
|
||||
return ascend
|
||||
|
||||
|
||||
def generate_descend_point(self, from_cp):
|
||||
"""
|
||||
Generate approach/descend point
|
||||
:param from_cp: Airport you're landing at
|
||||
:return:
|
||||
"""
|
||||
ascend_heading = from_cp.heading
|
||||
descend = from_cp.position.point_from_heading(ascend_heading - 180, 30000)
|
||||
descend = from_cp.position.point_from_heading(ascend_heading - 180, 10000)
|
||||
descend = FlightWaypoint(descend.x, descend.y, PATTERN_ALTITUDE)
|
||||
descend.name = "DESCEND"
|
||||
descend.alt_type = "RADIO"
|
||||
@ -585,7 +696,13 @@ class FlightPlanner:
|
||||
descend.waypoint_type = FlightWaypointType.DESCENT_POINT
|
||||
return descend
|
||||
|
||||
|
||||
def generate_rtb_waypoint(self, from_cp):
|
||||
"""
|
||||
Generate RTB landing point
|
||||
:param from_cp: Airport you're landing at
|
||||
:return:
|
||||
"""
|
||||
rtb = from_cp.position
|
||||
rtb = FlightWaypoint(rtb.x, rtb.y, 0)
|
||||
rtb.name = "LANDING"
|
||||
@ -593,5 +710,4 @@ class FlightPlanner:
|
||||
rtb.description = "RTB"
|
||||
rtb.pretty_name = "RTB"
|
||||
rtb.waypoint_type = FlightWaypointType.LANDING_POINT
|
||||
return rtb
|
||||
|
||||
return rtb
|
||||
@ -46,6 +46,18 @@ class FlightWaypointType(Enum):
|
||||
TARGET_POINT = 12 # A target building or static object, position
|
||||
TARGET_GROUP_LOC = 13 # A target group approximate location
|
||||
TARGET_SHIP = 14 # A target ship known location
|
||||
CUSTOM = 15 # User waypoint (no specific behaviour)
|
||||
|
||||
|
||||
class PredefinedWaypointCategory(Enum):
|
||||
NOT_PREDEFINED = 0
|
||||
ALLY_CP = 1
|
||||
ENEMY_CP = 2
|
||||
FRONTLINE = 3
|
||||
ENEMY_BUILDING = 4
|
||||
ENEMY_UNIT = 5
|
||||
ALLY_BUILDING = 6
|
||||
ALLY_UNIT = 7
|
||||
|
||||
|
||||
class FlightWaypoint:
|
||||
@ -61,7 +73,9 @@ class FlightWaypoint:
|
||||
self.obj_name = ""
|
||||
self.pretty_name = ""
|
||||
self.waypoint_type = FlightWaypointType.TAKEOFF # type: FlightWaypointType
|
||||
self.category = PredefinedWaypointCategory.NOT_PREDEFINED# type: PredefinedWaypointCategory
|
||||
self.only_for_player = False
|
||||
self.data = None
|
||||
|
||||
|
||||
class Flight:
|
||||
|
||||
@ -1,153 +0,0 @@
|
||||
from PySide2.QtCore import QSortFilterProxyModel, Qt, QModelIndex
|
||||
from PySide2.QtGui import QStandardItem, QStandardItemModel
|
||||
from PySide2.QtWidgets import QComboBox, QCompleter
|
||||
from game import Game
|
||||
from gen import Conflict
|
||||
from gen.flights.flight import FlightWaypoint
|
||||
from theater import ControlPointType
|
||||
|
||||
|
||||
class QPredefinedWaypointSelectionComboBox(QComboBox):
|
||||
|
||||
def __init__(self, game: Game, parent=None):
|
||||
super(QPredefinedWaypointSelectionComboBox, self).__init__(parent)
|
||||
|
||||
self.game = game
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
self.setEditable(True)
|
||||
self.completer = QCompleter(self)
|
||||
|
||||
# always show all completions
|
||||
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
|
||||
self.pFilterModel = QSortFilterProxyModel(self)
|
||||
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
|
||||
|
||||
self.completer.setPopup(self.view())
|
||||
|
||||
self.setCompleter(self.completer)
|
||||
|
||||
self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
|
||||
self.completer.activated.connect(self.setTextIfCompleterIsClicked)
|
||||
|
||||
self.find_possible_waypoints()
|
||||
|
||||
def setModel(self, model):
|
||||
super(QPredefinedWaypointSelectionComboBox, self).setModel(model)
|
||||
self.pFilterModel.setSourceModel(model)
|
||||
self.completer.setModel(self.pFilterModel)
|
||||
|
||||
def setModelColumn(self, column):
|
||||
self.completer.setCompletionColumn(column)
|
||||
self.pFilterModel.setFilterKeyColumn(column)
|
||||
super(QPredefinedWaypointSelectionComboBox, self).setModelColumn(column)
|
||||
|
||||
def view(self):
|
||||
return self.completer.popup()
|
||||
|
||||
def index(self):
|
||||
return self.currentIndex()
|
||||
|
||||
def setTextIfCompleterIsClicked(self, text):
|
||||
if text:
|
||||
index = self.findText(text)
|
||||
self.setCurrentIndex(index)
|
||||
|
||||
def get_selected_waypoints(self, include_all_from_same_location=False):
|
||||
n = self.currentText()
|
||||
|
||||
first_waypoint = None
|
||||
for w in self.wpts:
|
||||
if w.pretty_name == n:
|
||||
first_waypoint = w
|
||||
break
|
||||
|
||||
if first_waypoint is None:
|
||||
return []
|
||||
|
||||
waypoints = [first_waypoint]
|
||||
if include_all_from_same_location:
|
||||
for w in self.wpts:
|
||||
if w is not first_waypoint and w.obj_name and w.obj_name == first_waypoint.obj_name:
|
||||
waypoints.append(w)
|
||||
|
||||
return waypoints
|
||||
|
||||
def find_possible_waypoints(self):
|
||||
|
||||
self.wpts = []
|
||||
model = QStandardItemModel()
|
||||
i = 0
|
||||
|
||||
def add_model_item(i, model, name, wpt):
|
||||
print(name)
|
||||
item = QStandardItem(name)
|
||||
model.setItem(i, 0, item)
|
||||
self.wpts.append(wpt)
|
||||
return i + 1
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
print(cp)
|
||||
if cp.captured:
|
||||
enemy_cp = [ecp for ecp in cp.connected_points if ecp.captured != cp.captured]
|
||||
for ecp in enemy_cp:
|
||||
pos = Conflict.frontline_position(self.game.theater, cp, ecp)[0]
|
||||
wpt = FlightWaypoint(pos.x, pos.y, 800)
|
||||
wpt.name = "Frontline " + cp.name + "/" + ecp.name + " [CAS]"
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.description = "Frontline"
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
for ground_object in cp.ground_objects:
|
||||
if not ground_object.is_dead and not ground_object.dcs_identifier == "AA":
|
||||
wpt = FlightWaypoint(ground_object.position.x,ground_object.position.y, 0)
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + ground_object.category + " #" + str(ground_object.object_id)
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.obj_name = ground_object.obj_name
|
||||
wpt.targets.append(ground_object)
|
||||
if cp.captured:
|
||||
wpt.description = "Friendly Building"
|
||||
else:
|
||||
wpt.description = "Enemy Building"
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
|
||||
for ground_object in cp.ground_objects:
|
||||
if not ground_object.is_dead and ground_object.dcs_identifier == "AA":
|
||||
for g in ground_object.groups:
|
||||
for j, u in enumerate(g.units):
|
||||
wpt = FlightWaypoint(u.position.x, u.position.y, 0)
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.targets.append(u)
|
||||
wpt.obj_name = ground_object.obj_name
|
||||
if cp.captured:
|
||||
wpt.description = "Friendly unit : " + u.type
|
||||
else:
|
||||
wpt.description = "Enemy unit : " + u.type
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
|
||||
wpt = FlightWaypoint(cp.position.x, cp.position.y, 0)
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.name = cp.name
|
||||
if cp.captured:
|
||||
wpt.description = "Position of " + cp.name + " [Friendly Airbase]"
|
||||
else:
|
||||
wpt.description = "Position of " + cp.name + " [Enemy Airbase]"
|
||||
|
||||
if cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP:
|
||||
wpt.pretty_name = cp.name + " (Aircraft Carrier Group)"
|
||||
elif cp.cptype == ControlPointType.LHA_GROUP:
|
||||
wpt.pretty_name = cp.name + " (LHA Group)"
|
||||
else:
|
||||
wpt.pretty_name = cp.name + " (Airbase)"
|
||||
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
self.setModel(model)
|
||||
53
qt_ui/widgets/combos/QFilteredComboBox.py
Normal file
53
qt_ui/widgets/combos/QFilteredComboBox.py
Normal file
@ -0,0 +1,53 @@
|
||||
from PySide2.QtCore import QSortFilterProxyModel, Qt
|
||||
from PySide2.QtWidgets import QComboBox, QCompleter
|
||||
|
||||
|
||||
class QFilteredComboBox(QComboBox):
|
||||
|
||||
def __init__(self, parent=None, include_targets=True, include_airbases=True,
|
||||
include_frontlines=True, include_units=True, include_enemy=True, include_friendly=True):
|
||||
super(QFilteredComboBox, self).__init__(parent)
|
||||
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
self.setEditable(True)
|
||||
self.completer = QCompleter(self)
|
||||
|
||||
self.include_targets = include_targets
|
||||
self.include_airbases = include_airbases
|
||||
self.include_frontlines = include_frontlines
|
||||
self.include_units = include_units
|
||||
self.include_enemy = include_enemy
|
||||
self.include_friendly = include_friendly
|
||||
|
||||
# always show all completions
|
||||
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
|
||||
self.pFilterModel = QSortFilterProxyModel(self)
|
||||
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
|
||||
|
||||
self.completer.setPopup(self.view())
|
||||
|
||||
self.setCompleter(self.completer)
|
||||
|
||||
self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
|
||||
self.completer.activated.connect(self.setTextIfCompleterIsClicked)
|
||||
|
||||
def setModel(self, model):
|
||||
super(QFilteredComboBox, self).setModel(model)
|
||||
self.pFilterModel.setSourceModel(model)
|
||||
self.completer.setModel(self.pFilterModel)
|
||||
|
||||
def setModelColumn(self, column):
|
||||
self.completer.setCompletionColumn(column)
|
||||
self.pFilterModel.setFilterKeyColumn(column)
|
||||
super(QFilteredComboBox, self).setModelColumn(column)
|
||||
|
||||
def view(self):
|
||||
return self.completer.popup()
|
||||
|
||||
def index(self):
|
||||
return self.currentIndex()
|
||||
|
||||
def setTextIfCompleterIsClicked(self, text):
|
||||
if text:
|
||||
index = self.findText(text)
|
||||
self.setCurrentIndex(index)
|
||||
139
qt_ui/widgets/combos/QPredefinedWaypointSelectionComboBox.py
Normal file
139
qt_ui/widgets/combos/QPredefinedWaypointSelectionComboBox.py
Normal file
@ -0,0 +1,139 @@
|
||||
from PySide2.QtCore import QSortFilterProxyModel, Qt, QModelIndex
|
||||
from PySide2.QtGui import QStandardItem, QStandardItemModel
|
||||
from PySide2.QtWidgets import QComboBox, QCompleter
|
||||
from game import Game
|
||||
from gen import Conflict, FlightWaypointType
|
||||
from gen.flights.flight import FlightWaypoint, PredefinedWaypointCategory
|
||||
from qt_ui.widgets.combos.QFilteredComboBox import QFilteredComboBox
|
||||
from theater import ControlPointType
|
||||
|
||||
|
||||
class QPredefinedWaypointSelectionComboBox(QFilteredComboBox):
|
||||
|
||||
def __init__(self, game: Game, parent=None, include_targets=True, include_airbases=True,
|
||||
include_frontlines=True, include_units=True, include_enemy=True, include_friendly=True):
|
||||
super(QPredefinedWaypointSelectionComboBox, self).__init__(parent)
|
||||
self.game = game
|
||||
self.include_targets = include_targets
|
||||
self.include_airbases = include_airbases
|
||||
self.include_frontlines = include_frontlines
|
||||
self.include_units = include_units
|
||||
self.include_enemy = include_enemy
|
||||
self.include_friendly = include_friendly
|
||||
self.find_possible_waypoints()
|
||||
|
||||
def get_selected_waypoints(self, include_all_from_same_location=False):
|
||||
n = self.currentText()
|
||||
first_waypoint = None
|
||||
for w in self.wpts:
|
||||
if w.pretty_name == n:
|
||||
first_waypoint = w
|
||||
break
|
||||
if first_waypoint is None:
|
||||
return []
|
||||
waypoints = [first_waypoint]
|
||||
if include_all_from_same_location:
|
||||
for w in self.wpts:
|
||||
if w is not first_waypoint and w.obj_name and w.obj_name == first_waypoint.obj_name:
|
||||
waypoints.append(w)
|
||||
return waypoints
|
||||
|
||||
def find_possible_waypoints(self):
|
||||
|
||||
self.wpts = []
|
||||
model = QStandardItemModel()
|
||||
i = 0
|
||||
|
||||
def add_model_item(i, model, name, wpt):
|
||||
print(name)
|
||||
item = QStandardItem(name)
|
||||
model.setItem(i, 0, item)
|
||||
self.wpts.append(wpt)
|
||||
return i + 1
|
||||
|
||||
if self.include_frontlines:
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.captured:
|
||||
enemy_cp = [ecp for ecp in cp.connected_points if ecp.captured != cp.captured]
|
||||
for ecp in enemy_cp:
|
||||
pos = Conflict.frontline_position(self.game.theater, cp, ecp)[0]
|
||||
wpt = FlightWaypoint(pos.x, pos.y, 800)
|
||||
wpt.name = "Frontline " + cp.name + "/" + ecp.name + " [CAS]"
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.description = "Frontline"
|
||||
wpt.data = [cp, ecp]
|
||||
wpt.waypoint_type = FlightWaypointType.CUSTOM
|
||||
wpt.category = PredefinedWaypointCategory.FRONTLINE
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
if self.include_targets:
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if (self.include_enemy and not cp.captured) or (self.include_friendly and cp.captured):
|
||||
for ground_object in cp.ground_objects:
|
||||
if not ground_object.is_dead and not ground_object.dcs_identifier == "AA":
|
||||
wpt = FlightWaypoint(ground_object.position.x,ground_object.position.y, 0)
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + ground_object.category + " #" + str(ground_object.object_id)
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.obj_name = ground_object.obj_name
|
||||
wpt.targets.append(ground_object)
|
||||
wpt.data = ground_object
|
||||
wpt.waypoint_type = FlightWaypointType.CUSTOM
|
||||
if cp.captured:
|
||||
wpt.description = "Friendly Building"
|
||||
wpt.category = PredefinedWaypointCategory.ALLY_BUILDING
|
||||
else:
|
||||
wpt.description = "Enemy Building"
|
||||
wpt.category = PredefinedWaypointCategory.ENEMY_BUILDING
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
if self.include_units:
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if (self.include_enemy and not cp.captured) or (self.include_friendly and cp.captured):
|
||||
for ground_object in cp.ground_objects:
|
||||
if not ground_object.is_dead and ground_object.dcs_identifier == "AA":
|
||||
for g in ground_object.groups:
|
||||
for j, u in enumerate(g.units):
|
||||
wpt = FlightWaypoint(u.position.x, u.position.y, 0)
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + u.type + " #" + str(j)
|
||||
wpt.pretty_name = wpt.name
|
||||
wpt.targets.append(u)
|
||||
wpt.data = u
|
||||
wpt.obj_name = ground_object.obj_name
|
||||
wpt.waypoint_type = FlightWaypointType.CUSTOM
|
||||
if cp.captured:
|
||||
wpt.description = "Friendly unit : " + u.type
|
||||
wpt.category = PredefinedWaypointCategory.ALLY_UNIT
|
||||
else:
|
||||
wpt.description = "Enemy unit : " + u.type
|
||||
wpt.category = PredefinedWaypointCategory.ENEMY_UNIT
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
if self.include_airbases:
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if (self.include_enemy and not cp.captured) or (self.include_friendly and cp.captured):
|
||||
wpt = FlightWaypoint(cp.position.x, cp.position.y, 0)
|
||||
wpt.alt_type = "RADIO"
|
||||
wpt.name = cp.name
|
||||
wpt.data = cp
|
||||
wpt.waypoint_type = FlightWaypointType.CUSTOM
|
||||
if cp.captured:
|
||||
wpt.description = "Position of " + cp.name + " [Friendly Airbase]"
|
||||
wpt.category = PredefinedWaypointCategory.ALLY_CP
|
||||
else:
|
||||
wpt.description = "Position of " + cp.name + " [Enemy Airbase]"
|
||||
wpt.category = PredefinedWaypointCategory.ENEMY_CP
|
||||
|
||||
if cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP:
|
||||
wpt.pretty_name = cp.name + " (Aircraft Carrier Group)"
|
||||
elif cp.cptype == ControlPointType.LHA_GROUP:
|
||||
wpt.pretty_name = cp.name + " (LHA Group)"
|
||||
else:
|
||||
wpt.pretty_name = cp.name + " (Airbase)"
|
||||
|
||||
|
||||
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||
|
||||
self.setModel(model)
|
||||
76
qt_ui/widgets/combos/QSEADTargetSelectionComboBox.py
Normal file
76
qt_ui/widgets/combos/QSEADTargetSelectionComboBox.py
Normal file
@ -0,0 +1,76 @@
|
||||
from PySide2.QtCore import QSortFilterProxyModel, Qt, QModelIndex
|
||||
from PySide2.QtGui import QStandardItem, QStandardItemModel
|
||||
from PySide2.QtWidgets import QComboBox, QCompleter
|
||||
from game import Game
|
||||
from gen import Conflict, FlightWaypointType, db
|
||||
from gen.flights.flight import FlightWaypoint, PredefinedWaypointCategory
|
||||
from qt_ui.widgets.combos.QFilteredComboBox import QFilteredComboBox
|
||||
from theater import ControlPointType
|
||||
|
||||
|
||||
class SEADTargetInfo:
|
||||
|
||||
def __init__(self):
|
||||
self.name = ""
|
||||
self.location = None
|
||||
self.radars = []
|
||||
self.threat_range = 0
|
||||
self.detection_range = 0
|
||||
|
||||
class QSEADTargetSelectionComboBox(QFilteredComboBox):
|
||||
|
||||
def __init__(self, game: Game, parent=None):
|
||||
super(QSEADTargetSelectionComboBox, self).__init__(parent)
|
||||
self.game = game
|
||||
self.find_possible_sead_targets()
|
||||
|
||||
def get_selected_target(self):
|
||||
n = self.currentText()
|
||||
for target in self.targets:
|
||||
if target.name == n:
|
||||
return target
|
||||
|
||||
def find_possible_sead_targets(self):
|
||||
|
||||
self.targets = []
|
||||
i = 0
|
||||
model = QStandardItemModel()
|
||||
|
||||
def add_model_item(i, model, target):
|
||||
item = QStandardItem(target.name)
|
||||
model.setItem(i, 0, item)
|
||||
self.targets.append(target)
|
||||
return i + 1
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.captured: continue
|
||||
for g in cp.ground_objects:
|
||||
|
||||
radars = []
|
||||
detection_range = 0
|
||||
threat_range = 0
|
||||
if g.dcs_identifier == "AA":
|
||||
for group in g.groups:
|
||||
for u in group.units:
|
||||
utype = db.unit_type_from_name(u.type)
|
||||
if hasattr(utype, "detection_range") and utype.detection_range > 1000:
|
||||
if utype.detection_range > detection_range:
|
||||
detection_range = utype.detection_range
|
||||
radars.append(u)
|
||||
if hasattr(utype, "threat_range"):
|
||||
if utype.threat_range > threat_range:
|
||||
threat_range = utype.threat_range
|
||||
if len(radars) > 0:
|
||||
tgt_info = SEADTargetInfo()
|
||||
tgt_info.name = g.obj_name + " [" + ",".join([db.unit_type_from_name(u.type).id for u in radars]) + " ]"
|
||||
if len(tgt_info.name) > 25:
|
||||
tgt_info.name = g.obj_name + " [" + str(len(radars)) + " units]"
|
||||
tgt_info.radars = radars
|
||||
tgt_info.location = g
|
||||
tgt_info.threat_range = threat_range
|
||||
tgt_info.detection_range = detection_range
|
||||
i = add_model_item(i, model, tgt_info)
|
||||
|
||||
self.setModel(model)
|
||||
|
||||
|
||||
69
qt_ui/widgets/combos/QStrikeTargetSelectionComboBox.py
Normal file
69
qt_ui/widgets/combos/QStrikeTargetSelectionComboBox.py
Normal file
@ -0,0 +1,69 @@
|
||||
from PySide2.QtGui import QStandardItem, QStandardItemModel
|
||||
|
||||
from game import Game
|
||||
from qt_ui.widgets.combos.QFilteredComboBox import QFilteredComboBox
|
||||
|
||||
|
||||
class StrikeTargetInfo:
|
||||
|
||||
def __init__(self):
|
||||
self.name = ""
|
||||
self.location = None
|
||||
self.units = []
|
||||
self.buildings = []
|
||||
|
||||
|
||||
class QStrikeTargetSelectionComboBox(QFilteredComboBox):
|
||||
|
||||
def __init__(self, game: Game, parent=None):
|
||||
super(QStrikeTargetSelectionComboBox, self).__init__(parent)
|
||||
self.game = game
|
||||
self.find_possible_strike_targets()
|
||||
|
||||
def get_selected_target(self):
|
||||
n = self.currentText()
|
||||
for target in self.targets:
|
||||
if target.name == n:
|
||||
return target
|
||||
|
||||
def find_possible_strike_targets(self):
|
||||
|
||||
self.targets = []
|
||||
i = 0
|
||||
model = QStandardItemModel()
|
||||
|
||||
def add_model_item(i, model, target):
|
||||
item = QStandardItem(target.name)
|
||||
model.setItem(i, 0, item)
|
||||
self.targets.append(target)
|
||||
return i + 1
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.captured: continue
|
||||
|
||||
added_obj_names = []
|
||||
|
||||
for g in cp.ground_objects:
|
||||
if g.obj_name in added_obj_names: continue
|
||||
|
||||
target = StrikeTargetInfo()
|
||||
target.location = g
|
||||
target.name = g.obj_name
|
||||
|
||||
if g.dcs_identifier == "AA":
|
||||
target.name = g.obj_name + " [units]"
|
||||
for group in g.groups:
|
||||
for u in group.units:
|
||||
target.units.append(u)
|
||||
else:
|
||||
target.name = g.obj_name + " [" + g.category + "]"
|
||||
for g2 in cp.ground_objects:
|
||||
if g2 is not g and g2.obj_name == g.obj_name:
|
||||
target.buildings.append(g2)
|
||||
|
||||
i = add_model_item(i, model, target)
|
||||
added_obj_names.append(g.obj_name)
|
||||
|
||||
self.setModel(model)
|
||||
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtWidgets import QDialog, QPushButton
|
||||
|
||||
from game import Game
|
||||
from gen.flights.flight import Flight
|
||||
from qt_ui.uiconstants import EVENT_ICONS
|
||||
from qt_ui.windows.mission.flight.waypoints.QFlightWaypointInfoBox import QFlightWaypointInfoBox
|
||||
|
||||
|
||||
class QAbstractMissionGenerator(QDialog):
|
||||
|
||||
def __init__(self, game: Game, flight: Flight, flight_waypoint_list, title):
|
||||
super(QAbstractMissionGenerator, self).__init__()
|
||||
self.game = game
|
||||
self.flight = flight
|
||||
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||
self.setMinimumSize(400, 250)
|
||||
self.setModal(True)
|
||||
self.setWindowTitle(title)
|
||||
self.setWindowIcon(EVENT_ICONS["strike"])
|
||||
self.flight_waypoint_list = flight_waypoint_list
|
||||
self.planner = self.game.planners[self.flight.from_cp.id]
|
||||
|
||||
self.selected_waypoints = []
|
||||
self.wpt_info = QFlightWaypointInfoBox()
|
||||
|
||||
self.ok_button = QPushButton("Ok")
|
||||
self.ok_button.clicked.connect(self.apply)
|
||||
|
||||
def on_select_wpt_changed(self):
|
||||
self.selected_waypoints = self.wpt_selection_box.get_selected_waypoints(False)
|
||||
if self.selected_waypoints is None or len(self.selected_waypoints) <= 0:
|
||||
self.ok_button.setDisabled(True)
|
||||
else:
|
||||
self.wpt_info.set_flight_waypoint(self.selected_waypoints[0])
|
||||
self.ok_button.setDisabled(False)
|
||||
|
||||
def apply(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
from PySide2.QtWidgets import QLabel, QHBoxLayout, QVBoxLayout
|
||||
|
||||
from game import Game
|
||||
from gen.flights.flight import Flight, PredefinedWaypointCategory
|
||||
from qt_ui.widgets.combos.QPredefinedWaypointSelectionComboBox import QPredefinedWaypointSelectionComboBox
|
||||
from qt_ui.windows.mission.flight.generator.QAbstractMissionGenerator import QAbstractMissionGenerator
|
||||
|
||||
|
||||
class QCAPMissionGenerator(QAbstractMissionGenerator):
|
||||
|
||||
def __init__(self, game: Game, flight: Flight, flight_waypoint_list):
|
||||
super(QCAPMissionGenerator, self).__init__(game, flight, flight_waypoint_list, "CAP Generator")
|
||||
|
||||
self.wpt_selection_box = QPredefinedWaypointSelectionComboBox(self.game, self, False, True, True, False, False, True)
|
||||
self.wpt_selection_box.setMinimumWidth(200)
|
||||
self.wpt_selection_box.currentTextChanged.connect(self.on_select_wpt_changed)
|
||||
|
||||
self.init_ui()
|
||||
self.on_select_wpt_changed()
|
||||
|
||||
def init_ui(self):
|
||||
layout = QVBoxLayout()
|
||||
|
||||
wpt_layout = QHBoxLayout()
|
||||
wpt_layout.addWidget(QLabel("CAP mission on : "))
|
||||
wpt_layout.addWidget(self.wpt_selection_box)
|
||||
wpt_layout.addStretch()
|
||||
|
||||
layout.addLayout(wpt_layout)
|
||||
layout.addWidget(self.wpt_info)
|
||||
layout.addStretch()
|
||||
layout.addWidget(self.ok_button)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def apply(self):
|
||||
self.flight.points = []
|
||||
|
||||
wpt = self.selected_waypoints[0]
|
||||
if wpt.category == PredefinedWaypointCategory.FRONTLINE:
|
||||
self.planner.generate_frontline_cap(self.flight, wpt.data[0], wpt.data[1])
|
||||
elif wpt.category == PredefinedWaypointCategory.ALLY_CP:
|
||||
self.planner.generate_barcap(self.flight, wpt.data)
|
||||
else:
|
||||
return
|
||||
|
||||
self.flight_waypoint_list.update_list()
|
||||
self.close()
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
from PySide2.QtGui import Qt
|
||||
from PySide2.QtWidgets import QLabel, QHBoxLayout, QVBoxLayout
|
||||
from dcs import Point
|
||||
|
||||
from game import Game
|
||||
from gen.flights.ai_flight_planner import meter_to_nm
|
||||
from gen.flights.flight import Flight
|
||||
from qt_ui.widgets.combos.QPredefinedWaypointSelectionComboBox import QPredefinedWaypointSelectionComboBox
|
||||
from qt_ui.windows.mission.flight.generator.QAbstractMissionGenerator import QAbstractMissionGenerator
|
||||
|
||||
|
||||
class QCASMissionGenerator(QAbstractMissionGenerator):
|
||||
|
||||
def __init__(self, game: Game, flight: Flight, flight_waypoint_list):
|
||||
super(QCASMissionGenerator, self).__init__(game, flight, flight_waypoint_list, "CAS Generator")
|
||||
|
||||
self.wpt_selection_box = QPredefinedWaypointSelectionComboBox(self.game, self, False, False, True, False, False)
|
||||
self.wpt_selection_box.setMinimumWidth(200)
|
||||
self.wpt_selection_box.currentTextChanged.connect(self.on_select_wpt_changed)
|
||||
|
||||
self.distanceToTargetLabel = QLabel("0 nm")
|
||||
self.init_ui()
|
||||
self.on_select_wpt_changed()
|
||||
|
||||
def on_select_wpt_changed(self):
|
||||
super(QCASMissionGenerator, self).on_select_wpt_changed()
|
||||
wpts = self.wpt_selection_box.get_selected_waypoints()
|
||||
|
||||
if len(wpts) > 0:
|
||||
self.distanceToTargetLabel.setText("~" + str(meter_to_nm(self.flight.from_cp.position.distance_to_point(Point(wpts[0].x, wpts[0].y)))) + " nm")
|
||||
else:
|
||||
self.distanceToTargetLabel.setText("??? nm")
|
||||
|
||||
|
||||
|
||||
def init_ui(self):
|
||||
layout = QVBoxLayout()
|
||||
|
||||
wpt_layout = QHBoxLayout()
|
||||
wpt_layout.addWidget(QLabel("CAS : "))
|
||||
wpt_layout.addWidget(self.wpt_selection_box)
|
||||
wpt_layout.addStretch()
|
||||
|
||||
distToTarget = QHBoxLayout()
|
||||
distToTarget.addWidget(QLabel("Distance to target : "))
|
||||
distToTarget.addStretch()
|
||||
distToTarget.addWidget(self.distanceToTargetLabel, alignment=Qt.AlignRight)
|
||||
|
||||
layout.addLayout(wpt_layout)
|
||||
layout.addWidget(self.wpt_info)
|
||||
layout.addLayout(distToTarget)
|
||||
layout.addStretch()
|
||||
layout.addWidget(self.ok_button)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def apply(self):
|
||||
self.flight.points = []
|
||||
self.planner.generate_cas(self.flight, self.selected_waypoints[0].data[0], self.selected_waypoints[0].data[1])
|
||||
self.flight_waypoint_list.update_list()
|
||||
self.close()
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
from PySide2.QtGui import Qt
|
||||
from PySide2.QtWidgets import QLabel, QHBoxLayout, QVBoxLayout
|
||||
|
||||
from game import Game
|
||||
from gen.flights.ai_flight_planner import meter_to_nm
|
||||
from gen.flights.flight import Flight
|
||||
from qt_ui.widgets.combos.QSEADTargetSelectionComboBox import QSEADTargetSelectionComboBox
|
||||
from qt_ui.windows.mission.flight.generator.QAbstractMissionGenerator import QAbstractMissionGenerator
|
||||
|
||||
|
||||
class QSEADMissionGenerator(QAbstractMissionGenerator):
|
||||
|
||||
def __init__(self, game: Game, flight: Flight, flight_waypoint_list):
|
||||
super(QSEADMissionGenerator, self).__init__(game, flight, flight_waypoint_list, "SEAD/DEAD Generator")
|
||||
|
||||
self.tgt_selection_box = QSEADTargetSelectionComboBox(self.game)
|
||||
self.tgt_selection_box.setMinimumWidth(200)
|
||||
self.tgt_selection_box.currentTextChanged.connect(self.on_selected_target_changed)
|
||||
|
||||
self.distanceToTargetLabel = QLabel("0 nm")
|
||||
self.threatRangeLabel = QLabel("0 nm")
|
||||
self.detectionRangeLabel = QLabel("0 nm")
|
||||
self.init_ui()
|
||||
self.on_selected_target_changed()
|
||||
|
||||
def on_selected_target_changed(self):
|
||||
target = self.tgt_selection_box.get_selected_target()
|
||||
self.distanceToTargetLabel.setText("~" + str(meter_to_nm(self.flight.from_cp.position.distance_to_point(target.location.position))) + " nm")
|
||||
self.threatRangeLabel.setText(str(meter_to_nm(target.threat_range)) + " nm")
|
||||
self.detectionRangeLabel.setText(str(meter_to_nm(target.detection_range)) + " nm")
|
||||
|
||||
def init_ui(self):
|
||||
layout = QVBoxLayout()
|
||||
|
||||
wpt_layout = QHBoxLayout()
|
||||
wpt_layout.addWidget(QLabel("SEAD/DEAD target : "))
|
||||
wpt_layout.addStretch()
|
||||
wpt_layout.addWidget(self.tgt_selection_box, alignment=Qt.AlignRight)
|
||||
|
||||
distToTarget = QHBoxLayout()
|
||||
distToTarget.addWidget(QLabel("Distance to site : "))
|
||||
distToTarget.addStretch()
|
||||
distToTarget.addWidget(self.distanceToTargetLabel, alignment=Qt.AlignRight)
|
||||
|
||||
threatRangeLayout = QHBoxLayout()
|
||||
threatRangeLayout.addWidget(QLabel("Site threat range : "))
|
||||
threatRangeLayout.addStretch()
|
||||
threatRangeLayout.addWidget(self.threatRangeLabel, alignment=Qt.AlignRight)
|
||||
|
||||
detectionRangeLayout = QHBoxLayout()
|
||||
detectionRangeLayout.addWidget(QLabel("Site radar detection range: "))
|
||||
detectionRangeLayout.addStretch()
|
||||
detectionRangeLayout.addWidget(self.detectionRangeLabel, alignment=Qt.AlignRight)
|
||||
|
||||
layout.addLayout(wpt_layout)
|
||||
layout.addLayout(distToTarget)
|
||||
layout.addLayout(threatRangeLayout)
|
||||
layout.addLayout(detectionRangeLayout)
|
||||
layout.addStretch()
|
||||
layout.addWidget(self.ok_button)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def apply(self):
|
||||
self.flight.points = []
|
||||
target = self.tgt_selection_box.get_selected_target()
|
||||
self.planner.generate_sead(self.flight, target.location, target.radars)
|
||||
self.flight_waypoint_list.update_list()
|
||||
self.close()
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
from PySide2.QtGui import Qt
|
||||
from PySide2.QtWidgets import QLabel, QHBoxLayout, QVBoxLayout
|
||||
|
||||
from game import Game
|
||||
from gen.flights.ai_flight_planner import meter_to_nm
|
||||
from gen.flights.flight import Flight
|
||||
from qt_ui.widgets.combos.QStrikeTargetSelectionComboBox import QStrikeTargetSelectionComboBox
|
||||
from qt_ui.windows.mission.flight.generator.QAbstractMissionGenerator import QAbstractMissionGenerator
|
||||
|
||||
|
||||
class QSTRIKEMissionGenerator(QAbstractMissionGenerator):
|
||||
|
||||
def __init__(self, game: Game, flight: Flight, flight_waypoint_list):
|
||||
super(QSTRIKEMissionGenerator, self).__init__(game, flight, flight_waypoint_list, "SEAD/DEAD Generator")
|
||||
|
||||
self.tgt_selection_box = QStrikeTargetSelectionComboBox(self.game)
|
||||
self.tgt_selection_box.setMinimumWidth(200)
|
||||
self.tgt_selection_box.currentTextChanged.connect(self.on_selected_target_changed)
|
||||
|
||||
self.distanceToTargetLabel = QLabel("0 nm")
|
||||
self.init_ui()
|
||||
self.on_selected_target_changed()
|
||||
|
||||
def on_selected_target_changed(self):
|
||||
target = self.tgt_selection_box.get_selected_target()
|
||||
self.distanceToTargetLabel.setText("~" + str(meter_to_nm(self.flight.from_cp.position.distance_to_point(target.location.position))) + " nm")
|
||||
|
||||
def init_ui(self):
|
||||
layout = QVBoxLayout()
|
||||
|
||||
wpt_layout = QHBoxLayout()
|
||||
wpt_layout.addWidget(QLabel("SEAD/DEAD target : "))
|
||||
wpt_layout.addStretch()
|
||||
wpt_layout.addWidget(self.tgt_selection_box, alignment=Qt.AlignRight)
|
||||
|
||||
distToTarget = QHBoxLayout()
|
||||
distToTarget.addWidget(QLabel("Distance to target : "))
|
||||
distToTarget.addStretch()
|
||||
distToTarget.addWidget(self.distanceToTargetLabel, alignment=Qt.AlignRight)
|
||||
|
||||
layout.addLayout(wpt_layout)
|
||||
layout.addLayout(distToTarget)
|
||||
layout.addStretch()
|
||||
layout.addWidget(self.ok_button)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def apply(self):
|
||||
self.flight.points = []
|
||||
# target = self.tgt_selection_box.get_selected_target()
|
||||
# self.planner.generate_sead(self.flight, target.location, target.radars)
|
||||
# self.flight_waypoint_list.update_list()
|
||||
# self.close()
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
from PySide2.QtWidgets import QFrame, QGridLayout, QLabel, QPushButton, QVBoxLayout
|
||||
|
||||
from gen.flights.flight import Flight
|
||||
from gen.flights.flight import Flight, FlightWaypoint, FlightWaypointType
|
||||
from qt_ui.windows.mission.flight.generator.QCAPMissionGenerator import QCAPMissionGenerator
|
||||
from qt_ui.windows.mission.flight.generator.QCASMissionGenerator import QCASMissionGenerator
|
||||
from qt_ui.windows.mission.flight.generator.QSEADMissionGenerator import QSEADMissionGenerator
|
||||
from qt_ui.windows.mission.flight.generator.QSTRIKEMissionGenerator import QSTRIKEMissionGenerator
|
||||
from qt_ui.windows.mission.flight.waypoints.QFlightWaypointList import QFlightWaypointList
|
||||
from qt_ui.windows.mission.flight.waypoints.QPredefinedWaypointSelectionWindow import QPredefinedWaypointSelectionWindow
|
||||
from game import Game
|
||||
@ -11,6 +15,7 @@ class QFlightWaypointTab(QFrame):
|
||||
super(QFlightWaypointTab, self).__init__()
|
||||
self.flight = flight
|
||||
self.game = game
|
||||
self.planner = self.game.planners[self.flight.from_cp.id]
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
@ -19,10 +24,44 @@ class QFlightWaypointTab(QFrame):
|
||||
self.flight_waypoint_list = QFlightWaypointList(self.flight)
|
||||
self.open_fast_waypoint_button = QPushButton("Add Waypoint")
|
||||
self.open_fast_waypoint_button.clicked.connect(self.on_fast_waypoint)
|
||||
|
||||
self.cas_generator = QPushButton("Gen. CAS")
|
||||
self.cas_generator.clicked.connect(self.on_cas_generator)
|
||||
|
||||
self.cap_generator = QPushButton("Gen. CAP")
|
||||
self.cap_generator.clicked.connect(self.on_cap_generator)
|
||||
|
||||
self.sead_generator = QPushButton("Gen. SEAD/DEAD")
|
||||
self.sead_generator.clicked.connect(self.on_sead_generator)
|
||||
|
||||
self.strike_generator = QPushButton("Gen. STRIKE")
|
||||
self.strike_generator.clicked.connect(self.on_strike_generator)
|
||||
|
||||
self.rtb_waypoint = QPushButton("Add RTB Waypoint")
|
||||
self.rtb_waypoint.clicked.connect(self.on_rtb_waypoint)
|
||||
|
||||
self.ascend_waypoint = QPushButton("Add Ascend Waypoint")
|
||||
self.ascend_waypoint.clicked.connect(self.on_ascend_waypoint)
|
||||
|
||||
self.descend_waypoint = QPushButton("Add Descend Waypoint")
|
||||
self.descend_waypoint.clicked.connect(self.on_descend_waypoint)
|
||||
|
||||
self.delete_selected = QPushButton("Delete Selected")
|
||||
self.delete_selected.clicked.connect(self.on_delete_waypoint)
|
||||
|
||||
layout.addWidget(self.flight_waypoint_list,0,0)
|
||||
layout.addWidget(self.flight_waypoint_list, 0, 0)
|
||||
|
||||
rlayout.addWidget(QLabel("<strong>Generator :</strong>"))
|
||||
rlayout.addWidget(QLabel("<small>AI compatible</small>"))
|
||||
rlayout.addWidget(self.cas_generator)
|
||||
rlayout.addWidget(self.cap_generator)
|
||||
rlayout.addWidget(self.sead_generator)
|
||||
rlayout.addWidget(self.strike_generator)
|
||||
rlayout.addWidget(QLabel("<strong>Advanced : </strong>"))
|
||||
rlayout.addWidget(QLabel("<small>Do not use for AI flights</small>"))
|
||||
rlayout.addWidget(self.ascend_waypoint)
|
||||
rlayout.addWidget(self.descend_waypoint)
|
||||
rlayout.addWidget(self.rtb_waypoint)
|
||||
rlayout.addWidget(self.open_fast_waypoint_button)
|
||||
rlayout.addWidget(self.delete_selected)
|
||||
rlayout.addStretch()
|
||||
@ -37,4 +76,36 @@ class QFlightWaypointTab(QFrame):
|
||||
|
||||
def on_fast_waypoint(self):
|
||||
self.subwindow = QPredefinedWaypointSelectionWindow(self.game, self.flight, self.flight_waypoint_list)
|
||||
self.subwindow.show()
|
||||
self.subwindow.show()
|
||||
|
||||
def on_ascend_waypoint(self):
|
||||
ascend = self.planner.generate_ascend_point(self.flight.from_cp)
|
||||
self.flight.points.append(ascend)
|
||||
self.flight_waypoint_list.update_list()
|
||||
|
||||
def on_rtb_waypoint(self):
|
||||
rtb = self.planner.generate_rtb_waypoint(self.flight.from_cp)
|
||||
self.flight.points.append(rtb)
|
||||
self.flight_waypoint_list.update_list()
|
||||
|
||||
def on_descend_waypoint(self):
|
||||
descend = self.planner.generate_descend_point(self.flight.from_cp)
|
||||
self.flight.points.append(descend)
|
||||
self.flight_waypoint_list.update_list()
|
||||
|
||||
def on_cas_generator(self):
|
||||
self.subwindow = QCASMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
|
||||
self.subwindow.show()
|
||||
|
||||
def on_cap_generator(self):
|
||||
self.subwindow = QCAPMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
|
||||
self.subwindow.show()
|
||||
|
||||
def on_sead_generator(self):
|
||||
self.subwindow = QSEADMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
|
||||
self.subwindow.show()
|
||||
|
||||
def on_strike_generator(self):
|
||||
self.subwindow = QSTRIKEMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
|
||||
self.subwindow.show()
|
||||
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtWidgets import QDialog, QGridLayout, QLabel, QComboBox, QHBoxLayout, QVBoxLayout, QPushButton, QCheckBox
|
||||
from dcs import Point
|
||||
from PySide2.QtWidgets import QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton, QCheckBox
|
||||
|
||||
from game import Game
|
||||
from gen.flights.flight import Flight, FlightWaypoint
|
||||
from gen.flights.flight import Flight
|
||||
from qt_ui.uiconstants import EVENT_ICONS
|
||||
from qt_ui.widgets.QPredefinedWaypointSelectionComboBox import QPredefinedWaypointSelectionComboBox
|
||||
from qt_ui.widgets.combos.QPredefinedWaypointSelectionComboBox import QPredefinedWaypointSelectionComboBox
|
||||
from qt_ui.windows.mission.flight.waypoints.QFlightWaypointInfoBox import QFlightWaypointInfoBox
|
||||
from theater import ControlPointType
|
||||
|
||||
PREDEFINED_WAYPOINT_CATEGORIES = [
|
||||
"Frontline (CAS AREA)",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 800 KiB After Width: | Height: | Size: 800 KiB |
Loading…
x
Reference in New Issue
Block a user