refactor of previous commits

refactor to enum

typing and many other fixes

fix tests

attempt to fix some typescript

more typescript fixes

more typescript test fixes

revert all API changes

update to pydcs

mypy fixes

Use properties to check if player is blue/red/neutral

update requirements.txt

black -_-

bump pydcs and fix mypy

add opponent property

bump pydcs
This commit is contained in:
Eclipse/Druss99
2025-01-17 17:02:07 -05:00
committed by Raffson
parent 362ce66f80
commit 31c80dfd02
78 changed files with 739 additions and 350 deletions

View File

@@ -220,7 +220,7 @@ class AircraftGenerator:
):
continue
if control_point.captured:
if control_point.captured.is_blue:
country = player_country
else:
country = enemy_country
@@ -237,12 +237,12 @@ class AircraftGenerator:
squadron.location, Fob
)
if (
squadron.coalition.player
squadron.coalition.player.is_blue
and self.game.settings.perf_disable_untasked_blufor_aircraft
):
return
elif (
not squadron.coalition.player
not squadron.coalition.player.is_red
and self.game.settings.perf_disable_untasked_opfor_aircraft
):
return
@@ -274,7 +274,7 @@ class AircraftGenerator:
).create_idle_aircraft()
if group:
if (
not squadron.coalition.player
squadron.coalition.player.is_red
and squadron.aircraft.flyable
and (
self.game.settings.enable_squadron_pilot_limits

View File

@@ -14,6 +14,7 @@ if TYPE_CHECKING:
from game.dcs.aircrafttype import AircraftType
from game.radio.radios import RadioFrequency
from game.runways import RunwayData
from game.theater.player import Player
@dataclass(frozen=True)
@@ -42,7 +43,7 @@ class FlightData:
size: int
#: True if this flight belongs to the player's coalition.
friendly: bool
friendly: Player
#: Number of seconds after mission start the flight is set to depart.
departure_delay: timedelta

View File

@@ -299,7 +299,7 @@ class FlightGroupConfigurator:
unit.set_player()
def skill_level_for(self, unit: FlyingUnit, pilot: Optional[Pilot]) -> Skill:
if self.flight.squadron.player:
if self.flight.squadron.player.is_blue:
base_skill = Skill(self.game.settings.player_skill)
else:
base_skill = Skill(self.game.settings.enemy_skill)

View File

@@ -17,8 +17,8 @@ from game.radio.radios import RadioFrequency
from game.runways import RunwayData
from game.theater import ControlPoint, FrontLine
from .aircraft.flightdata import FlightData
from .missiondata import AwacsInfo, TankerInfo
from .flotgenerator import JtacInfo
from .missiondata import AwacsInfo, TankerInfo
if TYPE_CHECKING:
from game import Game
@@ -182,7 +182,7 @@ class BriefingGenerator(MissionInfoGenerator):
def generate_allied_flights_by_departure(self) -> None:
"""Create iterable to display allied flights grouped by departure airfield."""
for flight in self.flights:
if not flight.client_units and flight.friendly:
if not flight.client_units and flight.friendly.is_blue:
name = flight.departure.airfield_name
if (
name in self.allied_flights_by_departure

View File

@@ -18,6 +18,7 @@ from game.utils import kph
if TYPE_CHECKING:
from game import Game
from game.theater.player import Player
class ConvoyGenerator:
@@ -94,7 +95,7 @@ class ConvoyGenerator:
name: str,
position: Point,
units: dict[GroundUnitType, int],
for_player: bool,
for_player: Player,
) -> VehicleGroup:
unit_types = list(units.items())
main_unit_type, main_unit_count = unit_types[0]

View File

@@ -15,6 +15,7 @@ FRONTLINE_COLORS = Rgba(255, 0, 0, 255)
WHITE = Rgba(255, 255, 255, 255)
CP_RED = Rgba(255, 0, 0, 80)
CP_BLUE = Rgba(0, 0, 255, 80)
CP_NEUTRAL = Rgba(128, 128, 128, 80)
BLUE_PATH_COLOR = Rgba(0, 0, 255, 100)
RED_PATH_COLOR = Rgba(255, 0, 0, 100)
ACTIVE_PATH_COLOR = Rgba(255, 80, 80, 100)
@@ -35,10 +36,12 @@ class DrawingsGenerator:
Generate cps as circles
"""
for cp in self.game.theater.controlpoints:
if cp.captured:
if cp.captured.is_blue:
color = CP_BLUE
else:
elif cp.captured.is_red:
color = CP_RED
else:
color = CP_NEUTRAL
shape = self.player_layer.add_circle(
cp.position,
TRIGGER_RADIUS_CAPTURE,
@@ -61,9 +64,9 @@ class DrawingsGenerator:
continue
else:
# Determine path color
if cp.captured and destination.captured:
if cp.captured.is_blue and destination.captured.is_blue:
color = BLUE_PATH_COLOR
elif not cp.captured and not destination.captured:
elif cp.captured.is_red and destination.captured.is_red:
color = RED_PATH_COLOR
else:
color = ACTIVE_PATH_COLOR

View File

@@ -40,7 +40,7 @@ from game.ground_forces.ai_ground_planner import (
from game.ground_forces.combat_stance import CombatStance
from game.naming import namegen
from game.radio.radios import RadioRegistry
from game.theater.controlpoint import ControlPoint
from game.theater.controlpoint import ControlPoint, Player
from game.unitmap import UnitMap
from game.utils import Heading
from .frontlineconflictdescription import FrontLineConflictDescription
@@ -101,12 +101,12 @@ class FlotGenerator:
# Create player groups at random position
player_groups = self._generate_groups(
self.player_planned_combat_groups, is_player=True
self.player_planned_combat_groups, is_player=Player.BLUE
)
# Create enemy groups at random position
enemy_groups = self._generate_groups(
self.enemy_planned_combat_groups, is_player=False
self.enemy_planned_combat_groups, is_player=Player.RED
)
# TODO: Differentiate AirConflict and GroundConflict classes.
@@ -193,7 +193,7 @@ class FlotGenerator:
callsign=callsign,
region=frontline,
code=str(code),
blue=True,
blue=Player.BLUE,
freq=freq,
)
)
@@ -215,7 +215,7 @@ class FlotGenerator:
def gen_infantry_group_for_group(
self,
group: VehicleGroup,
is_player: bool,
is_player: Player,
side: Country,
forward_heading: Heading,
) -> None:
@@ -294,7 +294,7 @@ class FlotGenerator:
GroundForcePainter(faction, vehicle).apply_livery()
vg.hidden_on_mfd = True
def _earliest_tot_on_flot(self, player: bool) -> timedelta:
def _earliest_tot_on_flot(self, player: Player) -> timedelta:
tots = [
x.time_over_target
for x in self.game.ato_for(player).packages
@@ -413,7 +413,7 @@ class FlotGenerator:
"""
duration = timedelta()
if stance in [CombatStance.DEFENSIVE, CombatStance.AGGRESSIVE]:
duration = self._earliest_tot_on_flot(not to_cp.coalition.player)
duration = self._earliest_tot_on_flot(to_cp.coalition.player.opponent)
self._set_reform_waypoint(dcs_group, forward_heading, duration)
if stance == CombatStance.AGGRESSIVE:
# Attack nearest enemy if any
@@ -503,7 +503,7 @@ class FlotGenerator:
"""
duration = timedelta()
if stance in [CombatStance.DEFENSIVE, CombatStance.AGGRESSIVE]:
duration = self._earliest_tot_on_flot(not to_cp.coalition.player)
duration = self._earliest_tot_on_flot(to_cp.coalition.player.opponent)
self._set_reform_waypoint(dcs_group, forward_heading, duration)
if stance in [
CombatStance.AGGRESSIVE,
@@ -762,7 +762,7 @@ class FlotGenerator:
)
def _generate_groups(
self, groups: list[CombatGroup], is_player: bool
self, groups: list[CombatGroup], is_player: Player
) -> List[Tuple[VehicleGroup, CombatGroup]]:
"""Finds valid positions for planned groups and generates a pydcs group for them"""
positioned_groups = []
@@ -795,7 +795,7 @@ class FlotGenerator:
final_position,
heading=spawn_heading.opposite,
)
if is_player:
if is_player == Player.BLUE:
g.set_skill(Skill(self.game.settings.player_skill))
else:
g.set_skill(Skill(self.game.settings.enemy_vehicle_skill))
@@ -813,7 +813,7 @@ class FlotGenerator:
def _generate_group(
self,
player: bool,
player: Player,
side: Country,
unit_type: GroundUnitType,
count: int,

View File

@@ -10,15 +10,14 @@ from dcs import Mission
from dcs.action import DoScript, DoScriptFile
from dcs.translation import String
from dcs.triggers import TriggerStart
from dcs.unit import Skill
from game.ato import FlightType
from game.data.units import UnitClass
from game.dcs.aircrafttype import AircraftType
from game.plugins import LuaPluginManager
from game.theater import TheaterGroundObject
from game.theater.iadsnetwork.iadsrole import IadsRole
from game.utils import escape_string_for_lua
from game.data.units import UnitClass
from .missiondata import MissionData
if TYPE_CHECKING:
@@ -144,7 +143,7 @@ class LuaGenerator:
target_points = lua_data.add_item("TargetPoints")
for flight in self.mission_data.flights:
if flight.friendly and flight.flight_type in [
if flight.friendly.is_blue and flight.flight_type in [
FlightType.ANTISHIP,
FlightType.DEAD,
FlightType.SEAD,
@@ -178,7 +177,7 @@ class LuaGenerator:
for cp in self.game.theater.controlpoints:
coalition_object = (
lua_data.get_or_create_item("BlueAA")
if cp.captured
if cp.captured.is_blue
else lua_data.get_or_create_item("RedAA")
)
for ground_object in cp.ground_objects:

View File

@@ -15,6 +15,7 @@ from game.runways import RunwayData
if TYPE_CHECKING:
from game.radio.radios import RadioFrequency
from game.radio.tacan import TacanChannel
from game.theater.player import Player
from game.utils import Distance
from uuid import UUID
@@ -24,7 +25,7 @@ class GroupInfo:
group_name: str
callsign: str
freq: RadioFrequency
blue: bool
blue: Player
@dataclass
@@ -85,7 +86,7 @@ class LogisticsInfo:
pilot_names: list[str]
transport: AircraftType
blue: bool
blue: Player
logistic_unit: str = field(default_factory=str)
pickup_zone: str = field(default_factory=str)

View File

@@ -391,9 +391,12 @@ class MissionGenerator:
tmu.theater_unit.position,
self.mission.terrain,
).dict()
warehouse["coalition"] = (
"blue" if tmu.theater_unit.ground_object.coalition.player else "red"
)
if tmu.theater_unit.ground_object.coalition.player.is_neutral:
warehouse["coalition"] = "neutral"
elif tmu.theater_unit.ground_object.coalition.player.is_blue:
warehouse["coalition"] = "blue"
else:
warehouse["coalition"] = "red"
warehouse["dynamicCargo"] = settings.dynamic_cargo
if tmu.theater_unit.is_ship or tmu.dcs_unit.category == "Heliports": # type: ignore
warehouse["dynamicSpawn"] = settings.dynamic_slots

View File

@@ -13,6 +13,7 @@ from dcs.vehicles import vehicle_map
from game.dcs.groundunittype import GroundUnitType
from game.naming import namegen
from game.theater import Player
if TYPE_CHECKING:
from game import Game
@@ -25,12 +26,12 @@ class RebellionGenerator:
def generate(self) -> None:
ownfor_country = self.mission.country(
self.game.coalition_for(player=True).faction.country.name
self.game.coalition_for(player=Player.BLUE).faction.country.name
)
for rz in self.game.theater.ownfor_rebel_zones:
self._generate_rebel_zone(ownfor_country, rz)
opfor_country = self.mission.country(
self.game.coalition_for(player=False).faction.country.name
self.game.coalition_for(player=Player.RED).faction.country.name
)
for rz in self.game.theater.opfor_rebel_zones:
self._generate_rebel_zone(opfor_country, rz)

View File

@@ -67,6 +67,7 @@ from game.radio.tacan import TacanBand, TacanChannel, TacanRegistry, TacanUsage
from game.runways import RunwayData
from game.theater import (
ControlPoint,
Player,
TheaterGroundObject,
TheaterUnit,
NavalControlPoint,
@@ -408,7 +409,7 @@ class GroundObjectGenerator:
# Align the trigger zones to the faction color on the DCS briefing/F10 map.
color = (
{1: 0.2, 2: 0.7, 3: 1, 4: 0.15}
if scenery.ground_object.is_friendly(to_player=True)
if scenery.ground_object.is_friendly(to_player=Player.BLUE)
else {1: 1, 2: 0.2, 3: 0.2, 4: 0.15}
)
@@ -878,7 +879,12 @@ class HelipadGenerator:
pad.position,
self.m.terrain,
).dict()
warehouse["coalition"] = "blue" if self.cp.coalition.player else "red"
if self.cp.coalition.player.is_neutral:
warehouse["coalition"] = "neutral"
elif self.cp.coalition.player.is_blue:
warehouse["coalition"] = "blue"
else:
warehouse["coalition"] = "red"
# configure dynamic spawn + hot start of DS, plus dynamic cargo?
self.m.warehouses.warehouses[pad.id] = warehouse
@@ -1005,7 +1011,12 @@ class GroundSpawnRoadbaseGenerator:
pad.position,
self.m.terrain,
).dict()
warehouse["coalition"] = "blue" if self.cp.coalition.player else "red"
if self.cp.coalition.player.is_neutral:
warehouse["coalition"] = "neutral"
elif self.cp.coalition.player.is_blue:
warehouse["coalition"] = "blue"
else:
warehouse["coalition"] = "red"
# configure dynamic spawn + hot start of DS, plus dynamic cargo?
self.m.warehouses.warehouses[pad.id] = warehouse
@@ -1131,7 +1142,12 @@ class GroundSpawnLargeGenerator:
pad.position,
self.m.terrain,
).dict()
warehouse["coalition"] = "blue" if self.cp.coalition.player else "red"
if self.cp.coalition.player.is_neutral:
warehouse["coalition"] = "neutral"
elif self.cp.coalition.player.is_blue:
warehouse["coalition"] = "blue"
else:
warehouse["coalition"] = "red"
# configure dynamic spawn + hot start of DS, plus dynamic cargo?
self.m.warehouses.warehouses[pad.id] = warehouse
@@ -1275,7 +1291,12 @@ class GroundSpawnGenerator:
pad.position,
self.m.terrain,
).dict()
warehouse["coalition"] = "blue" if self.cp.coalition.player else "red"
if self.cp.coalition.player.is_neutral:
warehouse["coalition"] = "neutral"
elif self.cp.coalition.player.is_blue:
warehouse["coalition"] = "blue"
else:
warehouse["coalition"] = "red"
# configure dynamic spawn + hot start of DS, plus dynamic cargo?
self.m.warehouses.warehouses[pad.id] = warehouse

View File

@@ -12,7 +12,6 @@ from dcs.action import (
RemoveSceneObjects,
RemoveSceneObjectsMask,
SceneryDestructionZone,
Smoke,
)
from dcs.condition import (
AllOfCoalitionOutsideZone,
@@ -99,9 +98,12 @@ class TriggerGenerator:
raise RuntimeError(
f"Could not find {airfield.airport.name} in the mission"
)
cp_airport.set_coalition(
airfield.captured and player_coalition or enemy_coalition
)
if airfield.captured.is_neutral:
cp_airport.set_coalition("neutral")
elif airfield.captured.is_blue:
cp_airport.set_coalition(player_coalition)
elif airfield.captured.is_red:
cp_airport.set_coalition(enemy_coalition)
def _set_skill(self, player_coalition: str, enemy_coalition: str) -> None:
"""
@@ -138,7 +140,7 @@ class TriggerGenerator:
zone = self.mission.triggers.add_triggerzone(
location, radius=10, hidden=True, name="MARK"
)
if cp.captured:
if cp.captured.is_blue:
name = ground_object.obj_name + " [ALLY]"
else:
name = ground_object.obj_name + " [ENEMY]"
@@ -186,7 +188,7 @@ class TriggerGenerator:
"""
for cp in self.game.theater.controlpoints:
if isinstance(cp, self.capture_zone_types) and not cp.is_carrier:
if cp.captured:
if cp.captured.is_blue:
attacking_coalition = enemy_coalition
attack_coalition_int = 1 # 1 is the Event int for Red
defending_coalition = player_coalition
@@ -242,6 +244,51 @@ class TriggerGenerator:
recapture_trigger.add_action(ClearFlag(flag=flag))
self.mission.triggerrules.triggers.append(recapture_trigger)
if cp.captured.is_neutral:
red_capture_trigger = TriggerCondition(
Event.NoEvent, "Capture Trigger"
)
red_capture_trigger.add_condition(
AllOfCoalitionOutsideZone(
attacking_coalition, trigger_zone.id, unit_type="GROUND"
)
)
red_capture_trigger.add_condition(
PartOfCoalitionInZone(
defending_coalition, trigger_zone.id, unit_type="GROUND"
)
)
red_capture_trigger.add_condition(FlagIsFalse(flag=flag))
script_string = String(
f'base_capture_events[#base_capture_events + 1] = "{cp.id}||{defend_coalition_int}||{cp.full_name}"'
)
red_capture_trigger.add_action(DoScript(script_string))
red_capture_trigger.add_action(SetFlag(flag=flag))
self.mission.triggerrules.triggers.append(red_capture_trigger)
inverted_recapture_trigger = TriggerCondition(
Event.NoEvent, "Capture Trigger"
)
inverted_recapture_trigger.add_condition(
AllOfCoalitionOutsideZone(
defending_coalition, trigger_zone.id, unit_type="GROUND"
)
)
inverted_recapture_trigger.add_condition(
PartOfCoalitionInZone(
attacking_coalition, trigger_zone.id, unit_type="GROUND"
)
)
inverted_recapture_trigger.add_condition(FlagIsTrue(flag=flag))
script_string = String(
f'base_capture_events[#base_capture_events + 1] = "{cp.id}||{attack_coalition_int}||{cp.full_name}"'
)
inverted_recapture_trigger.add_action(DoScript(script_string))
inverted_recapture_trigger.add_action(ClearFlag(flag=flag))
self.mission.triggerrules.triggers.append(
inverted_recapture_trigger
)
def generate(self) -> None:
player_coalition = "blue"
enemy_coalition = "red"