mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
parent
b7bc9efb52
commit
a8a37fa3e7
@ -426,6 +426,7 @@ export type Tgo = {
|
|||||||
detection_ranges: number[];
|
detection_ranges: number[];
|
||||||
dead: boolean;
|
dead: boolean;
|
||||||
sidc: string;
|
sidc: string;
|
||||||
|
task?: string[];
|
||||||
};
|
};
|
||||||
export type SupplyRoute = {
|
export type SupplyRoute = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@ -57,6 +57,7 @@ describe("AirDefenseRangeLayer", () => {
|
|||||||
detection_ranges: [20],
|
detection_ranges: [20],
|
||||||
dead: false,
|
dead: false,
|
||||||
sidc: "",
|
sidc: "",
|
||||||
|
task: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -86,6 +87,7 @@ describe("AirDefenseRangeLayer", () => {
|
|||||||
detection_ranges: [20],
|
detection_ranges: [20],
|
||||||
dead: false,
|
dead: false,
|
||||||
sidc: "",
|
sidc: "",
|
||||||
|
task: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -125,6 +127,7 @@ describe("AirDefenseRangeLayer", () => {
|
|||||||
detection_ranges: [20],
|
detection_ranges: [20],
|
||||||
dead: false,
|
dead: false,
|
||||||
sidc: "",
|
sidc: "",
|
||||||
|
task: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -53,6 +53,18 @@ export default function LiberationMap() {
|
|||||||
<LayersControl.Overlay name="Air defenses" checked>
|
<LayersControl.Overlay name="Air defenses" checked>
|
||||||
<TgosLayer categories={["aa"]} />
|
<TgosLayer categories={["aa"]} />
|
||||||
</LayersControl.Overlay>
|
</LayersControl.Overlay>
|
||||||
|
<LayersControl.Overlay name="LORAD" >
|
||||||
|
<TgosLayer categories={["aa"]} task={"LORAD"} />
|
||||||
|
</LayersControl.Overlay>
|
||||||
|
<LayersControl.Overlay name="MERAD" >
|
||||||
|
<TgosLayer categories={["aa"]} task={"MERAD"} />
|
||||||
|
</LayersControl.Overlay>
|
||||||
|
<LayersControl.Overlay name="SHORAD" >
|
||||||
|
<TgosLayer categories={["aa"]} task={"SHORAD"} />
|
||||||
|
</LayersControl.Overlay>
|
||||||
|
<LayersControl.Overlay name="AAA" >
|
||||||
|
<TgosLayer categories={["aa"]} task={"AAA"} />
|
||||||
|
</LayersControl.Overlay>
|
||||||
<LayersControl.Overlay name="Factories" checked>
|
<LayersControl.Overlay name="Factories" checked>
|
||||||
<TgosLayer categories={["factory"]} />
|
<TgosLayer categories={["factory"]} />
|
||||||
</LayersControl.Overlay>
|
</LayersControl.Overlay>
|
||||||
|
|||||||
@ -6,14 +6,21 @@ import { LayerGroup } from "react-leaflet";
|
|||||||
interface TgosLayerProps {
|
interface TgosLayerProps {
|
||||||
categories?: string[];
|
categories?: string[];
|
||||||
exclude?: true;
|
exclude?: true;
|
||||||
|
task?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TgosLayer(props: TgosLayerProps) {
|
export default function TgosLayer(props: TgosLayerProps) {
|
||||||
const allTgos = Object.values(useAppSelector(selectTgos).tgos);
|
const allTgos = Object.values(useAppSelector(selectTgos).tgos);
|
||||||
const categoryFilter = props.categories ?? [];
|
const categoryFilter = props.categories ?? [];
|
||||||
|
const taskFilter = props.task ?? "";
|
||||||
const tgos = allTgos.filter(
|
const tgos = allTgos.filter(
|
||||||
(tgo) => categoryFilter.includes(tgo.category) === !(props.exclude ?? false)
|
(tgo) => {
|
||||||
);
|
if (taskFilter && tgo.task){
|
||||||
|
return taskFilter === tgo.task[0]
|
||||||
|
}
|
||||||
|
return categoryFilter.includes(tgo.category) === !(props.exclude ?? false)
|
||||||
|
}
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<LayerGroup>
|
<LayerGroup>
|
||||||
{tgos.map((tgo) => {
|
{tgos.map((tgo) => {
|
||||||
|
|||||||
@ -191,11 +191,12 @@ class ForceGroup:
|
|||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
game: Game,
|
game: Game,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> TheaterGroundObject:
|
) -> TheaterGroundObject:
|
||||||
"""Create a random TheaterGroundObject from the available templates"""
|
"""Create a random TheaterGroundObject from the available templates"""
|
||||||
layout = random.choice(self.layouts)
|
layout = random.choice(self.layouts)
|
||||||
return self.create_ground_object_for_layout(
|
return self.create_ground_object_for_layout(
|
||||||
layout, name, location, control_point, game
|
layout, name, location, control_point, game, task
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_ground_object_for_layout(
|
def create_ground_object_for_layout(
|
||||||
@ -205,9 +206,10 @@ class ForceGroup:
|
|||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
game: Game,
|
game: Game,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> TheaterGroundObject:
|
) -> TheaterGroundObject:
|
||||||
"""Create a TheaterGroundObject for the given template"""
|
"""Create a TheaterGroundObject for the given template"""
|
||||||
go = layout.create_ground_object(name, location, control_point)
|
go = layout.create_ground_object(name, location, control_point, task)
|
||||||
# Generate all groups using the randomization if it defined
|
# Generate all groups using the randomization if it defined
|
||||||
for tgo_group in layout.groups:
|
for tgo_group in layout.groups:
|
||||||
for unit_group in tgo_group.unit_groups:
|
for unit_group in tgo_group.unit_groups:
|
||||||
|
|||||||
@ -220,6 +220,7 @@ class TgoLayout:
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> TheaterGroundObject:
|
) -> TheaterGroundObject:
|
||||||
"""Create the TheaterGroundObject for the TgoLayout
|
"""Create the TheaterGroundObject for the TgoLayout
|
||||||
|
|
||||||
@ -240,11 +241,12 @@ class AntiAirLayout(TgoLayout):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> IadsGroundObject:
|
) -> IadsGroundObject:
|
||||||
if GroupTask.EARLY_WARNING_RADAR in self.tasks:
|
if GroupTask.EARLY_WARNING_RADAR in self.tasks:
|
||||||
return EwrGroundObject(name, location, control_point)
|
return EwrGroundObject(name, location, control_point)
|
||||||
elif any(tasking in self.tasks for tasking in GroupRole.AIR_DEFENSE.tasks):
|
elif any(tasking in self.tasks for tasking in GroupRole.AIR_DEFENSE.tasks):
|
||||||
return SamGroundObject(name, location, control_point)
|
return SamGroundObject(name, location, control_point, task)
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f" No Template for AntiAir tasking ({', '.join(task.description for task in self.tasks)})"
|
f" No Template for AntiAir tasking ({', '.join(task.description for task in self.tasks)})"
|
||||||
)
|
)
|
||||||
@ -256,6 +258,7 @@ class BuildingLayout(TgoLayout):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> BuildingGroundObject:
|
) -> BuildingGroundObject:
|
||||||
iads_role = IadsRole.for_category(self.category)
|
iads_role = IadsRole.for_category(self.category)
|
||||||
tgo_type = (
|
tgo_type = (
|
||||||
@ -266,6 +269,7 @@ class BuildingLayout(TgoLayout):
|
|||||||
self.category,
|
self.category,
|
||||||
location,
|
location,
|
||||||
control_point,
|
control_point,
|
||||||
|
task,
|
||||||
self.category == "fob",
|
self.category == "fob",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -283,6 +287,7 @@ class NavalLayout(TgoLayout):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> TheaterGroundObject:
|
) -> TheaterGroundObject:
|
||||||
if GroupTask.NAVY in self.tasks:
|
if GroupTask.NAVY in self.tasks:
|
||||||
return ShipGroundObject(name, location, control_point)
|
return ShipGroundObject(name, location, control_point)
|
||||||
@ -299,6 +304,7 @@ class DefensesLayout(TgoLayout):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> TheaterGroundObject:
|
) -> TheaterGroundObject:
|
||||||
if GroupTask.MISSILE in self.tasks:
|
if GroupTask.MISSILE in self.tasks:
|
||||||
return MissileSiteGroundObject(name, location, control_point)
|
return MissileSiteGroundObject(name, location, control_point)
|
||||||
@ -313,5 +319,6 @@ class GroundForceLayout(TgoLayout):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> TheaterGroundObject:
|
) -> TheaterGroundObject:
|
||||||
return VehicleGroupGroundObject(name, location, control_point)
|
return VehicleGroupGroundObject(name, location, control_point, task)
|
||||||
|
|||||||
@ -36,6 +36,7 @@ class Migrator:
|
|||||||
self._update_squadrons()
|
self._update_squadrons()
|
||||||
self._release_untasked_flights()
|
self._release_untasked_flights()
|
||||||
self._update_weather()
|
self._update_weather()
|
||||||
|
self._update_tgos()
|
||||||
|
|
||||||
def _update_doctrine(self) -> None:
|
def _update_doctrine(self) -> None:
|
||||||
doctrines = [
|
doctrines = [
|
||||||
@ -197,3 +198,7 @@ class Migrator:
|
|||||||
midnight_turbulence_per_10cm=0.4,
|
midnight_turbulence_per_10cm=0.4,
|
||||||
weather_type_chances=sc.weather_type_chances,
|
weather_type_chances=sc.weather_type_chances,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _update_tgos(self) -> None:
|
||||||
|
for go in self.game.theater.ground_objects:
|
||||||
|
go.task = None # TODO: attempt to deduce tasking?
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Iterable, List, TYPE_CHECKING
|
from typing import Iterable, List, TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from dcs.mapping import Polygon
|
from dcs.mapping import Polygon
|
||||||
from dcs.triggers import TriggerZone, TriggerZoneCircular, TriggerZoneQuadPoint
|
from dcs.triggers import TriggerZone, TriggerZoneCircular, TriggerZoneQuadPoint
|
||||||
|
|
||||||
|
from game.data.groups import GroupTask
|
||||||
from game.theater.theatergroundobject import NAME_BY_CATEGORY
|
from game.theater.theatergroundobject import NAME_BY_CATEGORY
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -88,6 +89,38 @@ class SceneryGroup:
|
|||||||
|
|
||||||
return scenery_groups
|
return scenery_groups
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def group_task_for_scenery_group_category(category: str) -> Optional[GroupTask]:
|
||||||
|
if category == "allycamp":
|
||||||
|
return GroupTask.ALLY_CAMP
|
||||||
|
elif category == "ammo":
|
||||||
|
return GroupTask.AMMO
|
||||||
|
elif category == "commandcenter":
|
||||||
|
return GroupTask.COMMAND_CENTER
|
||||||
|
elif category == "comms":
|
||||||
|
return GroupTask.COMMS
|
||||||
|
elif category == "derrick":
|
||||||
|
return GroupTask.DERRICK
|
||||||
|
elif category == "factory":
|
||||||
|
return GroupTask.FACTORY
|
||||||
|
elif category == "farp":
|
||||||
|
return GroupTask.FARP
|
||||||
|
elif category == "fob":
|
||||||
|
return GroupTask.FOB
|
||||||
|
elif category == "fuel":
|
||||||
|
return GroupTask.FUEL
|
||||||
|
elif category == "oil":
|
||||||
|
return GroupTask.OIL
|
||||||
|
elif category == "power":
|
||||||
|
return GroupTask.POWER
|
||||||
|
elif category == "village":
|
||||||
|
return GroupTask.VILLAGE
|
||||||
|
elif category == "ware":
|
||||||
|
return GroupTask.WARE
|
||||||
|
elif category == "ww2bunker":
|
||||||
|
return GroupTask.WW2_BUNKER
|
||||||
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_blue(zone: TriggerZone) -> bool:
|
def is_blue(zone: TriggerZone) -> bool:
|
||||||
# Blue in RGB is [0 Red], [0 Green], [1 Blue]. Ignore the fourth position: Transparency.
|
# Blue in RGB is [0 Red], [0 Green], [1 Blue]. Ignore the fourth position: Transparency.
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING, Optional
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from game.data.groups import GroupTask
|
||||||
from game.server.leaflet import LeafletPoint
|
from game.server.leaflet import LeafletPoint
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -24,6 +25,7 @@ class TgoJs(BaseModel):
|
|||||||
detection_ranges: list[float] # TODO: Event stream
|
detection_ranges: list[float] # TODO: Event stream
|
||||||
dead: bool # TODO: Event stream
|
dead: bool # TODO: Event stream
|
||||||
sidc: str # TODO: Event stream
|
sidc: str # TODO: Event stream
|
||||||
|
task: Optional[GroupTask]
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
title = "Tgo"
|
title = "Tgo"
|
||||||
@ -44,6 +46,7 @@ class TgoJs(BaseModel):
|
|||||||
detection_ranges=detection_ranges,
|
detection_ranges=detection_ranges,
|
||||||
dead=tgo.is_dead,
|
dead=tgo.is_dead,
|
||||||
sidc=str(tgo.sidc()),
|
sidc=str(tgo.sidc()),
|
||||||
|
task=tgo.groups[0].ground_object.task,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@ -177,13 +177,17 @@ class ControlPointGroundObjectGenerator:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def generate_ground_object_from_group(
|
def generate_ground_object_from_group(
|
||||||
self, unit_group: ForceGroup, location: PresetLocation
|
self,
|
||||||
|
unit_group: ForceGroup,
|
||||||
|
location: PresetLocation,
|
||||||
|
task: Optional[GroupTask] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
ground_object = unit_group.generate(
|
ground_object = unit_group.generate(
|
||||||
namegen.random_objective_name(),
|
namegen.random_objective_name(),
|
||||||
location,
|
location,
|
||||||
self.control_point,
|
self.control_point,
|
||||||
self.game,
|
self.game,
|
||||||
|
task,
|
||||||
)
|
)
|
||||||
self.control_point.connected_objectives.append(ground_object)
|
self.control_point.connected_objectives.append(ground_object)
|
||||||
|
|
||||||
@ -199,7 +203,7 @@ class ControlPointGroundObjectGenerator:
|
|||||||
if not unit_group:
|
if not unit_group:
|
||||||
logging.warning(f"{self.faction_name} has no ForceGroup for Navy")
|
logging.warning(f"{self.faction_name} has no ForceGroup for Navy")
|
||||||
return
|
return
|
||||||
self.generate_ground_object_from_group(unit_group, position)
|
self.generate_ground_object_from_group(unit_group, position, GroupTask.NAVY)
|
||||||
|
|
||||||
|
|
||||||
class NoOpGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
class NoOpGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||||
@ -241,6 +245,7 @@ class CarrierGroundObjectGenerator(GenericCarrierGroundObjectGenerator):
|
|||||||
self.control_point.position,
|
self.control_point.position,
|
||||||
self.control_point.heading,
|
self.control_point.heading,
|
||||||
),
|
),
|
||||||
|
GroupTask.AIRCRAFT_CARRIER,
|
||||||
)
|
)
|
||||||
self.update_carrier_name(random.choice(list(carrier_names)))
|
self.update_carrier_name(random.choice(list(carrier_names)))
|
||||||
return True
|
return True
|
||||||
@ -272,6 +277,7 @@ class LhaGroundObjectGenerator(GenericCarrierGroundObjectGenerator):
|
|||||||
self.control_point.position,
|
self.control_point.position,
|
||||||
self.control_point.heading,
|
self.control_point.heading,
|
||||||
),
|
),
|
||||||
|
GroupTask.HELICOPTER_CARRIER,
|
||||||
)
|
)
|
||||||
self.update_carrier_name(random.choice(list(lha_names)))
|
self.update_carrier_name(random.choice(list(lha_names)))
|
||||||
return True
|
return True
|
||||||
@ -340,7 +346,9 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
if not unit_group:
|
if not unit_group:
|
||||||
logging.error(f"{self.faction_name} has no ForceGroup for Armor")
|
logging.error(f"{self.faction_name} has no ForceGroup for Armor")
|
||||||
return
|
return
|
||||||
self.generate_ground_object_from_group(unit_group, position)
|
self.generate_ground_object_from_group(
|
||||||
|
unit_group, position, GroupTask.BASE_DEFENSE
|
||||||
|
)
|
||||||
|
|
||||||
def generate_aa(self) -> None:
|
def generate_aa(self) -> None:
|
||||||
presets = self.control_point.preset_locations
|
presets = self.control_point.preset_locations
|
||||||
@ -365,7 +373,9 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
if not unit_group:
|
if not unit_group:
|
||||||
logging.error(f"{self.faction_name} has no ForceGroup for EWR")
|
logging.error(f"{self.faction_name} has no ForceGroup for EWR")
|
||||||
return
|
return
|
||||||
self.generate_ground_object_from_group(unit_group, position)
|
self.generate_ground_object_from_group(
|
||||||
|
unit_group, position, GroupTask.EARLY_WARNING_RADAR
|
||||||
|
)
|
||||||
|
|
||||||
def generate_building_at(
|
def generate_building_at(
|
||||||
self,
|
self,
|
||||||
@ -378,7 +388,7 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"{self.faction_name} has no access to Building {group_task.description}"
|
f"{self.faction_name} has no access to Building {group_task.description}"
|
||||||
)
|
)
|
||||||
self.generate_ground_object_from_group(unit_group, location)
|
self.generate_ground_object_from_group(unit_group, location, group_task)
|
||||||
|
|
||||||
def generate_ammunition_depots(self) -> None:
|
def generate_ammunition_depots(self) -> None:
|
||||||
for position in self.control_point.preset_locations.ammunition_depots:
|
for position in self.control_point.preset_locations.ammunition_depots:
|
||||||
@ -394,7 +404,7 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
if unit_group:
|
if unit_group:
|
||||||
# Only take next (smaller) aa_range when no template available for the
|
# Only take next (smaller) aa_range when no template available for the
|
||||||
# most requested range. Otherwise break the loop and continue
|
# most requested range. Otherwise break the loop and continue
|
||||||
self.generate_ground_object_from_group(unit_group, location)
|
self.generate_ground_object_from_group(unit_group, location, task)
|
||||||
return
|
return
|
||||||
|
|
||||||
logging.error(
|
logging.error(
|
||||||
@ -430,6 +440,7 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
scenery.category,
|
scenery.category,
|
||||||
PresetLocation(scenery.zone_def.name, scenery.position),
|
PresetLocation(scenery.zone_def.name, scenery.position),
|
||||||
self.control_point,
|
self.control_point,
|
||||||
|
SceneryGroup.group_task_for_scenery_group_category(scenery.category),
|
||||||
)
|
)
|
||||||
ground_group = TheaterGroup(
|
ground_group = TheaterGroup(
|
||||||
self.game.next_group_id(),
|
self.game.next_group_id(),
|
||||||
@ -464,7 +475,9 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
if not unit_group:
|
if not unit_group:
|
||||||
logging.warning(f"{self.faction_name} has no ForceGroup for Missile")
|
logging.warning(f"{self.faction_name} has no ForceGroup for Missile")
|
||||||
return
|
return
|
||||||
self.generate_ground_object_from_group(unit_group, position)
|
self.generate_ground_object_from_group(
|
||||||
|
unit_group, position, GroupTask.MISSILE
|
||||||
|
)
|
||||||
|
|
||||||
def generate_coastal_sites(self) -> None:
|
def generate_coastal_sites(self) -> None:
|
||||||
for position in self.control_point.preset_locations.coastal_defenses:
|
for position in self.control_point.preset_locations.coastal_defenses:
|
||||||
@ -472,7 +485,9 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
if not unit_group:
|
if not unit_group:
|
||||||
logging.warning(f"{self.faction_name} has no ForceGroup for Coastal")
|
logging.warning(f"{self.faction_name} has no ForceGroup for Coastal")
|
||||||
return
|
return
|
||||||
self.generate_ground_object_from_group(unit_group, position)
|
self.generate_ground_object_from_group(
|
||||||
|
unit_group, position, GroupTask.COASTAL
|
||||||
|
)
|
||||||
|
|
||||||
def generate_strike_targets(self) -> None:
|
def generate_strike_targets(self) -> None:
|
||||||
for position in self.control_point.preset_locations.strike_locations:
|
for position in self.control_point.preset_locations.strike_locations:
|
||||||
|
|||||||
@ -21,6 +21,7 @@ from game.sidc import (
|
|||||||
)
|
)
|
||||||
from game.theater.presetlocation import PresetLocation
|
from game.theater.presetlocation import PresetLocation
|
||||||
from .missiontarget import MissionTarget
|
from .missiontarget import MissionTarget
|
||||||
|
from ..data.groups import GroupTask
|
||||||
from ..utils import Distance, Heading, meters
|
from ..utils import Distance, Heading, meters
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -62,6 +63,7 @@ class TheaterGroundObject(MissionTarget, SidcDescribable, ABC):
|
|||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
sea_object: bool,
|
sea_object: bool,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(name, location)
|
super().__init__(name, location)
|
||||||
self.id = uuid.uuid4()
|
self.id = uuid.uuid4()
|
||||||
@ -72,6 +74,7 @@ class TheaterGroundObject(MissionTarget, SidcDescribable, ABC):
|
|||||||
self.groups: List[TheaterGroup] = []
|
self.groups: List[TheaterGroup] = []
|
||||||
self.original_name = location.original_name
|
self.original_name = location.original_name
|
||||||
self._threat_poly: ThreatPoly | None = None
|
self._threat_poly: ThreatPoly | None = None
|
||||||
|
self.task = task
|
||||||
|
|
||||||
def __getstate__(self) -> dict[str, Any]:
|
def __getstate__(self) -> dict[str, Any]:
|
||||||
state = self.__dict__.copy()
|
state = self.__dict__.copy()
|
||||||
@ -286,6 +289,7 @@ class BuildingGroundObject(TheaterGroundObject):
|
|||||||
category: str,
|
category: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
is_fob_structure: bool = False,
|
is_fob_structure: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -294,6 +298,7 @@ class BuildingGroundObject(TheaterGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=False,
|
sea_object=False,
|
||||||
|
task=task,
|
||||||
)
|
)
|
||||||
self.is_fob_structure = is_fob_structure
|
self.is_fob_structure = is_fob_structure
|
||||||
|
|
||||||
@ -389,6 +394,7 @@ class CarrierGroundObject(GenericCarrierGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=True,
|
sea_object=True,
|
||||||
|
task=GroupTask.AIRCRAFT_CARRIER,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -410,6 +416,7 @@ class LhaGroundObject(GenericCarrierGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=True,
|
sea_object=True,
|
||||||
|
task=GroupTask.HELICOPTER_CARRIER,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -430,6 +437,7 @@ class MissileSiteGroundObject(TheaterGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=False,
|
sea_object=False,
|
||||||
|
task=GroupTask.MISSILE,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -470,6 +478,7 @@ class CoastalSiteGroundObject(TheaterGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=False,
|
sea_object=False,
|
||||||
|
task=GroupTask.COASTAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -503,6 +512,7 @@ class IadsGroundObject(TheaterGroundObject, ABC):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
category: str = "aa",
|
category: str = "aa",
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -511,6 +521,7 @@ class IadsGroundObject(TheaterGroundObject, ABC):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=False,
|
sea_object=False,
|
||||||
|
task=task,
|
||||||
)
|
)
|
||||||
|
|
||||||
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
||||||
@ -538,12 +549,14 @@ class SamGroundObject(IadsGroundObject):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
name=name,
|
name=name,
|
||||||
category="aa",
|
category="aa",
|
||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
|
task=task,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -589,6 +602,7 @@ class VehicleGroupGroundObject(TheaterGroundObject):
|
|||||||
name: str,
|
name: str,
|
||||||
location: PresetLocation,
|
location: PresetLocation,
|
||||||
control_point: ControlPoint,
|
control_point: ControlPoint,
|
||||||
|
task: Optional[GroupTask],
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
name=name,
|
name=name,
|
||||||
@ -596,6 +610,7 @@ class VehicleGroupGroundObject(TheaterGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=False,
|
sea_object=False,
|
||||||
|
task=task,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -637,6 +652,7 @@ class EwrGroundObject(IadsGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
category="ewr",
|
category="ewr",
|
||||||
|
task=GroupTask.EARLY_WARNING_RADAR,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -662,6 +678,7 @@ class ShipGroundObject(NavalGroundObject):
|
|||||||
location=location,
|
location=location,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
sea_object=True,
|
sea_object=True,
|
||||||
|
task=GroupTask.NAVY,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import pytest
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
import pytest
|
||||||
from dcs.mapping import Point
|
from dcs.mapping import Point
|
||||||
|
|
||||||
from game.ato.flighttype import FlightType
|
from game.ato.flighttype import FlightType
|
||||||
|
from game.theater.controlpoint import OffMapSpawn
|
||||||
from game.theater.presetlocation import PresetLocation
|
from game.theater.presetlocation import PresetLocation
|
||||||
from game.theater.theatergroundobject import (
|
from game.theater.theatergroundobject import (
|
||||||
BuildingGroundObject,
|
BuildingGroundObject,
|
||||||
@ -16,7 +18,6 @@ from game.theater.theatergroundobject import (
|
|||||||
ShipGroundObject,
|
ShipGroundObject,
|
||||||
IadsBuildingGroundObject,
|
IadsBuildingGroundObject,
|
||||||
)
|
)
|
||||||
from game.theater.controlpoint import OffMapSpawn
|
|
||||||
from game.utils import Heading
|
from game.utils import Heading
|
||||||
|
|
||||||
|
|
||||||
@ -49,20 +50,22 @@ def test_mission_types_friendly(mocker: Any) -> None:
|
|||||||
EwrGroundObject,
|
EwrGroundObject,
|
||||||
ShipGroundObject,
|
ShipGroundObject,
|
||||||
]:
|
]:
|
||||||
ground_object = ground_object_type( # type: ignore
|
ground_object = ground_object_type(
|
||||||
name="test",
|
name="test",
|
||||||
location=dummy_location,
|
location=dummy_location,
|
||||||
control_point=dummy_control_point,
|
control_point=dummy_control_point,
|
||||||
|
task=None,
|
||||||
)
|
)
|
||||||
mission_types = list(ground_object.mission_types(for_player=True))
|
mission_types = list(ground_object.mission_types(for_player=True))
|
||||||
assert mission_types == [FlightType.BARCAP]
|
assert mission_types == [FlightType.BARCAP]
|
||||||
|
|
||||||
for ground_object_type in [BuildingGroundObject, IadsBuildingGroundObject]: # type: ignore
|
for ground_object_type in [BuildingGroundObject, IadsBuildingGroundObject]:
|
||||||
ground_object = ground_object_type( # type: ignore
|
ground_object = ground_object_type(
|
||||||
name="test",
|
name="test",
|
||||||
category="ammo",
|
category="ammo",
|
||||||
location=dummy_location,
|
location=dummy_location,
|
||||||
control_point=dummy_control_point,
|
control_point=dummy_control_point,
|
||||||
|
task=None,
|
||||||
)
|
)
|
||||||
mission_types = list(ground_object.mission_types(for_player=True))
|
mission_types = list(ground_object.mission_types(for_player=True))
|
||||||
assert mission_types == [FlightType.BARCAP]
|
assert mission_types == [FlightType.BARCAP]
|
||||||
@ -94,6 +97,7 @@ def test_mission_types_enemy(mocker: Any) -> None:
|
|||||||
category="ammo",
|
category="ammo",
|
||||||
location=dummy_location,
|
location=dummy_location,
|
||||||
control_point=dummy_control_point,
|
control_point=dummy_control_point,
|
||||||
|
task=None,
|
||||||
)
|
)
|
||||||
mission_types = list(building.mission_types(for_player=False))
|
mission_types = list(building.mission_types(for_player=False))
|
||||||
assert len(mission_types) == 6
|
assert len(mission_types) == 6
|
||||||
@ -109,6 +113,7 @@ def test_mission_types_enemy(mocker: Any) -> None:
|
|||||||
category="ammo",
|
category="ammo",
|
||||||
location=dummy_location,
|
location=dummy_location,
|
||||||
control_point=dummy_control_point,
|
control_point=dummy_control_point,
|
||||||
|
task=None,
|
||||||
)
|
)
|
||||||
mission_types = list(iads_building.mission_types(for_player=False))
|
mission_types = list(iads_building.mission_types(for_player=False))
|
||||||
assert len(mission_types) == 7
|
assert len(mission_types) == 7
|
||||||
@ -129,6 +134,7 @@ def test_mission_types_enemy(mocker: Any) -> None:
|
|||||||
name="test",
|
name="test",
|
||||||
location=dummy_location,
|
location=dummy_location,
|
||||||
control_point=dummy_control_point,
|
control_point=dummy_control_point,
|
||||||
|
task=None,
|
||||||
)
|
)
|
||||||
mission_types = list(ground_object.mission_types(for_player=False))
|
mission_types = list(ground_object.mission_types(for_player=False))
|
||||||
assert len(mission_types) == 7
|
assert len(mission_types) == 7
|
||||||
@ -144,6 +150,7 @@ def test_mission_types_enemy(mocker: Any) -> None:
|
|||||||
name="test",
|
name="test",
|
||||||
location=dummy_location,
|
location=dummy_location,
|
||||||
control_point=dummy_control_point,
|
control_point=dummy_control_point,
|
||||||
|
task=None,
|
||||||
)
|
)
|
||||||
mission_types = list(sam.mission_types(for_player=False))
|
mission_types = list(sam.mission_types(for_player=False))
|
||||||
assert len(mission_types) == 8
|
assert len(mission_types) == 8
|
||||||
@ -194,6 +201,7 @@ def test_mission_types_enemy(mocker: Any) -> None:
|
|||||||
name="test",
|
name="test",
|
||||||
location=dummy_location,
|
location=dummy_location,
|
||||||
control_point=dummy_control_point,
|
control_point=dummy_control_point,
|
||||||
|
task=None,
|
||||||
)
|
)
|
||||||
mission_types = list(vehicles.mission_types(for_player=False))
|
mission_types = list(vehicles.mission_types(for_player=False))
|
||||||
assert len(mission_types) == 7
|
assert len(mission_types) == 7
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user