Exemplo n.º 1
0
 def __init__(
     self, game: Game, transfer: TransferOrder, next_stop: ControlPoint
 ) -> None:
     self.game = game
     self.transfer = transfer
     self.next_stop = next_stop
     self.for_player = transfer.destination.captured
     self.package = Package(target=next_stop, auto_asap=True)
Exemplo n.º 2
0
 def __init__(self, location: MissionTarget,
              closest_airfields: ClosestAirfields,
              global_inventory: GlobalAircraftInventory, is_player: bool,
              start_type: str) -> None:
     self.package = Package(location)
     self.allocator = AircraftAllocator(closest_airfields, global_inventory,
                                        is_player)
     self.global_inventory = global_inventory
     self.start_type = start_type
Exemplo n.º 3
0
    def __init__(self, game_model: GameModel, model: AtoModel,
                 target: MissionTarget, parent=None) -> None:
        super().__init__(game_model, PackageModel(Package(target)), parent=parent)
        self.ato_model = model

        self.save_button = QPushButton("Save")
        self.save_button.setProperty("style", "start-button")
        self.save_button.clicked.connect(self.accept)
        self.button_layout.addWidget(self.save_button)
Exemplo n.º 4
0
 def __init__(
     self,
     location: MissionTarget,
     closest_airfields: ClosestAirfields,
     global_inventory: GlobalAircraftInventory,
     air_wing: AirWing,
     is_player: bool,
     package_country: str,
     start_type: str,
     asap: bool,
 ) -> None:
     self.closest_airfields = closest_airfields
     self.is_player = is_player
     self.package_country = package_country
     self.package = Package(location, auto_asap=asap)
     self.allocator = AircraftAllocator(
         air_wing, closest_airfields, global_inventory, is_player
     )
     self.global_inventory = global_inventory
     self.start_type = start_type
Exemplo n.º 5
0
class PackageBuilder:
    """Builds a Package for the flights it receives."""
    def __init__(self, location: MissionTarget,
                 closest_airfields: ClosestAirfields,
                 global_inventory: GlobalAircraftInventory, is_player: bool,
                 start_type: str) -> None:
        self.package = Package(location)
        self.allocator = AircraftAllocator(closest_airfields, global_inventory,
                                           is_player)
        self.global_inventory = global_inventory
        self.start_type = start_type

    def plan_flight(self, plan: ProposedFlight) -> bool:
        """Allocates aircraft for the given flight and adds them to the package.

        If no suitable aircraft are available, False is returned. If the failed
        flight was critical and the rest of the mission will be scrubbed, the
        caller should return any previously planned flights to the inventory
        using release_planned_aircraft.
        """
        assignment = self.allocator.find_aircraft_for_flight(plan)
        if assignment is None:
            return False
        airfield, aircraft = assignment
        flight = Flight(self.package, aircraft, plan.num_aircraft, airfield,
                        plan.task, self.start_type)
        self.package.add_flight(flight)
        return True

    def build(self) -> Package:
        """Returns the built package."""
        return self.package

    def release_planned_aircraft(self) -> None:
        """Returns any planned flights to the inventory."""
        flights = list(self.package.flights)
        for flight in flights:
            self.global_inventory.return_from_flight(flight)
            self.package.remove_flight(flight)
