Replace CP integer ID with a UUID.

This allows unique identification across saves. The front-end needs to
be able to differentiate the first carrier in game A and the first
carrier in game B, but because carriers (and other non-airfield CPs) are
assigned IDs sequentially, collisions were to be expected. The front-end
can't tell the difference between a reloaded game and a new turn, so we
need to ensure different IDs across games.

This is a handy cleanup anyway, since callers constructing CPs no longer
need to manually track the CP ID counter.

Fixes https://github.com/dcs-liberation/dcs_liberation/issues/2078.
This commit is contained in:
Dan Albert
2022-03-20 15:11:58 -07:00
parent 941a7d441c
commit 039ac9ec74
21 changed files with 127 additions and 179 deletions

View File

@@ -1,4 +1,3 @@
import copy
import logging
import random
from typing import Any, Union
@@ -8,7 +7,6 @@ from dcs.country import Country
from dcs.mapping import Vector2
from dcs.mission import StartType as DcsStartType
from dcs.planes import F_14A, Su_33
from dcs.point import PointAction
from dcs.ships import KUZNECOW
from dcs.terrain import Airport, NoParkingSlotError
from dcs.unitgroup import FlyingGroup, ShipGroup, StaticGroup
@@ -16,10 +14,10 @@ from dcs.unitgroup import FlyingGroup, ShipGroup, StaticGroup
from game.ato import Flight
from game.ato.flightstate import InFlight
from game.ato.starttype import StartType
from game.ato.traveltime import GroundSpeed
from game.naming import namegen
from game.theater import Airfield, ControlPoint, Fob, NavalControlPoint, OffMapSpawn
from game.utils import feet, meters
from game.ato.traveltime import GroundSpeed
WARM_START_HELI_ALT = meters(500)
WARM_START_ALTITUDE = meters(3000)
@@ -79,12 +77,11 @@ class FlightGroupSpawner:
return self.generate_mid_mission()
def create_idle_aircraft(self) -> FlyingGroup[Any]:
assert isinstance(self.flight.squadron.location, Airfield)
airport = self.flight.squadron.location.dcs_airport
assert airport is not None
group = self._generate_at_airport(
name=namegen.next_aircraft_name(
self.country, self.flight.departure.id, self.flight
),
airport=self.flight.squadron.location.airport,
name=namegen.next_aircraft_name(self.country, self.flight),
airport=airport,
)
group.uncontrolled = True
@@ -95,9 +92,7 @@ class FlightGroupSpawner:
return self.flight.state.spawn_type
def generate_flight_at_departure(self) -> FlyingGroup[Any]:
name = namegen.next_aircraft_name(
self.country, self.flight.departure.id, self.flight
)
name = namegen.next_aircraft_name(self.country, self.flight)
cp = self.flight.departure
try:
if self.start_type is StartType.IN_FLIGHT:
@@ -135,9 +130,7 @@ class FlightGroupSpawner:
def generate_mid_mission(self) -> FlyingGroup[Any]:
assert isinstance(self.flight.state, InFlight)
name = namegen.next_aircraft_name(
self.country, self.flight.departure.id, self.flight
)
name = namegen.next_aircraft_name(self.country, self.flight)
speed = self.flight.state.estimate_speed()
pos = self.flight.state.estimate_position()
pos += Vector2(random.randint(100, 1000), random.randint(100, 1000))

View File

