diff --git a/game/missiongenerator/aircraft/waypoints/pydcswaypointbuilder.py b/game/missiongenerator/aircraft/waypoints/pydcswaypointbuilder.py index fee5a3f8..d5588e82 100644 --- a/game/missiongenerator/aircraft/waypoints/pydcswaypointbuilder.py +++ b/game/missiongenerator/aircraft/waypoints/pydcswaypointbuilder.py @@ -31,6 +31,7 @@ class PydcsWaypointBuilder: now: datetime, mission_data: MissionData, unit_map: UnitMap, + generated_waypoint_idx: int, ) -> None: self.waypoint = waypoint self.group = group @@ -40,6 +41,7 @@ class PydcsWaypointBuilder: self.now = now self.mission_data = mission_data self.unit_map = unit_map + self.generated_waypoint_idx = generated_waypoint_idx def build(self) -> MovingPoint: waypoint = self.group.add_waypoint( diff --git a/game/missiongenerator/aircraft/waypoints/seadingress.py b/game/missiongenerator/aircraft/waypoints/seadingress.py index ba9a5cd5..3070c43e 100644 --- a/game/missiongenerator/aircraft/waypoints/seadingress.py +++ b/game/missiongenerator/aircraft/waypoints/seadingress.py @@ -3,11 +3,14 @@ import logging from dcs.point import MovingPoint from dcs.task import ( AttackGroup, + ControlledTask, EngageGroup, Expend, OptECMUsing, + SwitchWaypoint, WeaponType as DcsWeaponType, ) +from game.ato.flightstate import InFlight from game.data.weapons import WeaponType from game.theater import TheaterGroundObject from .pydcswaypointbuilder import PydcsWaypointBuilder @@ -49,13 +52,21 @@ class SeadIngressBuilder(PydcsWaypointBuilder): # - Specify that DECOY weapon type is used in AttackGroup task so that # the flight actually launches the decoy. See link below for details # https://github.com/dcs-liberation/dcs_liberation/issues/2780 + # - Set a stop condition of 120 seconds so that the flight does not continue + # press the engagement as a DCS limitation means the RTB on winchester + # does not work well with decoys. See link below for details. + # https://github.com/dcs-liberation/dcs_liberation/issues/2781 + # This stop condition will allow the SwitchWaypoint task defined below + # to kick in. attack_task = AttackGroup( miz_group.id, weapon_type=DcsWeaponType.Decoy, group_attack=True, expend=Expend.All, ) - waypoint.tasks.append(attack_task) + attack_task_control = ControlledTask(attack_task) + attack_task_control.stop_after_duration(120) + waypoint.tasks.append(attack_task_control) else: # All non ARM and non DECOY types will use the normal AttackGroup Task attack_task = AttackGroup( @@ -69,3 +80,14 @@ class SeadIngressBuilder(PydcsWaypointBuilder): # Preemptively use ECM to better avoid getting swatted. ecm_option = OptECMUsing(value=OptECMUsing.Values.UseIfDetectedLockByRadar) waypoint.tasks.append(ecm_option) + + # For DECOY type flights, setup a waypoint task to skip the target waypoint after + # the attack task is complete. This is achieved using a switch waypoint task from the + # INGRESS point to the SPLIT point. This tasking prevents the flights continuing to + # overfly the target. See link below for the details of this issue + # https://github.com/dcs-liberation/dcs_liberation/issues/2781 + if self.flight.loadout.has_weapon_of_type(WeaponType.DECOY): + switch_waypoint_task = SwitchWaypoint( + self.generated_waypoint_idx, self.generated_waypoint_idx + 2 + ) + waypoint.tasks.append(switch_waypoint_task) diff --git a/game/missiongenerator/aircraft/waypoints/waypointgenerator.py b/game/missiongenerator/aircraft/waypoints/waypointgenerator.py index 9ed4b93d..259dadf4 100644 --- a/game/missiongenerator/aircraft/waypoints/waypointgenerator.py +++ b/game/missiongenerator/aircraft/waypoints/waypointgenerator.py @@ -80,7 +80,7 @@ class WaypointGenerator: # us, but we do need to configure the tasks for it so that mid- # mission aircraft starting at a waypoint with tasks behave # correctly. - self.builder_for_waypoint(point).add_tasks(self.group.points[0]) + self.builder_for_waypoint(point, 1).add_tasks(self.group.points[0]) if not self.flight.state.has_passed_waypoint(point): filtered_points.append(point) else: @@ -110,7 +110,10 @@ class WaypointGenerator: ] for idx, point in enumerate(filtered_points): - self.builder_for_waypoint(point).build() + # We add 2 to idx to get the generated waypoint index as + # 1) pydcs seems to decrement the index by 1 and + # 2) DCS starts the first waypoint at index 1 as 0 is the starting position + self.builder_for_waypoint(point, idx + 2).build() # Set here rather than when the FlightData is created so they waypoints # have their TOTs and fuel minimums set. Once we're more confident in our fuel @@ -120,7 +123,9 @@ class WaypointGenerator: self._estimate_min_fuel_for(waypoints) return mission_start_time, waypoints - def builder_for_waypoint(self, waypoint: FlightWaypoint) -> PydcsWaypointBuilder: + def builder_for_waypoint( + self, waypoint: FlightWaypoint, generated_waypoint_index: int + ) -> PydcsWaypointBuilder: builders = { FlightWaypointType.INGRESS_BAI: BaiIngressBuilder, FlightWaypointType.INGRESS_CAS: CasIngressBuilder, @@ -151,6 +156,7 @@ class WaypointGenerator: self.time, self.mission_data, self.unit_map, + generated_waypoint_index, ) def _estimate_min_fuel_for(self, waypoints: list[FlightWaypoint]) -> None: