Пример #1
0
    def add_runway_waypoint(
        self,
        airport: Airport,
        runway: Optional[Runway] = None,
        distance=random.randrange(6000, 8000, 100)
    ) -> MovingPoint:
        """Adds a waypoint parallel to the given runway heading, for start or approach.

        :param airport: start airport object
        :param runway: runway for heading direction, if None first(default) airport runway will be used.
        :param distance: distance of the waypoint from the airport
        :return: MovePoint object describing the waypoint
        """
        runway = runway if runway else airport.runways[0]

        mp = MovingPoint()
        mp.type = "Turning Point"
        mp.action = PointAction.TurningPoint
        mp.alt_type = "RADIO"
        mp.position = airport.position.point_from_heading(
            runway.heading, distance)
        mp.alt = 300
        mp.speed = 200 / 3.6
        mp.ETA_locked = False
        mp.properties = PointProperties()

        self.add_point(mp)
        return mp
Пример #2
0
 def configure_escort_tasks(waypoint: MovingPoint,
                            target_types: List[Type[TargetType]]) -> None:
     # Ideally we would use the escort mission type and escort task to have
     # the AI automatically but the AI only escorts AI flights while they are
     # traveling between waypoints. When an AI flight performs an attack
     # (such as attacking the mission target), AI escorts wander aimlessly
     # until the escorted group resumes its flight plan.
     #
     # As such, we instead use the Search Then Engage task, which is an
     # enroute task that causes the AI to follow their flight plan and engage
     # enemies of the set type within a certain distance. The downside to
     # this approach is that AI escorts are no longer related to the group
     # they are escorting, aside from the fact that they fly a similar flight
     # plan at the same time. With Escort, the escorts will follow the
     # escorted group out of the area. The strike element may or may not fly
     # directly over the target, and they may or may not require multiple
     # attack runs. For the escort flight we must just assume a flight plan
     # for the escort to fly. If the strike flight doesn't need to overfly
     # the target, the escorts are needlessly going in harms way. If the
     # strike flight needs multiple passes, the escorts may leave before the
     # escorted aircraft do.
     #
     # Another possible option would be to use Search Then Engage for join ->
     # ingress and egress -> split, but use a Search Then Engage in Zone task
     # for the target area that is set to end on a flag flip that occurs when
     # the strike aircraft finish their attack task.
     #
     # https://forums.eagle.ru/topic/251798-options-for-alternate-ai-escort-behavior
     waypoint.add_task(
         ControlledTask(
             EngageTargets(
                 # TODO: From doctrine.
                 max_distance=int(nautical_miles(30).meters),
                 targets=target_types,
             )))
Пример #3
0
 def set_waypoint_tot(self, waypoint: MovingPoint, tot: timedelta) -> None:
     self.waypoint.tot = tot
     if not self._viggen_client_tot():
         waypoint.ETA = int(
             (tot - self.elapsed_mission_time).total_seconds())
         waypoint.ETA_locked = True
         waypoint.speed_locked = False
Пример #4
0
 def add_tasks(self, waypoint: MovingPoint) -> None:
     if isinstance(self.flight.flight_plan, CasFlightPlan):
         waypoint.add_task(
             EngageTargetsInZone(
                 position=self.flight.flight_plan.layout.target.position,
                 radius=int(
                     self.flight.flight_plan.engagement_distance.meters),
                 targets=[
                     Targets.All.GroundUnits.GroundVehicles,
                     Targets.All.GroundUnits.AirDefence.AAA,
                     Targets.All.GroundUnits.Infantry,
                 ],
             ))
     else:
         logging.error(
             "No CAS waypoint found. Falling back to search and engage")
         waypoint.add_task(
             EngageTargets(
                 max_distance=int(nautical_miles(10).meters),
                 targets=[
                     Targets.All.GroundUnits.GroundVehicles,
                     Targets.All.GroundUnits.AirDefence.AAA,
                     Targets.All.GroundUnits.Infantry,
                 ],
             ))
Пример #5
0
 def _import_moving_point(mission, group: unitgroup.Group, imp_group) -> unitgroup.Group:
     for imp_point_idx in imp_group["route"]["points"]:
         imp_point = imp_group["route"]["points"][imp_point_idx]
         point = MovingPoint()
         point.load_from_dict(imp_point, mission.translation)
         group.add_point(point)
     return group
Пример #6
0
    def _import_moving_point(mission, group: unitgroup.Group,
                             imp_group) -> unitgroup.Group:
        keys = Coalition._sort_keys(imp_group["route"]["points"])

        for imp_point_idx in keys:
            imp_point = imp_group["route"]["points"][imp_point_idx]
            point = MovingPoint(Point(0, 0, mission.terrain))
            point.load_from_dict(imp_point, mission.translation)
            group.add_point(point)
        return group
Пример #7
0
    def land_at(self, airport: Airport) -> MovingPoint:
        mp = MovingPoint()
        mp.type = "Land"
        mp.action = PointAction.Landing
        mp.position = copy.copy(airport.position)
        mp.airdrome_id = airport.id
        mp.alt = 0
        mp.speed = 0
        mp.ETA_locked = False
        mp.properties = PointProperties()

        self.add_point(mp)
        return mp