@@ -18,7 +18,6 @@ from game.ato.flightwaypointtype import FlightWaypointType
from game.ato.starttype import StartType
from game.missiongenerator.airsupport import AirSupport
from game.settings import Settings
from game.theater import ControlPointType
from game.utils import pairwise
from .baiingress import BaiIngressBuilder
from .cargostop import CargoStopBuilder
@@ -27,7 +26,6 @@ from .deadingress import DeadIngressBuilder
from .default import DefaultWaypointBuilder
from .holdpoint import HoldPointBuilder
from .joinpoint import JoinPointBuilder
from .splitpoint import SplitPointBuilder
from .landingpoint import LandingPointBuilder
from .ocaaircraftingress import OcaAircraftIngressBuilder
from .ocarunwayingress import OcaRunwayIngressBuilder
@@ -36,6 +34,7 @@ from .racetrack import RaceTrackBuilder
from .racetrackend import RaceTrackEndBuilder
from .refuel import RefuelPointBuilder
from .seadingress import SeadIngressBuilder
from .splitpoint import SplitPointBuilder
from .strikeingress import StrikeIngressBuilder
from .sweepingress import SweepIngressBuilder
@@ -213,14 +212,12 @@ class WaypointGenerator:
def prevent_spawn_at_hostile_airbase(self, trigger: TriggerRule) -> None:
# Prevent delayed flights from spawning at airbases if they were
# captured before they've spawned.
if self.flight.from_cp.cptype != ControlPointType.AIRBASE:
return
trigger.add_condition(
CoalitionHasAirdrome(
self.flight.squadron.coalition.coalition_id, self.flight.from_cp.id
if (airport := self.flight.departure.dcs_airport) is not None:
trigger.add_condition(
CoalitionHasAirdrome(
self.flight.squadron.coalition.coalition_id, airport.id
)
)
)
def set_startup_time(self, delay: timedelta) -> None:
# Uncontrolled causes the AI unit to spawn, but not begin startup.

View File

@@ -227,7 +227,7 @@ class FlotGenerator:
)[0]
self.mission.vehicle_group(
side,
namegen.next_infantry_name(side, cp.id, u),
namegen.next_infantry_name(side, u),
u.dcs_unit_type,
position=infantry_position,
group_size=1,
@@ -252,7 +252,7 @@ class FlotGenerator:
)
self.mission.vehicle_group(
side,
namegen.next_infantry_name(side, cp.id, units[0]),
namegen.next_infantry_name(side, units[0]),
units[0].dcs_unit_type,
position=infantry_position,
group_size=1,
@@ -264,7 +264,7 @@ class FlotGenerator:
position = infantry_position.random_point_within(55, 5)
self.mission.vehicle_group(
side,
namegen.next_infantry_name(side, cp.id, unit),
namegen.next_infantry_name(side, unit),
unit.dcs_unit_type,
position=position,
group_size=1,
@@ -782,7 +782,7 @@ class FlotGenerator:
group = self.mission.vehicle_group(
side,
namegen.next_unit_name(side, cp.id, unit_type),
namegen.next_unit_name(side, unit_type),
unit_type.dcs_unit_type,
position=at,
group_size=count,

View File

@@ -2,22 +2,18 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from dcs.action import MarkToAll, SetFlag, DoScript, ClearFlag
from dcs.action import ClearFlag, DoScript, MarkToAll, SetFlag
from dcs.condition import (
TimeAfter,
AllOfCoalitionOutsideZone,
PartOfCoalitionInZone,
FlagIsFalse,
FlagIsTrue,
PartOfCoalitionInZone,
TimeAfter,
)
from dcs.mission import Mission
from dcs.task import Option
from dcs.translation import String
from dcs.triggers import (
Event,
TriggerOnce,
TriggerCondition,
)
from dcs.triggers import Event, TriggerCondition, TriggerOnce
from dcs.unit import Skill
from game.theater import Airfield
@@ -61,9 +57,12 @@ class TriggerGenerator:
"""
# Empty neutrals airports
cp_ids = [cp.id for cp in self.game.theater.controlpoints]
airfields = [
cp for cp in self.game.theater.controlpoints if isinstance(cp, Airfield)
]
airport_ids = {cp.airport.id for cp in airfields}
for airport in self.mission.terrain.airport_list():
if airport.id not in cp_ids:
if airport.id not in airport_ids:
airport.unlimited_fuel = False
airport.unlimited_munitions = False
airport.unlimited_aircrafts = False
@@ -76,21 +75,20 @@ class TriggerGenerator:
airport.operating_level_fuel = 0
for airport in self.mission.terrain.airport_list():
if airport.id not in cp_ids:
if airport.id not in airport_ids:
airport.unlimited_fuel = True
airport.unlimited_munitions = True
airport.unlimited_aircrafts = True
for cp in self.game.theater.controlpoints:
if isinstance(cp, Airfield):
cp_airport = self.mission.terrain.airport_by_id(cp.airport.id)
if cp_airport is None:
raise RuntimeError(
f"Could not find {cp.airport.name} in the mission"
)
cp_airport.set_coalition(
cp.captured and player_coalition or enemy_coalition
for airfield in airfields:
cp_airport = self.mission.terrain.airport_by_id(airfield.airport.id)
if cp_airport is None:
raise RuntimeError(
f"Could not find {airfield.airport.name} in the mission"
)
cp_airport.set_coalition(
airfield.captured and player_coalition or enemy_coalition
)
def _set_skill(self, player_coalition: str, enemy_coalition: str) -> None:
"""