mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Set up bullseye early, create waypoints.
Setting this up as part of the game makes it possible for us to show in the UI. https://github.com/dcs-liberation/dcs_liberation/issues/136
This commit is contained in:
parent
3c8c76f50d
commit
a382e74a89
@ -11,6 +11,7 @@ Saves from 2.5 are not compatible with 3.0.
|
||||
* **[Campaign AI]** AI now considers Ju-88s for CAS, strike, and DEAD missions.
|
||||
* **[Campaign AI]** Fix purchase of aircraft by priority (the faction's list was being used as the priority list rather than the game's).
|
||||
* **[Flight Planner]** AI strike flight plans now include the correct target actions for building groups.
|
||||
* **[Flight Planner]** Flight plans now include bullseye waypoints.
|
||||
* **[Kneeboard]** ATC table overflow alleviated by wrapping long airfield names and splitting ATC frequency and channel into separate rows.
|
||||
* **[UI]** Added new web based map UI. This is mostly functional but many of the old display options are a WIP. Revert to the old map with --old-map.
|
||||
* **[UI]** Campaigns generated for an older or newer version of the game will now be marked as incompatible. They can still be played, but bugs may be present.
|
||||
|
||||
16
game/game.py
16
game/game.py
@ -34,6 +34,7 @@ from .procurement import AircraftProcurementRequest, ProcurementAi
|
||||
from .profiling import logged_duration
|
||||
from .settings import Settings
|
||||
from .theater import ConflictTheater
|
||||
from .theater.bullseye import Bullseye
|
||||
from .theater.transitnetwork import TransitNetwork, TransitNetworkBuilder
|
||||
from .threatzones import ThreatZones
|
||||
from .transfers import PendingTransfers
|
||||
@ -130,6 +131,9 @@ class Game:
|
||||
self.blue_ato = AirTaskingOrder()
|
||||
self.red_ato = AirTaskingOrder()
|
||||
|
||||
self.blue_bullseye = Bullseye(Point(0, 0))
|
||||
self.red_bullseye = Bullseye(Point(0, 0))
|
||||
|
||||
self.aircraft_inventory = GlobalAircraftInventory(self.theater.controlpoints)
|
||||
|
||||
self.transfers = PendingTransfers(self)
|
||||
@ -201,6 +205,11 @@ class Game:
|
||||
return self.player_faction
|
||||
return self.enemy_faction
|
||||
|
||||
def bullseye_for(self, player: bool) -> Bullseye:
|
||||
if player:
|
||||
return self.blue_bullseye
|
||||
return self.red_bullseye
|
||||
|
||||
def _roll(self, prob, mult):
|
||||
if self.settings.version == "dev":
|
||||
# always generate all events for dev
|
||||
@ -337,10 +346,17 @@ class Game:
|
||||
|
||||
return TurnState.CONTINUE
|
||||
|
||||
def set_bullseye(self) -> None:
|
||||
player_cp, enemy_cp = self.theater.closest_opposing_control_points()
|
||||
self.blue_bullseye = Bullseye(enemy_cp.position)
|
||||
self.red_bullseye = Bullseye(player_cp.position)
|
||||
|
||||
def initialize_turn(self) -> None:
|
||||
self.events = []
|
||||
self._generate_events()
|
||||
|
||||
self.set_bullseye()
|
||||
|
||||
# Update statistics
|
||||
self.game_stats.update(self)
|
||||
|
||||
|
||||
@ -108,8 +108,12 @@ class Operation:
|
||||
|
||||
@classmethod
|
||||
def _setup_mission_coalitions(cls):
|
||||
cls.current_mission.coalition["blue"] = Coalition("blue")
|
||||
cls.current_mission.coalition["red"] = Coalition("red")
|
||||
cls.current_mission.coalition["blue"] = Coalition(
|
||||
"blue", bullseye=cls.game.blue_bullseye.to_pydcs()
|
||||
)
|
||||
cls.current_mission.coalition["red"] = Coalition(
|
||||
"red", bullseye=cls.game.red_bullseye.to_pydcs()
|
||||
)
|
||||
|
||||
p_country = cls.game.player_country
|
||||
e_country = cls.game.enemy_country
|
||||
|
||||
26
game/theater/bullseye.py
Normal file
26
game/theater/bullseye.py
Normal file
@ -0,0 +1,26 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, TYPE_CHECKING
|
||||
|
||||
from dcs import Point
|
||||
|
||||
from game.theater import LatLon
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.theater import ConflictTheater
|
||||
|
||||
|
||||
@dataclass
|
||||
class Bullseye:
|
||||
position: Point
|
||||
|
||||
@classmethod
|
||||
def from_pydcs(cls, bulls: Dict[str, float]) -> Bullseye:
|
||||
return cls(Point(bulls["x"], bulls["y"]))
|
||||
|
||||
def to_pydcs(self) -> Dict[str, float]:
|
||||
return {"x": self.position.x, "y": self.position.y}
|
||||
|
||||
def to_lat_lon(self, theater: ConflictTheater) -> LatLon:
|
||||
return theater.point_to_ll(self.position)
|
||||
@ -41,6 +41,7 @@ from dcs.unitgroup import (
|
||||
)
|
||||
from dcs.vehicles import AirDefence, Armor, MissilesSS, Unarmed
|
||||
|
||||
from .latlon import LatLon
|
||||
from ..scenery_group import SceneryGroup
|
||||
from pyproj import CRS, Transformer
|
||||
from shapely import geometry, ops
|
||||
@ -582,15 +583,6 @@ class ReferencePoint:
|
||||
image_coordinates: Point
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LatLon:
|
||||
latitude: float
|
||||
longitude: float
|
||||
|
||||
def as_list(self) -> List[float]:
|
||||
return [self.latitude, self.longitude]
|
||||
|
||||
|
||||
class ConflictTheater:
|
||||
terrain: Terrain
|
||||
|
||||
|
||||
11
game/theater/latlon.py
Normal file
11
game/theater/latlon.py
Normal file
@ -0,0 +1,11 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LatLon:
|
||||
latitude: float
|
||||
longitude: float
|
||||
|
||||
def as_list(self) -> List[float]:
|
||||
return [self.latitude, self.longitude]
|
||||
@ -79,6 +79,7 @@ class FlightWaypointType(Enum):
|
||||
INGRESS_OCA_AIRCRAFT = 25
|
||||
PICKUP = 26
|
||||
DROP_OFF = 27
|
||||
BULLSEYE = 28
|
||||
|
||||
|
||||
class FlightWaypoint:
|
||||
|
||||
@ -426,6 +426,7 @@ class BarCapFlightPlan(PatrollingFlightPlan):
|
||||
takeoff: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
bullseye: FlightWaypoint
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.takeoff
|
||||
@ -438,6 +439,7 @@ class BarCapFlightPlan(PatrollingFlightPlan):
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@ -446,6 +448,7 @@ class CasFlightPlan(PatrollingFlightPlan):
|
||||
target: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
bullseye: FlightWaypoint
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.takeoff
|
||||
@ -459,6 +462,7 @@ class CasFlightPlan(PatrollingFlightPlan):
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
||||
return self.patrol_start
|
||||
@ -472,6 +476,7 @@ class TarCapFlightPlan(PatrollingFlightPlan):
|
||||
takeoff: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
bullseye: FlightWaypoint
|
||||
lead_time: timedelta
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
@ -485,6 +490,7 @@ class TarCapFlightPlan(PatrollingFlightPlan):
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
@property
|
||||
def tot_offset(self) -> timedelta:
|
||||
@ -523,6 +529,7 @@ class StrikeFlightPlan(FormationFlightPlan):
|
||||
nav_from: List[FlightWaypoint]
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
bullseye: FlightWaypoint
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.takeoff
|
||||
@ -537,6 +544,7 @@ class StrikeFlightPlan(FormationFlightPlan):
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
@property
|
||||
def package_speed_waypoints(self) -> Set[FlightWaypoint]:
|
||||
@ -641,6 +649,7 @@ class SweepFlightPlan(LoiterFlightPlan):
|
||||
nav_from: List[FlightWaypoint]
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
bullseye: FlightWaypoint
|
||||
lead_time: timedelta
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
@ -653,6 +662,7 @@ class SweepFlightPlan(LoiterFlightPlan):
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||
@ -704,6 +714,7 @@ class AwacsFlightPlan(LoiterFlightPlan):
|
||||
nav_from: List[FlightWaypoint]
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
bullseye: FlightWaypoint
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.takeoff
|
||||
@ -713,6 +724,7 @@ class AwacsFlightPlan(LoiterFlightPlan):
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
@property
|
||||
def mission_start_time(self) -> Optional[timedelta]:
|
||||
@ -746,6 +758,7 @@ class AirliftFlightPlan(FlightPlan):
|
||||
nav_to_home: List[FlightWaypoint]
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
bullseye: FlightWaypoint
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.takeoff
|
||||
@ -758,6 +771,7 @@ class AirliftFlightPlan(FlightPlan):
|
||||
yield self.land
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||
@ -1053,6 +1067,7 @@ class FlightPlanBuilder:
|
||||
),
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
hold=start,
|
||||
hold_duration=timedelta(hours=4),
|
||||
)
|
||||
@ -1151,6 +1166,7 @@ class FlightPlanBuilder:
|
||||
patrol_end=end,
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
)
|
||||
|
||||
def generate_sweep(self, flight: Flight) -> SweepFlightPlan:
|
||||
@ -1187,6 +1203,7 @@ class FlightPlanBuilder:
|
||||
sweep_end=end,
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
)
|
||||
|
||||
def generate_transport(self, flight: Flight) -> AirliftFlightPlan:
|
||||
@ -1238,6 +1255,7 @@ class FlightPlanBuilder:
|
||||
),
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
)
|
||||
|
||||
def racetrack_for_objective(
|
||||
@ -1389,6 +1407,7 @@ class FlightPlanBuilder:
|
||||
patrol_end=end,
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
)
|
||||
|
||||
def generate_dead(
|
||||
@ -1517,6 +1536,7 @@ class FlightPlanBuilder:
|
||||
),
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
)
|
||||
|
||||
def generate_cas(self, flight: Flight) -> CasFlightPlan:
|
||||
@ -1562,6 +1582,7 @@ class FlightPlanBuilder:
|
||||
patrol_end=builder.egress(egress, location),
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@ -1696,6 +1717,7 @@ class FlightPlanBuilder:
|
||||
),
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
)
|
||||
|
||||
def _retreating_rendezvous_point(self, attack_transition: Point) -> Point:
|
||||
|
||||
@ -50,6 +50,7 @@ class WaypointBuilder:
|
||||
self.threat_zones = game.threat_zone_for(not player)
|
||||
self.navmesh = game.navmesh_for(player)
|
||||
self.targets = targets
|
||||
self._bullseye = game.bullseye_for(player)
|
||||
|
||||
@property
|
||||
def is_helo(self) -> bool:
|
||||
@ -145,6 +146,19 @@ class WaypointBuilder:
|
||||
waypoint.only_for_player = True
|
||||
return waypoint
|
||||
|
||||
def bullseye(self) -> FlightWaypoint:
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.BULLSEYE,
|
||||
self._bullseye.position.x,
|
||||
self._bullseye.position.y,
|
||||
meters(0),
|
||||
)
|
||||
waypoint.pretty_name = "Bullseye"
|
||||
waypoint.description = "Bullseye"
|
||||
waypoint.name = "BULLSEYE"
|
||||
waypoint.only_for_player = True
|
||||
return waypoint
|
||||
|
||||
def hold(self, position: Point) -> FlightWaypoint:
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.LOITER,
|
||||
|
||||
@ -209,16 +209,6 @@ class TriggersGenerator:
|
||||
player_coalition = "blue"
|
||||
enemy_coalition = "red"
|
||||
|
||||
player_cp, enemy_cp = self.game.theater.closest_opposing_control_points()
|
||||
self.mission.coalition["blue"].bullseye = {
|
||||
"x": enemy_cp.position.x,
|
||||
"y": enemy_cp.position.y,
|
||||
}
|
||||
self.mission.coalition["red"].bullseye = {
|
||||
"x": player_cp.position.x,
|
||||
"y": player_cp.position.y,
|
||||
}
|
||||
|
||||
self._set_skill(player_coalition, enemy_coalition)
|
||||
self._set_allegiances(player_coalition, enemy_coalition)
|
||||
self._gen_markers()
|
||||
|
||||
@ -375,6 +375,7 @@ class WaypointJs(QObject):
|
||||
timingChanged = Signal()
|
||||
isTakeoffChanged = Signal()
|
||||
isDivertChanged = Signal()
|
||||
isBullseyeChanged = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -439,6 +440,10 @@ class WaypointJs(QObject):
|
||||
def isDivert(self) -> bool:
|
||||
return self.waypoint.waypoint_type is FlightWaypointType.DIVERT
|
||||
|
||||
@Property(bool, notify=isBullseyeChanged)
|
||||
def isBullseye(self) -> bool:
|
||||
return self.waypoint.waypoint_type is FlightWaypointType.BULLSEYE
|
||||
|
||||
@Slot(list, result=str)
|
||||
def setPosition(self, position: LeafletLatLon) -> str:
|
||||
point = self.theater.ll_to_point(LatLon(*position))
|
||||
|
||||
@ -570,7 +570,7 @@ class Waypoint {
|
||||
}
|
||||
|
||||
includeInPath() {
|
||||
return !this.waypoint.isDivert;
|
||||
return !this.waypoint.isDivert && !this.waypoint.isBullseye;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user