From f86709ebd0c00992456e83ded211bbc53573e9e6 Mon Sep 17 00:00:00 2001 From: zhexu14 <64713351+zhexu14@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:30:34 +1000 Subject: [PATCH] Prevent decoy flights from overflying the target. Force decoy flights to the next waypoints 120 seconds after the IP. The duration is just an approximation, but it seems to work. See discussion in https://github.com/dcs-liberation/dcs_liberation/pull/2810 for more details. Fixes https://github.com/dcs-liberation/dcs_liberation/issues/2781. --- .../waypoints/pydcswaypointbuilder.py | 2 ++ .../aircraft/waypoints/seadingress.py | 24 ++++++++++++++++++- .../aircraft/waypoints/waypointgenerator.py | 12 +++++++--- 3 files changed, 34 insertions(+), 4 deletions(-) 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: