Reduce fuel for fast-forwarded player flights.

This only has an effect for aircraft for which we have fuel consumption
data, but that's fine.

Fixes https://github.com/dcs-liberation/dcs_liberation/issues/1681
This commit is contained in:
Dan Albert
2021-10-30 11:32:29 -07:00
parent b2cbf4b6f4
commit 1a3b8d1dd6
10 changed files with 127 additions and 50 deletions

View File

@@ -1,12 +1,13 @@
from __future__ import annotations
from datetime import datetime, timedelta
from typing import Any, Optional, List, TYPE_CHECKING
from typing import Any, List, Optional, TYPE_CHECKING
from dcs.planes import C_101CC, C_101EB, Su_33
from gen.flights.loadouts import Loadout
from .flightroster import FlightRoster
from .flightstate import Uninitialized, FlightState
from .flightstate import FlightState, Uninitialized
if TYPE_CHECKING:
from game.dcs.aircrafttype import AircraftType
@@ -122,6 +123,18 @@ class Flight:
self.roster.clear()
self.squadron.claim_inventory(-self.count)
def max_takeoff_fuel(self) -> Optional[float]:
# Special case so Su 33 and C101 can take off
unit_type = self.unit_type.dcs_unit_type
if unit_type == Su_33:
if self.flight_type.is_air_to_air:
return Su_33.fuel_max / 2.2
else:
return Su_33.fuel_max * 0.8
elif unit_type in {C_101EB, C_101CC}:
return unit_type.fuel_max * 0.5
return None
def __repr__(self) -> str:
if self.custom_name:
return f"{self.custom_name} {self.count} x {self.unit_type}"

View File

@@ -37,3 +37,9 @@ class FlightState(ABC):
def a2a_commit_region(self) -> Optional[ThreatPoly]:
return None
def estimate_fuel(self) -> float:
"""Returns the estimated remaining fuel **in kilograms**."""
if (max_takeoff_fuel := self.flight.max_takeoff_fuel()) is not None:
return max_takeoff_fuel
return self.flight.unit_type.dcs_unit_type.fuel_max

View File

@@ -11,7 +11,7 @@ from game.ato.flightstate.flightstate import FlightState
from game.ato.flightwaypoint import FlightWaypoint
from game.ato.flightwaypointtype import FlightWaypointType
from game.ato.starttype import StartType
from game.utils import Distance, Speed, meters
from game.utils import Distance, LBS_TO_KG, Speed, meters, pairwise
from gen.flights.flightplan import LoiterFlightPlan
if TYPE_CHECKING:
@@ -83,6 +83,30 @@ class InFlight(FlightState):
self.current_waypoint, self.next_waypoint
)
def estimate_fuel_at_current_waypoint(self) -> float:
initial_fuel = super().estimate_fuel()
if self.flight.unit_type.fuel_consumption is None:
return initial_fuel
initial_fuel -= self.flight.unit_type.fuel_consumption.taxi * LBS_TO_KG
waypoints = self.flight.flight_plan.waypoints[: self.waypoint_index + 1]
for a, b in pairwise(waypoints[:-1]):
consumption = self.flight.flight_plan.fuel_consumption_between_points(a, b)
assert consumption is not None
initial_fuel -= consumption * LBS_TO_KG
return initial_fuel
def estimate_fuel(self) -> float:
initial_fuel = self.estimate_fuel_at_current_waypoint()
ppm = self.flight.flight_plan.fuel_rate_to_between_points(
self.current_waypoint, self.next_waypoint
)
if ppm is None:
return initial_fuel
position = self.estimate_position()
distance = meters(self.current_waypoint.position.distance_to_point(position))
consumption = distance.nautical_miles * ppm * LBS_TO_KG
return initial_fuel - consumption
def next_waypoint_state(self) -> FlightState:
from game.ato.flightstate.loiter import Loiter
from game.ato.flightstate.racetrack import RaceTrack

View File

@@ -29,6 +29,10 @@ class Loiter(InFlight):
def estimate_speed(self) -> Speed:
return self.flight.unit_type.preferred_patrol_speed(self.estimate_altitude()[0])
def estimate_fuel(self) -> float:
# TODO: Estimate loiter consumption per minute?
return self.estimate_fuel_at_current_waypoint()
def next_waypoint_state(self) -> FlightState:
# Do not automatically advance to the next waypoint. Just proceed from the
# current one with the normal flying state.

View File

@@ -40,6 +40,10 @@ class RaceTrack(InFlight):
def estimate_speed(self) -> Speed:
return self.flight.unit_type.preferred_patrol_speed(self.estimate_altitude()[0])
def estimate_fuel(self) -> float:
# TODO: Estimate loiter consumption per minute?
return self.estimate_fuel_at_current_waypoint()
def travel_time_between_waypoints(self) -> timedelta:
return self.patrol_duration

View File

@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING
from .flightstate import FlightState
from .inflight import InFlight
from ..starttype import StartType
from ...utils import LBS_TO_KG
if TYPE_CHECKING:
from game.ato.flight import Flight
@@ -33,6 +34,12 @@ class Takeoff(FlightState):
def spawn_type(self) -> StartType:
return StartType.RUNWAY
def estimate_fuel(self) -> float:
initial_fuel = super().estimate_fuel()
if self.flight.unit_type.fuel_consumption is None:
return initial_fuel
return initial_fuel - self.flight.unit_type.fuel_consumption.taxi * LBS_TO_KG
def should_halt_sim(self, enemy_aircraft_coverage: AircraftEngagementZones) -> bool:
if (
self.flight.client_count > 0