Support mobile CPs in the new map.

https://github.com/dcs-liberation/dcs_liberation/issues/2039
This commit is contained in:
Dan Albert
2022-03-05 15:41:58 -08:00
parent 2c6e8c414c
commit 995e28cb32
4 changed files with 336 additions and 13 deletions

View File

@@ -1,8 +1,13 @@
from dcs import Point
from dcs.mapping import LatLng
from fastapi import APIRouter, Depends, HTTPException, status
from game import Game
from .models import ControlPointJs
from .. import EventStream
from ..dependencies import GameContext
from ..leaflet import LeafletPoint
from ...sim import GameUpdateEvents
router: APIRouter = APIRouter(prefix="/control-points")
@@ -26,3 +31,67 @@ def get_control_point(
detail=f"Game has no control point with ID {cp_id}",
)
return ControlPointJs.for_control_point(cp)
@router.get("/{cp_id}/destination-in-range")
def destination_in_range(
cp_id: int, lat: float, lng: float, game: Game = Depends(GameContext.get)
) -> bool:
cp = game.theater.find_control_point_by_id(cp_id)
if cp is None:
raise HTTPException(
status.HTTP_404_NOT_FOUND,
detail=f"Game has no control point with ID {cp_id}",
)
point = Point.from_latlng(LatLng(lat, lng), game.theater.terrain)
return cp.destination_in_range(point)
@router.put("/{cp_id}/destination")
def set_destination(
cp_id: int, destination: LeafletPoint, game: Game = Depends(GameContext.get)
) -> None:
cp = game.theater.find_control_point_by_id(cp_id)
if cp is None:
raise HTTPException(
status.HTTP_404_NOT_FOUND,
detail=f"Game has no control point with ID {cp_id}",
)
if not cp.moveable:
raise HTTPException(status.HTTP_403_FORBIDDEN, detail=f"{cp} is not mobile")
if not cp.captured:
raise HTTPException(
status.HTTP_403_FORBIDDEN, detail=f"{cp} is not owned by the player"
)
point = Point.from_latlng(
LatLng(destination.lat, destination.lng), game.theater.terrain
)
if not cp.destination_in_range(point):
raise HTTPException(
status.HTTP_400_BAD_REQUEST,
detail=f"Cannot move {cp} more than "
f"{cp.max_move_distance.nautical_miles}nm.",
)
cp.target_position = point
EventStream.put_nowait(GameUpdateEvents().update_control_point(cp))
@router.put("/{cp_id}/cancel-travel")
def cancel_travel(cp_id: int, game: Game = Depends(GameContext.get)) -> None:
cp = game.theater.find_control_point_by_id(cp_id)
if cp is None:
raise HTTPException(
status.HTTP_404_NOT_FOUND,
detail=f"Game has no control point with ID {cp_id}",
)
if not cp.moveable:
raise HTTPException(status.HTTP_403_FORBIDDEN, detail=f"{cp} is not mobile")
if not cp.captured:
raise HTTPException(
status.HTTP_403_FORBIDDEN, detail=f"{cp} is not owned by the player"
)
cp.target_position = None
EventStream.put_nowait(GameUpdateEvents().update_control_point(cp))

View File

@@ -41,7 +41,7 @@ from game.sidc import (
Status,
SymbolSet,
)
from game.utils import Heading
from game.utils import Distance, Heading, meters
from .base import Base
from .frontline import FrontLine
from .missiontarget import MissionTarget
@@ -540,7 +540,15 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
"""
:return: Whether this control point can be moved around
"""
return False
return self.max_move_distance > meters(0)
@property
def max_move_distance(self) -> Distance:
return meters(0)
def destination_in_range(self, destination: Point) -> bool:
distance = meters(destination.distance_to_point(self.position))
return distance <= self.max_move_distance
@property
@abstractmethod
@@ -1117,8 +1125,8 @@ class NavalControlPoint(ControlPoint, ABC):
return False
@property
def moveable(self) -> bool:
return True
def max_move_distance(self) -> Distance:
return nautical_miles(80)
@property
def can_deploy_ground_units(self) -> bool: