From de0802a3c2293b79da6c8fceb5d57e9975c11db9 Mon Sep 17 00:00:00 2001 From: MetalStormGhost Date: Wed, 22 Nov 2023 19:46:44 +0200 Subject: [PATCH] Implemented new options in settings: - Pretense: Extra friendly zone connections - Add connections from each zone to this many closest friendly zones, which don't have an existing supply route defined in the campaign. - Number of cargo planes per side - Number of AI SEAD flights per control point / zone - Number of AI CAS flights per control point / zone - Number of AI BAI flights per control point / zone - Number of AI Strike flights per control point / zone - Number of AI BARCAP flights per control point / zone - Number of AI aircraft per flight - Number of player flights per aircraft type at each base - Number of AI cargo planes per side Implemented CAS helo mission handling for Pretense. Implemented separate pretense_air_groups container for storing/referencing Flight objects. Tweaked the supply costs of SAM sites and Command centers. Will no longer generate player air starts at roadbases either. Restored the missing DEAD flights to Pretense. Removed spawning of frontline units and moved the JTAC spawning to pretensemissiongenerator.py --- game/game.py | 2 + game/missiongenerator/tgogenerator.py | 315 ++++++++++-------- game/pretense/pretenseaircraftgenerator.py | 112 ++++--- game/pretense/pretenseflightgroupspawner.py | 14 +- game/pretense/pretenseluagenerator.py | 64 ++-- game/pretense/pretensemissiongenerator.py | 81 +++-- game/settings/settings.py | 93 +++++- resources/plugins/pretense/init_header.lua | 30 +- .../plugins/pretense/pretense_compiled.lua | 89 +---- 9 files changed, 461 insertions(+), 339 deletions(-) diff --git a/game/game.py b/game/game.py index 47f8cfc4..3f71939d 100644 --- a/game/game.py +++ b/game/game.py @@ -22,6 +22,7 @@ from game.models.game_stats import GameStats from game.plugins import LuaPluginManager from game.utils import Distance from . import naming, persistency +from .ato import Flight from .ato.flighttype import FlightType from .campaignloader import CampaignAirWingConfig from .coalition import Coalition @@ -155,6 +156,7 @@ class Game: 1: {}, 2: {}, } + self.pretense_air_groups: dict[str, Flight] = {} self.on_load(game_still_initializing=True) diff --git a/game/missiongenerator/tgogenerator.py b/game/missiongenerator/tgogenerator.py index a01f33e1..ed83823e 100644 --- a/game/missiongenerator/tgogenerator.py +++ b/game/missiongenerator/tgogenerator.py @@ -290,11 +290,9 @@ class GroundObjectGenerator: # All alive Ships ship_units.append(unit) if vehicle_units: - vg = self.create_vehicle_group(group.group_name, vehicle_units) - vg.hidden_on_mfd = self.ground_object.hide_on_mfd + self.create_vehicle_group(group.group_name, vehicle_units) if ship_units: - sg = self.create_ship_group(group.group_name, ship_units) - sg.hidden_on_mfd = self.ground_object.hide_on_mfd + self.create_ship_group(group.group_name, ship_units) def create_vehicle_group( self, group_name: str, units: list[TheaterUnit] @@ -827,30 +825,45 @@ class HelipadGenerator: else: self.helipads.append(sg) - # Generate a FARP Ammo and Fuel stack for each pad - self.m.static_group( - country=country, - name=(name + "_fuel"), - _type=Fortification.FARP_Fuel_Depot, - position=pad.position.point_from_heading(helipad.heading.degrees, 35), - heading=pad.heading + 180, - ) - self.m.static_group( - country=country, - name=(name + "_ammo"), - _type=Fortification.FARP_Ammo_Dump_Coating, - position=pad.position.point_from_heading( - helipad.heading.degrees, 35 - ).point_from_heading(helipad.heading.degrees + 90, 10), - heading=pad.heading + 90, - ) - self.m.static_group( - country=country, - name=(name + "_ws"), - _type=Fortification.Windsock, - position=helipad.point_from_heading(helipad.heading.degrees + 45, 35), - heading=pad.heading, - ) + if self.game.position_culled(helipad): + cull_farp_statics = True + if self.cp.coalition.player: + for package in self.cp.coalition.ato.packages: + for flight in package.flights: + if flight.squadron.location == self.cp: + cull_farp_statics = False + break + elif flight.divert and flight.divert == self.cp: + cull_farp_statics = False + break + else: + cull_farp_statics = False + + if not cull_farp_statics: + # Generate a FARP Ammo and Fuel stack for each pad + self.m.static_group( + country=country, + name=(name + "_fuel"), + _type=Fortification.FARP_Fuel_Depot, + position=pad.position.point_from_heading(helipad.heading.degrees, 35), + heading=pad.heading + 180, + ) + self.m.static_group( + country=country, + name=(name + "_ammo"), + _type=Fortification.FARP_Ammo_Dump_Coating, + position=pad.position.point_from_heading( + helipad.heading.degrees, 35 + ).point_from_heading(helipad.heading.degrees + 90, 10), + heading=pad.heading + 90, + ) + self.m.static_group( + country=country, + name=(name + "_ws"), + _type=Fortification.Windsock, + position=helipad.point_from_heading(helipad.heading.degrees + 45, 35), + heading=pad.heading, + ) def append_helipad( self, @@ -927,61 +940,76 @@ class GroundSpawnRoadbaseGenerator: country.id ) - # Generate ammo truck/farp and fuel truck/stack for each pad - if self.game.settings.ground_start_trucks_roadbase: - self.m.vehicle_group( - country=country, - name=(name + "_fuel"), - _type=tanker_type, - position=pad.position.point_from_heading( - ground_spawn[0].heading.degrees + 90, 35 - ), - group_size=1, - heading=pad.heading + 315, - move_formation=PointAction.OffRoad, - ) - self.m.vehicle_group( - country=country, - name=(name + "_ammo"), - _type=ammo_truck_type, - position=pad.position.point_from_heading( - ground_spawn[0].heading.degrees + 90, 35 - ).point_from_heading(ground_spawn[0].heading.degrees + 180, 10), - group_size=1, - heading=pad.heading + 315, - move_formation=PointAction.OffRoad, - ) + if self.game.position_culled(ground_spawn[0]): + cull_farp_statics = True + if self.cp.coalition.player: + for package in self.cp.coalition.ato.packages: + for flight in package.flights: + if flight.squadron.location == self.cp: + cull_farp_statics = False + break + elif flight.divert and flight.divert == self.cp: + cull_farp_statics = False + break else: - self.m.static_group( - country=country, - name=(name + "_fuel"), - _type=Fortification.FARP_Fuel_Depot, - position=pad.position.point_from_heading( - ground_spawn[0].heading.degrees + 90, 35 - ), - heading=pad.heading + 270, - ) - self.m.static_group( - country=country, - name=(name + "_ammo"), - _type=Fortification.FARP_Ammo_Dump_Coating, - position=pad.position.point_from_heading( - ground_spawn[0].heading.degrees + 90, 35 - ).point_from_heading(ground_spawn[0].heading.degrees + 180, 10), - heading=pad.heading + 180, - ) - if self.game.settings.ground_start_ground_power_trucks_roadbase: - self.m.vehicle_group( - country=country, - name=(name + "_power"), - _type=power_truck_type, - position=pad.position.point_from_heading( - ground_spawn[0].heading.degrees + 90, 35 - ).point_from_heading(ground_spawn[0].heading.degrees + 180, 20), - group_size=1, - heading=pad.heading + 315, - move_formation=PointAction.OffRoad, - ) + cull_farp_statics = False + + if not cull_farp_statics: + # Generate ammo truck/farp and fuel truck/stack for each pad + if self.game.settings.ground_start_trucks_roadbase: + self.m.vehicle_group( + country=country, + name=(name + "_fuel"), + _type=tanker_type, + position=pad.position.point_from_heading( + ground_spawn[0].heading.degrees + 90, 35 + ), + group_size=1, + heading=pad.heading + 315, + move_formation=PointAction.OffRoad, + ) + self.m.vehicle_group( + country=country, + name=(name + "_ammo"), + _type=ammo_truck_type, + position=pad.position.point_from_heading( + ground_spawn[0].heading.degrees + 90, 35 + ).point_from_heading(ground_spawn[0].heading.degrees + 180, 10), + group_size=1, + heading=pad.heading + 315, + move_formation=PointAction.OffRoad, + ) + else: + self.m.static_group( + country=country, + name=(name + "_fuel"), + _type=Fortification.FARP_Fuel_Depot, + position=pad.position.point_from_heading( + ground_spawn[0].heading.degrees + 90, 35 + ), + heading=pad.heading + 270, + ) + self.m.static_group( + country=country, + name=(name + "_ammo"), + _type=Fortification.FARP_Ammo_Dump_Coating, + position=pad.position.point_from_heading( + ground_spawn[0].heading.degrees + 90, 35 + ).point_from_heading(ground_spawn[0].heading.degrees + 180, 10), + heading=pad.heading + 180, + ) + if self.game.settings.ground_start_ground_power_trucks_roadbase: + self.m.vehicle_group( + country=country, + name=(name + "_power"), + _type=power_truck_type, + position=pad.position.point_from_heading( + ground_spawn[0].heading.degrees + 90, 35 + ).point_from_heading(ground_spawn[0].heading.degrees + 180, 20), + group_size=1, + heading=pad.heading + 315, + move_formation=PointAction.OffRoad, + ) def generate(self) -> None: try: @@ -1044,61 +1072,76 @@ class GroundSpawnGenerator: country.id ) - # Generate a FARP Ammo and Fuel stack for each pad - if self.game.settings.ground_start_trucks: - self.m.vehicle_group( - country=country, - name=(name + "_fuel"), - _type=tanker_type, - position=pad.position.point_from_heading( - vtol_pad[0].heading.degrees - 175, 35 - ), - group_size=1, - heading=pad.heading + 45, - move_formation=PointAction.OffRoad, - ) - self.m.vehicle_group( - country=country, - name=(name + "_ammo"), - _type=ammo_truck_type, - position=pad.position.point_from_heading( - vtol_pad[0].heading.degrees - 185, 35 - ), - group_size=1, - heading=pad.heading + 45, - move_formation=PointAction.OffRoad, - ) + if self.game.position_culled(vtol_pad[0]): + cull_farp_statics = True + if self.cp.coalition.player: + for package in self.cp.coalition.ato.packages: + for flight in package.flights: + if flight.squadron.location == self.cp: + cull_farp_statics = False + break + elif flight.divert and flight.divert == self.cp: + cull_farp_statics = False + break else: - self.m.static_group( - country=country, - name=(name + "_fuel"), - _type=Fortification.FARP_Fuel_Depot, - position=pad.position.point_from_heading( - vtol_pad[0].heading.degrees - 180, 45 - ), - heading=pad.heading, - ) - self.m.static_group( - country=country, - name=(name + "_ammo"), - _type=Fortification.FARP_Ammo_Dump_Coating, - position=pad.position.point_from_heading( - vtol_pad[0].heading.degrees - 180, 35 - ), - heading=pad.heading + 270, - ) - if self.game.settings.ground_start_ground_power_trucks: - self.m.vehicle_group( - country=country, - name=(name + "_power"), - _type=power_truck_type, - position=pad.position.point_from_heading( - vtol_pad[0].heading.degrees - 185, 35 - ), - group_size=1, - heading=pad.heading + 45, - move_formation=PointAction.OffRoad, - ) + cull_farp_statics = False + + if not cull_farp_statics: + # Generate a FARP Ammo and Fuel stack for each pad + if self.game.settings.ground_start_trucks: + self.m.vehicle_group( + country=country, + name=(name + "_fuel"), + _type=tanker_type, + position=pad.position.point_from_heading( + vtol_pad[0].heading.degrees - 175, 35 + ), + group_size=1, + heading=pad.heading + 45, + move_formation=PointAction.OffRoad, + ) + self.m.vehicle_group( + country=country, + name=(name + "_ammo"), + _type=ammo_truck_type, + position=pad.position.point_from_heading( + vtol_pad[0].heading.degrees - 185, 35 + ), + group_size=1, + heading=pad.heading + 45, + move_formation=PointAction.OffRoad, + ) + else: + self.m.static_group( + country=country, + name=(name + "_fuel"), + _type=Fortification.FARP_Fuel_Depot, + position=pad.position.point_from_heading( + vtol_pad[0].heading.degrees - 180, 45 + ), + heading=pad.heading, + ) + self.m.static_group( + country=country, + name=(name + "_ammo"), + _type=Fortification.FARP_Ammo_Dump_Coating, + position=pad.position.point_from_heading( + vtol_pad[0].heading.degrees - 180, 35 + ), + heading=pad.heading + 270, + ) + if self.game.settings.ground_start_ground_power_trucks: + self.m.vehicle_group( + country=country, + name=(name + "_power"), + _type=power_truck_type, + position=pad.position.point_from_heading( + vtol_pad[0].heading.degrees - 185, 35 + ), + group_size=1, + heading=pad.heading + 45, + move_formation=PointAction.OffRoad, + ) def generate(self) -> None: try: diff --git a/game/pretense/pretenseaircraftgenerator.py b/game/pretense/pretenseaircraftgenerator.py index 1bfe7b8b..6b0a316c 100644 --- a/game/pretense/pretenseaircraftgenerator.py +++ b/game/pretense/pretenseaircraftgenerator.py @@ -49,17 +49,9 @@ if TYPE_CHECKING: PRETENSE_SQUADRON_DEF_RETRIES = 100 -PRETENSE_SEAD_FLIGHTS_PER_CP = 2 -PRETENSE_CAS_FLIGHTS_PER_CP = 2 -PRETENSE_BAI_FLIGHTS_PER_CP = 2 -PRETENSE_STRIKE_FLIGHTS_PER_CP = 2 -PRETENSE_BARCAP_FLIGHTS_PER_CP = 2 -PRETENSE_AI_AIRCRAFT_PER_FLIGHT = 2 PRETENSE_AI_AWACS_PER_FLIGHT = 1 PRETENSE_AI_TANKERS_PER_FLIGHT = 1 -PRETENSE_AI_CARGO_PLANES_PER_SIDE = 2 PRETENSE_PLAYER_AIRCRAFT_PER_FLIGHT = 1 -PRETENSE_PLAYER_FLIGHTS_PER_TYPE = 2 class PretenseAircraftGenerator: @@ -300,8 +292,12 @@ class PretenseAircraftGenerator: if cp.coalition != squadron.coalition: continue - squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT - squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT + squadron.owned_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + squadron.untasked_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) squadron.populate_for_turn_0(False) package = Package(cp, squadron.flight_db, auto_asap=False) mission_types = squadron.auto_assignable_mission_types @@ -320,46 +316,46 @@ class PretenseAircraftGenerator: FlightType.SEAD in mission_types or FlightType.SEAD_SWEEP in mission_types or FlightType.SEAD_ESCORT in mission_types - ) and num_of_sead < PRETENSE_SEAD_FLIGHTS_PER_CP: + ) and num_of_sead < self.game.settings.pretense_sead_flights_per_cp: flight_type = FlightType.SEAD num_of_sead += 1 - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight elif ( FlightType.DEAD in mission_types - and num_of_sead < PRETENSE_SEAD_FLIGHTS_PER_CP + and num_of_sead < self.game.settings.pretense_sead_flights_per_cp ): flight_type = FlightType.DEAD num_of_sead += 1 - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight elif ( FlightType.CAS in mission_types - ) and num_of_cas < PRETENSE_CAS_FLIGHTS_PER_CP: + ) and num_of_cas < self.game.settings.pretense_cas_flights_per_cp: flight_type = FlightType.CAS num_of_cas += 1 - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight elif ( FlightType.BAI in mission_types - ) and num_of_bai < PRETENSE_BAI_FLIGHTS_PER_CP: + ) and num_of_bai < self.game.settings.pretense_bai_flights_per_cp: flight_type = FlightType.BAI num_of_bai += 1 - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight elif ( FlightType.STRIKE in mission_types or FlightType.OCA_RUNWAY in mission_types or FlightType.OCA_AIRCRAFT in mission_types - ) and num_of_strike < PRETENSE_STRIKE_FLIGHTS_PER_CP: + ) and num_of_strike < self.game.settings.pretense_strike_flights_per_cp: flight_type = FlightType.STRIKE num_of_strike += 1 - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight elif ( FlightType.BARCAP in mission_types or FlightType.TARCAP in mission_types or FlightType.ESCORT in mission_types or FlightType.INTERCEPTION in mission_types - ) and num_of_cap < PRETENSE_BARCAP_FLIGHTS_PER_CP: + ) and num_of_cap < self.game.settings.pretense_barcap_flights_per_cp: flight_type = FlightType.BARCAP num_of_cap += 1 - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight elif FlightType.AEWC in mission_types: flight_type = FlightType.AEWC aircraft_per_flight = PRETENSE_AI_AWACS_PER_FLIGHT @@ -429,8 +425,12 @@ class PretenseAircraftGenerator: PRETENSE_SQUADRON_DEF_RETRIES, ) if squadron is not None: - squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT - squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT + squadron.owned_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + squadron.untasked_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) squadron.populate_for_turn_0(False) package = Package(cp, squadron.flight_db, auto_asap=False) flight = Flight( @@ -453,7 +453,7 @@ class PretenseAircraftGenerator: if isinstance(cp, Airfield): # Generate SEAD flight flight_type = FlightType.SEAD - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight squadron = self.generate_pretense_squadron( cp, coalition, @@ -470,8 +470,12 @@ class PretenseAircraftGenerator: PRETENSE_SQUADRON_DEF_RETRIES, ) if squadron is not None: - squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT - squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT + squadron.owned_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + squadron.untasked_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) squadron.populate_for_turn_0(False) package = Package(cp, squadron.flight_db, auto_asap=False) flight = Flight( @@ -494,7 +498,7 @@ class PretenseAircraftGenerator: # Generate CAS flight flight_type = FlightType.CAS - aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT + aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight squadron = self.generate_pretense_squadron( cp, coalition, @@ -511,8 +515,12 @@ class PretenseAircraftGenerator: PRETENSE_SQUADRON_DEF_RETRIES, ) if squadron is not None: - squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT - squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT + squadron.owned_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + squadron.untasked_aircraft += ( + self.game.settings.pretense_ai_aircraft_per_flight + ) squadron.populate_for_turn_0(False) package = Package(cp, squadron.flight_db, auto_asap=False) flight = Flight( @@ -561,7 +569,7 @@ class PretenseAircraftGenerator: if not cp.can_operate(aircraft_type): continue - for i in range(PRETENSE_PLAYER_FLIGHTS_PER_TYPE): + for i in range(self.game.settings.pretense_player_flights_per_type): squadron = self.generate_pretense_squadron_for( aircraft_type, cp, @@ -607,7 +615,7 @@ class PretenseAircraftGenerator: cp: Control point to generate aircraft for. flight: The current flight being generated. """ - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) for side in range(1, 3): if cp_name_trimmed not in cp.coalition.game.pretense_air[side]: @@ -627,7 +635,7 @@ class PretenseAircraftGenerator: flight: The current flight being generated. """ flight_type = flight.flight_type - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) for side in range(1, 3): if cp_name_trimmed not in flight.coalition.game.pretense_air[side]: @@ -675,7 +683,7 @@ class PretenseAircraftGenerator: PRETENSE_SQUADRON_DEF_RETRIES, ) num_of_cargo_sq_to_generate = ( - PRETENSE_AI_CARGO_PLANES_PER_SIDE + self.game.settings.pretense_ai_cargo_planes_per_side - self.number_of_pretense_cargo_plane_sq_for(cp.coalition.air_wing) ) for i in range(num_of_cargo_sq_to_generate): @@ -795,7 +803,8 @@ class PretenseAircraftGenerator: if flight.package.target != flight.departure: break for mission_target in cp.ground_objects: - flight.package.target = mission_target + if mission_target.alive_unit_count > 0: + flight.package.target = mission_target break elif ( flight.flight_type == FlightType.OCA_RUNWAY @@ -837,23 +846,30 @@ class PretenseAircraftGenerator: break now = self.game.conditions.start_time - flight.package.set_tot_asap(now) + try: + flight.package.set_tot_asap(now) + except: + raise RuntimeError( + f"Pretense flight group {group.name} {flight.squadron.aircraft} {flight.flight_type} for target {flight.package.target} configuration failed. Please check if your Retribution campaign is compatible with Pretense." + ) logging.info( f"Configuring flight {group.name} {flight.squadron.aircraft} {flight.flight_type}, number of players: {flight.client_count}" ) - PretenseFlightGroupConfigurator( - flight, - group, - self.game, - self.mission, - self.time, - self.radio_registry, - self.tacan_registy, - self.mission_data, - dynamic_runways, - self.use_client, - ).configure() + self.mission_data.flights.append( + PretenseFlightGroupConfigurator( + flight, + group, + self.game, + self.mission, + self.time, + self.radio_registry, + self.tacan_registy, + self.mission_data, + dynamic_runways, + self.use_client, + ).configure() + ) if self.ewrj: self._track_ewrj_flight(flight, group) diff --git a/game/pretense/pretenseflightgroupspawner.py b/game/pretense/pretenseflightgroupspawner.py index cdb10a23..dad732c8 100644 --- a/game/pretense/pretenseflightgroupspawner.py +++ b/game/pretense/pretenseflightgroupspawner.py @@ -30,7 +30,7 @@ class PretenseNameGenerator(NameGenerator): @classmethod def next_pretense_aircraft_name(cls, cp: ControlPoint, flight: Flight) -> str: cls.aircraft_number += 1 - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) return "{}-{}-{}".format( cp_name_trimmed, str(flight.flight_type).lower(), cls.aircraft_number ) @@ -77,12 +77,17 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner): == self.flight.coalition.game.coalition_for(is_player) else 1 ) - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) if self.flight.client_count == 0: self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][ self.flight.flight_type ].append(name) + try: + self.flight.coalition.game.pretense_air_groups[name] = self.flight + except AttributeError: + self.flight.coalition.game.pretense_air_groups = {} + self.flight.coalition.game.pretense_air_groups[name] = self.flight def generate_flight_at_departure(self) -> FlyingGroup[Any]: cp = self.flight.departure @@ -94,7 +99,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner): == self.flight.coalition.game.coalition_for(is_player) else 1 ) - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) try: if self.start_type is StartType.IN_FLIGHT: @@ -139,8 +144,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner): pad_group = self._generate_at_cp_ground_spawn(name, cp) if pad_group is not None: return pad_group - self.insert_into_pretense(name) - return self._generate_over_departure(name, cp) + raise NoParkingSlotError elif isinstance(cp, Airfield): is_heli = self.flight.squadron.aircraft.helicopter if cp.has_helipads and is_heli: diff --git a/game/pretense/pretenseluagenerator.py b/game/pretense/pretenseluagenerator.py index 605e257f..2a56ba8c 100644 --- a/game/pretense/pretenseluagenerator.py +++ b/game/pretense/pretenseluagenerator.py @@ -259,7 +259,7 @@ class PretenseLuaGenerator(LuaGenerator): def generate_pretense_land_upgrade_supply(self, cp_name: str, cp_side: int) -> str: lua_string_zones = "" - cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalpha()]) cp_side_str = "blue" if cp_side == PRETENSE_BLUE_SIDE else "red" cp = self.game.theater.controlpoints[0] for loop_cp in self.game.theater.controlpoints: @@ -398,7 +398,7 @@ class PretenseLuaGenerator(LuaGenerator): ) lua_string_zones += " products = {\n" for mission_type in self.game.pretense_air[cp_side][cp_name_trimmed]: - if mission_type == FlightType.SEAD: + if mission_type in (FlightType.SEAD, FlightType.DEAD): mission_name = "attack.sead" for air_group in self.game.pretense_air[cp_side][cp_name_trimmed][ mission_type @@ -414,6 +414,9 @@ class PretenseLuaGenerator(LuaGenerator): for air_group in self.game.pretense_air[cp_side][cp_name_trimmed][ mission_type ]: + flight = self.game.pretense_air_groups[air_group] + if flight.is_helo: + mission_name = "attack.helo" lua_string_zones += ( f" presets.missions.{mission_name}:extend" + "({name='" @@ -503,7 +506,7 @@ class PretenseLuaGenerator(LuaGenerator): def generate_pretense_sea_upgrade_supply(self, cp_name: str, cp_side: int) -> str: lua_string_zones = "" - cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalpha()]) cp_side_str = "blue" if cp_side == PRETENSE_BLUE_SIDE else "red" if cp_side == PRETENSE_BLUE_SIDE: @@ -608,6 +611,9 @@ class PretenseLuaGenerator(LuaGenerator): for air_group in self.game.pretense_air[cp_side][cp_name_trimmed][ mission_type ]: + flight = self.game.pretense_air_groups[air_group] + if flight.is_helo: + mission_name = "attack.helo" lua_string_zones += ( f" presets.missions.{mission_name}:extend" + "({name='" @@ -697,7 +703,7 @@ class PretenseLuaGenerator(LuaGenerator): def generate_pretense_zone_land(self, cp_name: str) -> str: lua_string_zones = "" - cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalpha()]) lua_string_zones += f"zones.{cp_name_trimmed}:defineUpgrades(" + "{\n" lua_string_zones += " [1] = { --red side\n" @@ -771,7 +777,7 @@ class PretenseLuaGenerator(LuaGenerator): def generate_pretense_zone_sea(self, cp_name: str) -> str: lua_string_zones = "" - cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp_name.lower() if i.isalpha()]) lua_string_zones += f"zones.{cp_name_trimmed}:defineUpgrades(" + "{\n" lua_string_zones += " [1] = { --red side\n" @@ -823,29 +829,29 @@ class PretenseLuaGenerator(LuaGenerator): def generate_pretense_plugin_data(self) -> None: self.inject_plugin_script("base", "mist_4_5_107.lua", "mist_4_5_107") - self.inject_plugin_script( - "pretense", "pretense_compiled.lua", "pretense_compiled" - ) - trigger = TriggerStart(comment="Pretense init") - - lua_string_config = "" + lua_string_config = "Config = Config or {}\n" lua_string_config += ( f"Config.maxDistFromFront = " + str(self.game.settings.pretense_maxdistfromfront_distance * 1000) + "\n" ) - lua_string_config += ( - f"Config.closeOverride = " - + str(self.game.settings.pretense_closeoverride_distance * 1000) - + "\n" - ) if self.game.settings.pretense_do_not_generate_sead_missions: lua_string_config += "Config.disablePlayerSead = true\n" else: lua_string_config += "Config.disablePlayerSead = false\n" + trigger = TriggerStart(comment="Pretense config") + trigger.add_action(DoScript(String(lua_string_config))) + self.mission.triggerrules.triggers.append(trigger) + + self.inject_plugin_script( + "pretense", "pretense_compiled.lua", "pretense_compiled" + ) + + trigger = TriggerStart(comment="Pretense init") + init_header_file = open("./resources/plugins/pretense/init_header.lua", "r") init_header = init_header_file.read() @@ -855,7 +861,7 @@ class PretenseLuaGenerator(LuaGenerator): if isinstance(cp, OffMapSpawn): continue - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) cp_side = 2 if cp.captured else 1 for side in range(1, 3): if cp_name_trimmed not in self.game.pretense_air[cp_side]: @@ -947,12 +953,17 @@ class PretenseLuaGenerator(LuaGenerator): else: # Finally, connect remaining non-connected points closest_cps = self.game.theater.closest_friendly_control_points_to(cp) - lua_string_connman += self.generate_pretense_zone_connection( - connected_points, cp.name, closest_cps[0].name - ) - lua_string_connman += self.generate_pretense_zone_connection( - connected_points, cp.name, closest_cps[1].name - ) + for extra_connection in range( + self.game.settings.pretense_extra_zone_connections + ): + if len(closest_cps) > extra_connection: + lua_string_connman += self.generate_pretense_zone_connection( + connected_points, + cp.name, + closest_cps[extra_connection].name, + ) + else: + break lua_string_supply = "local redSupply = {\n" # Generate supply @@ -963,7 +974,7 @@ class PretenseLuaGenerator(LuaGenerator): cp_side_captured = cp_side == 2 if cp_side_captured != cp.captured: continue - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) for mission_type in self.game.pretense_air[cp_side][cp_name_trimmed]: if mission_type == FlightType.PRETENSE_CARGO: for air_group in self.game.pretense_air[cp_side][ @@ -976,7 +987,7 @@ class PretenseLuaGenerator(LuaGenerator): lua_string_supply += "local offmapZones = {\n" for cp in self.game.theater.controlpoints: if isinstance(cp, Airfield): - cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) + cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalpha()]) lua_string_supply += f" zones.{cp_name_trimmed},\n" lua_string_supply += "}\n" @@ -997,8 +1008,7 @@ class PretenseLuaGenerator(LuaGenerator): init_footer = init_footer_file.read() lua_string = ( - lua_string_config - + init_header + init_header + lua_string_zones + lua_string_connman + init_body_1 diff --git a/game/pretense/pretensemissiongenerator.py b/game/pretense/pretensemissiongenerator.py index e67ece34..a6dc8013 100644 --- a/game/pretense/pretensemissiongenerator.py +++ b/game/pretense/pretensemissiongenerator.py @@ -12,6 +12,7 @@ from dcs.countries import ( CombinedJointTaskForcesBlue, CombinedJointTaskForcesRed, ) +from dcs.task import AFAC, FAC, SetInvisibleCommand, SetImmortalCommand, OrbitAction from game.lasercodes.lasercoderegistry import LaserCodeRegistry from game.missiongenerator.convoygenerator import ConvoyGenerator @@ -21,7 +22,7 @@ from game.missiongenerator.forcedoptionsgenerator import ForcedOptionsGenerator from game.missiongenerator.frontlineconflictdescription import ( FrontLineConflictDescription, ) -from game.missiongenerator.missiondata import MissionData +from game.missiongenerator.missiondata import MissionData, JtacInfo from game.missiongenerator.tgogenerator import TgoGenerator from game.missiongenerator.visualsgenerator import VisualsGenerator from game.naming import namegen @@ -34,6 +35,8 @@ from .pretenseluagenerator import PretenseLuaGenerator from .pretensetgogenerator import PretenseTgoGenerator from .pretensetriggergenerator import PretenseTriggerGenerator from ..ato.airtaaskingorder import AirTaskingOrder +from ..callsigns import callsign_for_support_unit +from ..dcs.aircrafttype import AircraftType from ..missiongenerator import MissionGenerator if TYPE_CHECKING: @@ -148,27 +151,61 @@ class PretenseMissionGenerator(MissionGenerator): for front_line in self.game.theater.conflicts(): player_cp = front_line.blue_cp enemy_cp = front_line.red_cp - conflict = FrontLineConflictDescription.frontline_cas_conflict( - front_line, self.game.theater - ) - # Generate frontline ops - player_gp = self.game.ground_planners[player_cp.id].units_per_cp[ - enemy_cp.id - ] - enemy_gp = self.game.ground_planners[enemy_cp.id].units_per_cp[player_cp.id] - ground_conflict_gen = FlotGenerator( - self.mission, - conflict, - self.game, - player_gp, - enemy_gp, - player_cp.stances[enemy_cp.id], - enemy_cp.stances[player_cp.id], - self.unit_map, - self.radio_registry, - self.mission_data, - ) - ground_conflict_gen.generate() + + # Add JTAC + if self.game.blue.faction.has_jtac: + freq = self.radio_registry.alloc_uhf() + # If the option fc3LaserCode is enabled, force all JTAC + # laser codes to 1113 to allow lasing for Su-25 Frogfoots and A-10A Warthogs. + # Otherwise use 1688 for the first JTAC, 1687 for the second etc. + if self.game.settings.plugins.get("ctld.fc3LaserCode"): + code = self.game.laser_code_registry.fc3_code + else: + code = front_line.laser_code + + utype = self.game.blue.faction.jtac_unit + if utype is None: + utype = AircraftType.named("MQ-9 Reaper") + + country = self.mission.country(self.game.blue.faction.country.name) + position = FrontLineConflictDescription.frontline_position( + front_line, self.game.theater, self.game.settings + ) + jtac = self.mission.flight_group( + country=country, + name=namegen.next_jtac_name(), + aircraft_type=utype.dcs_unit_type, + position=position[0], + airport=None, + altitude=5000, + maintask=AFAC, + ) + jtac.points[0].tasks.append( + FAC( + callsign=len(self.mission_data.jtacs) + 1, + frequency=int(freq.mhz), + modulation=freq.modulation, + ) + ) + jtac.points[0].tasks.append(SetInvisibleCommand(True)) + jtac.points[0].tasks.append(SetImmortalCommand(True)) + jtac.points[0].tasks.append( + OrbitAction(5000, 300, OrbitAction.OrbitPattern.Circle) + ) + frontline = f"Frontline {player_cp.name}/{enemy_cp.name}" + # Note: Will need to change if we ever add ground based JTAC. + callsign = callsign_for_support_unit(jtac) + self.mission_data.jtacs.append( + JtacInfo( + group_name=jtac.name, + unit_name=jtac.units[0].name, + callsign=callsign, + region=frontline, + code=str(code), + blue=True, + freq=freq, + ) + ) def generate_air_units(self, tgo_generator: TgoGenerator) -> None: """Generate the air units for the Operation""" diff --git a/game/settings/settings.py b/game/settings/settings.py index 3acc74c8..d7c5348b 100644 --- a/game/settings/settings.py +++ b/game/settings/settings.py @@ -980,21 +980,102 @@ class Settings: default=130, min=10, max=10000, + detail=( + "Zones farther away than this from the front line are switched " + "into low activity state, but will still be there as functional " + "parts of the economy. Use this to adjust performance." + ), ) - pretense_closeoverride_distance: int = bounded_int_option( - "Close override distance (km)", + pretense_extra_zone_connections: int = bounded_int_option( + "Extra friendly zone connections", page=PRETENSE_PAGE, section=GENERAL_SECTION, - default=28, - min=5, - max=10000, + default=2, + min=0, + max=10, + detail=( + "Add connections from each zone to this many closest friendly zones," + "which don't have an existing supply route defined in the campaign." + ), ) pretense_do_not_generate_sead_missions: bool = boolean_option( "Do not generate player SEAD missions", page=PRETENSE_PAGE, - section=PERFORMANCE_SECTION, + section=GENERAL_SECTION, default=False, ) + pretense_num_of_cargo_planes: int = bounded_int_option( + "Number of cargo planes per side", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=100, + ) + pretense_sead_flights_per_cp: int = bounded_int_option( + "Number of AI SEAD flights per control point / zone", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=10, + ) + pretense_cas_flights_per_cp: int = bounded_int_option( + "Number of AI CAS flights per control point / zone", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=10, + ) + pretense_bai_flights_per_cp: int = bounded_int_option( + "Number of AI BAI flights per control point / zone", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=10, + ) + pretense_strike_flights_per_cp: int = bounded_int_option( + "Number of AI Strike flights per control point / zone", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=10, + ) + pretense_barcap_flights_per_cp: int = bounded_int_option( + "Number of AI BARCAP flights per control point / zone", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=10, + ) + pretense_ai_aircraft_per_flight: int = bounded_int_option( + "Number of AI aircraft per flight", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=4, + ) + pretense_player_flights_per_type: int = bounded_int_option( + "Number of player flights per aircraft type at each base", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=10, + ) + pretense_ai_cargo_planes_per_side: int = bounded_int_option( + "Number of AI cargo planes per side", + page=PRETENSE_PAGE, + section=GENERAL_SECTION, + default=2, + min=1, + max=20, + ) # Cheating. Not using auto settings because the same page also has buttons which do # not alter settings. diff --git a/resources/plugins/pretense/init_header.lua b/resources/plugins/pretense/init_header.lua index c73f5444..d7481f31 100644 --- a/resources/plugins/pretense/init_header.lua +++ b/resources/plugins/pretense/init_header.lua @@ -494,7 +494,7 @@ presets = { }), comCenter = Preset:new({ display = 'Command Center', - cost = 2500, + cost = 12500, type = 'upgrade', template = "command-center" }) @@ -522,43 +522,43 @@ presets = { }), sa10 = Preset:new({ display = 'SAM', - cost=3000, + cost=30000, type='defense', template='sa10', }), sa5 = Preset:new({ display = 'SAM', - cost=3000, + cost=20000, type='defense', template='sa5', }), sa3 = Preset:new({ display = 'SAM', - cost=3000, + cost=4000, type='defense', template='sa3', }), sa6 = Preset:new({ display = 'SAM', - cost=3000, + cost=6000, type='defense', template='sa6', }), sa11 = Preset:new({ display = 'SAM', - cost=3000, + cost=10000, type='defense', template='sa11', }), hawk = Preset:new({ display = 'SAM', - cost=3000, + cost=6000, type='defense', template='hawk', }), patriot = Preset:new({ display = 'SAM', - cost=3000, + cost=30000, type='defense', template='patriot', }), @@ -596,43 +596,43 @@ presets = { }), sa10 = Preset:new({ display = 'SAM', - cost=3000, + cost=30000, type='defense', template='sa10', }), sa5 = Preset:new({ display = 'SAM', - cost=3000, + cost=20000, type='defense', template='sa5', }), sa3 = Preset:new({ display = 'SAM', - cost=3000, + cost=4000, type='defense', template='sa3', }), sa6 = Preset:new({ display = 'SAM', - cost=3000, + cost=6000, type='defense', template='sa6', }), sa11 = Preset:new({ display = 'SAM', - cost=3000, + cost=10000, type='defense', template='sa11', }), hawk = Preset:new({ display = 'SAM', - cost=3000, + cost=6000, type='defense', template='hawk', }), patriot = Preset:new({ display = 'SAM', - cost=3000, + cost=30000, type='defense', template='patriot', }), diff --git a/resources/plugins/pretense/pretense_compiled.lua b/resources/plugins/pretense/pretense_compiled.lua index cf8bb881..5dbece1a 100644 --- a/resources/plugins/pretense/pretense_compiled.lua +++ b/resources/plugins/pretense/pretense_compiled.lua @@ -32,7 +32,6 @@ Config.buildSpeed = Config.buildSpeed or 10 -- structure and defense build speed Config.supplyBuildSpeed = Config.supplyBuildSpeed or 85 -- supply helicopters and convoys build speed Config.missionBuildSpeedReduction = Config.missionBuildSpeedReduction or 0.12 -- reduction of build speed in case of ai missions Config.maxDistFromFront = Config.maxDistFromFront or 129640 -- max distance in meters from front after which zone is forced into low activity state (export mode) -Config.closeOverride = Config.closeOverride or 27780 -- close override distance in meters from front within which zone is never forced into low activity state Config.disablePlayerSead = Config.disablePlayerSead or false Config.missions = Config.missions or {} @@ -505,8 +504,6 @@ end GroupMonitor = {} do GroupMonitor.blockedDespawnTime = 10*60 --used to despawn aircraft that are stuck taxiing for some reason - GroupMonitor.blockedDespawnTimeGround = 30*60 --used to despawn ground units that are stuck en route for some reason - GroupMonitor.blockedDespawnTimeGroundAssault = 90*60 --used to despawn assault units that are stuck en route for some reason GroupMonitor.landedDespawnTime = 10 GroupMonitor.atDestinationDespawnTime = 2*60 GroupMonitor.recoveryReduction = 0.8 -- reduce recovered resource from landed missions by this amount to account for maintenance @@ -642,13 +639,7 @@ do group.state = 'enroute' group.lastStateTime = timer.getAbsTime() MissionTargetRegistry.addBaiTarget(group) - elseif group.product.missionType == 'assault' and timer.getAbsTime() - group.lastStateTime > GroupMonitor.blockedDespawnTimeGroundAssault then - env.info('GroupMonitor: processSurface ['..group.name..'] despawned due to blockage') - gr:destroy() - local todeliver = math.floor(group.product.cost) - z:addResource(todeliver) - return true - elseif timer.getAbsTime() - group.lastStateTime > GroupMonitor.blockedDespawnTimeGround then + elseif timer.getAbsTime() - group.lastStateTime > GroupMonitor.blockedDespawnTime then env.info('GroupMonitor: processSurface ['..group.name..'] despawned due to blockage') gr:destroy() local todeliver = math.floor(group.product.cost) @@ -744,7 +735,7 @@ do y = group.target.zone.point.z } - TaskExtensions.moveOffRoadToPointAndAssault(gr, tp, group.target.built) + TaskExtensions.moveOnRoadToPointAndAssault(gr, tp, group.target.built) group.isstopped = false end end @@ -1231,7 +1222,7 @@ do if v.type == 'defense' and v.side ~= group:getCoalition() then local gr = Group.getByName(v.name) for _,unit in ipairs(gr:getUnits()) do - if unit:hasAttribute('SAM SR') or unit:hasAttribute('SAM TR') or unit:hasAttribute('AAA') or unit:hasAttribute('IR Guided SAM') or unit:hasAttribute('SAM LL') then + if unit:hasAttribute('SAM SR') or unit:hasAttribute('SAM TR') then table.insert(viable, unit:getName()) end end @@ -1245,7 +1236,7 @@ do { id = 'EngageTargets', params = { - targetTypes = {'SAM SR', 'SAM TR', 'AAA', 'IR Guided SAM', 'SAM LL'} + targetTypes = {'SAM SR', 'SAM TR'} } } } @@ -2145,68 +2136,7 @@ do } group:getController():setTask(mis) end - - function TaskExtensions.moveOffRoadToPointAndAssault(group, point, targets) - if not group or not point then return end - if not group:isExist() or group:getSize()==0 then return end - local startPos = group:getUnit(1):getPoint() - - local srx, sry = land.getClosestPointOnRoads('roads', startPos.x, startPos.z) - local erx, ery = land.getClosestPointOnRoads('roads', point.x, point.y) - - local mis = { - id='Mission', - params = { - route = { - points = { - [1] = { - type= AI.Task.WaypointType.TURNING_POINT, - x = srx, - y = sry, - speed = 1000, - action = AI.Task.VehicleFormation.DIAMOND - }, - [2] = { - type= AI.Task.WaypointType.TURNING_POINT, - x = erx, - y = ery, - speed = 1000, - action = AI.Task.VehicleFormation.DIAMOND - }, - [3] = { - type= AI.Task.WaypointType.TURNING_POINT, - x = point.x, - y = point.y, - speed = 1000, - action = AI.Task.VehicleFormation.DIAMOND - } - } - } - } - } - - for i,v in pairs(targets) do - if v.type == 'defense' then - local group = Group.getByName(v.name) - if group then - for i,v in ipairs(group:getUnits()) do - local unpos = v:getPoint() - local pnt = {x=unpos.x, y = unpos.z} - - table.insert(mis.params.route.points, { - type= AI.Task.WaypointType.TURNING_POINT, - x = pnt.x, - y = pnt.y, - speed = 10, - action = AI.Task.VehicleFormation.DIAMOND - }) - end - end - end - end - group:getController():setTask(mis) - end - + function TaskExtensions.landAtPointFromAir(group, point, alt) if not group or not point then return end if not group:isExist() or group:getSize()==0 then return end @@ -4882,7 +4812,7 @@ do product.lastMission = {zoneName = zone.name} timer.scheduleFunction(function(param) local gr = Group.getByName(param.name) - TaskExtensions.moveOffRoadToPointAndAssault(gr, param.point, param.targets) + TaskExtensions.moveOnRoadToPointAndAssault(gr, param.point, param.targets) end, {name=product.name, point={ x=tgtPoint.point.x, y = tgtPoint.point.z}, targets=zone.built}, timer.getTime()+1) end end @@ -5413,7 +5343,7 @@ do product.lastMission = {zoneName = v.name} timer.scheduleFunction(function(param) local gr = Group.getByName(param.name) - TaskExtensions.moveOffRoadToPointAndAssault(gr, param.point, param.targets) + TaskExtensions.moveOnRoadToPointAndAssault(gr, param.point, param.targets) end, {name=product.name, point={ x=tgtPoint.point.x, y = tgtPoint.point.z}, targets=v.built}, timer.getTime()+1) env.info("ZoneCommand - "..product.name.." targeting "..v.name) @@ -5975,7 +5905,7 @@ end BattlefieldManager = {} do - BattlefieldManager.closeOverride = Config.closeOverride -- default 15nm + BattlefieldManager.closeOverride = 27780 -- 15nm BattlefieldManager.farOverride = Config.maxDistFromFront -- default 100nm BattlefieldManager.boostScale = {[0] = 1.0, [1]=1.0, [2]=1.0} BattlefieldManager.noRedZones = false @@ -10554,7 +10484,6 @@ do end end end - return false end function SEAD:getMissionName() @@ -12208,7 +12137,7 @@ do if toGen > 0 then local validMissions = {} for _,v in pairs(Mission.types) do - if timer.getAbsTime() - timer.getTime0() > 120 and self:canCreateMission(v) then + if self:canCreateMission(v) then table.insert(validMissions,v) end end