Exemplo n.º 6
0
class AirliftPlanner:
    #: Maximum range from for any link in the route of takeoff, pickup, dropoff, and RTB
    #: for a helicopter to be considered for airlift. Total route length is not
    #: considered because the helicopter can refuel at each stop. Cargo planes have no
    #: maximum range.
    HELO_MAX_RANGE = nautical_miles(100)

    def __init__(
        self, game: Game, transfer: TransferOrder, next_stop: ControlPoint
    ) -> None:
        self.game = game
        self.transfer = transfer
        self.next_stop = next_stop
        self.for_player = transfer.destination.captured
        self.package = Package(target=next_stop, auto_asap=True)

    def compatible_with_mission(
        self, unit_type: AircraftType, airfield: ControlPoint
    ) -> bool:
        if unit_type not in aircraft_for_task(FlightType.TRANSPORT):
            return False
        if not self.transfer.origin.can_operate(unit_type):
            return False
        if not self.next_stop.can_operate(unit_type):
            return False

        # Cargo planes have no maximum range.
        if not unit_type.dcs_unit_type.helicopter:
            return True

        # A helicopter that is transport capable and able to operate at both bases. Need
        # to check that no leg of the journey exceeds the maximum range. This doesn't
        # account for any routing around threats that might take place, but it's close
        # enough.

        home = airfield.position
        pickup = self.transfer.position.position
        drop_off = self.transfer.position.position
        if meters(home.distance_to_point(pickup)) > self.HELO_MAX_RANGE:
            return False

        if meters(pickup.distance_to_point(drop_off)) > self.HELO_MAX_RANGE:
            return False

        if meters(drop_off.distance_to_point(home)) > self.HELO_MAX_RANGE:
            return False

        return True

    def create_package_for_airlift(self) -> None:
        distance_cache = ObjectiveDistanceCache.get_closest_airfields(
            self.transfer.position
        )
        air_wing = self.game.air_wing_for(self.for_player)
        for cp in distance_cache.closest_airfields:
            if cp.captured != self.for_player:
                continue

            inventory = self.game.aircraft_inventory.for_control_point(cp)
            for unit_type, available in inventory.all_aircraft:
                squadrons = air_wing.auto_assignable_for_task_with_type(
                    unit_type, FlightType.TRANSPORT
                )
                for squadron in squadrons:
                    if self.compatible_with_mission(unit_type, cp):
                        while (
                            available
                            and squadron.has_available_pilots
                            and self.transfer.transport is None
                        ):
                            flight_size = self.create_airlift_flight(
                                squadron, inventory
                            )
                            available -= flight_size
        if self.package.flights:
            self.game.ato_for(self.for_player).add_package(self.package)

    def create_airlift_flight(
        self, squadron: Squadron, inventory: ControlPointAircraftInventory
    ) -> int:
        available_aircraft = inventory.available(squadron.aircraft)
        capacity_each = 1 if squadron.aircraft.dcs_unit_type.helicopter else 2
        required = math.ceil(self.transfer.size / capacity_each)
        flight_size = min(
            required,
            available_aircraft,
            squadron.aircraft.dcs_unit_type.group_size_max,
        )
        # TODO: Use number_of_available_pilots directly once feature flag is gone.
        # The number of currently available pilots is not relevant when pilot limits
        # are disabled.
        if not squadron.can_provide_pilots(flight_size):
            flight_size = squadron.number_of_available_pilots
        capacity = flight_size * capacity_each

        if capacity < self.transfer.size:
            transfer = self.game.transfers.split_transfer(self.transfer, capacity)
        else:
            transfer = self.transfer

        player = inventory.control_point.captured
        flight = Flight(
            self.package,
            self.game.country_for(player),
            squadron,
            flight_size,
            FlightType.TRANSPORT,
            self.game.settings.default_start_type,
            departure=inventory.control_point,
            arrival=inventory.control_point,
            divert=None,
            cargo=transfer,
        )

        transport = Airlift(transfer, flight, self.next_stop)
        transfer.transport = transport

        self.package.add_flight(flight)
        planner = FlightPlanBuilder(self.game, self.package, self.for_player)
        planner.populate_flight_plan(flight)
        self.game.aircraft_inventory.claim_for_flight(flight)
        return flight_size
Exemplo n.º 7
0
class PackageBuilder:
    """Builds a Package for the flights it receives."""
    def __init__(
        self,
        location: MissionTarget,
        closest_airfields: ClosestAirfields,
        global_inventory: GlobalAircraftInventory,
        is_player: bool,
        package_country: str,
        start_type: str,
    ) -> None:
        self.closest_airfields = closest_airfields
        self.is_player = is_player
        self.package_country = package_country
        self.package = Package(location)
        self.allocator = AircraftAllocator(closest_airfields, global_inventory,
                                           is_player)
        self.global_inventory = global_inventory
        self.start_type = start_type

    def plan_flight(self, plan: ProposedFlight) -> bool:
        """Allocates aircraft for the given flight and adds them to the package.

        If no suitable aircraft are available, False is returned. If the failed
        flight was critical and the rest of the mission will be scrubbed, the
        caller should return any previously planned flights to the inventory
        using release_planned_aircraft.
        """
        assignment = self.allocator.find_aircraft_for_flight(plan)
        if assignment is None:
            return False
        airfield, aircraft = assignment
        if isinstance(airfield, OffMapSpawn):
            start_type = "In Flight"
        else:
            start_type = self.start_type

        flight = Flight(
            self.package,
            self.package_country,
            aircraft,
            plan.num_aircraft,
            plan.task,
            start_type,
            departure=airfield,
            arrival=airfield,
            divert=self.find_divert_field(aircraft, airfield),
        )
        self.package.add_flight(flight)
        return True

    def find_divert_field(self, aircraft: Type[FlyingType],
                          arrival: ControlPoint) -> Optional[ControlPoint]:
        divert_limit = nautical_miles(150)
        for airfield in self.closest_airfields.airfields_within(divert_limit):
            if airfield.captured != self.is_player:
                continue
            if airfield == arrival:
                continue
            if not airfield.can_operate(aircraft):
                continue
            if isinstance(airfield, OffMapSpawn):
                continue
            return airfield
        return None

    def build(self) -> Package:
        """Returns the built package."""
        return self.package

    def release_planned_aircraft(self) -> None:
        """Returns any planned flights to the inventory."""
        flights = list(self.package.flights)
        for flight in flights:
            self.global_inventory.return_from_flight(flight)
            self.package.remove_flight(flight)