Пример #8
0
    def add_waypoint(self, pos: mapping.Point, altitude, speed=600, name: String=None) -> MovingPoint:
        mp = MovingPoint()
        mp.type = "Turning Point"
        mp.action = PointAction.TurningPoint
        mp.name = name if name else String()
        mp.position = mapping.Point(pos.x, pos.y)
        mp.alt = altitude
        mp.speed = speed / 3.6
        mp.ETA_locked = False
        mp.properties = PointProperties()

        self.add_point(mp)
        return mp
Пример #9
0
 def add_tasks(self, waypoint: MovingPoint) -> None:
     loiter = ControlledTask(
         OrbitAction(altitude=waypoint.alt, pattern=OrbitAction.OrbitPattern.Circle)
     )
     if not isinstance(self.flight.flight_plan, LoiterFlightPlan):
         flight_plan_type = self.flight.flight_plan.__class__.__name__
         logging.error(
             f"Cannot configure hold for for {self.flight} because "
             f"{flight_plan_type} does not define a push time. AI will push "
             "immediately and may flight unsuitable speeds."
         )
         return
     push_time = self.flight.flight_plan.push_time
     self.waypoint.departure_time = push_time
     loiter.stop_after_time(
         int((push_time - self.elapsed_mission_time).total_seconds())
     )
     waypoint.add_task(loiter)
     waypoint.add_task(OptFormation.finger_four_close())
Пример #10
0
    def configure_refueling_actions(self, waypoint: MovingPoint) -> None:
        waypoint.add_task(Tanker())

        if self.flight.unit_type.dcs_unit_type.tacan:
            tanker_info = self.air_support.tankers[-1]
            tacan = tanker_info.tacan
            tacan_callsign = {
                "Texaco": "TEX",
                "Arco": "ARC",
                "Shell": "SHL",
            }.get(tanker_info.callsign)

            waypoint.add_task(
                ActivateBeaconCommand(
                    tacan.number,
                    tacan.band.value,
                    tacan_callsign,
                    bearing=True,
                    unit_id=self.group.units[0].id,
                    aa=True,
                ))
Пример #11
0
    def add_waypoint(self, position: mapping.Point, speed=20) -> MovingPoint:
        mp = MovingPoint()
        mp.type = "Turning Point"
        mp.action = PointAction.TurningPoint
        mp.position = copy.copy(position)
        mp.speed = speed / 3.6
        mp.ETA_locked = False

        self.add_point(mp)
        return mp
Пример #12
0
    def add_tasks(self, waypoint: MovingPoint) -> None:
        flight_plan = self.flight.flight_plan

        if not isinstance(flight_plan, PatrollingFlightPlan):
            flight_plan_type = flight_plan.__class__.__name__
            logging.error(
                f"Cannot create race track for {self.flight} because "
                f"{flight_plan_type} does not define a patrol.")
            return

        # NB: It's important that the engage task comes before the orbit task.
        # Though they're on the same waypoint, if the orbit task comes first it
        # is their first priority and they will not engage any targets because
        # they're fully focused on orbiting. If the STE task is first, they will
        # engage targets if available and orbit if they find nothing to shoot.
        if self.flight.flight_type is FlightType.REFUELING:
            self.configure_refueling_actions(waypoint)

        # TODO: Move the properties of this task into the flight plan?
        # CAP is the only current user of this so it's not a big deal, but might
        # be good to make this usable for things like BAI when we add that
        # later.
        cap_types = {FlightType.BARCAP, FlightType.TARCAP}
        if self.flight.flight_type in cap_types:
            engagement_distance = int(flight_plan.engagement_distance.meters)
            waypoint.tasks.append(
                EngageTargets(max_distance=engagement_distance,
                              targets=[Targets.All.Air]))

        orbit = OrbitAction(
            altitude=waypoint.alt,
            pattern=OrbitAction.OrbitPattern.RaceTrack,
            speed=int(flight_plan.patrol_speed.kph),
        )

        racetrack = ControlledTask(orbit)
        self.set_waypoint_tot(waypoint, flight_plan.patrol_start_time)
        loiter_duration = flight_plan.patrol_end_time - self.elapsed_mission_time
        racetrack.stop_after_time(int(loiter_duration.total_seconds()))
        waypoint.add_task(racetrack)
Пример #13
0
    def add_waypoint(self, position: mapping.Point,
                     move_formation: PointAction=PointAction.OffRoad, speed=32) -> MovingPoint:
        mp = MovingPoint()
        mp.type = "Turning Point"
        mp.action = move_formation
        mp.position = copy.copy(position)
        mp.speed = speed / 3.6
        mp.ETA_locked = False

        self.add_point(mp)
        return mp
Пример #14
0
 def add_tasks(self, waypoint: MovingPoint) -> None:
     waypoint.add_task(RefuelingTaskAction())
     return super().add_tasks(waypoint)