Draw frozen combat on the map.

Very basic display. Draws the engagement footprint for air-to-air
combat, a line from the flight to the target for IP, and lines from SAMs
to their target for air defense.

https://github.com/dcs-liberation/dcs_liberation/issues/1680
This commit is contained in:
Dan Albert
2021-12-21 14:06:04 -08:00
parent fb10a8d28e
commit 515efd0598
11 changed files with 268 additions and 11 deletions

View File

@@ -18,14 +18,16 @@ from game.ato.flightstate import (
from game.ato.starttype import StartType
from gen.flights.traveltime import TotEstimator
from .combat import CombatInitiator, FrozenCombat
from .gameupdatecallbacks import GameUpdateCallbacks
if TYPE_CHECKING:
from game import Game
class AircraftSimulation:
def __init__(self, game: Game) -> None:
def __init__(self, game: Game, callbacks: GameUpdateCallbacks) -> None:
self.game = game
self.callbacks = callbacks
self.combats: list[FrozenCombat] = []
def begin_simulation(self) -> None:
@@ -38,7 +40,7 @@ class AircraftSimulation:
# Finish updating all flights before checking for combat so that the new
# positions are used.
CombatInitiator(self.game, self.combats).update_active_combats()
CombatInitiator(self.game, self.combats, self.callbacks).update_active_combats()
# After updating all combat states, check for halts.
for flight in self.iter_flights():

View File

@@ -12,6 +12,7 @@ from .atip import AtIp
from .defendingsam import DefendingSam
from .joinablecombat import JoinableCombat
from .samengagementzones import SamEngagementZones
from ..gameupdatecallbacks import GameUpdateCallbacks
if TYPE_CHECKING:
from game import Game
@@ -20,9 +21,12 @@ if TYPE_CHECKING:
class CombatInitiator:
def __init__(self, game: Game, combats: list[FrozenCombat]) -> None:
def __init__(
self, game: Game, combats: list[FrozenCombat], callbacks: GameUpdateCallbacks
) -> None:
self.game = game
self.combats = combats
self.callbacks = callbacks
def update_active_combats(self) -> None:
blue_a2a = AircraftEngagementZones.from_ato(self.game.blue.ato)
@@ -60,6 +64,7 @@ class CombatInitiator:
logging.info(f"{flight} is joining existing combat {joined}")
joined.join(flight)
own_a2a.remove_flight(flight)
self.callbacks.on_combat_changed(joined)
elif (combat := self.check_flight_for_new_combat(flight, a2a, sam)) is not None:
logging.info(f"Interrupting simulation because {combat.because()}")
combat.update_flight_states()
@@ -70,6 +75,7 @@ class CombatInitiator:
a2a.update_for_combat(combat)
own_a2a.update_for_combat(combat)
self.combats.append(combat)
self.callbacks.on_add_combat(combat)
def check_flight_for_joined_combat(
self, flight: Flight

View File

@@ -3,9 +3,10 @@ from __future__ import annotations
import logging
from datetime import datetime, timedelta
from pathlib import Path
from typing import Callable, TYPE_CHECKING
from typing import TYPE_CHECKING
from .gamelooptimer import GameLoopTimer
from .gameupdatecallbacks import GameUpdateCallbacks
from .missionsimulation import MissionSimulation, SimulationAlreadyCompletedError
from .simspeedsetting import SimSpeedSetting
@@ -15,11 +16,11 @@ if TYPE_CHECKING:
class GameLoop:
def __init__(self, game: Game, on_complete: Callable[[], None]) -> None:
def __init__(self, game: Game, callbacks: GameUpdateCallbacks) -> None:
self.game = game
self.on_complete = on_complete
self.callbacks = callbacks
self.timer = GameLoopTimer(self.tick)
self.sim = MissionSimulation(self.game)
self.sim = MissionSimulation(self.game, self.callbacks)
self.started = False
self.completed = False
@@ -75,6 +76,6 @@ class GameLoop:
if self.completed:
self.pause()
logging.info(f"Simulation completed at {self.sim.time}")
self.on_complete()
self.callbacks.on_simulation_complete()
except SimulationAlreadyCompletedError:
logging.exception("Attempted to tick already completed sim")

View File

@@ -0,0 +1,17 @@
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from game.sim.combat import FrozenCombat
# Ought to be frozen but mypy can't handle that:
# https://github.com/python/mypy/issues/5485
@dataclass
class GameUpdateCallbacks:
on_simulation_complete: Callable[[], None]
on_add_combat: Callable[[FrozenCombat], None]
on_combat_changed: Callable[[FrozenCombat], None]

View File

@@ -9,6 +9,7 @@ from game.debriefing import Debriefing
from game.missiongenerator import MissionGenerator
from game.unitmap import UnitMap
from .aircraftsimulation import AircraftSimulation
from .gameupdatecallbacks import GameUpdateCallbacks
from .missionresultsprocessor import MissionResultsProcessor
if TYPE_CHECKING:
@@ -24,10 +25,10 @@ class SimulationAlreadyCompletedError(RuntimeError):
class MissionSimulation:
def __init__(self, game: Game) -> None:
def __init__(self, game: Game, callbacks: GameUpdateCallbacks) -> None:
self.game = game
self.unit_map: Optional[UnitMap] = None
self.aircraft_simulation = AircraftSimulation(self.game)
self.aircraft_simulation = AircraftSimulation(self.game, callbacks)
self.completed = False
self.time = self.game.conditions.start_time