mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Fix save issues after aborting mission.
When the mission is aborted the pending mission is still in the event list, which is part of the game option. That event has a reference to the operation, which in turn contains all the mission generator objects. Two of these objects are the radio/TACAN allocators, which use a generator to track the next free channel. Generators cannot be picked, so because these are transitively part of the game object the game cannot be saved. Aside from the briefing generator, none of those objects are actually needed outside the generation function itself, so just make them locals instead. This probably needs a larger refactor at some point. It doesn't look like we need so many calls into the operation type (it has an initialize, a prepare, and a generate, and it doesn't seem to need anything but the last one). The only reason breifinggen needs to remain a part of the class is because the briefing title and description are filled in from the derived class, where title and description should probably be overridden properties instead. I'm also not sure if we need to make the event list a part of game at all, and also don't think that the mission needs to be one of these events.
This commit is contained in:
parent
e27625556c
commit
f040804d02
@ -68,26 +68,8 @@ class Operation:
|
|||||||
def initialize(self, mission: Mission, conflict: Conflict):
|
def initialize(self, mission: Mission, conflict: Conflict):
|
||||||
self.current_mission = mission
|
self.current_mission = mission
|
||||||
self.conflict = conflict
|
self.conflict = conflict
|
||||||
self.radio_registry = RadioRegistry()
|
self.briefinggen = BriefingGenerator(self.current_mission,
|
||||||
self.tacan_registry = TacanRegistry()
|
self.conflict, self.game)
|
||||||
self.airgen = AircraftConflictGenerator(
|
|
||||||
mission, conflict, self.game.settings, self.game,
|
|
||||||
self.radio_registry)
|
|
||||||
self.airsupportgen = AirSupportConflictGenerator(
|
|
||||||
mission, conflict, self.game, self.radio_registry,
|
|
||||||
self.tacan_registry)
|
|
||||||
self.triggersgen = TriggersGenerator(mission, conflict, self.game)
|
|
||||||
self.visualgen = VisualGenerator(mission, conflict, self.game)
|
|
||||||
self.envgen = EnviromentGenerator(mission, conflict, self.game)
|
|
||||||
self.forcedoptionsgen = ForcedOptionsGenerator(mission, conflict, self.game)
|
|
||||||
self.groundobjectgen = GroundObjectsGenerator(
|
|
||||||
mission,
|
|
||||||
conflict,
|
|
||||||
self.game,
|
|
||||||
self.radio_registry,
|
|
||||||
self.tacan_registry
|
|
||||||
)
|
|
||||||
self.briefinggen = BriefingGenerator(mission, conflict, self.game)
|
|
||||||
|
|
||||||
def prepare(self, terrain: Terrain, is_quick: bool):
|
def prepare(self, terrain: Terrain, is_quick: bool):
|
||||||
with open("resources/default_options.lua", "r") as f:
|
with open("resources/default_options.lua", "r") as f:
|
||||||
@ -127,6 +109,9 @@ class Operation:
|
|||||||
self.defenders_starting_position = self.to_cp.at
|
self.defenders_starting_position = self.to_cp.at
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
|
radio_registry = RadioRegistry()
|
||||||
|
tacan_registry = TacanRegistry()
|
||||||
|
|
||||||
# Dedup beacon/radio frequencies, since some maps have some frequencies
|
# Dedup beacon/radio frequencies, since some maps have some frequencies
|
||||||
# used multiple times.
|
# used multiple times.
|
||||||
beacons = load_beacons_for_terrain(self.game.theater.terrain.name)
|
beacons = load_beacons_for_terrain(self.game.theater.terrain.name)
|
||||||
@ -138,7 +123,7 @@ class Operation:
|
|||||||
logging.error(
|
logging.error(
|
||||||
f"TACAN beacon has no channel: {beacon.callsign}")
|
f"TACAN beacon has no channel: {beacon.callsign}")
|
||||||
else:
|
else:
|
||||||
self.tacan_registry.reserve(beacon.tacan_channel)
|
tacan_registry.reserve(beacon.tacan_channel)
|
||||||
|
|
||||||
for airfield, data in AIRFIELD_DATA.items():
|
for airfield, data in AIRFIELD_DATA.items():
|
||||||
if data.theater == self.game.theater.terrain.name:
|
if data.theater == self.game.theater.terrain.name:
|
||||||
@ -150,16 +135,26 @@ class Operation:
|
|||||||
# beacon list.
|
# beacon list.
|
||||||
|
|
||||||
for frequency in unique_map_frequencies:
|
for frequency in unique_map_frequencies:
|
||||||
self.radio_registry.reserve(frequency)
|
radio_registry.reserve(frequency)
|
||||||
|
|
||||||
# Generate meteo
|
# Generate meteo
|
||||||
|
envgen = EnviromentGenerator(self.current_mission, self.conflict,
|
||||||
|
self.game)
|
||||||
if self.environment_settings is None:
|
if self.environment_settings is None:
|
||||||
self.environment_settings = self.envgen.generate()
|
self.environment_settings = envgen.generate()
|
||||||
else:
|
else:
|
||||||
self.envgen.load(self.environment_settings)
|
envgen.load(self.environment_settings)
|
||||||
|
|
||||||
# Generate ground object first
|
# Generate ground object first
|
||||||
self.groundobjectgen.generate()
|
|
||||||
|
groundobjectgen = GroundObjectsGenerator(
|
||||||
|
self.current_mission,
|
||||||
|
self.conflict,
|
||||||
|
self.game,
|
||||||
|
radio_registry,
|
||||||
|
tacan_registry
|
||||||
|
)
|
||||||
|
groundobjectgen.generate()
|
||||||
|
|
||||||
# Generate destroyed units
|
# Generate destroyed units
|
||||||
for d in self.game.get_destroyed_units():
|
for d in self.game.get_destroyed_units():
|
||||||
@ -180,11 +175,16 @@ class Operation:
|
|||||||
dead=True,
|
dead=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Air Support (Tanker & Awacs)
|
# Air Support (Tanker & Awacs)
|
||||||
self.airsupportgen.generate(self.is_awacs_enabled)
|
airsupportgen = AirSupportConflictGenerator(
|
||||||
|
self.current_mission, self.conflict, self.game, radio_registry,
|
||||||
|
tacan_registry)
|
||||||
|
airsupportgen.generate(self.is_awacs_enabled)
|
||||||
|
|
||||||
# Generate Activity on the map
|
# Generate Activity on the map
|
||||||
|
airgen = AircraftConflictGenerator(
|
||||||
|
self.current_mission, self.conflict, self.game.settings, self.game,
|
||||||
|
radio_registry)
|
||||||
for cp in self.game.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
side = cp.captured
|
side = cp.captured
|
||||||
if side:
|
if side:
|
||||||
@ -192,11 +192,11 @@ class Operation:
|
|||||||
else:
|
else:
|
||||||
country = self.current_mission.country(self.game.enemy_country)
|
country = self.current_mission.country(self.game.enemy_country)
|
||||||
if cp.id in self.game.planners.keys():
|
if cp.id in self.game.planners.keys():
|
||||||
self.airgen.generate_flights(
|
airgen.generate_flights(
|
||||||
cp,
|
cp,
|
||||||
country,
|
country,
|
||||||
self.game.planners[cp.id],
|
self.game.planners[cp.id],
|
||||||
self.groundobjectgen.runways
|
groundobjectgen.runways
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generate ground units on frontline everywhere
|
# Generate ground units on frontline everywhere
|
||||||
@ -221,18 +221,20 @@ class Operation:
|
|||||||
self.current_mission.groundControl.red_tactical_commander = self.ca_slots
|
self.current_mission.groundControl.red_tactical_commander = self.ca_slots
|
||||||
|
|
||||||
# Triggers
|
# Triggers
|
||||||
if self.game.is_player_attack(self.conflict.attackers_country):
|
triggersgen = TriggersGenerator(self.current_mission, self.conflict,
|
||||||
cp = self.conflict.from_cp
|
self.game)
|
||||||
else:
|
triggersgen.generate()
|
||||||
cp = self.conflict.to_cp
|
|
||||||
self.triggersgen.generate()
|
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
self.forcedoptionsgen.generate()
|
forcedoptionsgen = ForcedOptionsGenerator(self.current_mission,
|
||||||
|
self.conflict, self.game)
|
||||||
|
forcedoptionsgen.generate()
|
||||||
|
|
||||||
# Generate Visuals Smoke Effects
|
# Generate Visuals Smoke Effects
|
||||||
|
visualgen = VisualGenerator(self.current_mission, self.conflict,
|
||||||
|
self.game)
|
||||||
if self.game.settings.perf_smoke_gen:
|
if self.game.settings.perf_smoke_gen:
|
||||||
self.visualgen.generate()
|
visualgen.generate()
|
||||||
|
|
||||||
# Inject Plugins Lua Scripts
|
# Inject Plugins Lua Scripts
|
||||||
listOfPluginsScripts = []
|
listOfPluginsScripts = []
|
||||||
@ -327,19 +329,20 @@ class Operation:
|
|||||||
trigger.add_action(DoScript(String(lua)))
|
trigger.add_action(DoScript(String(lua)))
|
||||||
self.current_mission.triggerrules.triggers.append(trigger)
|
self.current_mission.triggerrules.triggers.append(trigger)
|
||||||
|
|
||||||
self.assign_channels_to_flights()
|
self.assign_channels_to_flights(airgen.flights,
|
||||||
|
airsupportgen.air_support)
|
||||||
|
|
||||||
kneeboard_generator = KneeboardGenerator(self.current_mission)
|
kneeboard_generator = KneeboardGenerator(self.current_mission)
|
||||||
|
|
||||||
for dynamic_runway in self.groundobjectgen.runways.values():
|
for dynamic_runway in groundobjectgen.runways.values():
|
||||||
self.briefinggen.add_dynamic_runway(dynamic_runway)
|
self.briefinggen.add_dynamic_runway(dynamic_runway)
|
||||||
|
|
||||||
for tanker in self.airsupportgen.air_support.tankers:
|
for tanker in airsupportgen.air_support.tankers:
|
||||||
self.briefinggen.add_tanker(tanker)
|
self.briefinggen.add_tanker(tanker)
|
||||||
kneeboard_generator.add_tanker(tanker)
|
kneeboard_generator.add_tanker(tanker)
|
||||||
|
|
||||||
if self.is_awacs_enabled:
|
if self.is_awacs_enabled:
|
||||||
for awacs in self.airsupportgen.air_support.awacs:
|
for awacs in airsupportgen.air_support.awacs:
|
||||||
self.briefinggen.add_awacs(awacs)
|
self.briefinggen.add_awacs(awacs)
|
||||||
kneeboard_generator.add_awacs(awacs)
|
kneeboard_generator.add_awacs(awacs)
|
||||||
|
|
||||||
@ -347,21 +350,23 @@ class Operation:
|
|||||||
self.briefinggen.add_jtac(jtac)
|
self.briefinggen.add_jtac(jtac)
|
||||||
kneeboard_generator.add_jtac(jtac)
|
kneeboard_generator.add_jtac(jtac)
|
||||||
|
|
||||||
for flight in self.airgen.flights:
|
for flight in airgen.flights:
|
||||||
self.briefinggen.add_flight(flight)
|
self.briefinggen.add_flight(flight)
|
||||||
kneeboard_generator.add_flight(flight)
|
kneeboard_generator.add_flight(flight)
|
||||||
|
|
||||||
self.briefinggen.generate()
|
self.briefinggen.generate()
|
||||||
kneeboard_generator.generate()
|
kneeboard_generator.generate()
|
||||||
|
|
||||||
def assign_channels_to_flights(self) -> None:
|
def assign_channels_to_flights(self, flights: List[FlightData],
|
||||||
|
air_support: AirSupport) -> None:
|
||||||
"""Assigns preset radio channels for client flights."""
|
"""Assigns preset radio channels for client flights."""
|
||||||
for flight in self.airgen.flights:
|
for flight in flights:
|
||||||
if not flight.client_units:
|
if not flight.client_units:
|
||||||
continue
|
continue
|
||||||
self.assign_channels_to_flight(flight)
|
self.assign_channels_to_flight(flight, air_support)
|
||||||
|
|
||||||
def assign_channels_to_flight(self, flight: FlightData) -> None:
|
def assign_channels_to_flight(self, flight: FlightData,
|
||||||
|
air_support: AirSupport) -> None:
|
||||||
"""Assigns preset radio channels for a client flight."""
|
"""Assigns preset radio channels for a client flight."""
|
||||||
airframe = flight.aircraft_type
|
airframe = flight.aircraft_type
|
||||||
|
|
||||||
@ -372,4 +377,5 @@ class Operation:
|
|||||||
return
|
return
|
||||||
|
|
||||||
aircraft_data.channel_allocator.assign_channels_for_flight(
|
aircraft_data.channel_allocator.assign_channels_for_flight(
|
||||||
flight, self.airsupportgen.air_support)
|
flight, air_support
|
||||||
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user