mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Add off-map spawn locations.
The AI isn't making use of these yet, but it's not smart enough to do so anyway. Would benefit from an icon to differentiate it on the map. I'm stretching the definition of "control point" quite a bit. We might want to put a class above `ControlPoint` for `AirSpawnLocation` to represent types of spawn locations that can't be captured and don't have ground objectives. Fixes https://github.com/Khopa/dcs_liberation/issues/274
This commit is contained in:
@@ -70,7 +70,7 @@ from dcs.unittype import FlyingType, UnitType
|
||||
from game import db
|
||||
from game.data.cap_capabilities_db import GUNFIGHTERS
|
||||
from game.settings import Settings
|
||||
from game.utils import nm_to_meter
|
||||
from game.utils import knots_to_kph, nm_to_meter
|
||||
from gen.airsupportgen import AirSupport
|
||||
from gen.ato import AirTaskingOrder, Package
|
||||
from gen.callsigns import create_group_callsign_from_unit
|
||||
@@ -84,7 +84,11 @@ from gen.flights.flight import (
|
||||
from gen.radios import MHz, Radio, RadioFrequency, RadioRegistry, get_radio
|
||||
from gen.runways import RunwayData
|
||||
from theater import TheaterGroundObject
|
||||
from game.theater.controlpoint import ControlPoint, ControlPointType
|
||||
from game.theater.controlpoint import (
|
||||
ControlPoint,
|
||||
ControlPointType,
|
||||
OffMapSpawn,
|
||||
)
|
||||
from .conflictgen import Conflict
|
||||
from .flights.flightplan import (
|
||||
CasFlightPlan,
|
||||
@@ -92,7 +96,7 @@ from .flights.flightplan import (
|
||||
PatrollingFlightPlan,
|
||||
SweepFlightPlan,
|
||||
)
|
||||
from .flights.traveltime import TotEstimator
|
||||
from .flights.traveltime import GroundSpeed, TotEstimator
|
||||
from .naming import namegen
|
||||
from .runways import RunwayAssigner
|
||||
|
||||
@@ -804,31 +808,37 @@ class AircraftConflictGenerator:
|
||||
group_size=count,
|
||||
parking_slots=None)
|
||||
|
||||
def _generate_inflight(self, name: str, side: Country, unit_type: FlyingType, count: int, at: Point) -> FlyingGroup:
|
||||
assert count > 0
|
||||
def _generate_inflight(self, name: str, side: Country, flight: Flight,
|
||||
origin: ControlPoint) -> FlyingGroup:
|
||||
assert flight.count > 0
|
||||
at = origin.position
|
||||
|
||||
if unit_type in helicopters.helicopter_map.values():
|
||||
alt_type = "RADIO"
|
||||
if isinstance(origin, OffMapSpawn):
|
||||
alt = flight.flight_plan.waypoints[0].alt
|
||||
alt_type = flight.flight_plan.waypoints[0].alt_type
|
||||
elif flight.unit_type in helicopters.helicopter_map.values():
|
||||
alt = WARM_START_HELI_ALT
|
||||
speed = WARM_START_HELI_AIRSPEED
|
||||
else:
|
||||
alt = WARM_START_ALTITUDE
|
||||
speed = WARM_START_AIRSPEED
|
||||
|
||||
speed = knots_to_kph(GroundSpeed.for_flight(flight, alt))
|
||||
|
||||
pos = Point(at.x + random.randint(100, 1000), at.y + random.randint(100, 1000))
|
||||
|
||||
logging.info("airgen: {} for {} at {} at {}".format(unit_type, side.id, alt, speed))
|
||||
logging.info("airgen: {} for {} at {} at {}".format(flight.unit_type, side.id, alt, speed))
|
||||
group = self.m.flight_group(
|
||||
country=side,
|
||||
name=name,
|
||||
aircraft_type=unit_type,
|
||||
aircraft_type=flight.unit_type,
|
||||
airport=None,
|
||||
position=pos,
|
||||
altitude=alt,
|
||||
speed=speed,
|
||||
maintask=None,
|
||||
group_size=count)
|
||||
group_size=flight.count)
|
||||
|
||||
group.points[0].alt_type = "RADIO"
|
||||
group.points[0].alt_type = alt_type
|
||||
return group
|
||||
|
||||
def _generate_at_group(self, name: str, side: Country,
|
||||
@@ -974,9 +984,8 @@ class AircraftConflictGenerator:
|
||||
group = self._generate_inflight(
|
||||
name=namegen.next_unit_name(country, cp.id, flight.unit_type),
|
||||
side=country,
|
||||
unit_type=flight.unit_type,
|
||||
count=flight.count,
|
||||
at=cp.position)
|
||||
flight=flight,
|
||||
origin=cp)
|
||||
elif cp.is_fleet:
|
||||
group_name = cp.get_carrier_group_name()
|
||||
group = self._generate_at_group(
|
||||
@@ -1002,9 +1011,8 @@ class AircraftConflictGenerator:
|
||||
group = self._generate_inflight(
|
||||
name=namegen.next_unit_name(country, cp.id, flight.unit_type),
|
||||
side=country,
|
||||
unit_type=flight.unit_type,
|
||||
count=flight.count,
|
||||
at=cp.position)
|
||||
flight=flight,
|
||||
origin=cp)
|
||||
group.points[0].alt = 1500
|
||||
|
||||
return group
|
||||
|
||||
@@ -50,7 +50,7 @@ from theater import (
|
||||
ControlPoint,
|
||||
FrontLine,
|
||||
MissionTarget,
|
||||
TheaterGroundObject,
|
||||
OffMapSpawn, TheaterGroundObject,
|
||||
SamGroundObject,
|
||||
)
|
||||
|
||||
@@ -232,8 +232,12 @@ class PackageBuilder:
|
||||
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, aircraft, plan.num_aircraft, airfield,
|
||||
plan.task, self.start_type)
|
||||
plan.task, start_type)
|
||||
self.package.add_flight(flight)
|
||||
return True
|
||||
|
||||
@@ -406,6 +410,9 @@ class ObjectiveFinder:
|
||||
CP.
|
||||
"""
|
||||
for cp in self.friendly_control_points():
|
||||
if isinstance(cp, OffMapSpawn):
|
||||
# Off-map spawn locations don't need protection.
|
||||
continue
|
||||
airfields_in_proximity = self.closest_airfields_to(cp)
|
||||
airfields_in_threat_range = airfields_in_proximity.airfields_within(
|
||||
self.AIRFIELD_THREAT_RANGE
|
||||
|
||||
@@ -8,11 +8,15 @@ from dcs.unit import Unit
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
|
||||
from game.data.doctrine import Doctrine
|
||||
from game.utils import nm_to_meter
|
||||
from game.utils import feet_to_meter
|
||||
from game.weather import Conditions
|
||||
from theater import ControlPoint, MissionTarget, TheaterGroundObject
|
||||
from theater import (
|
||||
ControlPoint,
|
||||
MissionTarget,
|
||||
OffMapSpawn,
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from .flight import Flight, FlightWaypoint, FlightWaypointType
|
||||
from ..runways import RunwayAssigner
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -34,8 +38,7 @@ class WaypointBuilder:
|
||||
def is_helo(self) -> bool:
|
||||
return getattr(self.flight.unit_type, "helicopter", False)
|
||||
|
||||
@staticmethod
|
||||
def takeoff(departure: ControlPoint) -> FlightWaypoint:
|
||||
def takeoff(self, departure: ControlPoint) -> FlightWaypoint:
|
||||
"""Create takeoff waypoint for the given arrival airfield or carrier.
|
||||
|
||||
Note that the takeoff waypoint will automatically be created by pydcs
|
||||
@@ -46,36 +49,59 @@ class WaypointBuilder:
|
||||
departure: Departure airfield or carrier.
|
||||
"""
|
||||
position = departure.position
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.TAKEOFF,
|
||||
position.x,
|
||||
position.y,
|
||||
0
|
||||
)
|
||||
waypoint.name = "TAKEOFF"
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.description = "Takeoff"
|
||||
waypoint.pretty_name = "Takeoff"
|
||||
if isinstance(departure, OffMapSpawn):
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.NAV,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
)
|
||||
waypoint.name = "NAV"
|
||||
waypoint.alt_type = "BARO"
|
||||
waypoint.description = "Enter theater"
|
||||
waypoint.pretty_name = "Enter theater"
|
||||
else:
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.TAKEOFF,
|
||||
position.x,
|
||||
position.y,
|
||||
0
|
||||
)
|
||||
waypoint.name = "TAKEOFF"
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.description = "Takeoff"
|
||||
waypoint.pretty_name = "Takeoff"
|
||||
return waypoint
|
||||
|
||||
@staticmethod
|
||||
def land(arrival: ControlPoint) -> FlightWaypoint:
|
||||
def land(self, arrival: ControlPoint) -> FlightWaypoint:
|
||||
"""Create descent waypoint for the given arrival airfield or carrier.
|
||||
|
||||
Args:
|
||||
arrival: Arrival airfield or carrier.
|
||||
"""
|
||||
position = arrival.position
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.LANDING_POINT,
|
||||
position.x,
|
||||
position.y,
|
||||
0
|
||||
)
|
||||
waypoint.name = "LANDING"
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.description = "Land"
|
||||
waypoint.pretty_name = "Land"
|
||||
if isinstance(arrival, OffMapSpawn):
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.NAV,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
)
|
||||
waypoint.name = "NAV"
|
||||
waypoint.alt_type = "BARO"
|
||||
waypoint.description = "Exit theater"
|
||||
waypoint.pretty_name = "Exit theater"
|
||||
else:
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.LANDING_POINT,
|
||||
position.x,
|
||||
position.y,
|
||||
0
|
||||
)
|
||||
waypoint.name = "LANDING"
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.description = "Land"
|
||||
waypoint.pretty_name = "Land"
|
||||
return waypoint
|
||||
|
||||
def hold(self, position: Point) -> FlightWaypoint:
|
||||
|
||||
Reference in New Issue
Block a user