diff --git a/changelog.md b/changelog.md index b55d5aaa..fb374c64 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,8 @@ # Retribution v1.3.0 +#### Note: Re-save your missions in DCS' Mission Editor to avoid possible crashes due to datalink (usually the case when F-16C blk50s are used) when hosting missions on a dedicated server. ## Features/Improvements +* **[Engine]** Support for DCS v2.9.3.51704 * **[Package Planning]** Option to "Auto-Create" package * **[Modding]** Custom weapons injection system (definition in aircraft's yaml file) * **[Payload Editor]** Ability to save/back-up payloads @@ -30,12 +32,15 @@ * **[COMMs]** Aircraft-specific callsigns will now also be used. * **[COMMs]** Ability to set a specific callsign to a flight. * **[Mission Generator]** Channel terrain fix on exclusion zones, sea zones and inclusion zones -* **[Options]** Cheat-option for accessing Air Wing Config Dialog after campaign start +* **[Options]** Cheat-option for accessing Air Wing Config Dialog after campaign start (re-initializes turn if applied, thus plan your mission ___after___ making changes) * **[Options]** Option to enable unlimited fuel for AI (player and non-player flights) * **[Mission Generator]** F-15E Strike targets are automatically added as Mission Set 1 * **[Mission Generator]** Set F-14's IP waypoint according to the flight-plan's ingress point * **[Mission Generator]** Automatically de-spawn aircraft when arrival/divert is an off-map spawn * **[Options]** Option to de-spawn AI flights in the air if their start-type was manually set to In-Flight +* **[Config]** Preference setting to use custom Liberation payloads instead of prioritizing Retribution's default +* **[Config]** Preference setting to configure the server-port on which Retribution's back-end will run +* **[Options]** Made AI jettisoning empty fuel tanks optional (disabled by default) ## Fixes * **[Mission Generation]** Anti-ship strikes should use "group attack" in their attack-task @@ -49,6 +54,8 @@ * **[Capture Logic]** Release all parking slots when an airbase is captured * **[Modding]** Swedish Military Assets Pack air defence presets are now correctly removed from the faction when the mod is disabled. * **[Mission Generation]** Naval aircraft not always returning to carrier +* **[Mission Generation]** AI AirLift aircraft crashing into terrain due to insufficient waypoints +* **[Mission Generation]** Fix friendly AI shooting at fires on the front-line # Retribution v1.2.1 (hotfix) diff --git a/game/ato/flightplans/airassault.py b/game/ato/flightplans/airassault.py index 3ea47c2b..ec4b72c0 100644 --- a/game/ato/flightplans/airassault.py +++ b/game/ato/flightplans/airassault.py @@ -1,5 +1,6 @@ from __future__ import annotations +import random from dataclasses import dataclass from datetime import datetime from typing import Iterator, TYPE_CHECKING, Type @@ -38,6 +39,7 @@ class AirAssaultLayout(FormationAttackLayout): if self.pickup is not None: yield self.pickup yield from self.nav_to + yield self.join yield self.ingress if self.drop_off is not None: yield self.drop_off @@ -131,19 +133,34 @@ class Builder(FormationAttackBuilder[AirAssaultFlightPlan, AirAssaultLayout]): self._generate_ctld_pickup(), ) ) + pickup.alt = heli_alt pickup_position = pickup.position + + ingress = builder.ingress( + FlightWaypointType.INGRESS_AIR_ASSAULT, + self.package.waypoints.ingress, + self.package.target, + ) + assault_area = builder.assault_area(self.package.target) - heading = self.package.target.position.heading_between_point(pickup_position) if self.flight.is_hercules: assault_area.only_for_player = False assault_area.alt = feet(1000) - # TODO: define CTLD dropoff zones in campaign miz? - drop_off_zone = MissionTarget( - "Dropoff zone", - self.package.target.position.point_from_heading(heading, 1200), - ) + tgt = self.package.target + if isinstance(tgt, CTLD) and tgt.ctld_zones: + top3 = sorted( + tgt.ctld_zones, key=lambda x: ingress.position.distance_to_point(x[0]) + )[:3] + pos, dist = random.choice(top3) + drop_pos = pos.random_point_within(dist) + else: + heading = tgt.position.heading_between_point(ingress.position) + drop_pos = tgt.position.point_from_heading(heading, 1200) + drop_off_zone = MissionTarget("Dropoff zone", drop_pos) dz = builder.dropoff_zone(drop_off_zone) if self.flight.is_helo else None + if dz: + dz.alt = heli_alt return AirAssaultLayout( departure=builder.takeoff(self.flight.departure), @@ -154,11 +171,7 @@ class Builder(FormationAttackBuilder[AirAssaultFlightPlan, AirAssaultLayout]): altitude, altitude_is_agl, ), - ingress=builder.ingress( - FlightWaypointType.INGRESS_AIR_ASSAULT, - self.package.waypoints.ingress, - self.package.target, - ), + ingress=ingress, drop_off=dz, targets=[assault_area], nav_from=builder.nav_path( @@ -171,8 +184,8 @@ class Builder(FormationAttackBuilder[AirAssaultFlightPlan, AirAssaultLayout]): divert=builder.divert(self.flight.divert), bullseye=builder.bullseye(), hold=None, - join=builder.join(pickup_position), - split=builder.split(self.package.waypoints.split), + join=builder.join(ingress.position), + split=builder.split(self.flight.arrival.position), refuel=None, ) diff --git a/game/ato/flightplans/airlift.py b/game/ato/flightplans/airlift.py index 1cc15d84..17692ac1 100644 --- a/game/ato/flightplans/airlift.py +++ b/game/ato/flightplans/airlift.py @@ -1,5 +1,6 @@ from __future__ import annotations +import random from collections.abc import Iterator from dataclasses import dataclass from datetime import datetime @@ -7,7 +8,7 @@ from typing import Optional from typing import TYPE_CHECKING, Type from game.theater.missiontarget import MissionTarget -from game.utils import feet +from game.utils import feet, Distance from ._common_ctld import generate_random_ctld_point from .ibuilder import IBuilder from .planningerror import PlanningError @@ -23,13 +24,17 @@ if TYPE_CHECKING: @dataclass class AirliftLayout(StandardLayout): + pickup_ascent: FlightWaypoint | None + pickup_descent: FlightWaypoint | None # There will not be a pickup waypoint when the pickup airfield is the departure # airfield for cargo planes, as the cargo is pre-loaded. Helicopters will still pick # up the cargo near the airfield. pickup: FlightWaypoint | None # pickup_zone will be used for player flights to create the CTLD stuff ctld_pickup_zone: FlightWaypoint | None + drop_off_ascent: FlightWaypoint | None nav_to_drop_off: list[FlightWaypoint] + drop_off_descent: FlightWaypoint | None # There will not be a drop-off waypoint when the drop-off airfield and the arrival # airfield is the same for a cargo plane, as planes will land to unload and we don't # want a double landing. Helicopters will still drop their cargo near the airfield @@ -37,6 +42,8 @@ class AirliftLayout(StandardLayout): drop_off: FlightWaypoint | None # drop_off_zone will be used for player flights to create the CTLD stuff ctld_drop_off_zone: FlightWaypoint | None + return_ascent: FlightWaypoint + return_descent: FlightWaypoint def add_waypoint( self, wpt: FlightWaypoint, next_wpt: Optional[FlightWaypoint] @@ -60,17 +67,27 @@ class AirliftLayout(StandardLayout): def iter_waypoints(self) -> Iterator[FlightWaypoint]: yield self.departure + if self.pickup_ascent is not None: + yield self.pickup_ascent yield from self.nav_to + if self.pickup_descent is not None: + yield self.pickup_descent if self.pickup is not None: yield self.pickup if self.ctld_pickup_zone is not None: yield self.ctld_pickup_zone + if self.drop_off_ascent is not None: + yield self.drop_off_ascent yield from self.nav_to_drop_off + if self.drop_off_descent is not None: + yield self.drop_off_descent if self.drop_off is not None: yield self.drop_off + yield self.return_ascent if self.ctld_drop_off_zone is not None: yield self.ctld_drop_off_zone yield from self.nav_from + yield self.return_descent yield self.arrival if self.divert is not None: yield self.divert @@ -121,15 +138,47 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]): builder = WaypointBuilder(self.flight) + pickup_ascent = None + pickup_descent = None pickup = None + drop_off_ascent = None + drop_off_descent = None drop_off = None pickup_zone = None drop_off_zone = None if cargo.origin != self.flight.departure: pickup = builder.cargo_stop(cargo.origin) + pickup_ascent = self._create_ascent_or_descent( + builder, + self.flight.departure.position, + cargo.origin.position, + altitude, + altitude_is_agl, + ) + pickup_descent = self._create_ascent_or_descent( + builder, + cargo.origin.position, + self.flight.departure.position, + altitude, + altitude_is_agl, + ) if cargo.next_stop != self.flight.arrival: drop_off = builder.cargo_stop(cargo.next_stop) + drop_off_ascent = self._create_ascent_or_descent( + builder, + cargo.origin.position, + cargo.next_stop.position, + altitude, + altitude_is_agl, + ) + drop_off_descent = self._create_ascent_or_descent( + builder, + cargo.next_stop.position, + cargo.origin.position, + altitude, + altitude_is_agl, + ) if self.flight.is_helo: # Create CTLD Zones for Helo flights @@ -150,25 +199,50 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]): altitude_is_agl, ) + return_ascent = self._create_ascent_or_descent( + builder, + cargo.next_stop.position + if cargo.next_stop != self.flight.arrival + else cargo.origin.position, + self.flight.arrival.position, + altitude, + altitude_is_agl, + ) + return_descent = self._create_ascent_or_descent( + builder, + self.flight.arrival.position, + cargo.next_stop.position + if cargo.next_stop != self.flight.arrival + else cargo.origin.position, + altitude, + altitude_is_agl, + ) + return AirliftLayout( departure=builder.takeoff(self.flight.departure), + pickup_ascent=pickup_ascent, nav_to=nav_to_pickup, + pickup_descent=pickup_descent, pickup=pickup, ctld_pickup_zone=pickup_zone, + drop_off_ascent=drop_off_ascent, nav_to_drop_off=builder.nav_path( cargo.origin.position, cargo.next_stop.position, altitude, altitude_is_agl, ), + drop_off_descent=drop_off_descent, drop_off=drop_off, ctld_drop_off_zone=drop_off_zone, + return_ascent=return_ascent, nav_from=builder.nav_path( cargo.origin.position, self.flight.arrival.position, altitude, altitude_is_agl, ), + return_descent=return_descent, arrival=builder.land(self.flight.arrival), divert=builder.divert(self.flight.divert), bullseye=builder.bullseye(), @@ -188,3 +262,18 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]): if cargo and cargo.transport and isinstance(cargo.transport.destination, CTLD): return generate_random_ctld_point(cargo.transport.destination) raise RuntimeError("Could not generate CTLD dropoff") + + @staticmethod + def _create_ascent_or_descent( + builder: WaypointBuilder, + start: Point, + end: Point, + alt: Distance, + agl: bool, + ) -> FlightWaypoint: + distance = start.distance_to_point(end) + rdistance = 1000 if agl else min(distance / 10, 20000) + heading = round(start.heading_between_point(end)) + rheading = random.randint(heading - 30, heading + 30) % 360 + pos = start.point_from_heading(float(rheading), rdistance) + return builder.nav(pos, alt, agl) diff --git a/game/ato/flightplans/escort.py b/game/ato/flightplans/escort.py index b89663b9..794f5cf1 100644 --- a/game/ato/flightplans/escort.py +++ b/game/ato/flightplans/escort.py @@ -1,6 +1,5 @@ from __future__ import annotations -from datetime import timedelta, datetime from typing import Type from .airassault import AirAssaultLayout @@ -16,18 +15,6 @@ from ...utils import feet class EscortFlightPlan(FormationAttackFlightPlan): - @property - def push_time(self) -> datetime: - hold2join_time = ( - self.travel_time_between_waypoints( - self.layout.hold, - self.layout.join, - ) - if self.layout.hold is not None - else timedelta(0) - ) - return self.join_time - hold2join_time - @staticmethod def builder_type() -> Type[Builder]: return Builder @@ -44,16 +31,17 @@ class Builder(FormationAttackBuilder[EscortFlightPlan, FormationAttackLayout]): ingress.only_for_player = True target.only_for_player = True hold = None - if not self.primary_flight_is_air_assault: + if not self.flight.is_helo: hold = builder.hold(self._hold_point()) - elif self.package.primary_flight is not None: - fp = self.package.primary_flight.flight_plan - assert isinstance(fp.layout, AirAssaultLayout) - if fp.layout.pickup: - hold = builder.hold(fp.layout.pickup.position) - join = builder.join(self.package.waypoints.join) - split = builder.split(self.package.waypoints.split) + join_pos = ( + self.package.waypoints.ingress + if self.flight.is_helo + else self.package.waypoints.join + ) + join = builder.join(join_pos) + + split = builder.split(self._get_split()) ingress_alt = self.doctrine.ingress_altitude is_helo = builder.flight.is_helo @@ -70,10 +58,12 @@ class Builder(FormationAttackBuilder[EscortFlightPlan, FormationAttackLayout]): layout, AirliftLayout ) if isinstance(layout, AirliftLayout): - join = builder.join(layout.departure.position) - else: - join = builder.join(layout.ingress.position) - if layout.pickup: + ascent = layout.pickup_ascent or layout.drop_off_ascent + assert ascent is not None + join = builder.join(ascent.position) + if layout.pickup and layout.drop_off_ascent: + join = builder.join(layout.drop_off_ascent.position) + elif layout.pickup: join = builder.join(layout.pickup.position) split = builder.split(layout.arrival.position) if layout.drop_off: diff --git a/game/ato/flightplans/flightplan.py b/game/ato/flightplans/flightplan.py index 32e1d7c3..196ab3f1 100644 --- a/game/ato/flightplans/flightplan.py +++ b/game/ato/flightplans/flightplan.py @@ -71,15 +71,6 @@ class FlightPlan(ABC, Generic[LayoutT]): """A list of all waypoints in the flight plan, in order.""" return list(self.iter_waypoints()) - def get_index_of_wpt_by_type(self, wpt_type: FlightWaypointType) -> int: - index = 0 - for wpt in self.waypoints: - if wpt and not wpt.only_for_player: - index += 1 - if wpt.waypoint_type == wpt_type: - return index - return -1 - def iter_waypoints(self) -> Iterator[FlightWaypoint]: """Iterates over all waypoints in the flight plan, in order.""" yield from self.layout.iter_waypoints() @@ -113,6 +104,19 @@ class FlightPlan(ABC, Generic[LayoutT]): # # Plus, it's a loiter point so there's no reason to hurry. factor = 0.75 + elif ( + self.flight.is_helo + and ( + a.waypoint_type == FlightWaypointType.JOIN + or "INGRESS" in a.waypoint_type.name + or a.waypoint_type == FlightWaypointType.CUSTOM + ) + and self.package.primary_flight + and not self.package.primary_flight.flight_plan.is_airassault + ): + # Helicopter flights should be slowed down between JOIN & INGRESS + # to allow the escort to keep up while engaging targets along the way. + factor = 0.50 # TODO: Adjust if AGL. # We don't have an exact heightmap, but we should probably be performing # *some* adjustment for NTTR since the minimum altitude of the map is diff --git a/game/ato/flightplans/formation.py b/game/ato/flightplans/formation.py index 3d42ac04..92d4aba8 100644 --- a/game/ato/flightplans/formation.py +++ b/game/ato/flightplans/formation.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: @dataclass class FormationLayout(LoiterLayout, ABC): - join: Optional[FlightWaypoint] + join: FlightWaypoint split: FlightWaypoint refuel: Optional[FlightWaypoint] @@ -92,10 +92,15 @@ class FormationFlightPlan(LoiterFlightPlan, ABC): @property def push_time(self) -> datetime: - return self.join_time - self.travel_time_between_waypoints( - self.layout.hold, - self.layout.join, + hold2join_time = ( + self.travel_time_between_waypoints( + self.layout.hold, + self.layout.join, + ) + if self.layout.hold + else timedelta(0) ) + return self.join_time - hold2join_time @property def mission_begin_on_station_time(self) -> datetime | None: diff --git a/game/ato/flightplans/formationattack.py b/game/ato/flightplans/formationattack.py index c684d763..ae759815 100644 --- a/game/ato/flightplans/formationattack.py +++ b/game/ato/flightplans/formationattack.py @@ -142,8 +142,7 @@ class FormationAttackLayout(FormationLayout): if self.hold: yield self.hold yield from self.nav_to - if self.join: - yield self.join + yield self.join if self.lineup: yield self.lineup yield self.ingress @@ -187,11 +186,13 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC): ) hold = None - join = None - if not self.primary_flight_is_air_assault: + if not self.flight.is_helo: hold = builder.hold(self._hold_point()) - join = builder.join(self.package.waypoints.join) - split = builder.split(self.package.waypoints.split) + join_pos = self.package.waypoints.join + if self.flight.is_helo: + join_pos = self.package.waypoints.ingress + join = builder.join(join_pos) + split = builder.split(self._get_split()) refuel = self._build_refuel(builder) ingress = builder.ingress( @@ -255,6 +256,9 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC): @property def primary_flight_is_air_assault(self) -> bool: if self.flight is self.package.primary_flight: + # Can't call self.package.primary_flight.flight_plan here + # because the flight-plan wasn't created yet. + # Calling the fligh_plan property would result in infinite recursion return self.flight.flight_type == FlightType.AIR_ASSAULT else: assert self.package.primary_flight is not None @@ -296,3 +300,13 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC): return HoldZoneGeometry( target, origin, ip, join, self.coalition, self.theater ).find_best_hold_point() + + def _get_split(self) -> Point: + assert self.package.waypoints is not None + assert self.package.primary_flight is not None + split_pos = ( + self.package.primary_flight.arrival.position + if self.package.primary_flight.is_helo + else self.package.waypoints.split + ) + return split_pos diff --git a/game/ato/flightplans/waypointbuilder.py b/game/ato/flightplans/waypointbuilder.py index f60962e9..3ed23cb3 100644 --- a/game/ato/flightplans/waypointbuilder.py +++ b/game/ato/flightplans/waypointbuilder.py @@ -15,7 +15,6 @@ from typing import ( from dcs.mapping import Point, Vector2 -from game.ato.flightplans._common_ctld import generate_random_ctld_point from game.ato.flightwaypoint import AltitudeReference, FlightWaypoint from game.ato.flightwaypointtype import FlightWaypointType from game.theater import ( @@ -25,7 +24,6 @@ from game.theater import ( TheaterGroundObject, TheaterUnit, ) -from game.theater.interfaces.CTLD import CTLD from game.utils import Distance, meters, nautical_miles, feet if TYPE_CHECKING: @@ -250,10 +248,14 @@ class WaypointBuilder: else feet(1000) ) + heading = objective.position.heading_between_point(position) + return FlightWaypoint( "INGRESS", ingress_type, - position, + objective.position.point_from_heading(heading, nautical_miles(5).meters) + if self.is_helo + else position, alt, alt_type, description=f"INGRESS on {objective.name}", @@ -635,14 +637,10 @@ class WaypointBuilder: """Creates a cargo stop waypoint. This waypoint is used by AirLift as a landing and stopover waypoint """ - if isinstance(control_point, CTLD) and control_point.ctld_zones: - pos = generate_random_ctld_point(control_point) - else: - pos = control_point.position return FlightWaypoint( "CARGOSTOP", FlightWaypointType.CARGO_STOP, - pos, + control_point.position, meters(0), "RADIO", description=f"Stop for cargo at {control_point.name}", diff --git a/game/ato/loadouts.py b/game/ato/loadouts.py index b1478f05..6f6d61da 100644 --- a/game/ato/loadouts.py +++ b/game/ato/loadouts.py @@ -11,6 +11,7 @@ from dcs.unittype import FlyingType from game.data.weapons import Pylon, Weapon, WeaponType from game.dcs.aircrafttype import AircraftType from .flighttype import FlightType +from ..persistency import prefer_liberation_payloads if TYPE_CHECKING: from .flight import Flight @@ -161,7 +162,10 @@ class Loadout: # last - the first element in the tuple will be tried first, then the second, # etc. loadout_names = { - t: [f"Retribution {t.value}", f"Liberation {t.value}"] for t in FlightType + t: [f"Liberation {t.value}", f"Retribution {t.value}"] + if prefer_liberation_payloads() + else [f"Retribution {t.value}", f"Liberation {t.value}"] + for t in FlightType } legacy_names = { FlightType.TARCAP: ( diff --git a/game/commander/missionproposals.py b/game/commander/missionproposals.py index 628bc50c..7fcae8f3 100644 --- a/game/commander/missionproposals.py +++ b/game/commander/missionproposals.py @@ -3,6 +3,7 @@ from enum import Enum, auto from typing import Optional from game.ato.flighttype import FlightType +from game.dcs.aircrafttype import AircraftType from game.theater import MissionTarget @@ -33,6 +34,8 @@ class ProposedFlight: #: field is None. escort_type: Optional[EscortType] = field(default=None) + preferred_type: Optional[AircraftType] = field(default=None) + def __str__(self) -> str: return f"{self.task} {self.num_aircraft} ship" diff --git a/game/commander/objectivefinder.py b/game/commander/objectivefinder.py index f88410d0..c789392e 100644 --- a/game/commander/objectivefinder.py +++ b/game/commander/objectivefinder.py @@ -140,7 +140,7 @@ class ObjectiveFinder: def vulnerable_control_points(self) -> Iterator[ControlPoint]: """Iterates over friendly CPs that are vulnerable to enemy CPs. - Vulnerability is defined as any enemy CP within threat range of of the + Vulnerability is defined as any enemy CP within threat range of the CP. """ for cp in self.friendly_control_points(): diff --git a/game/commander/packagebuilder.py b/game/commander/packagebuilder.py index 6ea28ac7..9936c8e4 100644 --- a/game/commander/packagebuilder.py +++ b/game/commander/packagebuilder.py @@ -49,7 +49,12 @@ class PackageBuilder: pf = self.package.primary_flight heli = pf.is_helo if pf else False squadron = self.air_wing.best_squadron_for( - self.package.target, plan.task, plan.num_aircraft, heli, this_turn=True + self.package.target, + plan.task, + plan.num_aircraft, + heli, + this_turn=True, + preferred_type=plan.preferred_type, ) if squadron is None: return False diff --git a/game/commander/tasks/compound/attackships.py b/game/commander/tasks/compound/attackships.py new file mode 100644 index 00000000..e035c65b --- /dev/null +++ b/game/commander/tasks/compound/attackships.py @@ -0,0 +1,15 @@ +from collections.abc import Iterator + +from game.commander.tasks.primitive.antiship import PlanAntiShip +from game.commander.theaterstate import TheaterState +from game.htn import CompoundTask, Method + + +class AttackShips(CompoundTask[TheaterState]): + def each_valid_method(self, state: TheaterState) -> Iterator[Method[TheaterState]]: + for ship in state.enemy_ships: + # Ammo depots are targeted based on the needs of the front line by + # ReduceEnemyFrontLineCapacity. No reason to target them before that front + # line is active. + if ship.has_live_radar_sam: + yield [PlanAntiShip(ship)] diff --git a/game/commander/tasks/compound/nextaction.py b/game/commander/tasks/compound/nextaction.py index e09b4054..4f1aac5e 100644 --- a/game/commander/tasks/compound/nextaction.py +++ b/game/commander/tasks/compound/nextaction.py @@ -6,6 +6,7 @@ from game.commander.tasks.compound.attackairinfrastructure import ( ) from game.commander.tasks.compound.attackbattlepositions import AttackBattlePositions from game.commander.tasks.compound.attackbuildings import AttackBuildings +from game.commander.tasks.compound.attackships import AttackShips from game.commander.tasks.compound.capturebases import CaptureBases from game.commander.tasks.compound.defendbases import DefendBases from game.commander.tasks.compound.degradeiads import DegradeIads @@ -25,10 +26,11 @@ class PlanNextAction(CompoundTask[TheaterState]): def each_valid_method(self, state: TheaterState) -> Iterator[Method[TheaterState]]: yield [TheaterSupport()] yield [ProtectAirSpace()] - yield [CaptureBases()] yield [DefendBases()] yield [InterdictReinforcements()] + yield [DegradeIads()] yield [AttackBattlePositions()] + yield [CaptureBases()] yield [AttackAirInfrastructure(self.aircraft_cold_start)] yield [AttackBuildings()] - yield [DegradeIads()] + yield [AttackShips()] diff --git a/game/game.py b/game/game.py index 3f71939d..dfb0c2f7 100644 --- a/game/game.py +++ b/game/game.py @@ -372,10 +372,10 @@ class Game: persistency.autosave(self) def check_win_loss(self) -> TurnState: - if not self.theater.player_points(): + if not self.theater.player_points(state_check=True): return TurnState.LOSS - if not self.theater.enemy_points(): + if not self.theater.enemy_points(state_check=True): return TurnState.WIN return TurnState.CONTINUE diff --git a/game/migrator.py b/game/migrator.py index f6899a0e..51715261 100644 --- a/game/migrator.py +++ b/game/migrator.py @@ -7,6 +7,8 @@ from typing import TYPE_CHECKING, Any from dcs.countries import countries_by_name from game.ato import FlightType +from game.ato.flightplans.formation import FormationLayout +from game.ato.flightplans.waypointbuilder import WaypointBuilder from game.ato.packagewaypoints import PackageWaypoints from game.data.doctrine import MODERN_DOCTRINE, COLDWAR_DOCTRINE, WWII_DOCTRINE from game.theater import ParkingType, SeasonalConditions @@ -107,6 +109,10 @@ class Migrator: try_set_attr(layout, "nav_from", []) if f.flight_type == FlightType.CAS: try_set_attr(layout, "ingress", None) + if isinstance(layout, FormationLayout): + if not layout.join and f.package.waypoints: + builder = WaypointBuilder(f, []) + layout.join = builder.join(f.package.waypoints.join) def _update_flights(self) -> None: to_remove = [] diff --git a/game/missiongenerator/aircraft/aircraftbehavior.py b/game/missiongenerator/aircraft/aircraftbehavior.py index a949aa1d..9339133c 100644 --- a/game/missiongenerator/aircraft/aircraftbehavior.py +++ b/game/missiongenerator/aircraft/aircraftbehavior.py @@ -1,5 +1,5 @@ import logging -from typing import Any, Optional, Type +from typing import Any, Optional, Type, List from dcs.task import ( AWACS, @@ -124,7 +124,8 @@ class AircraftBehavior: unit.gun = 0 group.points[0].tasks.append(OptRTBOnBingoFuel(rtb_on_bingo)) - group.points[0].tasks.append(OptJettisonEmptyTanks()) + if flight.coalition.game.settings.ai_jettison_empty_tanks: + group.points[0].tasks.append(OptJettisonEmptyTanks()) # Do not restrict afterburner. # https://forums.eagle.ru/forum/english/digital-combat-simulator/dcs-world-2-5/bugs-and-problems-ai/ai-ad/7121294-ai-stuck-at-high-aoa-after-making-sharp-turn-if-afterburner-is-restricted @@ -152,7 +153,7 @@ class AircraftBehavior: self.configure_behavior(flight, group, rtb_winchester=ammo_type) def configure_cas(self, group: FlyingGroup[Any], flight: Flight) -> None: - self.configure_task(flight, group, CAS, AFAC) + self.configure_task(flight, group, CAS, [AFAC, AntishipStrike]) self.configure_behavior( flight, group, @@ -170,7 +171,7 @@ class AircraftBehavior: # Note that the only effect that the DCS task type has is in determining which # waypoint actions the group may perform. - self.configure_task(flight, group, SEAD, CAS) + self.configure_task(flight, group, SEAD, [CAS, AFAC, AntishipStrike]) self.configure_behavior( flight, group, @@ -186,7 +187,7 @@ class AircraftBehavior: # available aircraft, and F-14s are not able to be SEAD despite having TALDs. # https://forums.eagle.ru/topic/272112-cannot-assign-f-14-to-sead/ - self.configure_task(flight, group, SEAD, CAS) + self.configure_task(flight, group, SEAD, [CAS, AFAC, AntishipStrike]) self.configure_behavior( flight, group, @@ -200,7 +201,7 @@ class AircraftBehavior: ) def configure_strike(self, group: FlyingGroup[Any], flight: Flight) -> None: - self.configure_task(flight, group, GroundAttack, PinpointStrike) + self.configure_task(flight, group, GroundAttack, [PinpointStrike, AFAC]) self.configure_behavior( flight, group, @@ -211,7 +212,7 @@ class AircraftBehavior: ) def configure_anti_ship(self, group: FlyingGroup[Any], flight: Flight) -> None: - self.configure_task(flight, group, AntishipStrike, CAS) + self.configure_task(flight, group, AntishipStrike, [CAS, AFAC, SEAD]) self.configure_behavior( flight, group, @@ -233,7 +234,7 @@ class AircraftBehavior: ) def configure_oca_strike(self, group: FlyingGroup[Any], flight: Flight) -> None: - self.configure_task(flight, group, CAS) + self.configure_task(flight, group, CAS, [AFAC, SEAD]) self.configure_behavior( flight, group, @@ -345,7 +346,7 @@ class AircraftBehavior: flight: Flight, group: FlyingGroup[Any], preferred_task: Type[MainTask], - fallback_task: Optional[Type[MainTask]] = None, + fallback_tasks: Optional[List[Type[MainTask]]] = None, ) -> None: ac_type = flight.unit_type.dcs_unit_type.id @@ -358,15 +359,22 @@ class AircraftBehavior: if preferred_task in flight.unit_type.dcs_unit_type.tasks: group.task = preferred_task.name - elif fallback_task and fallback_task in flight.unit_type.dcs_unit_type.tasks: - group.task = fallback_task.name + elif fallback_tasks: + for task in fallback_tasks: + if task in flight.unit_type.dcs_unit_type.tasks: + group.task = task.name + return elif flight.unit_type.dcs_unit_type.task_default and preferred_task == Nothing: group.task = flight.unit_type.dcs_unit_type.task_default.name logging.warning( f"{ac_type} is not capable of 'Nothing', using default task '{group.task}'" ) else: - fallback_part = f" nor {fallback_task.name}" if fallback_task else "" + fallback_part = ( + f" nor any of the following fall-back tasks: {[task.name for task in fallback_tasks]}" + if fallback_tasks + else "" + ) raise RuntimeError( f"{ac_type} is neither capable of {preferred_task.name}" f"{fallback_part}. Can't generate {flight.flight_type} flight." diff --git a/game/missiongenerator/aircraft/flightgroupspawner.py b/game/missiongenerator/aircraft/flightgroupspawner.py index 181a58b7..bec3f522 100644 --- a/game/missiongenerator/aircraft/flightgroupspawner.py +++ b/game/missiongenerator/aircraft/flightgroupspawner.py @@ -243,6 +243,8 @@ class FlightGroupSpawner: speed=speed.kph, maintask=None, group_size=self.flight.count, + callsign_name=self.flight.callsign.name if self.flight.callsign else None, + callsign_nr=self.flight.callsign.nr if self.flight.callsign else None, ) group.points[0].alt_type = alt_type diff --git a/game/missiongenerator/aircraft/waypoints/antishipingress.py b/game/missiongenerator/aircraft/waypoints/antishipingress.py index 67211cea..da8d635f 100644 --- a/game/missiongenerator/aircraft/waypoints/antishipingress.py +++ b/game/missiongenerator/aircraft/waypoints/antishipingress.py @@ -15,9 +15,9 @@ class AntiShipIngressBuilder(PydcsWaypointBuilder): target = self.package.target if isinstance(target, NavalControlPoint): - carrier_name = target.get_carrier_group_name() - if carrier_name: - group_names.append(carrier_name) + carrier_tgo = target.ground_objects[0] + for g in carrier_tgo.groups: + group_names.append(g.group_name) elif isinstance(target, TheaterGroundObject): for group in target.groups: group_names.append(group.group_name) diff --git a/game/missiongenerator/aircraft/waypoints/baiingress.py b/game/missiongenerator/aircraft/waypoints/baiingress.py index db4499b3..1a3c7775 100644 --- a/game/missiongenerator/aircraft/waypoints/baiingress.py +++ b/game/missiongenerator/aircraft/waypoints/baiingress.py @@ -11,7 +11,8 @@ from .pydcswaypointbuilder import PydcsWaypointBuilder class BaiIngressBuilder(PydcsWaypointBuilder): def add_tasks(self, waypoint: MovingPoint) -> None: self.register_special_ingress_points() - waypoint.tasks.append(OptFormation.trail_open()) + if not self.flight.is_helo: + waypoint.tasks.append(OptFormation.trail_open()) # TODO: Add common "UnitGroupTarget" base type. group_names = [] target = self.package.target diff --git a/game/missiongenerator/aircraft/waypoints/joinpoint.py b/game/missiongenerator/aircraft/waypoints/joinpoint.py index 36724470..19056df9 100644 --- a/game/missiongenerator/aircraft/waypoints/joinpoint.py +++ b/game/missiongenerator/aircraft/waypoints/joinpoint.py @@ -94,7 +94,11 @@ class JoinPointBuilder(PydcsWaypointBuilder): max_dist: float = 30.0, vertical_spacing: float = 2000.0, ) -> None: - waypoint.tasks.append(OptROE(value=OptROE.Values.OpenFire)) + if self.flight.is_helo: + # Make helicopters a bit more aggressive + waypoint.tasks.append(OptROE(value=OptROE.Values.OpenFireWeaponFree)) + else: + waypoint.tasks.append(OptROE(value=OptROE.Values.OpenFire)) rx = (random.random() + 0.1) * 333 ry = feet(vertical_spacing).meters diff --git a/game/missiongenerator/aircraft/waypoints/seadsweepingress.py b/game/missiongenerator/aircraft/waypoints/seadsweepingress.py index e3912f95..2e165353 100644 --- a/game/missiongenerator/aircraft/waypoints/seadsweepingress.py +++ b/game/missiongenerator/aircraft/waypoints/seadsweepingress.py @@ -4,6 +4,7 @@ from dcs.task import ( ControlledTask, EngageTargets, Targets, + OptROE, ) from game.utils import nautical_miles @@ -13,6 +14,7 @@ from .pydcswaypointbuilder import PydcsWaypointBuilder class SeadSweepIngressBuilder(PydcsWaypointBuilder): def add_tasks(self, waypoint: MovingPoint) -> None: self.register_special_ingress_points() + waypoint.tasks.append(OptROE(value=OptROE.Values.OpenFireWeaponFree)) # Preemptively use ECM to better avoid getting swatted. ecm_option = OptECMUsing(value=OptECMUsing.Values.UseIfDetectedLockByRadar) waypoint.tasks.append(ecm_option) @@ -26,7 +28,7 @@ class SeadSweepIngressBuilder(PydcsWaypointBuilder): self.flight.coalition.game.settings.sead_sweep_engagement_range_distance ).meters ), - targets=[Targets.All.GroundUnits.AirDefence.AAA.SAMRelated], + targets=[Targets.All.GroundUnits.AirDefence], ) ) ) diff --git a/game/missiongenerator/aircraft/waypoints/splitpoint.py b/game/missiongenerator/aircraft/waypoints/splitpoint.py index b9394ba1..f3fe891e 100644 --- a/game/missiongenerator/aircraft/waypoints/splitpoint.py +++ b/game/missiongenerator/aircraft/waypoints/splitpoint.py @@ -7,6 +7,7 @@ from dcs.task import ( SwitchWaypoint, ) +from game.utils import knots from .pydcswaypointbuilder import PydcsWaypointBuilder @@ -29,10 +30,12 @@ class SplitPointBuilder(PydcsWaypointBuilder): waypoint.tasks.append(OptFormation.rotary_wedge()) else: waypoint.tasks.append(OptFormation.finger_four_close()) - if not self.flight.is_helo: - waypoint.speed_locked = True + waypoint.speed_locked = True + waypoint.ETA_locked = False + if self.flight.is_helo: + waypoint.speed = knots(100).meters_per_second + else: waypoint.speed = self.flight.coalition.doctrine.rtb_speed.meters_per_second - waypoint.ETA_locked = False if self.flight is self.package.primary_flight: script = RunScript( f'trigger.action.setUserFlag("split-{id(self.package)}", true)' diff --git a/game/missiongenerator/aircraft/waypoints/sweepingress.py b/game/missiongenerator/aircraft/waypoints/sweepingress.py index 268626d1..93f986f4 100644 --- a/game/missiongenerator/aircraft/waypoints/sweepingress.py +++ b/game/missiongenerator/aircraft/waypoints/sweepingress.py @@ -1,7 +1,7 @@ import logging from dcs.point import MovingPoint -from dcs.task import EngageTargets, OptFormation, Targets +from dcs.task import EngageTargets, OptFormation, Targets, OptROE from game.ato.flightplans.sweep import SweepFlightPlan from game.utils import nautical_miles @@ -16,6 +16,8 @@ class SweepIngressBuilder(PydcsWaypointBuilder): else: waypoint.tasks.append(OptFormation.spread_four_open()) + waypoint.tasks.append(OptROE(value=OptROE.Values.OpenFireWeaponFree)) + if not isinstance(self.flight.flight_plan, SweepFlightPlan): flight_plan_type = self.flight.flight_plan.__class__.__name__ logging.error( diff --git a/game/missiongenerator/visualsgenerator.py b/game/missiongenerator/visualsgenerator.py index 741a692f..02c06155 100644 --- a/game/missiongenerator/visualsgenerator.py +++ b/game/missiongenerator/visualsgenerator.py @@ -73,7 +73,7 @@ class VisualsGenerator: self.game = game def _generate_frontline_smokes(self) -> None: - country = self.mission.country(self.game.red.faction.country.name) + country = list(self.mission.coalition["neutrals"].countries.values())[0] for front_line in self.game.theater.conflicts(): from_cp = front_line.blue_cp to_cp = front_line.red_cp diff --git a/game/persistency.py b/game/persistency.py index 548d26be..0733995a 100644 --- a/game/persistency.py +++ b/game/persistency.py @@ -16,6 +16,8 @@ if TYPE_CHECKING: from game import Game _dcs_saved_game_folder: Optional[str] = None +_prefer_liberation_payloads: bool = False +_server_port: int = 16880 # fmt: off @@ -61,6 +63,8 @@ class MigrationUnpickler(pickle.Unpickler): return dcs.terrain.falklands.airports.Hipico_Flying_Club if name in ["SaveManager", "SaveGameBundle"]: return DummyObject + if name == "CaletaTortel": + return dcs.terrain.falklands.airports.Caleta_Tortel_Airport if module == "pydcs_extensions.f4b.f4b": return pydcs_extensions.f4 if module == "pydcs_extensions.irondome.irondome": @@ -74,9 +78,13 @@ class MigrationUnpickler(pickle.Unpickler): # fmt: on -def setup(user_folder: str) -> None: +def setup(user_folder: str, prefer_liberation_payloads: bool, port: int) -> None: global _dcs_saved_game_folder + global _prefer_liberation_payloads + global _server_port _dcs_saved_game_folder = user_folder + _prefer_liberation_payloads = prefer_liberation_payloads + _server_port = port if not save_dir().exists(): save_dir().mkdir(parents=True) @@ -110,6 +118,11 @@ def payloads_dir(backup: bool = False) -> Path: return payloads +def prefer_liberation_payloads() -> bool: + global _prefer_liberation_payloads + return _prefer_liberation_payloads + + def user_custom_weapon_injections_dir() -> Path: return base_path() / "Retribution" / "WeaponInjections" @@ -118,6 +131,11 @@ def save_dir() -> Path: return base_path() / "Retribution" / "Saves" +def server_port() -> int: + global _server_port + return _server_port + + def _temporary_save_file() -> str: return str(save_dir() / "tmpsave.retribution") diff --git a/game/pretense/pretenseaircraftgenerator.py b/game/pretense/pretenseaircraftgenerator.py index a8c45dde..f1b0d90c 100644 --- a/game/pretense/pretenseaircraftgenerator.py +++ b/game/pretense/pretenseaircraftgenerator.py @@ -281,9 +281,45 @@ class PretenseAircraftGenerator: num_of_bai = 0 num_of_strike = 0 num_of_cap = 0 + sead_tasks = [FlightType.SEAD, FlightType.SEAD_SWEEP, FlightType.SEAD_ESCORT] + strike_tasks = [ + FlightType.STRIKE, + FlightType.OCA_RUNWAY, + FlightType.OCA_AIRCRAFT, + ] + patrol_tasks = [ + FlightType.BARCAP, + FlightType.TARCAP, + FlightType.ESCORT, + FlightType.INTERCEPTION, + ] + sead_capable_cp = False + cas_capable_cp = False + bai_capable_cp = False + strike_capable_cp = False + patrol_capable_cp = False + + # First check what are the capabilities of the squadrons on this CP + for squadron in cp.squadrons: + for task in sead_tasks: + if task in squadron.auto_assignable_mission_types: + sead_capable_cp = True + for task in strike_tasks: + if task in squadron.auto_assignable_mission_types: + if not squadron.aircraft.helicopter: + strike_capable_cp = True + for task in patrol_tasks: + if task in squadron.auto_assignable_mission_types: + if not squadron.aircraft.helicopter: + patrol_capable_cp = True + if FlightType.CAS in squadron.auto_assignable_mission_types: + cas_capable_cp = True + if FlightType.BAI in squadron.auto_assignable_mission_types: + bai_capable_cp = True random_squadron_list = list(cp.squadrons) random.shuffle(random_squadron_list) + # Then plan transports, AEWC and tankers for squadron in random_squadron_list: # Intentionally don't spawn anything at OffMapSpawns in Pretense if isinstance(squadron.location, OffMapSpawn): @@ -291,14 +327,6 @@ class PretenseAircraftGenerator: if cp.coalition != squadron.coalition: continue - 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 aircraft_per_flight = 1 if squadron.aircraft.helicopter and ( @@ -311,52 +339,6 @@ class PretenseAircraftGenerator: or FlightType.AIR_ASSAULT in mission_types ): flight_type = FlightType.TRANSPORT - elif ( - FlightType.SEAD in mission_types - or FlightType.SEAD_SWEEP in mission_types - or FlightType.SEAD_ESCORT in mission_types - ) and num_of_sead < self.game.settings.pretense_sead_flights_per_cp: - flight_type = FlightType.SEAD - num_of_sead += 1 - aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight - elif ( - FlightType.DEAD in mission_types - and num_of_sead < self.game.settings.pretense_sead_flights_per_cp - ): - flight_type = FlightType.DEAD - num_of_sead += 1 - aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight - elif ( - (squadron.aircraft.helicopter and (FlightType.ESCORT in mission_types)) - or (FlightType.CAS in mission_types) - and num_of_cas < self.game.settings.pretense_cas_flights_per_cp - ): - flight_type = FlightType.CAS - num_of_cas += 1 - aircraft_per_flight = self.game.settings.pretense_ai_aircraft_per_flight - elif ( - FlightType.BAI in mission_types - ) and num_of_bai < self.game.settings.pretense_bai_flights_per_cp: - flight_type = FlightType.BAI - num_of_bai += 1 - 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 < self.game.settings.pretense_strike_flights_per_cp: - flight_type = FlightType.STRIKE - num_of_strike += 1 - 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 < self.game.settings.pretense_barcap_flights_per_cp: - flight_type = FlightType.BARCAP - num_of_cap += 1 - 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 @@ -366,37 +348,181 @@ class PretenseAircraftGenerator: else: continue - if flight_type == FlightType.TRANSPORT: - flight = Flight( - package, - squadron, - aircraft_per_flight, - FlightType.PRETENSE_CARGO, - StartType.IN_FLIGHT, - divert=cp, - ) - package.add_flight(flight) - flight.state = Navigating(flight, self.game.settings, waypoint_index=1) - else: - flight = Flight( - package, - squadron, - aircraft_per_flight, - flight_type, - StartType.COLD, - divert=cp, - ) - package.add_flight(flight) - flight.state = WaitingForStart( - flight, self.game.settings, self.game.conditions.start_time - ) - - print( - f"Generated flight for {flight_type} flying {squadron.aircraft.display_name} at {squadron.location.name}" + self.generate_pretense_flight( + ato, cp, squadron, aircraft_per_flight, flight_type ) - ato.add_package(package) + # Then plan SEAD and DEAD, if capable + if sead_capable_cp: + while num_of_sead < self.game.settings.pretense_sead_flights_per_cp: + for squadron in random_squadron_list: + # Intentionally don't spawn anything at OffMapSpawns in Pretense + if isinstance(squadron.location, OffMapSpawn): + continue + if cp.coalition != squadron.coalition: + continue + + mission_types = squadron.auto_assignable_mission_types + if ( + ( + FlightType.SEAD in mission_types + or FlightType.SEAD_SWEEP in mission_types + or FlightType.SEAD_ESCORT in mission_types + ) + and num_of_sead + < self.game.settings.pretense_sead_flights_per_cp + ): + flight_type = FlightType.SEAD + num_of_sead += 1 + aircraft_per_flight = ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + elif ( + FlightType.DEAD in mission_types + and num_of_sead + < self.game.settings.pretense_sead_flights_per_cp + ): + flight_type = FlightType.DEAD + num_of_sead += 1 + aircraft_per_flight = ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + else: + continue + self.generate_pretense_flight( + ato, cp, squadron, aircraft_per_flight, flight_type + ) + # Then plan Strike, if capable + if strike_capable_cp: + while num_of_strike < self.game.settings.pretense_strike_flights_per_cp: + for squadron in random_squadron_list: + # Intentionally don't spawn anything at OffMapSpawns in Pretense + if isinstance(squadron.location, OffMapSpawn): + continue + if cp.coalition != squadron.coalition: + continue + + mission_types = squadron.auto_assignable_mission_types + for task in strike_tasks: + if task in mission_types and not squadron.aircraft.helicopter: + flight_type = FlightType.STRIKE + num_of_strike += 1 + aircraft_per_flight = ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + self.generate_pretense_flight( + ato, cp, squadron, aircraft_per_flight, flight_type + ) + break + # Then plan air-to-air, if capable + if patrol_capable_cp: + while num_of_cap < self.game.settings.pretense_barcap_flights_per_cp: + for squadron in random_squadron_list: + # Intentionally don't spawn anything at OffMapSpawns in Pretense + if isinstance(squadron.location, OffMapSpawn): + continue + if cp.coalition != squadron.coalition: + continue + + mission_types = squadron.auto_assignable_mission_types + for task in patrol_tasks: + if task in mission_types and not squadron.aircraft.helicopter: + flight_type = FlightType.BARCAP + num_of_cap += 1 + aircraft_per_flight = ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + self.generate_pretense_flight( + ato, cp, squadron, aircraft_per_flight, flight_type + ) + break + # Then plan CAS, if capable + if cas_capable_cp: + while num_of_cas < self.game.settings.pretense_cas_flights_per_cp: + for squadron in random_squadron_list: + # Intentionally don't spawn anything at OffMapSpawns in Pretense + if isinstance(squadron.location, OffMapSpawn): + continue + if cp.coalition != squadron.coalition: + continue + + mission_types = squadron.auto_assignable_mission_types + if ( + squadron.aircraft.helicopter + and (FlightType.ESCORT in mission_types) + ) or (FlightType.CAS in mission_types): + flight_type = FlightType.CAS + num_of_cas += 1 + aircraft_per_flight = ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + self.generate_pretense_flight( + ato, cp, squadron, aircraft_per_flight, flight_type + ) + # And finally, plan BAI, if capable + if bai_capable_cp: + while num_of_bai < self.game.settings.pretense_bai_flights_per_cp: + for squadron in random_squadron_list: + # Intentionally don't spawn anything at OffMapSpawns in Pretense + if isinstance(squadron.location, OffMapSpawn): + continue + if cp.coalition != squadron.coalition: + continue + + mission_types = squadron.auto_assignable_mission_types + if FlightType.BAI in mission_types: + flight_type = FlightType.BAI + num_of_bai += 1 + aircraft_per_flight = ( + self.game.settings.pretense_ai_aircraft_per_flight + ) + self.generate_pretense_flight( + ato, cp, squadron, aircraft_per_flight, flight_type + ) + return + def generate_pretense_flight( + self, + ato: AirTaskingOrder, + cp: ControlPoint, + squadron: Squadron, + aircraft_per_flight: int, + flight_type: FlightType, + ) -> None: + 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) + if flight_type == FlightType.TRANSPORT: + flight = Flight( + package, + squadron, + aircraft_per_flight, + FlightType.PRETENSE_CARGO, + StartType.IN_FLIGHT, + divert=cp, + ) + package.add_flight(flight) + flight.state = Navigating(flight, self.game.settings, waypoint_index=1) + else: + flight = Flight( + package, + squadron, + aircraft_per_flight, + flight_type, + StartType.COLD, + divert=cp, + ) + package.add_flight(flight) + flight.state = WaitingForStart( + flight, self.game.settings, self.game.conditions.start_time + ) + + print( + f"Generated flight for {flight_type} flying {squadron.aircraft.display_name} at {squadron.location.name}" + ) + ato.add_package(package) + def generate_pretense_aircraft_for_other_side( self, cp: ControlPoint, coalition: Coalition, ato: AirTaskingOrder ) -> None: diff --git a/game/procurement.py b/game/procurement.py index 5820be18..5f0fdc8e 100644 --- a/game/procurement.py +++ b/game/procurement.py @@ -219,13 +219,6 @@ class ProcurementAi: budget, fulfilled = self.fulfill_aircraft_request( squadrons, request.number, budget ) - if not fulfilled: - # The request was not fulfilled because we could not afford any suitable - # aircraft. Rather than continuing, which could proceed to buy tons of - # cheap escorts that will never allow us to plan a strike package, stop - # buying so we can save the budget until a turn where we *can* afford to - # fill the package. - break return budget @property diff --git a/game/server/server.py b/game/server/server.py index 3cd47eb2..ff59fde2 100644 --- a/game/server/server.py +++ b/game/server/server.py @@ -2,6 +2,7 @@ import time from collections.abc import Iterator from contextlib import contextmanager from threading import Thread +from typing import Optional import uvicorn from uvicorn import Config @@ -13,12 +14,13 @@ from game.sim import GameUpdateEvents class Server(uvicorn.Server): - def __init__(self) -> None: + def __init__(self, port: Optional[int]) -> None: + settings = ServerSettings.get(port) super().__init__( Config( app=app, - host=ServerSettings.get().server_bind_address, - port=ServerSettings.get().server_port, + host=settings.server_bind_address, + port=settings.server_port, # Configured explicitly with default_logging.yaml or logging.yaml. log_config=None, ) diff --git a/game/server/settings.py b/game/server/settings.py index f24ae182..01540279 100644 --- a/game/server/settings.py +++ b/game/server/settings.py @@ -1,6 +1,7 @@ from __future__ import annotations from functools import lru_cache +from typing import Optional from pydantic_settings import BaseSettings @@ -30,5 +31,5 @@ class ServerSettings(BaseSettings): @classmethod @lru_cache - def get(cls) -> ServerSettings: - return cls() + def get(cls, port: Optional[int] = server_port) -> ServerSettings: + return cls(server_port=port) diff --git a/game/settings/settings.py b/game/settings/settings.py index 8266d60d..6cfc0b3b 100644 --- a/game/settings/settings.py +++ b/game/settings/settings.py @@ -193,11 +193,12 @@ class Settings: default=False, detail=( "If checked, squadrons with a primary task matching the mission will be " - "preferred even if there is a closer squadron capable of the mission as a" + "preferred even if there is a closer squadron capable of the mission as a " "secondary task. Expect longer flights, but squadrons will be more often " "assigned to their primary task." ), ) + # CAMPAIGN DOCTRINE autoplan_tankers_for_strike: bool = boolean_option( "Auto-planner plans refueling flights for Strike packages", page=CAMPAIGN_DOCTRINE_PAGE, @@ -283,6 +284,23 @@ class Settings: "setting to avoid the AI flying into the terrain." ), ) + atflir_autoswap: bool = boolean_option( + "Auto-swap ATFLIR to LITENING", + page=CAMPAIGN_DOCTRINE_PAGE, + section=GENERAL_SECTION, + default=True, + detail=( + "Automatically swaps ATFLIR to LITENING pod for newly generated land-based F-18 flights " + "without having to change the payload. Takes effect after current turn!" + ), + ) + ai_jettison_empty_tanks: bool = boolean_option( + "Enable AI empty fuel tank jettison", + page=CAMPAIGN_DOCTRINE_PAGE, + section=GENERAL_SECTION, + default=False, + detail=("AI will jettison their fuel tanks as soon as they're empty."), + ) airbase_threat_range: int = bounded_int_option( "Airbase threat range (nmi)", page=CAMPAIGN_DOCTRINE_PAGE, @@ -291,7 +309,7 @@ class Settings: min=0, max=300, detail=( - "Will impact both defensive (BARCAP) and offensive flights. Also has a performance impact," + "Will impact both defensive (BARCAP) and offensive flights. Also has a performance impact, " "lower threat range generally means less BARCAPs are planned." ), ) @@ -339,7 +357,7 @@ class Settings: min=0, max=300, detail=( - "How far, at minimum, will AEW&C racetracks be planned" + "How far, at minimum, will AEW&C racetracks be planned " "to known threat zones." ), ) @@ -375,7 +393,7 @@ class Settings: default=True, detail=( "If set, squadrons will be limited to a maximum number of pilots and dead " - "pilots will replenish at a fixed rate, each defined with the settings" + "pilots will replenish at a fixed rate, each defined with the settings " "below. Auto-purchase may buy aircraft for which there are no pilots" "available, so this feature is still a work-in-progress." ), @@ -573,7 +591,7 @@ class Settings: default=35, min=0, max=100, - detail="See 2-ship weight factor (WF2)", + detail="See 2-ship weight factor (WF3)", ) fpa_4ship_weight: int = bounded_int_option( "4-ship weight factor (WF4)", @@ -582,7 +600,7 @@ class Settings: default=15, min=0, max=100, - detail="See 2-ship weight factor (WF2)", + detail="See 2-ship weight factor (WF4)", ) # Mission Generator @@ -675,16 +693,6 @@ class Settings: "targets available for OCA/Aircraft missions." ), ) - atflir_autoswap: bool = boolean_option( - "Auto-swap ATFLIR to LITENING", - MISSION_GENERATOR_PAGE, - GAMEPLAY_SECTION, - default=True, - detail=( - "Automatically swaps ATFLIR to LITENING pod for newly generated land-based F-18 flights " - "without having to change the payload. Takes effect after current turn!" - ), - ) default_start_type: StartType = choices_option( "Default start type for AI aircraft", page=MISSION_GENERATOR_PAGE, @@ -777,7 +785,7 @@ class Settings: GAMEPLAY_SECTION, default=False, detail=( - "If enabled, AI can use roadbases or airbases which only have ground spawns." + "If enabled, AI can use roadbases or airbases which only have ground spawns. " "AI will always air-start from these bases (due to DCS limitation)." ), ) @@ -787,7 +795,7 @@ class Settings: GAMEPLAY_SECTION, default=True, detail=( - "Can be used to remove lightposts and other obstacles from roadbase runways." + "Can be used to remove lightposts and other obstacles from roadbase runways. " "Might not work in DCS multiplayer." ), ) diff --git a/game/squadrons/airwing.py b/game/squadrons/airwing.py index 4d50b78e..a6afbc79 100644 --- a/game/squadrons/airwing.py +++ b/game/squadrons/airwing.py @@ -51,6 +51,7 @@ class AirWing: size: int, heli: bool, this_turn: bool, + preferred_type: Optional[AircraftType] = None, ) -> list[Squadron]: airfield_cache = ObjectiveDistanceCache.get_closest_airfields(location) best_aircraft = AircraftType.priority_list_for_task(task) @@ -59,7 +60,13 @@ class AirWing: if control_point.captured != self.player: continue capable_at_base = [] - for squadron in control_point.squadrons: + squadrons = [ + s + for s in control_point.squadrons + if not preferred_type + or s.aircraft.variant_id == preferred_type.variant_id + ] + for squadron in squadrons: if squadron.can_auto_assign_mission( location, task, size, heli, this_turn ): @@ -92,8 +99,11 @@ class AirWing: size: int, heli: bool, this_turn: bool, + preferred_type: Optional[AircraftType] = None, ) -> Optional[Squadron]: - for squadron in self.best_squadrons_for(location, task, size, heli, this_turn): + for squadron in self.best_squadrons_for( + location, task, size, heli, this_turn, preferred_type + ): return squadron return None diff --git a/game/theater/conflicttheater.py b/game/theater/conflicttheater.py index 1649b6ea..875a2659 100644 --- a/game/theater/conflicttheater.py +++ b/game/theater/conflicttheater.py @@ -120,20 +120,27 @@ class ConflictTheater: ) return new_point - def control_points_for(self, player: bool) -> Iterator[ControlPoint]: + def control_points_for( + self, player: bool, state_check: bool = False + ) -> Iterator[ControlPoint]: for point in self.controlpoints: if point.captured == player: - yield point + if not state_check: + yield point + elif point.is_carrier and point.runway_is_operational(): + yield point + elif not point.is_carrier: + yield point - def player_points(self) -> List[ControlPoint]: - return list(self.control_points_for(player=True)) + def player_points(self, state_check: bool = False) -> List[ControlPoint]: + return list(self.control_points_for(player=True, state_check=state_check)) def conflicts(self) -> Iterator[FrontLine]: for cp in self.player_points(): yield from cp.front_lines.values() - def enemy_points(self) -> List[ControlPoint]: - return list(self.control_points_for(player=False)) + def enemy_points(self, state_check: bool = False) -> List[ControlPoint]: + return list(self.control_points_for(player=False, state_check=state_check)) def closest_control_point( self, point: Point, allow_naval: bool = False diff --git a/game/transfers.py b/game/transfers.py index 6cd157d3..efc14211 100644 --- a/game/transfers.py +++ b/game/transfers.py @@ -321,6 +321,13 @@ class AirliftPlanner: if self.package.flights: self.package.set_tot_asap(now) self.game.ato_for(self.for_player).add_package(self.package) + from game.server import EventStream + from game.sim import GameUpdateEvents + + events = GameUpdateEvents() + for f in self.package.flights: + events = events.new_flight(f) + EventStream.put_nowait(events) def create_airlift_flight(self, squadron: Squadron) -> int: available_aircraft = squadron.untasked_aircraft @@ -606,6 +613,8 @@ class PendingTransfers: == TransitConnection.Shipping ): return self.cargo_ships.add(transfer, next_stop) + else: + next_stop = transfer.destination AirliftPlanner(self.game, transfer, next_stop).create_package_for_airlift(now) def new_transfer(self, transfer: TransferOrder, now: datetime) -> None: diff --git a/qt_ui/liberation_install.py b/qt_ui/liberation_install.py index 19556104..290a394b 100644 --- a/qt_ui/liberation_install.py +++ b/qt_ui/liberation_install.py @@ -11,6 +11,8 @@ from game import persistency global __dcs_saved_game_directory global __dcs_installation_directory global __last_save_file +global __prefer_liberation_payloads +global __server_port USER_PATH = Path(os.environ["LOCALAPPDATA"]) / "DCSRetribution" @@ -23,6 +25,8 @@ def init(): global __dcs_installation_directory global __last_save_file global __ignore_empty_install_directory + global __prefer_liberation_payloads + global __server_port if PREFERENCES_PATH.exists(): try: @@ -35,16 +39,24 @@ def init(): __ignore_empty_install_directory = pref_data.get( "ignore_empty_install_directory", False ) + __prefer_liberation_payloads = pref_data.get( + "prefer_liberation_payloads", False + ) + __server_port = pref_data.get("server_port", 16880) is_first_start = False except (KeyError, json.JSONDecodeError): __dcs_saved_game_directory = "" __dcs_installation_directory = "" __last_save_file = "" __ignore_empty_install_directory = False + __prefer_liberation_payloads = False + __server_port = 16880 is_first_start = True else: __last_save_file = "" __ignore_empty_install_directory = False + __prefer_liberation_payloads = False + __server_port = 16880 try: __dcs_saved_game_directory = ( dcs.installation.get_dcs_saved_games_directory() @@ -61,16 +73,22 @@ def init(): __dcs_installation_directory = "" is_first_start = True - persistency.setup(__dcs_saved_game_directory) + persistency.setup( + __dcs_saved_game_directory, __prefer_liberation_payloads, __server_port + ) return is_first_start -def setup(saved_game_dir, install_dir): +def setup(saved_game_dir, install_dir, prefer_liberation_payloads, port): global __dcs_saved_game_directory global __dcs_installation_directory + global __prefer_liberation_payloads + global __server_port __dcs_saved_game_directory = saved_game_dir __dcs_installation_directory = install_dir - persistency.setup(__dcs_saved_game_directory) + __prefer_liberation_payloads = prefer_liberation_payloads + __server_port = port + persistency.setup(saved_game_dir, prefer_liberation_payloads, port) def setup_last_save_file(last_save_file): @@ -83,11 +101,14 @@ def save_config(): global __dcs_installation_directory global __last_save_file global __ignore_empty_install_directory + global __server_port pref_data = { "saved_game_dir": __dcs_saved_game_directory, "dcs_install_dir": __dcs_installation_directory, "last_save_file": __last_save_file, "ignore_empty_install_directory": __ignore_empty_install_directory, + "prefer_liberation_payloads": __prefer_liberation_payloads, + "server_port": __server_port, } PREFERENCES_PATH.parent.mkdir(exist_ok=True, parents=True) with PREFERENCES_PATH.open("w") as prefs: @@ -104,6 +125,16 @@ def get_saved_game_dir(): return __dcs_saved_game_directory +def prefer_liberation_payloads(): + global __prefer_liberation_payloads + return __prefer_liberation_payloads + + +def server_port(): + global __server_port + return __server_port + + def ignore_empty_install_directory(): global __ignore_empty_install_directory return __ignore_empty_install_directory diff --git a/qt_ui/main.py b/qt_ui/main.py index f8d8c91d..1e4757ee 100644 --- a/qt_ui/main.py +++ b/qt_ui/main.py @@ -61,18 +61,6 @@ def inject_custom_payloads(user_path: Path) -> None: PayloadDirectories.set_preferred(user_path / "MissionEditor" / "UnitPayloads") -def inject_mod_payloads(mod_path: Path) -> None: - if mod_path.exists(): - payloads = mod_path - else: - raise RuntimeError( - f"Could not find mod payloads at {mod_path}." - f"Aircraft will have no payloads." - ) - # We configure these as preferred so the mod's loadouts override the stock ones. - PayloadDirectories.set_preferred(payloads) - - def on_game_load(game: Optional[Game]) -> None: EventStream.drain() EventStream.put_nowait(GameUpdateEvents().game_loaded(game)) @@ -454,7 +442,8 @@ def main(): dump_task_priorities() return - with Server().run_in_thread(): + liberation_install.init() + with Server(liberation_install.server_port()).run_in_thread(): run_ui(game, UiFlags(args.dev, args.show_sim_speed_controls)) diff --git a/qt_ui/widgets/QTopPanel.py b/qt_ui/widgets/QTopPanel.py index bb97a192..5304121b 100644 --- a/qt_ui/widgets/QTopPanel.py +++ b/qt_ui/widgets/QTopPanel.py @@ -166,6 +166,8 @@ class QTopPanel(QFrame): with logged_duration("Skipping turn"): self.game.pass_turn(no_action=True) GameUpdateSignal.get_instance().updateGame(self.game) + state = self.game_model.game.check_win_loss() + GameUpdateSignal.get_instance().gameStateChanged(state) self.proceedButton.setEnabled(True) def negative_start_packages(self, now: datetime) -> List[Package]: diff --git a/qt_ui/widgets/map/QLiberationMap.py b/qt_ui/widgets/map/QLiberationMap.py index c1e9e616..49073feb 100644 --- a/qt_ui/widgets/map/QLiberationMap.py +++ b/qt_ui/widgets/map/QLiberationMap.py @@ -8,6 +8,7 @@ from PySide6.QtWebEngineCore import QWebEnginePage, QWebEngineSettings from PySide6.QtWebEngineWidgets import QWebEngineView from game.server.settings import ServerSettings +from qt_ui.liberation_install import server_port from qt_ui.models import GameModel @@ -44,7 +45,7 @@ class QLiberationMap(QWebEngineView): url = QUrl("http://localhost:3000") else: url = QUrl.fromLocalFile(str(Path("client/build/index.html").resolve())) - server_settings = ServerSettings.get() + server_settings = ServerSettings.get(server_port()) host = server_settings.server_bind_address if host.startswith("::"): host = f"[{host}]" diff --git a/qt_ui/windows/AirWingDialog.py b/qt_ui/windows/AirWingDialog.py index 3c56607f..87f902f3 100644 --- a/qt_ui/windows/AirWingDialog.py +++ b/qt_ui/windows/AirWingDialog.py @@ -19,6 +19,8 @@ from PySide6.QtWidgets import ( ) from game.ato.flight import Flight +from game.server import EventStream +from game.sim import GameUpdateEvents from game.squadrons import Squadron from game.theater import ConflictTheater from qt_ui.delegates import TwoColumnRowDelegate @@ -258,6 +260,9 @@ class AirWingTabs(QTabWidget): def open_awcd(self, gm: GameModel): AirWingConfigurationDialog(gm.game, True, self).exec_() + events = GameUpdateEvents().begin_new_turn() + EventStream.put_nowait(events) + gm.ato_model.on_sim_update(events) class AirWingDialog(QDialog): diff --git a/qt_ui/windows/QLiberationWindow.py b/qt_ui/windows/QLiberationWindow.py index f6a03968..e4de9ba0 100644 --- a/qt_ui/windows/QLiberationWindow.py +++ b/qt_ui/windows/QLiberationWindow.py @@ -569,7 +569,7 @@ class QLiberationWindow(QMainWindow): LAYOUTS.import_templates() def showLogsDialog(self): - self.dialog = QLogsWindow() + self.dialog = QLogsWindow(self) self.dialog.show() def onDebriefing(self, debrief: Debriefing): diff --git a/qt_ui/windows/logs/QLogsWindow.py b/qt_ui/windows/logs/QLogsWindow.py index b33fe77a..6d34f743 100644 --- a/qt_ui/windows/logs/QLogsWindow.py +++ b/qt_ui/windows/logs/QLogsWindow.py @@ -8,6 +8,7 @@ from PySide6.QtWidgets import ( QPlainTextEdit, QVBoxLayout, QPushButton, + QWidget, ) from qt_ui.logging_handler import HookableInMemoryHandler @@ -21,8 +22,8 @@ class QLogsWindow(QDialog): clear_button: QPushButton _logging_handler: typing.Optional[HookableInMemoryHandler] - def __init__(self): - super().__init__() + def __init__(self, parent: QWidget): + super().__init__(parent) self.setWindowTitle("Logs") self.setMinimumSize(400, 100) diff --git a/qt_ui/windows/mission/QAutoCreateDialog.py b/qt_ui/windows/mission/QAutoCreateDialog.py index 350c1d59..28eca71c 100644 --- a/qt_ui/windows/mission/QAutoCreateDialog.py +++ b/qt_ui/windows/mission/QAutoCreateDialog.py @@ -47,76 +47,100 @@ class QAutoCreateDialog(QDialog): hbox = QHBoxLayout() self.primary_combobox = QComboBox() + self.primary_combobox.setFixedWidth(100) self.primary_count = _spinbox_template() + self.primary_type = QComboBox() nr_targets = len(self.package.target.strike_targets) count = max(1, min(4, nr_targets // 2) + nr_targets % 1) if nr_targets else 4 self.primary_count.setValue(count) hbox.addWidget(self.primary_combobox) hbox.addWidget(self.primary_count) + hbox.addWidget(self.primary_type) self.layout.addLayout(hbox) self.checkboxes = {} hbox = QHBoxLayout() - self.tarcap = QCheckBox() - self.tarcap.setText("TARCAP") + self.tarcap = self._create_checkbox("TARCAP") self.tarcap_count = _spinbox_template() hbox.addWidget(self.tarcap) hbox.addWidget(self.tarcap_count) + self.tarcap_type = self._create_type_selector(FlightType.TARCAP) + hbox.addWidget(self.tarcap_type) self.layout.addLayout(hbox) - self.checkboxes[self.tarcap] = (FlightType.TARCAP, self.tarcap_count) + self.checkboxes[self.tarcap] = ( + FlightType.TARCAP, + self.tarcap_count, + self.tarcap_type, + ) hbox = QHBoxLayout() - self.escort = QCheckBox() - self.escort.setText("Escort") + self.escort = self._create_checkbox("Escort") self.escort_count = _spinbox_template() hbox.addWidget(self.escort) hbox.addWidget(self.escort_count) + self.escort_type = self._create_type_selector(FlightType.ESCORT) + hbox.addWidget(self.escort_type) self.layout.addLayout(hbox) - self.checkboxes[self.escort] = (FlightType.ESCORT, self.escort_count) + self.checkboxes[self.escort] = ( + FlightType.ESCORT, + self.escort_count, + self.escort_type, + ) hbox = QHBoxLayout() - self.sead_escort = QCheckBox() - self.sead_escort.setText("SEAD Escort") + self.sead_escort = self._create_checkbox("SEAD Escort") self.sead_escort_count = _spinbox_template() hbox.addWidget(self.sead_escort) hbox.addWidget(self.sead_escort_count) + self.sead_escort_type = self._create_type_selector(FlightType.SEAD_ESCORT) + hbox.addWidget(self.sead_escort_type) + self.layout.addLayout(hbox) self.checkboxes[self.sead_escort] = ( FlightType.SEAD_ESCORT, self.sead_escort_count, + self.sead_escort_type, ) hbox = QHBoxLayout() - self.sead = QCheckBox() - self.sead.setText("SEAD") + self.sead = self._create_checkbox("SEAD") self.sead_count = _spinbox_template() hbox.addWidget(self.sead) hbox.addWidget(self.sead_count) + self.sead_type = self._create_type_selector(FlightType.SEAD) + hbox.addWidget(self.sead_type) self.layout.addLayout(hbox) - self.checkboxes[self.sead] = (FlightType.SEAD, self.sead_count) + self.checkboxes[self.sead] = (FlightType.SEAD, self.sead_count, self.sead_type) hbox = QHBoxLayout() - self.sead_sweep = QCheckBox() - self.sead_sweep.setText("SEAD Sweep") + self.sead_sweep = self._create_checkbox("SEAD Sweep") self.sead_sweep_count = _spinbox_template() hbox.addWidget(self.sead_sweep) hbox.addWidget(self.sead_sweep_count) + self.sead_sweep_type = self._create_type_selector(FlightType.SEAD_SWEEP) + hbox.addWidget(self.sead_sweep_type) self.layout.addLayout(hbox) self.checkboxes[self.sead_sweep] = ( FlightType.SEAD_SWEEP, self.sead_sweep_count, + self.sead_sweep_type, ) hbox = QHBoxLayout() - self.refueling = QCheckBox() - self.refueling.setText("Refueling") + self.refueling = self._create_checkbox("Refueling") self.refueling_count = _spinbox_template() self.refueling_count.setValue(1) hbox.addWidget(self.refueling) hbox.addWidget(self.refueling_count) + self.refueling_type = self._create_type_selector(FlightType.REFUELING) + hbox.addWidget(self.refueling_type, 1) self.layout.addLayout(hbox) - self.checkboxes[self.refueling] = (FlightType.REFUELING, self.refueling_count) + self.checkboxes[self.refueling] = ( + FlightType.REFUELING, + self.refueling_count, + self.refueling_type, + ) self.create_button = QPushButton("Create") self.create_button.setProperty("style", "start-button") @@ -139,6 +163,28 @@ class QAutoCreateDialog(QDialog): if mt in primary_tasks: self.primary_combobox.addItem(mt.value, mt) self.primary_combobox.setCurrentIndex(0) + self._load_aircraft_types() + + @staticmethod + def _create_checkbox(label: str) -> QCheckBox: + cb = QCheckBox(label) + cb.setFixedWidth(100) + return cb + + def _create_type_selector(self, flight_type: FlightType) -> QComboBox: + airwing = self.game.blue.air_wing + cb = QComboBox() + for ac in airwing.best_available_aircrafts_for(flight_type): + cb.addItem(ac.variant_id, ac) + return cb + + def _load_aircraft_types(self): + self.primary_type.clear() + for ac in self.game.blue.air_wing.best_available_aircrafts_for( + self.primary_combobox.currentData() + ): + self.primary_type.addItem(ac.variant_id, ac) + self.primary_type.setCurrentIndex(0) def on_primary_task_changed(self) -> None: disable = self.primary_combobox.currentData() == FlightType.CAS @@ -147,15 +193,26 @@ class QAutoCreateDialog(QDialog): if disable: cb.setChecked(False) cb.setDisabled(disable) + self._load_aircraft_types() def on_create_clicked(self) -> None: pf: List[ProposedFlight] = [] count = self.primary_count.value() - pf.append(ProposedFlight(self.primary_combobox.currentData(), count)) + pf.append( + ProposedFlight( + self.primary_combobox.currentData(), + count, + preferred_type=self.primary_type.currentData(), + ) + ) for cb in self.checkboxes: if cb.isChecked(): - type, spinner = self.checkboxes[cb] - pf.append(ProposedFlight(type, spinner.value())) + type, spinner, ac_box = self.checkboxes[cb] + pf.append( + ProposedFlight( + type, spinner.value(), preferred_type=ac_box.currentData() + ) + ) with MultiEventTracer() as tracer: with tracer.trace(f"Auto-plan package"): pm = ProposedMission(self.package.target, pf, asap=True) diff --git a/qt_ui/windows/mission/QPackageDialog.py b/qt_ui/windows/mission/QPackageDialog.py index 22350929..75412f92 100644 --- a/qt_ui/windows/mission/QPackageDialog.py +++ b/qt_ui/windows/mission/QPackageDialog.py @@ -237,11 +237,12 @@ class QPackageDialog(QDialog): auto_create_dialog = QAutoCreateDialog( self.game, self.package_model, parent=self.window() ) - auto_create_dialog.exec_() - for f in self.package_model.package.flights: - EventStream.put_nowait(GameUpdateEvents().new_flight(f)) - self.package_model.update_tot() - self.package_changed.emit() + if auto_create_dialog.exec_() == QDialog.DialogCode.Accepted: + for f in self.package_model.package.flights: + EventStream.put_nowait(GameUpdateEvents().new_flight(f)) + self.package_model.update_tot() + self.package_changed.emit() + self.auto_create_button.setDisabled(True) def on_change_name(self) -> None: self.package_model.package.custom_name = self.package_name_text.text() diff --git a/qt_ui/windows/preferences/QLiberationPreferences.py b/qt_ui/windows/preferences/QLiberationPreferences.py index 13b94e6e..ed56f7af 100644 --- a/qt_ui/windows/preferences/QLiberationPreferences.py +++ b/qt_ui/windows/preferences/QLiberationPreferences.py @@ -11,6 +11,8 @@ from PySide6.QtWidgets import ( QMessageBox, QPushButton, QVBoxLayout, + QCheckBox, + QSpinBox, ) from qt_ui import liberation_install, liberation_theme @@ -40,6 +42,14 @@ class QLiberationPreferences(QFrame): self.themeSelect = QComboBox() [self.themeSelect.addItem(y["themeName"]) for x, y in THEMES.items()] + preference = liberation_install.prefer_liberation_payloads() + self.prefer_liberation_payloads = preference if preference else False + self.payloads_cb = QCheckBox() + self.payloads_cb.setChecked(self.prefer_liberation_payloads) + + self.port = liberation_install.server_port() + self.port_input = QSpinBox() + self.initUi() def initUi(self): @@ -73,6 +83,25 @@ class QLiberationPreferences(QFrame): layout.addWidget(self.themeSelect, 4, 1, alignment=Qt.AlignmentFlag.AlignRight) self.themeSelect.setCurrentIndex(get_theme_index()) + layout.addWidget( + QLabel("Prefer custom Liberation payloads:"), + 5, + 0, + alignment=Qt.AlignmentFlag.AlignLeft, + ) + layout.addWidget(self.payloads_cb, 5, 1, alignment=Qt.AlignmentFlag.AlignRight) + + layout.addWidget( + QLabel("Server port (restart required):"), + 6, + 0, + alignment=Qt.AlignmentFlag.AlignLeft, + ) + layout.addWidget(self.port_input, 6, 1, alignment=Qt.AlignmentFlag.AlignRight) + self.port_input.setRange(1, 2**16 - 1) + self.port_input.setValue(self.port) + self.port_input.setStyleSheet("QSpinBox{ width: 50 }") + main_layout.addLayout(layout) main_layout.addStretch() @@ -98,6 +127,8 @@ class QLiberationPreferences(QFrame): print("Applying changes") self.saved_game_dir = self.edit_saved_game_dir.text() self.dcs_install_dir = self.edit_dcs_install_dir.text() + self.prefer_liberation_payloads = self.payloads_cb.isChecked() + self.port = self.port_input.value() set_theme_index(self.themeSelect.currentIndex()) if not os.path.isdir(self.saved_game_dir): @@ -153,7 +184,12 @@ class QLiberationPreferences(QFrame): error_dialog.exec_() return False - liberation_install.setup(self.saved_game_dir, self.dcs_install_dir) + liberation_install.setup( + self.saved_game_dir, + self.dcs_install_dir, + self.prefer_liberation_payloads, + self.port, + ) liberation_install.save_config() liberation_theme.save_theme_config() return True diff --git a/requirements.txt b/requirements.txt index 5b81a493..8fe27802 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ click==8.1.7 colorama==0.4.6 distlib==0.3.8 Faker==22.6.0 -fastapi==0.109.1 +fastapi==0.109.2 filelock==3.13.1 h11==0.14.0 httptools==0.6.1 @@ -32,15 +32,15 @@ pluggy==1.4.0 pre-commit==3.6.0 pydantic==2.6.0 pydantic-settings==2.1.0 --e git+https://github.com/dcs-retribution/pydcs@0bcdeecb4bd9032878b4dbf6fedac5a951429e26#egg=pydcs +-e git+https://github.com/dcs-retribution/pydcs@353f5b177dd406122a83e8572fd6ca54adf84389#egg=pydcs pyinstaller==5.13.2 pyinstaller-hooks-contrib==2024.0 pyparsing==3.1.1 pyproj==3.6.1 pyshp==2.3.1 -PySide6==6.6.1 -PySide6-Addons==6.6.1 -PySide6-Essentials==6.6.1 +PySide6==6.4.3 +PySide6-Addons==6.4.3 +PySide6-Essentials==6.4.3 pytest==8.0.0 pytest-cov==4.1.0 python-dateutil==2.8.2 @@ -48,10 +48,10 @@ python-dotenv==1.0.1 pywin32-ctypes==0.2.2 PyYAML==6.0.1 Shapely==2.0.2 -shiboken6==6.6.1 +shiboken6==6.4.3 six==1.16.0 sniffio==1.3.0 -starlette==0.35.1 +starlette==0.36.3 suntime==1.2.5 tabulate==0.9.0 text-unidecode==1.3 diff --git a/resources/campaigns/RetakeTheFalklands.miz b/resources/campaigns/RetakeTheFalklands.miz index 6ab8fcde..aa5be875 100644 Binary files a/resources/campaigns/RetakeTheFalklands.miz and b/resources/campaigns/RetakeTheFalklands.miz differ diff --git a/resources/campaigns/RetakeTheFalklands.yaml b/resources/campaigns/RetakeTheFalklands.yaml index cc7f45c9..49d7c3e7 100644 --- a/resources/campaigns/RetakeTheFalklands.yaml +++ b/resources/campaigns/RetakeTheFalklands.yaml @@ -7,7 +7,7 @@ recommended_enemy_faction: China/Argentina Falklands Occupation Force description:
Argentina and China have taken the Falklands by surprise. Currently on the East Coast of the United States for training, an Invicible-class carrier is steaming down to the South Atlantic to retake the islands, with the help of the United States Carrier Group. A beachhead has been established on the small air base of San Julian where the USAF has parked a small number of F-15Es and F-16 to assist.
Retake the Falklands, and proceed inland to neutralize the enemy.
Author's notes
For this campaign, you can use UK Harrier and Apache skins, and Argentine JF-17 and Mirage Skins. Original campaign Gran Polvorin by Fuzzle.
This mission was modified by HolyOrangeJuice [OscarJuliet] for the WRL Group. Join us for weekly PVE events. werunliberation.com
Original Battle for Golan Heights by Khopa.
This modified campaign does not represent any historical time period or events. Attack from Ramat-David and eliminate the enemy around Damascus.
All WRL Campaigns use high budget and high income to focus on the PVE goals to eliminate the enemy. Use lower starting money and income for increased difficulty.
" +description: "This campaign is the gold standard of WRL campaigns. This campaign will always have the latest retribution additions. Consider this a feature complete campaign as it progresses through updates. Play Battle 4 Gerogia as a beginner mission. Play this one for an advanced experience
This mission was heavily modified by HolyOrangeJuice [OscarJuliet] for the WRL Group. Join us for weekly PVE events. werunliberation.com
Original Battle for Golan Heights by Khopa.
This modified campaign does not represent any historical time period or events. Attack from Ramat-David and eliminate the enemy around Damascus.
All WRL Campaigns use high budget and high income to focus on the PVE goals to eliminate the enemy. Use lower starting money and income for increased difficulty.
" miz: WRL_AssaultonDamascus.miz performance: 2 version: "10.7" #CTLD Zones Added @@ -13,9 +13,102 @@ recommended_player_money: 5000 recommended_enemy_money: 2000 recommended_player_income_multiplier: 5.0 recommended_enemy_income_multiplier: 1.0 -advanced_iads: false settings: max_frontline_width: 30 +advanced_iads: true # Campaign has connection_nodes / power_sources / command_centers +iads_config: +#REDFOR DEFENSE MARJ AIRBASE AREA + - M-COMMAND-1: + - M-POWER-1 + - M-POWER-2 + - M-TOWER-1 + - M-TOWER-2 + - M-EWR-1: + - M-POWER-1 + - M-TOWER-1 + - M-EWR-2: + - M-POWER-1 + - M-TOWER-1 + - M-EWR-3: + - M-POWER-2 + - M-TOWER-2 + - M-SAM-1: + - M-POWER-1 + - M-TOWER-1 + - M-SAM-2: + - M-POWER-1 + - M-TOWER-1 + - M-SAM-3: + - M-POWER-2 + - M-TOWER-2 + - M-SAM-4: + - M-POWER-2 + - M-TOWER-2 + - M-SAM-5: + - M-POWER-2 + - M-TOWER-2 + - M-SAM-6: + - M-POWER-2 + - M-TOWER-2 + #REDFOR DEFENSE DAMASCUS AIRBASE AREA + - D-COMMAND-1: + - D-POWER-1 + - D-POWER-2 + - D-TOWER-1 + - D-TOWER-2 + - D-EWR-1: + - D-POWER-1 + - D-TOWER-1 + - D-EWR-2: + - D-POWER-2 + - D-TOWER-2 + - D-EWR-3: + - D-POWER-2 + - D-TOWER-2 + - D-SAM-1: + - D-POWER-1 + - D-TOWER-1 + - D-SAM-2: + - D-POWER-2 + - D-TOWER-2 + - D-SAM-3: + - D-POWER-1 + - D-TOWER-1 + - D-SAM-4: + - D-POWER-2 + - D-TOWER-2 + #REDFOR DEFENSE AL-DUMAYR AIRBASE AREA + - A-COMMAND-1: + - A-POWER-1 + - A-TOWER-1 + - A-EWR-1: + - A-POWER-1 + - A-TOWER-1 + - A-EWR-2: + - A-POWER-1 + - A-TOWER-1 + - A-SAM-1: + - A-POWER-1 + - A-TOWER-1 + - A-SAM-2: + - A-POWER-1 + - A-TOWER-1 + #BLUEFOR RAMAT DEFENSE + - R-COMMAND-1: + - R-POWER-1 + - R-TOWER-1 + - RAMAT1: + - R-POWER-1 + - R-TOWER-1 + - RAMAT2: + - R-POWER-1 + - R-TOWER-1 + - RAMAT3: + - R-POWER-1 + - R-TOWER-1 + - RAMAT4: + - R-POWER-1 + - R-TOWER-1 squadrons: CVN-74 John Stennis: - primary: BARCAP @@ -75,7 +168,12 @@ squadrons: secondary: any aircraft: - F-117A Nighthawk - size: 5 + size: 8 + - primary: BARCAP + secondary: air-to-air + aircraft: + - F-15C Eagle + size: 16 # Ramat-David 30: - primary: BAI @@ -108,88 +206,103 @@ squadrons: aircraft: - AV-8B Harrier II Night Attack size: 16 - # Golan South -# Golan South: - # Golan North Golan North: - primary: BAI secondary: air-to-ground aircraft: - A Company, 1-211th ARB #AH-64D Apache Longbow - size: 10 + size: 8 - primary: BAI secondary: air-to-ground aircraft: - Mi-24P Hind-F - size: 10 + size: 8 - primary: BAI secondary: air-to-ground aircraft: - Ka-50 Hokum III - size: 10 + size: 8 + - primary: Transport + secondary: air-to-ground + aircraft: + - HMLA-169 (UH-1H) #UH-1H Iroquois + size: 8 + # Golan South + Golan South: + - primary: BAI + secondary: air-to-ground + aircraft: + - AH-1W SuperCobra + size: 4 - primary: BAI secondary: air-to-ground aircraft: - SA 342M Gazelle - size: 4 + size: 8 - primary: Transport - secondary: any - aircraft: - - HMLA-169 (UH-1H) #UH-1H Iroquois - size: 4 - - primary: Transport - secondary: any + secondary: air-to-ground aircraft: - Mi-8MTV2 Hip - size: 4 - # Marj Ruhayyil - 23: - - primary: BARCAP - secondary: air-to-air - aircraft: - - MiG-21bis Fishbed-N - size: 16 - # Al-Dumayr - 9: - - primary: BARCAP - secondary: any - aircraft: - - Su-27 Flanker-B - size: 16 - # Khalkhalah - 18: - - primary: BARCAP - secondary: any - aircraft: - - MiG-23MLD Flogger-K - size: 16 + size: 8 # Damascus 7: - primary: BARCAP - secondary: any + secondary: air-to-air aircraft: - MiG-29S Fulcrum-C - size: 16 + size: 12 + - primary: SEAD + secondary: air-to-ground + aircraft: + - Su-34 Fullback + size: 12 - primary: Strike secondary: air-to-ground aircraft: - Su-24M Fencer-D - size: 16 - - primary: SEAD - secondary: air-to-ground - aircraft: - - Su-25T Frogfoot - size: 16 + size: 12 + # Marj Ruhayyil +# 23: + # Al-Dumayr +# 9: + # Khalkhalah +# 18: + # MEZZEH +# 25: + # FOB ALPHA +# FOB ALPHA: + # FOB BRAVO +# FOB BRAVO: + # MARJ AS SULTAN SOUTH +# 8: + # MARJ AS SULTAN NORTH +# 22: + # QABR AS SITT +# 29: ground_forces: - KHALK1: SA-11 - KHALK2: SA-2/S-75 - DAMASCUS1: SA-11 - DUMAYR1: SA-2/S-75 - DUMAYR2: SA-2/S-75 - DUMAYR3: SA-10/S-300PS + M-SAM-1: SA-11 + M-SAM-2: SA-11 + M-SAM-3: SA-2/S-75 + M-SAM-4: SA-3/S-125 + M-SAM-5: SA-3/S-125 + M-SAM-6: SA-3/S-125 + M-SHORAD-1: SA-15 SHORAD +# M-AAA-1: + D-SAM-1: SA-2/S-75 + D-SAM-2: SA-2/S-75 + D-SAM-3: SA-6 + D-SAM-4: SA-3/S-125 + D-SHORAD-1: SA-15 SHORAD +# D-AAA-1: + K-SHORAD-1: SA-15 SHORAD +# K-AAA-1: + FOB-SHORAD-1: SA-15 SHORAD +# FOB-AAA-1: + A-SHORAD-1: SA-15 SHORAD RAMAT1: Patriot - RAMAT2: Hawk - RAMAT3: Patriot + RAMAT2: Patriot + RAMAT3: NASAMS AIM-120C + RAMAT4: NASAMS AIM-120C GSOUTH1: NASAMS AIM-120C - GSOUTH2: Hawk + GSOUTH2: NASAMS AIM-120C GNORTH1: NASAMS AIM-120C \ No newline at end of file diff --git a/resources/campaigns/WRL_Battle4SyriaNorth.miz b/resources/campaigns/WRL_Battle4SyriaNorth.miz index fc355c4f..f15ae469 100644 Binary files a/resources/campaigns/WRL_Battle4SyriaNorth.miz and b/resources/campaigns/WRL_Battle4SyriaNorth.miz differ diff --git a/resources/campaigns/WRL_Battle4SyriaNorth.yaml b/resources/campaigns/WRL_Battle4SyriaNorth.yaml index 02ef062b..b47795f9 100644 --- a/resources/campaigns/WRL_Battle4SyriaNorth.yaml +++ b/resources/campaigns/WRL_Battle4SyriaNorth.yaml @@ -1,28 +1,25 @@ --- -name: Syria - WRL - Battle For Syria North (1.0) #1.0 Release with Player F15e +name: Syria - WRL - Battle For Syria North (v1.2) #1.2 Complete Mission Overhaul - Frontlines Removed - CTLD or C130s are expected for base capture / Consider victory by destroying all airbases. theater: Syria authors: HolyOrangeJuice -description: "This mission was modified by HolyOrangeJuice [OscarJuliet] for the WRL Group. Original Mission by Sith1144. Join us for weekly PVE events. werunliberation.com
This modification of the mission is not meant to represent historical accuracy. An exciting battle on the Northern part of the Syria map.
All WRL Campaigns use high budget and high income to focus on the PVE goals to eliminate the enemy. Use lower starting money and income for increased difficulty
" +description: "This mission was heavily modified by HolyOrangeJuice [OscarJuliet] for the WRL Group. Original Mission by Sith1144. Join us for weekly PVE events. werunliberation.com
This modification of the mission is not meant to represent historical accuracy. An exciting battle on the Northern part of the Syria map.
All WRL Campaigns use high budget and high income to focus on the PVE goals to eliminate the enemy. Use lower starting money and income for increased difficulty
" recommended_player_faction: WRL - Task Force Blue recommended_enemy_faction: WRL - Task Force Red recommended_start_date: 2019-06-04 miz: WRL_Battle4SyriaNorth.miz performance: 2 -version: "10.7" #No CTLD zones, campaign is too large for CTLD focus +version: "10.7" #CTLD ZONES ADDED recommended_player_money: 5000 recommended_enemy_money: 2000 recommended_player_income_multiplier: 5.0 recommended_enemy_income_multiplier: 1.0 -advanced_iads: true # Campaign has connection_nodes / power_sources / command_centers -#IADS: EWR and C2 get power generators. batteries have their own generators. +advanced_iads: true iads_config: # NATO IADS -#EWRs - NATO EWR-1: - NATO IADS Command - NATO EWR: - NATO IADS Command -# SAMs - NATO SAM: - NATO IADS Command - NATO SAM-1: @@ -39,202 +36,129 @@ iads_config: - NATO IADS Command - NATO SAM-7: - NATO IADS Command -# Yellow defense zone (Gaziantep-Minakh) -#EWRs - - YellowEWRN: #mountainrange (north) - - YellowPPW - - YellowControlN - - YellowEWRS: #mountainrange (center) - - YellowPPW - - YellowControlW - - YellowEWRC: # internal - - HamidiyeControl - - GaziantepControl - - GaziantepPP - - GaziantepAirControl: - - GaziantepControl - - GaziantepPP -# The air defense barrier behind the mountains - - YellowBarrierN: - - YellowControlN - - YellowBarrierC1: - - YellowControlW - - YellowBarrierC2: - - YellowControlW - - YellowBarrierS: - - YellowControlW - - YellowBarrierAAA: - - YellowControlW -# the central long range SAM and its point defenses - - YellowLongRangeSAMPointDefense: - - HamidiyeControl - - YellowLongRangeSAM: - - HamidiyeControl - - YellowLongRangeSAMAAA: - - HamidiyeControl -# the defenses around Gaziantep airfield - - GAZSAMN: - - GaziantepControl - - GAZSAMW: - - GaziantepControl -# the defenses around Minakh airfield - - MinakhSAM1: - - MinakhControl - - MinakhSAM2: - - MinakhControl -#C2 links - - YellowControlN: - - HamidiyeControl - - YellowControlW: - - HamidiyeControl - - YellowControlN - - YellowZoneCommand: - - GaziantepControl - - MinakhControl - - HamidiyeControl - - GaziantepPP - - GaziantepAirControl -# Green Defense Zone (HATAY) -# EWRs - - CoastalEWRN: - - HatayControl - - AntakyaPower - - CoastalEWRS: - - SamandagControl - - AntakyaPower -# The air defense barrier behind the mountains - - GreenBarrierSAM: - - SamandagControl - - GreenBarrierSAM-1: - - SamandagControl - - GreenBarrierSAM-2: - - HatayControl - - GreenBarrierSAM-3: - - HatayControl - - GreenBarrierSAM-4: - - HatayControl -# Coastal Defenses - - GreenSAM-2: - - SamandagControl - - GreenSAM-3: - - SamandagControl - - GreenSAM-4: - - SamandagControl -# Hatay Airfield - - HataySAM: - - HatayControl - - HataySAM-1: - - HatayControl - - HatayAAA: - - HatayControl -# Industrial/Command zone - - GreenSAM: - - IdlibControl - - GreenZoneCommand - - GreenSAM-2: - - IdlibControl - - GreenZoneCommand -# long range battery and defenses - - GreenZoneSAM: - - ReyhanliControl - - GreenZoneSAMDefense: - - ReyhanliControl -# C2 links - - GreenZoneCommand: - - IdlibControl - - IdlibPower - - SamandagControl - - HatayControl: - - ReyhanliControl - - SamandagControl - - AntakyaPower - - SamandagControl: - - AntakyaPower - - IdlibControl: - - ReyhanliControl - - SamandagControl - - IdlibPower - - ReyhanliControl: - - IdlibPower -# Pink zone (Aleppo) -# EWR - - Abu al-Duhur Air Control: - - Al Safira Power - - Aleppo Air Control: - - Aleppo Power - - Kuweires Air Control: - - Al Safira Power - - Aleppo Power - - Jirah Air Control: - - Al Safira Power -# Aleppo city defenses - - AleppoSAM: - - AleppoCommand - - Aleppo Control - - AleppoSAM-1: - - AleppoCommand - - Aleppo Control - - AleppoSAM-2: - - AleppoCommand - - Aleppo Control - - AleppoSAM-3: - - AleppoCommand - - Aleppo Control - - AleppoSAM-4: - - AleppoCommand - - Aleppo Control - - AleppoSAM-5: - - AleppoCommand - - Aleppo Control - - AleppoSAM-6: - - AleppoCommand - - Aleppo Control - - AleppoSAM-7: - - AleppoCommand - - Aleppo Control -# Long Range SAM - - Pink SAM: - - Al Safira Power - - Aleppo Control - - AlSafiraCommand - - AlSafiraPD: - - Aleppo Control - - AlSafiraCommand -# Abu al-Duhur - - AbuSAM: - - Abu al-Duhur control - - AbuSAM-1: - - Abu al-Duhur control -# Kuweires - - KuweiresSAM: - - KuweiresControl -# Jirah - - JirahSAM: - - JirahControl - - JirahSAM-1: - - JirahControl - - JirahSAM-2: - - JirahControl -# C2 links - - AleppoCommand: - - Aleppo Power - - Al Safira Power - - Aleppo Control - - AlSafiraCommand: - - Al Safira Power - - Aleppo Power - - Aleppo Control - - KuweiresControl: - - Al Safira Power - - Aleppo Control - - JirahControl: - - Al Safira Power - - KuweiresControl - - Abu al-Duhur control: - - Aleppo Power - - Aleppo Control - - Aleppo Control: - - Aleppo Power +#BLUE DEFENSE AREA - HINT: Go after the power stations + - B-COMMAND-1: + - B-POWER-1 + - B-TOWER-1 + - B-POWER-2 + - B-TOWER-2 + - B-SAM-1: + - B-POWER-1 + - B-TOWER-1 + - B-SAM-2: + - B-POWER-1 + - B-TOWER-1 + - B-SAM-3: + - B-POWER-1 + - B-TOWER-1 + - B-SAM-4: + - B-POWER-2 + - B-TOWER-2 + - B-SAM-5: #SA10 + - B-POWER-2 + - B-TOWER-2 + - B-EWR-1: + - B-POWER-1 + - B-TOWER-1 + - B-EWR-2: + - B-POWER-1 + - B-TOWER-1 +#RED DEFENSE AREA - HINT: Go after the power stations + - R-COMMAND-1: + - R-POWER-1 + - R-TOWER-1 + - R-POWER-2 + - R-TOWER-2 + - R-SAM-1: + - R-POWER-1 + - R-TOWER-1 + - R-SAM-2: + - R-POWER-1 + - R-TOWER-1 + - R-SAM-3: + - R-POWER-1 + - R-TOWER-1 + - R-SAM-4: + - R-POWER-1 + - R-TOWER-1 + - R-SAM-5: + - R-POWER-1 + - R-TOWER-1 + - R-SAM-6: + - R-POWER-1 + - R-TOWER-1 + - R-SAM-7: + - R-POWER-1 + - R-TOWER-1 + - R-SAM-8: + - R-POWER-2 + - R-TOWER-2 + - R-SAM-9: #SA-10 + - R-POWER-2 + - R-TOWER-2 +#YELLOW DEFNESE AREA - HINT: Go after the command bunkers + - Y-COMMAND-1: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-TOWER-3 + - Y-COMMAND-2: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-TOWER-3 + - Y-SAM-1: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-SAM-2: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-SAM-3: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-SAM-4: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-SAM-5: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-SAM-6: + - Y-POWER-1 + - Y-TOWER-1 + - Y-POWER-2 + - Y-TOWER-2 + - Y-SAM-7: + - Y-POWER-2 + - Y-TOWER-2 + - Y-TOWER-3 + - Y-SAM-8: + - Y-POWER-2 + - Y-TOWER-2 + - Y-TOWER-3 + - Y-SAM-9: + - Y-POWER-2 + - Y-TOWER-2 + - Y-TOWER-3 + - Y-SAM-10: + - Y-POWER-2 + - Y-TOWER-2 + - Y-TOWER-3 + - Y-SAM-11: #SA-5 + - Y-POWER-2 + - Y-TOWER-2 + - Y-TOWER-3 squadrons: #Incirlik 16: @@ -340,8 +264,8 @@ squadrons: aircraft: - Mi-8MTV2 Hip size: 4 - #carrier - Blue Carrier: +#NATO CARRIERS + NATO CVN: - primary: BARCAP secondary: any aircraft: @@ -365,86 +289,88 @@ squadrons: aircraft: - S-3B Viking size: 4 - #Abu Al-Duhur - 1: - - primary: BARCAP - secondary: any - aircraft: - - MiG-29S Fulcrum-C - size: 16 - #Hatay - 15: - - primary: SEAD + NATO LHA: + - primary: BAI secondary: air-to-ground aircraft: - - Su-25T Frogfoot - size: 12 - #Minakh - 26: + - AV-8B Harrier II Night Attack + #Abu Al-Duhur + 1: - primary: BAI secondary: air-to-ground aircraft: - Su-34 Fullback + size: 12 + #Hatay + 15: + - primary: BAI + secondary: air-to-ground + aircraft: + - Su-24M Fencer-D + size: 12 + #Minakh + 26: + - primary: BARCAP + secondary: air-to-air + aircraft: + - MiG-21bis Fishbed-N size: 12 #Aleppo 27: - primary: BARCAP secondary: air-to-air aircraft: - - MiG-29S Fulcrum-C - size: 16 + - MiG-23MLD Flogger-K + size: 12 #Jirah 17: - primary: BARCAP secondary: air-to-air aircraft: - - MiG-31 Foxhound - size: 16 + - MiG-23MLD Flogger-K + size: 12 #Gaziantep 11: - - primary: BAI - secondary: air-to-ground + - primary: BARCAP + secondary: air-to-air aircraft: - - Su-30 Flanker-C + - MiG-21bis Fishbed-N size: 12 + #Kuweires + 31: + - primary: BARCAP + secondary: air-to-air + aircraft: + - MiG-29S Fulcrum-C + size: 12 ground_forces: NATO SAM: Hawk NATO SAM-1: Hawk NATO SAM-2: Hawk NATO SAM-3: Hawk NATO SAM-4: Hawk - YellowBarrierN: SA-2/S-75 with ZSU-23/57 - YellowBarrierC1: SA-6 - YellowBarrierC2: SA-11 - YellowBarrierS: SA-2/S-75 with ZSU-23/57 - YellowLongRangeSAM: SA-2/S-75 with ZSU-23/57 - GAZSAMN: SA-11 - GreenBarrierSAM-4: SA-2/S-75 with ZSU-23/57 - GreenBarrierSAM-3: SA-2/S-75 with ZSU-23/57 - GreenZoneSAMDefense: SA-11 - GreenZoneSAM: SA-2/S-75 with ZSU-23/57 - HataySAM: SA-11 - HataySAM-1: SA-2/S-75 with ZSU-23/57 - GreenSAM-2: SA-3/S-125 - GreenSAM-3: SA-6 - GreenSAM-1: SA-2/S-75 with ZSU-23/57 - JirahSAM: SA-10/S-300PS - JirahSAM-1: SA-11 - JirahSAM-2: SA-2/S-75 with ZSU-23/57 - KuweiresSAM: SA-6 - Pink SAM: SA-11 - AlSafiraPD: SA-15 SHORAD - AleppoSAM: SA-3/S-125 - AleppoSAM-1: SA-3/S-125 - AleppoSAM-2: SA-3/S-125 - AleppoSAM-3: SA-3/S-125 - AleppoSAM-4: SA-3/S-125 - AleppoSAM-5: SA-6 - AleppoSAM-6: SA-6 - AleppoSAM-7: SA-11 - MinakhSAM1: SA-3/S-125 - MinakhSAM2: SA-3/S-125 - GAZSAMN: SA-11 - GAZSAMW: SA-3/S-125 - AbuSAM: SA-2/S-75 with ZSU-23/57 - AbuSAM-1: SA-15 SHORAD \ No newline at end of file + B-SAM-1: SA-2/S-75 + B-SAM-2: SA-11 + B-SAM-3: SA-2/S-75 + B-SAM-4: SA-2/S-75 + B-SAM-5: SA-10/S-300PS + R-SAM-1: SA-2/S-75 + R-SAM-2: SA-2/S-75 + R-SAM-3: SA-11 + R-SAM-4: SA-11 + R-SAM-5: SA-6 + R-SAM-6: SA-3/S-125 + R-SAM-7: SA-6 + R-SAM-8: SA-11 + R-SAM-9: SA-10/S-300PS + Y-SAM-1: SA-6 + Y-SAM-2: SA-3/S-125 + Y-SAM-3: SA-6 + Y-SAM-4: SA-3/S-125 + Y-SAM-5: SA-6 + Y-SAM-6: SA-3/S-125 + Y-SAM-7: SA-11 + Y-SAM-8: SA-2/S-75 + Y-SAM-9: SA-2/S-75 + Y-SAM-10: SA-2/S-75 + Y-SAM-11: SA-10/S-300PS \ No newline at end of file diff --git a/resources/campaigns/battle_for_no_mans_land.miz b/resources/campaigns/battle_for_no_mans_land.miz new file mode 100644 index 00000000..36f3dda8 Binary files /dev/null and b/resources/campaigns/battle_for_no_mans_land.miz differ diff --git a/resources/campaigns/battle_for_no_mans_land.yaml b/resources/campaigns/battle_for_no_mans_land.yaml new file mode 100644 index 00000000..7c3856e6 --- /dev/null +++ b/resources/campaigns/battle_for_no_mans_land.yaml @@ -0,0 +1,69 @@ +--- +name: Falklands - Battle for No Man's Land +theater: Falklands +authors: Starfire +recommended_player_faction: USA 2005 +recommended_enemy_faction: Private Military Company - Russian (Hard) +description: +Note: This campaign was designed for helicopters.
+ Set against the rugged and windswept backdrop of the Falkland Islands, + this fictional campaign scenario unfolds with a dramatic dawn sneak attack + on RAF Mount Pleasant Airbase. Orchestrated by a Russia-backed private + military company, the deadly offensive with helicopter gunships and ground troops + has left the airbase's runways in ruins and its defences obliterated. This brutal + incursion resulted in significant casualties among the RAF personnel, with many + killed or wounded in the unexpected onslaught. The carrier HMS Queen Elizabeth and + its task force are on their way to evacuate the survivors and retake Mount Pleasant. + However, they are eight days away at full steam.
+ Amidst this chaos, a beacon of hope emerges in the heart of the Falklands. At Port + Stanley, a small detachment of US military personnel, including helicopter pilots + and armor units, find themselves inadvertently thrust into the fray. Originally at + Port Stanley for some R&R following a training exercise, these soldiers now face + an unexpected and urgent call to action. Their mission is daunting but clear - to + prevent the capture of Port Stanley and liberate East Falkland from the clutches + of the PMC forces.
+ This small group must strategically destroy the PMC forces deployed around the treacherous + valley lying between Wickham Heights and the Onion Ranges, an area ominously known + as No Man's Land. Their plan involves a daring assault to destroy the enemy's + helicopter gunships stationed at San Carlos FOB. Following this, they aim to force + the PMC ground forces into a strategic retreat southward, along the 1.6 mile wide + isthmus into Lafonia. This offensive is designed to create a defensible position + at Goose Green on the narrow isthmus, which can be held against a numerically + superior force until the arrival of Big Lizzie.
+miz: battle_for_no_mans_land.miz +performance: 1 +recommended_start_date: 2001-11-10 +version: "10.7" +squadrons: + #Port Stanley + 1: + - primary: DEAD + secondary: air-to-ground + aircraft: + - AH-64D Apache Longbow + size: 6 + - primary: BAI + secondary: air-to-ground + aircraft: + - AH-64D Apache Longbow + size: 6 + - primary: Air Assault + secondary: any + aircraft: + - UH-60L + - UH-60A + size: 4 + #San Carlos FOB + 3: + - primary: BAI + secondary: air-to-ground + aircraft: + - Mi-24P Hind-F + size: 6 + #Goose Green + 24: + - primary: DEAD + secondary: air-to-ground + aircraft: + - Ka-50 Hokum (Blackshark 3) + size: 6 \ No newline at end of file diff --git a/resources/campaigns/exercise_bright_star.miz b/resources/campaigns/exercise_bright_star.miz index a71f8325..10ce7fb3 100644 Binary files a/resources/campaigns/exercise_bright_star.miz and b/resources/campaigns/exercise_bright_star.miz differ diff --git a/resources/campaigns/exercise_bright_star.yaml b/resources/campaigns/exercise_bright_star.yaml index f1be76fc..ee5d8f04 100644 --- a/resources/campaigns/exercise_bright_star.yaml +++ b/resources/campaigns/exercise_bright_star.yaml @@ -1,152 +1,167 @@ ---- -name: Sinai - Exercise Bright Star -theater: Sinai -authors: Starfire -recommended_player_faction: Bluefor Modern -recommended_enemy_faction: Egypt 2010's -description:For over 4 decades, the United States and Egypt have run a series of biannual joint military exercises called Bright Star. Over the years, the number of participating countries has grown substantially. Exercise Bright Star 2025 boasts 8 participant nations and 14 observer nations. The United States and a portion of the exercise coalition will play the part of a fictional hostile nation dubbed Orangeland, staging a mock invasion against Cairo. Israel, having for the first time accepted the invitation to observe, is hosting the aggressor faction of the exercise coalition at its airfields.
-miz: exercise_bright_star.miz -performance: 1 -recommended_start_date: 2025-09-01 -version: "10.7" -squadrons: - Blue CV-1: - - primary: SEAD - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 24 - - primary: AEW&C - aircraft: - - E-2C Hawkeye - size: 2 - - primary: Refueling - aircraft: - - S-3B Tanker - size: 2 - - primary: Air Assault - secondary: any - aircraft: - - SH-60B Seahawk - size: 2 -# Hatzerim (141) - 7: - - primary: Escort - secondary: air-to-air - aircraft: - - F-15C Eagle - size: 20 - - primary: OCA/Runway - secondary: any - aircraft: - - F-15E Strike Eagle (Suite 4+) - size: 8 - - primary: Strike - secondary: air-to-ground - aircraft: - - F-15E Strike Eagle - size: 8 - - primary: DEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 20 - - primary: BAI - secondary: any - aircraft: - - JF-17 Thunder - size: 16 - - primary: BARCAP - secondary: any - aircraft: - - Mirage 2000C - size: 16 -# Kedem - 12: - - primary: Transport - aircraft: - - CH-47D - size: 20 - - primary: Air Assault - secondary: air-to-ground - aircraft: - - UH-1H Iroquois - size: 4 -# Nevatim (106) - 8: - - primary: AEW&C - aircraft: - - E-3A - size: 2 - - primary: Refueling - aircraft: - - KC-135 Stratotanker - size: 1 - - primary: Refueling - aircraft: - - KC-135 Stratotanker MPRS - size: 1 - - primary: CAS - secondary: air-to-ground - aircraft: - - A-10C Thunderbolt II (Suite 7) - size: 8 -# Melez (30) - 5: - - primary: CAS - secondary: air-to-ground - aircraft: - - Ka-50 Hokum (Blackshark 3) - size: 4 - - primary: TARCAP - secondary: air-to-air - aircraft: - - Mirage 2000C - size: 12 - - primary: Strike - secondary: air-to-ground - aircraft: - - Mirage 2000C - size: 12 -# Wadi al Jandali (72) - 13: - - primary: AEW&C - aircraft: - - E-2C Hawkeye - size: 2 - - primary: SEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 20 - - primary: DEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 20 - - primary: Air Assault - secondary: air-to-ground - aircraft: - - Mi-24P Hind-F - size: 4 - - primary: OCA/Aircraft - secondary: air-to-ground - aircraft: - - SA 342L Gazelle - size: 4 -# Cairo West (95) - 18: - - primary: Transport - aircraft: - - C-130 - size: 8 - - primary: Escort - secondary: air-to-air - aircraft: - - MiG-29S Fulcrum-C - size: 20 - - primary: BARCAP - secondary: any - aircraft: - - J-7B +--- +name: Sinai - Exercise Bright Star +theater: Sinai +authors: Starfire +recommended_player_faction: Bluefor Modern +recommended_enemy_faction: Egypt 2000 +description: +For over four decades, the United States and Egypt have conducted a series + of biannual joint military exercises known as Bright Star. As the + geopolitical landscape has transformed, so too has the scope and scale of + Exercise Bright Star. The exercise has grown over the years to incorporate + a wide array of international participants. The 2025 iteration of + Exercise Bright Star features eight participating nations alongside + fourteen observer nations.
+ For the 2025 exercises, the United States, along with a select contingent + from the exercise coalition, will take on the role of a hypothetical + adversarial nation, dubbed Orangeland. This scenario is designed to + simulate a mock invasion against Cairo, and presents a valuable + opportunity for participating nations to refine their joint operational + capabilities and improve logistical and tactical interoperability
+ A historic addition to Exercise Bright Star 2025 is the participation of + Israel as an observer nation. This marks a significant milestone, given + the complex historical relations in the region, and symbolises a step + forward in regional collaboration and military diplomacy. Israel's role, + hosting the aggressor faction of the exercise coalition at its airfields, + not only demonstrates the broadening scope of the exercise but also highlights + the value of fostering an environment of mutual cooperation and shared + security objectives.
+miz: exercise_bright_star.miz +performance: 1 +recommended_start_date: 2025-09-01 +version: "10.7" +squadrons: + Blue CV-1: + - primary: SEAD + secondary: any + aircraft: + - F/A-18C Hornet (Lot 20) + size: 24 + - primary: AEW&C + aircraft: + - E-2D Advanced Hawkeye + size: 2 + - primary: Refueling + aircraft: + - S-3B Tanker + size: 4 + Bombers from RAF Fairford: + - primary: Anti-ship + secondary: air-to-ground + aircraft: + - B-52H Stratofortress + size: 8 + - primary: Strike + secondary: air-to-ground + aircraft: + - B-1B Lancer + size: 8 + # Hatzerim (141) + 7: + - primary: Escort + secondary: any + aircraft: + - F-15C Eagle + size: 20 + - primary: OCA/Runway + secondary: any + aircraft: + - F-15E Strike Eagle (Suite 4+) + size: 16 + - primary: DEAD + secondary: any + aircraft: + - F-16CM Fighting Falcon (Block 50) + size: 20 + - primary: BAI + secondary: any + aircraft: + - JF-17 Thunder + size: 16 + - primary: BARCAP + secondary: any + aircraft: + - Mirage 2000C + size: 12 + # Kedem + 12: + - primary: Transport + secondary: any + aircraft: + - CH-47D + size: 20 + - primary: Air Assault + secondary: any + aircraft: + - UH-60L + - UH-60A + size: 4 + # Nevatim (106) + 8: + - primary: AEW&C + aircraft: + - E-3A + size: 2 + - primary: Refueling + aircraft: + - KC-135 Stratotanker + size: 2 + - primary: CAS + secondary: air-to-ground + aircraft: + - A-10C Thunderbolt II (Suite 7) + size: 8 + # Melez (30) + 5: + - primary: CAS + secondary: air-to-ground + aircraft: + - Ka-50 Hokum (Blackshark 3) + size: 4 + - primary: BAI + secondary: any + aircraft: + - Mirage 2000C + size: 12 + - primary: Escort + secondary: any + aircraft: + - MiG-21bis Fishbed-N + size: 12 + # Wadi al Jandali (72) + 13: + - primary: AEW&C + aircraft: + - E-2C Hawkeye + size: 2 + - primary: SEAD + secondary: any + aircraft: + - F-4E Phantom II + size: 20 + - primary: DEAD + secondary: any + aircraft: + - F-16CM Fighting Falcon (Block 50) + size: 20 + - primary: Air Assault + secondary: any + aircraft: + - Mi-24P Hind-F + size: 4 + - primary: OCA/Aircraft + secondary: any + aircraft: + - SA 342L Gazelle + size: 4 + # Cairo West (95) + 18: + - primary: Transport + aircraft: + - C-130 + size: 8 + - primary: BARCAP + secondary: air-to-air + aircraft: + - MiG-29S Fulcrum-C size: 20 \ No newline at end of file diff --git a/resources/campaigns/exercise_quasar.miz b/resources/campaigns/exercise_quasar.miz index e57dc73e..9110a8af 100644 Binary files a/resources/campaigns/exercise_quasar.miz and b/resources/campaigns/exercise_quasar.miz differ diff --git a/resources/campaigns/exercise_vegas_nerve.miz b/resources/campaigns/exercise_vegas_nerve.miz index 5b2542bb..6570446d 100644 Binary files a/resources/campaigns/exercise_vegas_nerve.miz and b/resources/campaigns/exercise_vegas_nerve.miz differ diff --git a/resources/campaigns/exercise_vegas_nerve.yaml b/resources/campaigns/exercise_vegas_nerve.yaml index 6a0d7ee4..70cc5c67 100644 --- a/resources/campaigns/exercise_vegas_nerve.yaml +++ b/resources/campaigns/exercise_vegas_nerve.yaml @@ -1,108 +1,127 @@ ---- -name: Nevada - Exercise Vegas Nerve -theater: Nevada -authors: Starfire -recommended_player_faction: USA 2005 -recommended_enemy_faction: Redfor (China) 2010 -description:Welcome to Vegas Nerve, an asymmetrical Red Flag Exercise scenario. You are starting off in control of the two Tonopah airports, and will push south from there. For the duration of this exercise, Creech AFB has been cleared of all fixed wing aircraft and will function as a FARP for rotor ops. OPFOR has a substantial resource advantage and an extensive IADS. Reducing that resource advantage while degrading their IADS will be vital to a successful completion of this exercise. Good luck, Commander.
-miz: exercise_vegas_nerve.miz -performance: 1 -recommended_start_date: 2011-02-24 -version: "10.7" -squadrons: -# Tonopah Airport - 17: - - primary: BARCAP - secondary: air-to-air - aircraft: - - F-15C Eagle - size: 12 - - primary: Strike - secondary: air-to-ground - aircraft: - - F-15E Strike Eagle (AI) - - F-15E Strike Eagle (Suite 4+) - size: 12 - - primary: AEW&C - aircraft: - - E-3A - size: 1 -# Tonopah Test Range - 18: - - primary: BAI - secondary: air-to-ground - aircraft: - - A-10C Thunderbolt II (Suite 7) - size: 8 - - primary: CAS - secondary: air-to-ground - aircraft: - - AH-64D Apache Longbow - size: 10 - - primary: DEAD - secondary: air-to-ground - aircraft: - - F/A-18C Hornet (Lot 20) - size: 24 - - primary: SEAD - secondary: air-to-ground - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 24 - - primary: Air Assault - secondary: air-to-ground - aircraft: - - UH-1H Iroquois - size: 2 -# Groom Lake - 2: - - primary: Escort - secondary: air-to-air - aircraft: - - J-11A Flanker-L - size: 20 - - primary: BAI - secondary: air-to-ground - aircraft: - - Su-25T Frogfoot - size: 20 -# Creech - Creech FARP: - - primary: CAS - secondary: air-to-ground - aircraft: - - Ka-50 Hokum (Blackshark 3) - size: 8 - - primary: Air Assault - secondary: air-to-ground - aircraft: - - Mi-24P Hind-F - size: 4 -# Nellis AFB - 4: - - primary: Strike - secondary: air-to-ground - aircraft: - - H-6J Badger - size: 20 - - primary: AEW&C - aircraft: - - KJ-2000 - size: 1 - - primary: SEAD - secondary: air-to-ground - aircraft: - - Su-24M Fencer-D - size: 20 - - primary: DEAD - secondary: air-to-ground - aircraft: - - Su-34 Fullback - size: 20 -# Boulder City Airport - 6: - - primary: SEAD Escort - secondary: any - aircraft: - - FC-1 Fierce Dragon - size: 20 +--- +name: Nevada - Exercise Vegas Nerve +theater: Nevada +authors: Starfire +recommended_player_faction: USA 2005 +recommended_enemy_faction: Redfor (China) 2010 +description: +Welcome to Vegas Nerve, an asymmetrical Red Flag Exercise scenario. You are + starting off in control of the two Tonopah airports, and will push south from + there. For the duration of this exercise, Creech AFB has been cleared of all + fixed wing aircraft and will function as a FARP for rotor ops. OPFOR has a + substantial resource advantage and an extensive IADS. Reducing that resource + advantage while degrading their IADS will be vital to a successful completion + of this exercise. Good luck, Commander.
+miz: exercise_vegas_nerve.miz +performance: 1 +recommended_start_date: 2011-02-24 +version: "10.7" +squadrons: + Bombers from Minot AFB: + - primary: Strike + secondary: air-to-ground + aircraft: + - B-52H Stratofortress + size: 4 + Bombers from Ellsworth AFB: + - primary: OCA/Runway + secondary: air-to-ground + aircraft: + - B-1B Lancer + size: 4 + # Tonopah Airport + 17: + - primary: TARCAP + secondary: any + aircraft: + - F-15C Eagle + size: 12 + - primary: Strike + secondary: air-to-ground + aircraft: + - F-15E Strike Eagle (Suite 4+) + size: 12 + - primary: AEW&C + aircraft: + - E-3A + size: 1 + # Tonopah Test Range + 18: + - primary: BAI + secondary: air-to-ground + aircraft: + - A-10C Thunderbolt II (Suite 7) + size: 8 + - primary: CAS + secondary: air-to-ground + aircraft: + - AH-64D Apache Longbow + size: 10 + - primary: DEAD + secondary: air-to-ground + aircraft: + - F/A-18C Hornet (Lot 20) + size: 24 + - primary: SEAD + secondary: air-to-ground + aircraft: + - F-16CM Fighting Falcon (Block 50) + size: 24 + - primary: Air Assault + secondary: air-to-ground + aircraft: + - UH-60L + - UH-60A + size: 2 + # Groom Lake + 2: + - primary: Escort + secondary: air-to-air + aircraft: + - J-11A Flanker-L + size: 20 + - primary: BAI + secondary: air-to-ground + aircraft: + - Su-25T Frogfoot + size: 20 + # Creech + 1: + - primary: CAS + secondary: air-to-ground + aircraft: + - Ka-50 Hokum (Blackshark 3) + size: 8 + - primary: Air Assault + secondary: air-to-ground + aircraft: + - Mi-24P Hind-F + size: 4 + # Nellis AFB + 4: + - primary: Strike + secondary: air-to-ground + aircraft: + - H-6J Badger + size: 20 + - primary: AEW&C + aircraft: + - KJ-2000 + size: 1 + - primary: SEAD + secondary: air-to-ground + aircraft: + - Su-24M Fencer-D + size: 20 + - primary: DEAD + secondary: air-to-ground + aircraft: + - Su-34 Fullback + size: 20 + # Boulder City Airport + 6: + - primary: SEAD Escort + secondary: any + aircraft: + - FC-1 Fierce Dragon + size: 20 diff --git a/resources/campaigns/final_countdown_2.miz b/resources/campaigns/final_countdown_2.miz index 64093951..835d69f5 100644 Binary files a/resources/campaigns/final_countdown_2.miz and b/resources/campaigns/final_countdown_2.miz differ diff --git a/resources/campaigns/final_countdown_2.yaml b/resources/campaigns/final_countdown_2.yaml index 4eb48f56..d08f7fa0 100644 --- a/resources/campaigns/final_countdown_2.yaml +++ b/resources/campaigns/final_countdown_2.yaml @@ -1,119 +1,136 @@ ---- -name: Normandy - The Final Countdown II -theater: Normandy -authors: Starfire -recommended_player_faction: D-Day Allied Forces 1944 and 1990 -recommended_enemy_faction: Germany 1944 -description: -While enroute to the Persian Gulf for Operation Desert Shield, the USS Theodore Roosevelt and its carrier strike group are engufled by an electrical vortex and transported through time and space to the English channel on the morning of the Normandy Landings - June 6th 1944. Seeking to reduce the cost in lives to the Allied Forces about to storm the beaches, the captain of the Roosevelt has elected to provide air support for the landings.
Note: This campaign has a custom faction that combines modern US naval forces with WW2 Allied forces. To play it as intended, you should carefully ration your use of modern aircraft and not replenish them if shot down (as you cannot get new Tomcats and Hornets in 1944). You can also choose to play it as a purely WW2 campaign by switching to one of the WW2 Ally factions.
-miz: final_countdown_2.miz -performance: 2 -recommended_start_date: 1944-06-06 -version: "10.7" -squadrons: - #Blue CV (90) - Blue-CV: - - primary: TARCAP - secondary: any - aircraft: - - F-14B Tomcat - size: 24 - - primary: DEAD - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 24 - - primary: AEW&C - aircraft: - - E-2C Hawkeye - size: 2 - - primary: Refueling - aircraft: - - S-3B Tanker - size: 2 - - primary: Air Assault - secondary: any - aircraft: - - SH-60B Seahawk - size: 4 - #Stoney Cross (39) - 58: - - primary: OCA/Runway - secondary: air-to-ground - aircraft: - - A-20G Havoc - - Boston Mk.III - size: 20 - #Needs Oar Point (55) - 28: - - primary: BARCAP - secondary: any - aircraft: - - Spitfire LF Mk IX - size: 20 - - primary: DEAD - secondary: air-to-ground - aircraft: - - MosquitoFBMkVI - size: 20 - #RAF Grafton Underwood (1000) - From RAF Grafton Underwood: - - primary: Strike - secondary: air-to-ground - aircraft: - - B-17G Flying Fortress - - Fortress Mk.III - size: 20 - #Lymington (56) - 37: - - primary: Escort - secondary: any - aircraft: - - P-51D-30-NA Mustang - - Mustang Mk.IV (Late) - size: 20 - - primary: BAI - secondary: any - aircraft: - - P-47D-40 Thunderbolt - - Thunderbolt Mk.II (Late) - size: 20 - - #Carpiquet (47) - 19: - - primary: TARCAP - secondary: air-to-air - aircraft: - - Fw 190 D-9 Dora - size: 12 - - primary: CAS - secondary: air-to-ground - aircraft: - - Ju 88 A-4 - size: 8 - #Broglie (32) - 68: - - primary: Escort - secondary: any - aircraft: - - Bf 109 K-4 Kurfürst - size: 24 - #Saint-Andre-de-lEure (30) - 70: - - primary: BAI - secondary: air-to-ground - aircraft: - - Ju 88 A-4 - size: 12 - - primary: Strike - secondary: air-to-ground - aircraft: - - Ju 88 A-4 - size: 12 - #Vilacoublay (76) - 42: - - primary: BARCAP - secondary: any - aircraft: - - Fw 190 A-8 Anton - size: 20 +--- +name: Normandy - The Final Countdown II +theater: Normandy +authors: Starfire +recommended_player_faction: D-Day Allied Forces 1944 and 1990 +recommended_enemy_faction: Germany 1944 +description: +While enroute to the Persian Gulf for Operation Desert Shield, the USS + Theodore Roosevelt and its carrier strike group are engufled by an electrical + vortex and transported through time and space to the English channel on the + morning of the Normandy Landings - June 6th 1944. Seeking to reduce the cost + in lives to the Allied Forces about to storm the beaches, the captain of the + Roosevelt has elected to provide air support for the + landings.
Note: This campaign has a custom faction that + combines modern US naval forces with WW2 Allied forces. To play it as + intended, you should carefully ration your use of modern aircraft and not + replenish them if shot down (as you cannot get new Tomcats and Hornets in + 1944). You can also choose to play it as a purely WW2 campaign by switching to + one of the WW2 Ally factions.
+miz: final_countdown_2.miz +performance: 2 +recommended_start_date: 1944-06-06 +version: "10.7" +squadrons: + #Blue CV (90) + Blue-CV: + - primary: TARCAP + secondary: any + aircraft: + - F-14B Tomcat + size: 24 + - primary: DEAD + secondary: any + aircraft: + - F/A-18C Hornet (Lot 20) + size: 24 + - primary: CAS + secondary: air-to-ground + aircraft: + - S-3B Viking + size: 12 + - primary: AEW&C + aircraft: + - E-2C Hawkeye + size: 2 + - primary: Refueling + aircraft: + - S-3B Tanker + size: 2 + - primary: Air Assault + secondary: any + aircraft: + - UH-60L + - UH-60A + size: 6 + #Stoney Cross (39) + 58: + - primary: OCA/Runway + secondary: air-to-ground + aircraft: + - A-20G Havoc + - Boston Mk.III + size: 20 + #Needs Oar Point (55) + 28: + - primary: BARCAP + secondary: any + aircraft: + - Spitfire LF Mk IX + size: 20 + - primary: DEAD + secondary: air-to-ground + aircraft: + - MosquitoFBMkVI + size: 20 + #RAF Grafton Underwood (1000) + Bombers from RAF Grafton Underwood: + - primary: Strike + secondary: air-to-ground + aircraft: + - B-17G Flying Fortress + - Fortress Mk.III + size: 20 + #Lymington (56) + 37: + - primary: Escort + secondary: any + aircraft: + - P-51D-30-NA Mustang + - Mustang Mk.IV (Late) + size: 20 + - primary: BAI + secondary: any + aircraft: + - P-47D-40 Thunderbolt + - Thunderbolt Mk.II (Late) + size: 20 + + #Carpiquet (47) + 19: + - primary: TARCAP + secondary: air-to-air + aircraft: + - Fw 190 D-9 Dora + size: 12 + - primary: CAS + secondary: air-to-ground + aircraft: + - Ju 88 A-4 + size: 8 + #Broglie (32) + 68: + - primary: Escort + secondary: any + aircraft: + - Bf 109 K-4 Kurfürst + size: 24 + #Saint-Andre-de-lEure (30) + 70: + - primary: BAI + secondary: air-to-ground + aircraft: + - Ju 88 A-4 + size: 12 + - primary: Strike + secondary: air-to-ground + aircraft: + - Ju 88 A-4 + size: 12 + #Vilacoublay (76) + 42: + - primary: BARCAP + secondary: any + aircraft: + - Fw 190 A-8 Anton + size: 20 \ No newline at end of file diff --git a/resources/campaigns/grabthars_hammer.miz b/resources/campaigns/grabthars_hammer.miz index 55058856..7c25dde7 100644 Binary files a/resources/campaigns/grabthars_hammer.miz and b/resources/campaigns/grabthars_hammer.miz differ diff --git a/resources/campaigns/grabthars_hammer.yaml b/resources/campaigns/grabthars_hammer.yaml index 28d33fdf..53d90ad8 100644 --- a/resources/campaigns/grabthars_hammer.yaml +++ b/resources/campaigns/grabthars_hammer.yaml @@ -1,149 +1,155 @@ ---- -name: Falklands - Operation Grabthar's Hammer -theater: Falklands -authors: Starfire -recommended_player_faction: USA 2005 -recommended_enemy_faction: Russia 2010 -description: -An Argentinean extremist group has contracted the Sons of Warvan (SoW), an - unusually well-equipped PMC with close ties to the Russian government, to - construct a beryllium bomb at the secret Omega 13 production facility in Ushaia - for use in its ongoing conflict with Chile. United States military forces have - established a foothold at San Julian. While the SoW are distracted up north, it - is up to the Marines to launch an assault upon Ushaia from an LHA in order to - disable the bomb production facility. Fortunately, Ushaia is lightly defended as - the SoW are trying to avoid unwanted attention.
-miz: grabthars_hammer.miz -performance: 2 -recommended_start_date: 1999-12-25 -version: "10.7" -squadrons: - #Mount Pleasant - 2: - - primary: DEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 16 - - primary: CAS - secondary: air-to-ground - aircraft: - - A-10C Thunderbolt II (Suite 7) - size: 8 - - primary: Strike - secondary: air-to-ground - aircraft: - - B-1B Lancer - size: 12 - - primary: Refueling - aircraft: - - KC-135 Stratotanker - size: 1 - #San Julian - 11: - - primary: BAI - secondary: air-to-ground - aircraft: - - F-15E Strike Eagle (AI) - - F-15E Strike Eagle (Suite 4+) - size: 8 - - primary: Air Assault - secondary: any - aircraft: - - UH-1H Iroquois - size: 1 - #Blue CV - Blue-CV: - - primary: BARCAP - secondary: any - aircraft: - - F-14B Tomcat - size: 20 - - primary: SEAD - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 32 - - primary: Escort - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 32 - - primary: AEW&C - aircraft: - - E-2C Hawkeye - size: 1 - - primary: Refueling - aircraft: - - S-3B Tanker - size: 3 - - primary: Air Assault - secondary: any - aircraft: - - SH-60B Seahawk - size: 2 - # Blue LHA - Blue-LHA: - - primary: DEAD - secondary: air-to-ground - aircraft: - - AV-8B Harrier II Night Attack - size: 18 - - primary: Air Assault - secondary: air-to-ground - aircraft: - - UH-1H Iroquois - size: 2 - #El Calafate - 14: - - primary: Transport - aircraft: - - Mi-8MTV2 Hip - size: 10 - #Rio Gallegros - 5: - - primary: BARCAP - secondary: air-to-air - aircraft: - - Su-27 Flanker-B - size: 12 - - primary: BAI - secondary: air-to-ground - aircraft: - - Su-25T Frogfoot - size: 12 - #Punta Arenas - 9: - - primary: SEAD - secondary: air-to-ground - aircraft: - - Su-24M Fencer-D - size: 16 - - primary: DEAD - secondary: air-to-ground - aircraft: - - Su-34 Fullback - size: 16 - - primary: Strike - secondary: air-to-ground - aircraft: - - Tu-22M3 Backfire-C - size: 16 - - primary: Refueling - aircraft: - - IL-78M - size: 2 - #Ushuaia - 7: - - primary: CAS - secondary: air-to-ground - aircraft: - - Ka-50 Hokum (Blackshark 3) - size: 8 - #Ushuaia Helo Port - 8: - - primary: Air Assault - secondary: air-to-ground - aircraft: - - Mi-24P Hind-F +--- +name: Falklands - Operation Grabthar's Hammer +theater: Falklands +authors: Starfire +recommended_player_faction: USA 2005 +recommended_enemy_faction: Russia 2010 +description: +An Argentinean extremist group has contracted the Sons of Warvan (SoW), an + unusually well-equipped PMC with close ties to the Russian government, to + construct a beryllium bomb at the secret Omega 13 production facility in + Ushuaia for use in its ongoing conflict with Chile. United States military + forces have established a foothold at San Julian. While the SoW are distracted + up north, it is up to the Marines to launch an assault upon Ushuaia from an LHA + in order to disable the bomb production facility. Fortunately, Ushuaia is + lightly defended as the SoW are trying to avoid unwanted attention.
+miz: grabthars_hammer.miz +performance: 2 +recommended_start_date: 1999-12-25 +version: "10.7" +squadrons: + #Mount Pleasant + 2: + - primary: DEAD + secondary: any + aircraft: + - F-16CM Fighting Falcon (Block 50) + size: 8 + - primary: CAS + secondary: air-to-ground + aircraft: + - A-10C Thunderbolt II (Suite 7) + size: 8 + - primary: Escort + secondary: any + aircraft: + - F-15C Eagle + size: 8 + - primary: Refueling + aircraft: + - KC-135 Stratotanker + size: 2 + #San Julian + 11: + - primary: BAI + secondary: any + aircraft: + - F-15E Strike Eagle (Suite 4+) + size: 8 + #Blue CV + Blue-CV: + - primary: BARCAP + secondary: any + aircraft: + - F-14B Tomcat + size: 20 + - primary: SEAD + secondary: any + aircraft: + - F/A-18C Hornet (Lot 20) + size: 40 + - primary: DEAD + secondary: air-to-ground + aircraft: + - S-3B Viking + size: 20 + - primary: AEW&C + aircraft: + - E-2C Hawkeye + size: 2 + - primary: Refueling + aircraft: + - S-3B Tanker + size: 4 + - primary: Air Assault + secondary: any + aircraft: + - UH-60L + - UH-60A + size: 4 + # Blue LHA + Blue-LHA: + - primary: DEAD + secondary: air-to-ground + aircraft: + - AV-8B Harrier II Night Attack + size: 18 + - primary: Air Assault + secondary: any + aircraft: + - UH-1H Iroquois + size: 2 + Bombers from Edwards AFB: + - primary: Strike + secondary: air-to-ground + aircraft: + - B-52H Stratofortress + size: 12 + - primary: OCA/Runway + secondary: air-to-ground + aircraft: + - B-1B Lancer + size: 12 + #El Calafate + 14: + - primary: Transport + aircraft: + - Mi-8MTV2 Hip + size: 10 + #Rio Gallegros + 5: + - primary: Escort + secondary: air-to-air + aircraft: + - Su-27 Flanker-B + size: 12 + - primary: BAI + secondary: air-to-ground + aircraft: + - Su-25T Frogfoot + size: 12 + #Punta Arenas + 9: + - primary: SEAD + secondary: air-to-ground + aircraft: + - Su-24M Fencer-D + size: 16 + - primary: DEAD + secondary: air-to-ground + aircraft: + - Su-34 Fullback + size: 16 + - primary: Strike + secondary: air-to-ground + aircraft: + - Tu-22M3 Backfire-C + size: 16 + - primary: Refueling + aircraft: + - IL-78M + size: 2 + #Ushuaia + 7: + - primary: CAS + secondary: air-to-ground + aircraft: + - Ka-50 Hokum (Blackshark 3) + size: 8 + #Ushuaia Helo Port + 8: + - primary: Air Assault + secondary: air-to-ground + aircraft: + - Mi-24P Hind-F size: 8 \ No newline at end of file diff --git a/resources/campaigns/operation_aegean_aegis.miz b/resources/campaigns/operation_aegean_aegis.miz new file mode 100644 index 00000000..b7d92525 Binary files /dev/null and b/resources/campaigns/operation_aegean_aegis.miz differ diff --git a/resources/campaigns/operation_aegean_aegis.yaml b/resources/campaigns/operation_aegean_aegis.yaml new file mode 100644 index 00000000..2b97f3f1 --- /dev/null +++ b/resources/campaigns/operation_aegean_aegis.yaml @@ -0,0 +1,100 @@ +--- +name: Syria - Operation Aegean Aegis +theater: Syria +authors: Starfire +recommended_player_faction: USA 2005 +recommended_enemy_faction: Turkey 2005 +description: +Note: This fictional campaign was designed for the Apache + and Harrier. It requires manual flight planning. While enemy aircraft are present + at airfields, there will be no enemy flights as their aircraft are grounded.
++ In a sudden and alarming escalation of tensions in Cyprus, the Anatolian Order, + a North Cypriot insurgent faction, has carried out a bold night-time assault on + three crucial airfields in the Republic of Cyprus; Paphos, Akrotiri, and Larnaca. + The insurgents, equipped with stolen surplus Turkish military hardware, used + chemical weapons in their attack, forcing the evacuation of all three airfields. + Notably, the capture of Akrotiri, a British Overseas Territory hosting a Royal + Air Force base, has drawn significant international attention and concern.
++ The EU has strongly condemned this unprovoked attack against one of its member + states. Turkey, despite its historical connections with North Cyprus, has also + denounced the Anatolian Order's actions and is investigating how its aircraft, + ground vehicles, and weaponry held in storage ended up in insurgent hands.
++ Amidst the crisis, a lone US Navy LHA, strategically positioned in the Aegean Sea, + is preparing a response to the crisis. Its mission is to deploy Apache helicopters + to neutralise the hastily erected air defenses around the captured airfields, before + Harrier jumpjets neutralise the Anatolian Order's aircraft. These aircraft, a + selection of mothballed Turkish F-4s and helicopters, are currently grounded due to + lack of suitable fuel and spare parts. It is imperative that they are dealt with + swiftly before ground troops are air-lifted in to reclaim the airfields.
++ The operation's final phase involves targeting North Cyprus's only airport at Ercan. + The plan is to bomb its runway, preventing any further airborne reinforcements by the + insurgents. However, due to the air defenses established along the northern edge of + the Green Line (the UN-patrolled demilitarised zone) there are strict advisories against + overflying North Cyprus unless absolutely necessary, to minimise the risk of losses. +
+miz: operation_aegean_aegis.miz +performance: 1 +recommended_start_date: 2017-04-20 +recommended_player_money: 1000 +recommended_enemy_money: 0 +recommended_player_income_multiplier: 1.0 +recommended_enemy_income_multiplier: 0.0 +version: "10.7" +squadrons: + #Tarawa Class LHA + Blue-LHA: + - primary: DEAD + secondary: air-to-ground + aircraft: + - AH-64D Apache Longbow + size: 12 + - primary: DEAD + secondary: air-to-ground + aircraft: + - AV-8B Harrier II Night Attack + size: 6 + - primary: Air Assault + secondary: any + aircraft: + - UH-1H Iroquois + size: 2 + #Paphos + 46: + - primary: DEAD + secondary: air-to-ground + aircraft: + - F-4E Phantom II + size: 12 + #Akrotiri + 44: + - primary: BAI + secondary: air-to-ground + aircraft: + - AH-1W SuperCobra + size: 4 + - primary: CAS + secondary: air-to-ground + aircraft: + - OH-58D Kiowa Warrior + size: 4 + - primary: Air Assault + secondary: air-to-ground + aircraft: + - UH-60A + size: 4 + #Larnaca + 47: + - primary: Transport + aircraft: + - C-130 + size: 6 + #Ercan + 49: + - primary: Transport + aircraft: + - CH-47D + size: 6 diff --git a/resources/campaigns/operation_noisy_cricket.miz b/resources/campaigns/operation_noisy_cricket.miz index 9236bbe5..78096bea 100644 Binary files a/resources/campaigns/operation_noisy_cricket.miz and b/resources/campaigns/operation_noisy_cricket.miz differ diff --git a/resources/campaigns/operation_noisy_cricket.yaml b/resources/campaigns/operation_noisy_cricket.yaml index 1593b6e9..9733fb2f 100644 --- a/resources/campaigns/operation_noisy_cricket.yaml +++ b/resources/campaigns/operation_noisy_cricket.yaml @@ -1,146 +1,147 @@ ---- -name: Persian Gulf - Operation Noisy Cricket -theater: Persian Gulf -authors: Starfire -recommended_player_faction: USA 2005 -recommended_enemy_faction: Iran 2015 -description: -In the face of mounting sanctions against their nuclear program, Iran has - barred all shipping from transiting the Strait of Hormuz. Three days ago, the - Iranian Vice-President ordered a series of missile attacks on commercial - vessels entering the Gulf of Oman through the highly strategic chokepoint, - sinking a container ship and damaging two oil tankers. Operation Noisy Cricket - is the American response to this threat to regional stability. The objective - is to render inoperative Iran's array of coastal anti-ship missile sites, as - well as disable the airfields from which maritime strike aircraft could be - launched.
While officially intended only to deter any further attempts - to disrupt the flow of maritime traffic and and protect the interests of the - global economy, The USAF will also leverage the resultant degradation in - Iranian air defences to launch a deep strike from airfields in the UAE in an - attempt to take out Iran's last combat-worthy F-14 Tomcats, currently - stationed at Kerman. At the same time, a carrier-based Marine detachment will - be inserted via helicopter to conduct an unscheduled inspection of the Bushehr - Nuclear Power Plant, in order to verify Iran's compliance with international - nuclear agreements and gather evidence of any ongoing nuclear weapons - development.
-miz: operation_noisy_cricket.miz -performance: 1 -recommended_start_date: 2019-07-13 -recommended_player_money: 0 -recommended_enemy_money: 0 -recommended_player_income_multiplier: 0.2 -recommended_enemy_income_multiplier: 0.2 -version: "10.9" -squadrons: - Blue CV-1: - - primary: SEAD - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 40 - - primary: AEW&C - aircraft: - - E-2C Hawkeye - size: 2 - - primary: Refueling - aircraft: - - S-3B Tanker - size: 4 - - primary: Air Assault - secondary: any - aircraft: - - SH-60B Seahawk - size: 4 - #Al Minhad AFB (61) - 12: - - primary: DEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 32 - - primary: Escort - secondary: air-to-air - aircraft: - - F-15C Eagle - size: 24 - #Al Dhafra AFB (251) - 4: - - primary: Strike - secondary: air-to-ground - aircraft: - - B-1B Lancer - size: 4 - - primary: Refueling - aircraft: - - KC-135 Stratotanker - size: 1 - - primary: OCA/Runway - secondary: any - aircraft: - - F-15E Strike Eagle (Suite 4+) - size: 8 - - primary: BAI - secondary: air-to-ground - aircraft: - - F-15E Strike Eagle - size: 12 - #Bandar Abbas Intl (51) - 2: - - primary: SEAD - secondary: air-to-ground - aircraft: - - F-4E Phantom II - size: 20 - - primary: TARCAP - secondary: air-to-air - aircraft: - - F-5E Tiger II - size: 16 - #Qeshm Island (12) - 13: - - primary: Air Assault - secondary: air-to-ground - aircraft: - - Mi-24P Hind-F - size: 12 - #Abu Musa Island (8) - 1: - - primary: DEAD - secondary: air-to-ground - aircraft: - - Su-25T Frogfoot - size: 8 - #Kish Intl (46) - 24: - - primary: Strike - secondary: air-to-ground - aircraft: - - Su-24MK Fencer-D - size: 20 - - primary: Escort - secondary: any - aircraft: - - Mirage-F1EQ - size: 16 - #Shiraz Intl (122) - 19: - - primary: Transport - aircraft: - - IL-76MD - size: 5 - - primary: BARCAP - secondary: air-to-air - aircraft: - - MiG-29A Fulcrum-A - size: 12 - #Kerman - 18: - - primary: AEW&C - aircraft: - - A-50 - size: 1 - - primary: BARCAP - secondary: air-to-air - aircraft: - - F-14A Tomcat (Block 135-GR Late) - size: 10 +--- +name: Persian Gulf - Operation Noisy Cricket +theater: Persian Gulf +authors: Starfire +recommended_player_faction: USA 2005 +recommended_enemy_faction: Iran 2015 +description: +In the face of mounting sanctions against their nuclear program, Iran has + barred all shipping from transiting the Strait of Hormuz. Three days ago, the + Iranian Vice-President ordered a series of missile attacks on commercial + vessels entering the Gulf of Oman through the highly strategic chokepoint, + sinking a container ship and damaging two oil tankers. Operation Noisy Cricket + is the American response to this threat to regional stability. The objective + is to render inoperative Iran's array of coastal anti-ship missile sites, as + well as disable the airfields from which maritime strike aircraft could be + launched.
While officially intended only to deter any further attempts + to disrupt the flow of maritime traffic and and protect the interests of the + global economy, The USAF will also leverage the resultant degradation in + Iranian air defences to launch a deep strike from airfields in the UAE in an + attempt to take out Iran's last combat-worthy F-14 Tomcats, currently + stationed at Kerman. At the same time, a carrier-based Marine detachment will + be inserted via helicopter to conduct an unscheduled inspection of the Bushehr + Nuclear Power Plant, in order to verify Iran's compliance with international + nuclear agreements and gather evidence of any ongoing nuclear weapons + development.
+miz: operation_noisy_cricket.miz +performance: 1 +recommended_start_date: 2019-07-13 +recommended_player_money: 0 +recommended_enemy_money: 0 +recommended_player_income_multiplier: 0.2 +recommended_enemy_income_multiplier: 0.2 +version: "10.7" +squadrons: + Blue CV-1: + - primary: SEAD + secondary: any + aircraft: + - F/A-18C Hornet (Lot 20) + size: 40 + - primary: AEW&C + aircraft: + - E-2D Advanced Hawkeye + size: 2 + - primary: Refueling + aircraft: + - S-3B Tanker + size: 4 + - primary: Air Assault + secondary: any + aircraft: + - UH-60L + - UH-60A + size: 4 + #Al Minhad AFB (61) + 12: + - primary: DEAD + secondary: any + aircraft: + - F-16CM Fighting Falcon (Block 50) + size: 32 + - primary: Escort + secondary: air-to-air + aircraft: + - F-15C Eagle + size: 24 + #Al Dhafra AFB (251) + 4: + - primary: Strike + secondary: air-to-ground + aircraft: + - B-1B Lancer + size: 4 + - primary: Refueling + aircraft: + - KC-135 Stratotanker + size: 1 + - primary: OCA/Runway + secondary: any + aircraft: + - F-15E Strike Eagle (Suite 4+) + size: 20 + - primary: DEAD + secondary: air-to-ground + aircraft: + - AV-8B Harrier II Night Attack + size: 20 + #Bandar Abbas Intl (51) + 2: + - primary: SEAD + secondary: air-to-ground + aircraft: + - F-4E Phantom II + size: 20 + - primary: TARCAP + secondary: air-to-air + aircraft: + - F-5E Tiger II + size: 16 + #Qeshm Island (12) + 13: + - primary: Air Assault + secondary: air-to-ground + aircraft: + - Mi-24P Hind-F + size: 12 + #Abu Musa Island (8) + 1: + - primary: DEAD + secondary: air-to-ground + aircraft: + - Su-25T Frogfoot + size: 8 + #Kish Intl (46) + 24: + - primary: Strike + secondary: air-to-ground + aircraft: + - Su-24MK Fencer-D + size: 20 + - primary: Escort + secondary: any + aircraft: + - Mirage-F1EQ + size: 16 + #Shiraz Intl (122) + 19: + - primary: Transport + aircraft: + - IL-76MD + size: 5 + - primary: BARCAP + secondary: air-to-air + aircraft: + - MiG-29A Fulcrum-A + size: 12 + #Kerman + 18: + - primary: AEW&C + aircraft: + - A-50 + size: 1 + - primary: BARCAP + secondary: air-to-air + aircraft: + - F-14A Tomcat (Block 135-GR Late) + size: 10 diff --git a/resources/campaigns/operation_peace_spring.miz b/resources/campaigns/operation_peace_spring.miz index 5420f118..d44be71b 100644 Binary files a/resources/campaigns/operation_peace_spring.miz and b/resources/campaigns/operation_peace_spring.miz differ diff --git a/resources/campaigns/operation_peace_spring.yaml b/resources/campaigns/operation_peace_spring.yaml index f6991171..b7c0bc74 100644 --- a/resources/campaigns/operation_peace_spring.yaml +++ b/resources/campaigns/operation_peace_spring.yaml @@ -1,132 +1,160 @@ ---- -name: Syria - Operation Peace Spring -theater: Syria -authors: Starfire -recommended_player_faction: Bluefor Modern -recommended_enemy_faction: Iraq 1991 -description:This is a semi-fictional what-if scenario for Operation Peace Spring, during which Turkish forces that crossed into Syria on an offensive against Kurdish militias were emboldened by early successes to continue pushing further southward. Attempts to broker a ceasefire have failed. Members of Operation Inherent Resolve have gathered at Ramat David Airbase in Israel to launch a counter-offensive.
Note: The default faction is set as Iraq 1991 in order to provide an opponent with a wider variety of units. While Turkey 2005 would be the historical faction (and has preset squadrons included), they only have two jets available (F-4 and F-16).
-miz: operation_peace_spring.miz -performance: 1 -recommended_start_date: 2019-12-23 -version: "10.7" -squadrons: -# Ramat David - 30: - - primary: CAS - secondary: air-to-ground - aircraft: - - A-10C Thunderbolt II (Suite 7) - size: 8 - - primary: SEAD - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 20 - - primary: Strike - secondary: air-to-ground - aircraft: - - F-15E Strike Eagle (AI) - - F-15E Strike Eagle (Suite 4+) - size: 12 - - primary: AEW&C - aircraft: - - E-3A - size: 2 -# King Hussein Air College - 19: - - primary: DEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 20 - - primary: BAI - secondary: air-to-ground - aircraft: - - AV-8B Harrier II Night Attack - size: 8 - - primary: BARCAP - secondary: air-to-air - aircraft: - - F-15C Eagle - size: 12 - - primary: CAS - secondary: air-to-ground - aircraft: - - AH-64D Apache Longbow - size: 8 - - primary: Refueling - aircraft: - - KC-135 Stratotanker - size: 2 - - primary: Air Assault - secondary: air-to-ground - aircraft: - - UH-1H Iroquois - size: 2 -# Damascus - 7: - - primary: TARCAP - secondary: air-to-air - aircraft: - - F-4E Phantom II - - Mirage-F1EQ - size: 12 - - primary: BAI - secondary: air-to-ground - aircraft: - - AH-1W SuperCobra - - Su-25 Frogfoot - size: 12 - - primary: CAS - secondary: air-to-ground - aircraft: - - OH-58D Kiowa Warrior - - Mi-24P Hind-F - size: 8 -# Tiyas - 39: - - primary: SEAD - secondary: air-to-ground - aircraft: - - F-16CM Fighting Falcon (Block 50) - - Su-24M Fencer-D - size: 20 -# Abu Al Duhur - 1: - - primary: Strike - secondary: air-to-ground - aircraft: - - F-4E Phantom II - - H-6J Badger - size: 20 -# Gaziantep - 11: - - primary: BARCAP - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - - MiG-29A Fulcrum-A - size: 12 -# Incirlik - 16: - - primary: Strike - secondary: air-to-ground - aircraft: - - F-4E Phantom II - - Tu-22M3 Backfire-C - size: 20 - - primary: AEW&C - aircraft: - - E-3A - - A-50 - size: 2 - - primary: Refueling - aircraft: - - KC-135 Stratotanker - - IL-78M - size: 2 - - primary: Transport - aircraft: - - C-130 - - IL-76MD - size: 4 \ No newline at end of file +--- +name: Syria - Operation Peace Spring +theater: Syria +authors: Starfire +recommended_player_faction: Bluefor Modern +recommended_enemy_faction: Iraq 1991 +description: +This is a semi-fictional what-if scenario for Operation Peace Spring, + during which Turkish forces that crossed into Syria on an offensive against + Kurdish militias were emboldened by early successes to continue pushing + further southward. Attempts to broker a ceasefire have failed. Members of + Operation Inherent Resolve have gathered at Ramat David Airbase in Israel to + launch a counter-offensive.
Note: The default faction + is set as Iraq 1991 in order to provide an opponent with a wider variety of + units. While Turkey 2005 would be the historical faction (and has preset + squadrons included), they only have two jets available (F-4 and F-16).
+miz: operation_peace_spring.miz +performance: 2 +recommended_start_date: 2019-12-23 +version: "10.7" +squadrons: + Blue CV-1: + - primary: SEAD + secondary: any + aircraft: + - F/A-18C Hornet (Lot 20) + size: 40 + - primary: BAI + secondary: air-to-ground + aircraft: + - S-3B Viking + size: 20 + - primary: AEW&C + aircraft: + - E-2D Advanced Hawkeye + size: 4 + - primary: Refueling + aircraft: + - S-3B Tanker + size: 4 + Bombers from RAF Fairford: + - primary: DEAD + secondary: air-to-ground + aircraft: + - B-52H Stratofortress + size: 8 + # Akrotiri + 44: + - primary: Strike + secondary: air-to-ground + aircraft: + - B-1B Lancer + size: 8 + - primary: OCA/Runway + secondary: any + aircraft: + - F-15E Strike Eagle (Suite 4+) + size: 12 + - primary: TARCAP + secondary: air-to-air + aircraft: + - F-15C Eagle + size: 20 + - primary: Air Assault + secondary: any + aircraft: + - UH-60L + - UH-60A + size: 4 + # Ramat David + 30: + - primary: BAI + secondary: air-to-ground + aircraft: + - A-10C Thunderbolt II (Suite 7) + size: 8 + - primary: DEAD + secondary: any + aircraft: + - F-16CM Fighting Falcon (Block 50) + size: 28 + - primary: CAS + secondary: air-to-ground + aircraft: + - AH-64D Apache Longbow + size: 4 + # Damascus + 7: + - primary: Strike + secondary: air-to-ground + aircraft: + - F-4E Phantom II + - H-6J Badger + size: 16 + - primary: BAI + secondary: air-to-ground + aircraft: + - AH-1W SuperCobra + - Su-25 Frogfoot + size: 16 + - primary: CAS + secondary: air-to-ground + aircraft: + - OH-58D Kiowa Warrior + - Mi-24P Hind-F + size: 4 + # Tiyas + 39: + - primary: SEAD + secondary: air-to-ground + aircraft: + - F-16CM Fighting Falcon (Block 50) + - Su-24M Fencer-D + size: 16 + - primary: Escort + secondary: air-to-air + aircraft: + - F-4E Phantom II + - Mirage-F1EQ + size: 16 + # Abu Al Duhur + 1: + - primary: Fighter sweep + secondary: air-to-air + aircraft: + - F-4E Phantom II + - MiG-23ML Flogger-G + size: 8 + # Gaziantep + 11: + - primary: BARCAP + secondary: any + aircraft: + - F-16CM Fighting Falcon (Block 50) + - MiG-29A Fulcrum-A + size: 8 + # Incirlik + 16: + - primary: Strike + secondary: air-to-ground + aircraft: + - F-4E Phantom II + - Tu-22M3 Backfire-C + size: 16 + - primary: AEW&C + aircraft: + - E-3A + - A-50 + size: 1 + - primary: Refueling + aircraft: + - KC-135 Stratotanker + - IL-78M + size: 1 + - primary: Escort + secondary: any + aircraft: + - F-4E Phantom II + - MiG-21bis Fishbed-N + size: 16 \ No newline at end of file diff --git a/resources/campaigns/operation_vectrons_claw.miz b/resources/campaigns/operation_vectrons_claw.miz index d1c6df1f..79ca542c 100644 Binary files a/resources/campaigns/operation_vectrons_claw.miz and b/resources/campaigns/operation_vectrons_claw.miz differ diff --git a/resources/campaigns/operation_vectrons_claw.yaml b/resources/campaigns/operation_vectrons_claw.yaml index 2b894b8e..1f147d74 100644 --- a/resources/campaigns/operation_vectrons_claw.yaml +++ b/resources/campaigns/operation_vectrons_claw.yaml @@ -1,148 +1,156 @@ ---- -name: Caucasus - Operation Vectron's Claw -theater: Caucasus -authors: Starfire -recommended_player_faction: USA 2005 -recommended_enemy_faction: Russia 2010 -description:United Nations Observer Mission in Georgia (UNOMIG) observers stationed in Georgia to monitor the ceasefire between Georgia and Abkhazia have been cut off from friendly forces by Russian troops backing the separatist state. The UNOMIG HQ at Sukhumi has been taken, and a small contingent of observers and troops at the Zugdidi Sector HQ will have to make a run for the coast, supported by offshore US naval aircraft. The contingent is aware that their best shot at survival is to swiftly retake Sukhumi before Russian forces have a chance to dig in, so that friendly ground forces can land and reinforce them.
Note: Ground unit purchase will not be available past Turn 0 until Sukhumi is retaken, so it is imperative you reach Sukhumi with at least one surviving ground unit to capture it. Two Hueys are available at Zugdidi for some close air support. The player can either play the first leg of the scenario as an evacuation with a couple of light vehicles (e.g. Humvees) set on breakthrough (modifying waypoints in the mission editor so they are not charging head-on into enemy ground forces is suggested), or purchase heavier ground units if they wish to experience a more traditional frontline ground war. Once Sukhumi has been captured, squadrons based in Incirlik Turkey can be ferried in via the "From Incirlik" off-map spawn point.
-miz: operation_vectrons_claw.miz -performance: 1 -recommended_start_date: 2008-08-08 -version: "10.7" -squadrons: - Blue CV-1: - - primary: BARCAP - secondary: any - aircraft: - - F-14B Tomcat - size: 20 - - primary: SEAD - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 32 - - primary: Escort - secondary: any - aircraft: - - F/A-18C Hornet (Lot 20) - size: 32 - - primary: AEW&C - aircraft: - - E-2C Hawkeye - size: 1 - - primary: Refueling - aircraft: - - S-3B Tanker - size: 3 - - primary: Air Assault - secondary: any - aircraft: - - SH-60B Seahawk - size: 2 - Blue LHA: - - primary: BAI - secondary: air-to-ground - aircraft: - - AV-8B Harrier II Night Attack - size: 20 - From Incirlik: - - primary: CAS - secondary: air-to-ground - aircraft: - - AH-64D Apache Longbow - size: 8 - - primary: CAS - secondary: air-to-ground - aircraft: - - A-10C Thunderbolt II (Suite 7) - size: 6 - - primary: DEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 16 - - primary: DEAD - secondary: any - aircraft: - - F-16CM Fighting Falcon (Block 50) - size: 16 - - primary: BAI - secondary: air-to-ground - aircraft: - - F-15E Strike Eagle (AI) - - F-15E Strike Eagle (Suite 4+) - size: 12 - - primary: Strike - secondary: air-to-ground - aircraft: - - B-1B Lancer - size: 8 - - primary: Strike - secondary: air-to-ground - aircraft: - - B-52H Stratofortress - size: 8 - - primary: Refueling - aircraft: - - KC-135 Stratotanker - size: 1 -#FARPs - UNOMIG Sector HQ: - - primary: Transport - secondary: any - aircraft: - - UH-1H Iroquois - size: 2 - Dzhugba: - - primary: CAS - secondary: any - aircraft: - - Mi-24P Hind-F - size: 8 -#Sukhumi-Babushara - 20: - - primary: TARCAP - secondary: air-to-air - aircraft: - - MiG-29S Fulcrum-C - size: 8 - - primary: BAI - secondary: air-to-ground - aircraft: - - Su-25T Frogfoot - size: 12 -#Sochi-Adler - 18: - - primary: Escort - secondary: air-to-air - aircraft: - - Su-27 Flanker-B - size: 8 - - primary: SEAD - secondary: air-to-ground - aircraft: - - Su-24M Fencer-D - size: 20 - - primary: DEAD - secondary: air-to-ground - aircraft: - - Su-34 Fullback - size: 20 -#Anapa-Vityazevo - 12: - - primary: Strike - secondary: air-to-ground - aircraft: - - Tu-95MS Bear-H - size: 16 - Red CV: - - primary: BARCAP - secondary: any - aircraft: - - SU-33 Flanker-D - size: 18 - #I am aware there is no Russian LHA. This is just for campaign inversion. - Red LHA: - - primary: BAI - secondary: air-to-ground - size: 20 \ No newline at end of file +--- +name: Caucasus - Operation Vectron's Claw +theater: Caucasus +authors: Starfire +recommended_player_faction: USA 2005 +recommended_enemy_faction: Russia 2010 +description: +Background - The United Nations Observer Mission in Georgia (UNOMIG) has been actively monitoring the ceasefire agreement between Georgia and its breakaway region of Abkhazia. Recent developments have escalated tensions in the area, leading to a precarious situation for UN observers and affiliated personnel. +
Current Situation - UNOMIG observers, along with a contingent of international troops, have found themselves isolated due to the intervention of Russian forces supporting the separatist ambitions of Abkhazia. The UNOMIG headquarters located in Sukhumi has fallen into enemy hands. A smaller group based at the Zugdidi Sector Headquarters now faces the daunting task of navigating to safety with the aid of offshore naval air support. +
Objective - The immediate goal is to orchestrate a strategic withdrawal of UN forces to the coastline, leveraging support from US naval aircraft positioned offshore. The critical mission objective is the rapid recapture of Sukhumi. This action is essential to enable the landing of friendly ground forces and the ferrying in of land-based sqwuadrons from Incirlik. +
Operational Constraints - It is crucial to note that reinforcement of ground units will not be possible until Sukhumi is successfully recaptured. This recapture can either be performed using existing UN personnel and ground vehicles, or via heliborne assault troop insertion. +
Assets & Support - Available assets include two Huey helicopters for close air support. Commanders may opt to initiate the operation with light vehicles, such as Humvees, employing breakthrough tactics to avoid direct confrontations with enemy forces. Alternatively, the use of heavier ground units is an option for commanders seeking a more conventional combat engagement. Upon the recapture of Sukhumi, additional squadrons from Incirlik, Turkey, will become operational. +
Secondary Objective - Consider prioritising the capture of the Batumi airfield, located to the south, for its strategic value as a forward operating base. Commanders should be aware of the inherent risks, as the airfield is relatively small and lacks air defence systems, posing a significant threat to any stationed aircraft.
+miz: operation_vectrons_claw.miz +performance: 1 +recommended_start_date: 2008-08-08 +version: "10.7" +control_points: + Squadrons from Incirlik: + ferry_only: true +squadrons: + Blue CV-1: + - primary: BARCAP + secondary: any + aircraft: + - F-14B Tomcat + size: 16 + - primary: SEAD + secondary: any + aircraft: + - F/A-18C Hornet (Lot 20) + size: 60 + - primary: CAS + secondary: air-to-ground + aircraft: + - S-3B Viking + size: 8 + - primary: AEW&C + aircraft: + - E-2C Hawkeye + size: 2 + - primary: Refueling + aircraft: + - S-3B Tanker + size: 2 + - primary: Air Assault + secondary: any + aircraft: + - UH-60L + - UH-60A + size: 2 + Blue LHA: + - primary: BAI + secondary: air-to-ground + aircraft: + - AV-8B Harrier II Night Attack + size: 20 + Squadrons from Incirlik: + - primary: CAS + secondary: air-to-ground + aircraft: + - AH-64D Apache Longbow + size: 4 + - primary: CAS + secondary: air-to-ground + aircraft: + - A-10C Thunderbolt II (Suite 7) + size: 6 + - primary: DEAD + secondary: any + aircraft: + - F-16CM Fighting Falcon (Block 50) + size: 16 + - primary: BAI + secondary: any + aircraft: + - F-15E Strike Eagle (Suite 4+) + size: 8 + - primary: Refueling + aircraft: + - KC-135 Stratotanker + size: 1 + Bombers from RAF Fairford: + - primary: Anti-ship + secondary: air-to-ground + aircraft: + - B-52H Stratofortress + size: 4 + Bombers from Base Aérea de Morón: + - primary: OCA/Runway + secondary: air-to-ground + aircraft: + - B-1B Lancer + size: 4 + #FARPs + UNOMIG Sector HQ: + - primary: Transport + secondary: any + aircraft: + - UH-1H Iroquois + size: 2 + Dzhugba: + - primary: CAS + secondary: any + aircraft: + - Mi-24P Hind-F + size: 4 + #Sukhumi-Babushara + 20: + - primary: TARCAP + secondary: air-to-air + aircraft: + - MiG-29S Fulcrum-C + size: 8 + - primary: BAI + secondary: air-to-ground + aircraft: + - Su-25T Frogfoot + size: 12 + #Sochi-Adler + 18: + - primary: Escort + secondary: air-to-air + aircraft: + - Su-27 Flanker-B + size: 8 + - primary: SEAD + secondary: air-to-ground + aircraft: + - Su-24M Fencer-D + size: 20 + - primary: DEAD + secondary: air-to-ground + aircraft: + - Su-34 Fullback + size: 20 + #Maykop-Khanskaya + 16: + - primary: Strike + secondary: air-to-ground + aircraft: + - Tu-22M3 Backfire-C + size: 20 + #Anapa-Vityazevo + 12: + - primary: Strike + secondary: air-to-ground + aircraft: + - Tu-95MS Bear-H + size: 16 + Red CV: + - primary: BARCAP + secondary: any + aircraft: + - SU-33 Flanker-D + size: 16 \ No newline at end of file diff --git a/resources/campaigns/operation_velvet_thunder.miz b/resources/campaigns/operation_velvet_thunder.miz new file mode 100644 index 00000000..fadf6f49 Binary files /dev/null and b/resources/campaigns/operation_velvet_thunder.miz differ diff --git a/resources/campaigns/operation_velvet_thunder.yaml b/resources/campaigns/operation_velvet_thunder.yaml new file mode 100644 index 00000000..ce7869d7 --- /dev/null +++ b/resources/campaigns/operation_velvet_thunder.yaml @@ -0,0 +1,99 @@ +--- +name: Marianas - Operation Velvet Thunder +theater: MarianaIslands +authors: Starfire +recommended_player_faction: USA 1970 +recommended_enemy_faction: NVA 1970 +description: +Operation Velvet Thunder is a high-intensity training exercise designed to + prepare fresh troops for the challenges they will face in Vietnam. The dense + jungle and rugged terrain of the Mariana Islands will provide a realistic + backdrop, allowing our forces to hone essential skills in jungle warfare, + unconventional tactics, and counterinsurgency operations. There are multiple + checkpoints scattered across the area of operations that will have to be + captured by Air Assault. Due to the limited size and availability of LZs, it + is vital to pay close attention to where you designate troop drop off zones. +
Note: This campaign is intended to be played with the + A-4 Skyhawk and OV-10a aircraft mods active. The C-101CC has also been included + as a stand-in for the Cessna A-37 Dragonfly in order to provide a CAS platform + of roughly equivalent combat capability. This campaign will be updated to use + Heatblur's F-4 Phantom II once it is in early access.
+miz: operation_velvet_thunder.miz +performance: 1 +recommended_start_date: 1970-11-29 +version: "10.7" +settings: + a4_skyhawk: true + f4bc_phantom: true + ov10a_bronco: true +squadrons: + #Andersen AFB + 6: + - primary: Escort + secondary: any + aircraft: + - F-5E Tiger II + size: 8 + - primary: BAI + secondary: any + aircraft: + - C-101CC Aviojet + size: 8 + - primary: CAS + secondary: any + aircraft: + - OV-10A Bronco + size: 8 + - primary: SEAD + secondary: any + aircraft: + - F-4C Phantom II + - F-4E Phantom II + size: 8 + - primary: Strike + secondary: any + aircraft: + - B-52H Stratofortress + size: 4 + - primary: Air Assault + secondary: any + aircraft: + - UH-1H Iroquois + size: 4 + - primary: Transport + secondary: any + aircraft: + - CH-47D + size: 4 + #Blue CV + Blue-CV: + - primary: DEAD + secondary: any + aircraft: + - A-4E Skyhawk + size: 16 + - primary: AEW&C + aircraft: + - E-2C Hawkeye + size: 2 + #Rota Intl + 1: + - primary: TARCAP + secondary: any + aircraft: + - MiG-19P Farmer-B + size: 8 + #Tinian Intl + 3: + - primary: Air Assault + secondary: any + aircraft: + - Mi-8MTV2 Hip + size: 4 + #Saipan Intl + 2: + - primary: BAI + secondary: any + aircraft: + - MiG-21bis Fishbed-N + size: 8 \ No newline at end of file diff --git a/resources/campaigns/scenic_merge.yaml b/resources/campaigns/scenic_merge.yaml index 4c65e4c2..c5bab649 100644 --- a/resources/campaigns/scenic_merge.yaml +++ b/resources/campaigns/scenic_merge.yaml @@ -14,6 +14,8 @@ recommended_player_money: 2000 recommended_enemy_money: 1000 recommended_player_income_multiplier: 1.5 recommended_enemy_income_multiplier: 0.7 +settings: + airbase_threat_range: 300 squadrons: #BLUFOR CVN Naval-3: diff --git a/resources/customized_payloads/AH-64D_BLK_II.lua b/resources/customized_payloads/AH-64D_BLK_II.lua index 4cbb8c34..62b6f0b8 100644 --- a/resources/customized_payloads/AH-64D_BLK_II.lua +++ b/resources/customized_payloads/AH-64D_BLK_II.lua @@ -2,30 +2,6 @@ local unitPayloads = { ["name"] = "AH-64D_BLK_II", ["payloads"] = { [1] = { - ["name"] = "Retribution CAS", - ["pylons"] = { - [1] = { - ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", - ["num"] = 3, - }, - [2] = { - ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", - ["num"] = 4, - }, - [3] = { - ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", - ["num"] = 2, - }, - [4] = { - ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", - ["num"] = 1, - }, - }, - ["tasks"] = { - [1] = 31, - }, - }, - [2] = { ["displayName"] = "Retribution BAI", ["name"] = "Retribution BAI", ["pylons"] = { @@ -45,12 +21,16 @@ local unitPayloads = { ["CLSID"] = "{M299_4xAGM_114L}", ["num"] = 1, }, + [5] = { + ["CLSID"] = "{AN_APG_78}", + ["num"] = 6, + }, }, ["tasks"] = { [1] = 31, }, }, - [3] = { + [2] = { ["name"] = "Retribution OCA/Aircraft", ["pylons"] = { [1] = { @@ -69,14 +49,46 @@ local unitPayloads = { ["CLSID"] = "{M261_M229}", ["num"] = 1, }, + [5] = { + ["CLSID"] = "{AN_APG_78}", + ["num"] = 6, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [3] = { + ["name"] = "Retribution CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", + ["num"] = 3, + }, + [2] = { + ["CLSID"] = "{M299_4xAGM_114L}", + ["num"] = 4, + }, + [3] = { + ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{M299_4xAGM_114L}", + ["num"] = 1, + }, + [5] = { + ["CLSID"] = "{AN_APG_78}", + ["num"] = 6, + }, }, ["tasks"] = { [1] = 31, }, }, [4] = { - ["displayName"] = "Retribution Escort", - ["name"] = "Retribution Escort", + ["displayName"] = "Retribution DEAD", + ["name"] = "Retribution DEAD", ["pylons"] = { [1] = { ["CLSID"] = "{M299_4xAGM_114L}", @@ -94,6 +106,39 @@ local unitPayloads = { ["CLSID"] = "{M299_4xAGM_114L}", ["num"] = 1, }, + [5] = { + ["CLSID"] = "{AN_APG_78}", + ["num"] = 6, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [5] = { + ["displayName"] = "Retribution Escort", + ["name"] = "Retribution Escort", + ["pylons"] = { + [1] = { + ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", + ["num"] = 3, + }, + [2] = { + ["CLSID"] = "{M299_4xAGM_114L}", + ["num"] = 4, + }, + [3] = { + ["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{M299_4xAGM_114L}", + ["num"] = 1, + }, + [5] = { + ["CLSID"] = "{AN_APG_78}", + ["num"] = 6, + }, }, ["tasks"] = { [1] = 31, diff --git a/resources/customized_payloads/B-52H.lua b/resources/customized_payloads/B-52H.lua index e6ef89f2..5dc1b8c6 100644 --- a/resources/customized_payloads/B-52H.lua +++ b/resources/customized_payloads/B-52H.lua @@ -2,84 +2,81 @@ local unitPayloads = { ["name"] = "B-52H", ["payloads"] = { [1] = { - ["name"] = "ANTISHIP", - ["pylons"] = { - [1] = { - ["CLSID"] = "{46ACDCF8-5451-4E26-BDDB-E78D5830E93C}", - ["num"] = 2, - }, - }, - ["tasks"] = { - [1] = 30, - }, - }, - [2] = { - ["name"] = "STRIKE", - ["pylons"] = { - [1] = { - ["CLSID"] = "{696CFFC4-0BDE-42A8-BE4B-0BE3D9DD723C}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{696CFFC4-0BDE-42A8-BE4B-0BE3D9DD723C}", - ["num"] = 3, - }, - }, - ["tasks"] = { - [1] = 32, - [2] = 34, - }, - }, - [3] = { - ["name"] = "SEAD", - ["pylons"] = { - [1] = { - ["CLSID"] = "{8DCAF3A3-7FCF-41B8-BB88-58DEDA878EDE}", - ["num"] = 2, - }, - }, - ["tasks"] = { - [1] = 33, - }, - }, - [4] = { - ["name"] = "CAP", - ["pylons"] = { - }, - ["tasks"] = { - }, - }, - [5] = { - ["name"] = "CAS", - ["pylons"] = { - [1] = { - ["CLSID"] = "{696CFFC4-0BDE-42A8-BE4B-0BE3D9DD723C}", - ["num"] = 3, - }, - [2] = { - ["CLSID"] = "{696CFFC4-0BDE-42A8-BE4B-0BE3D9DD723C}", - ["num"] = 1, - }, - }, - ["tasks"] = { - }, - }, - [6] = { - ["displayName"] = "Retribution OCA/Runway", ["name"] = "Retribution OCA/Runway", ["pylons"] = { [1] = { - ["CLSID"] = "{696CFFC4-0BDE-42A8-BE4B-0BE3D9DD723C}", - ["num"] = 1, + ["CLSID"] = "{585D626E-7F42-4073-AB70-41E728C333E2}", + ["num"] = 3, }, [2] = { - ["CLSID"] = "{696CFFC4-0BDE-42A8-BE4B-0BE3D9DD723C}", - ["num"] = 3, + ["CLSID"] = "{6C47D097-83FF-4FB2-9496-EAB36DDF0B05}", + ["num"] = 2, + }, + [3] = { + ["CLSID"] = "{585D626E-7F42-4073-AB70-41E728C333E2}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 32, + }, + }, + [2] = { + ["name"] = "Retribution DEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{45447F82-01B5-4029-A572-9AAD28AF0275}", + ["num"] = 3, + }, + [2] = { + ["CLSID"] = "{8DCAF3A3-7FCF-41B8-BB88-58DEDA878EDE}", + ["num"] = 2, + }, + [3] = { + ["CLSID"] = "{45447F82-01B5-4029-A572-9AAD28AF0275}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 32, + }, + }, + [3] = { + ["displayName"] = "Retribution Anti-ship", + ["name"] = "Retribution Anti-ship", + ["pylons"] = { + [1] = { + ["CLSID"] = "{HSAB-6xAGM-84}", + ["num"] = 3, + }, + [2] = { + ["CLSID"] = "{HSAB-6xAGM-84}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 32, + }, + }, + [4] = { + ["displayName"] = "Retribution Strike", + ["name"] = "Retribution Strike", + ["pylons"] = { + [1] = { + ["CLSID"] = "{585D626E-7F42-4073-AB70-41E728C333E2}", + ["num"] = 3, + }, + [2] = { + ["CLSID"] = "{6C47D097-83FF-4FB2-9496-EAB36DDF0B05}", + ["num"] = 2, + }, + [3] = { + ["CLSID"] = "{585D626E-7F42-4073-AB70-41E728C333E2}", + ["num"] = 1, }, }, ["tasks"] = { [1] = 32, - [2] = 34, }, }, }, diff --git a/resources/customized_payloads/Ka-50.lua b/resources/customized_payloads/Ka-50.lua index eb80a8b7..b860a320 100644 --- a/resources/customized_payloads/Ka-50.lua +++ b/resources/customized_payloads/Ka-50.lua @@ -2,133 +2,127 @@ local unitPayloads = { ["name"] = "Ka-50", ["payloads"] = { [1] = { - ["name"] = "CAS", + ["name"] = "Retribution CAS", ["pylons"] = { [1] = { ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", - ["num"] = 1, + ["num"] = 4, }, [2] = { - ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", - ["num"] = 2, + ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", + ["num"] = 1, }, [3] = { - ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", + ["CLSID"] = "B_8V20A_OFP2", ["num"] = 3, }, [4] = { - ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", - ["num"] = 4, + ["CLSID"] = "B_8V20A_OFP2", + ["num"] = 2, }, }, ["tasks"] = { [1] = 31, - [2] = 32, - [3] = 18, }, }, [2] = { - ["name"] = "CAP", + ["displayName"] = "Retribution BAI", + ["name"] = "Retribution BAI", ["pylons"] = { [1] = { - ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", - ["num"] = 1, + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 4, }, [2] = { - ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", - ["num"] = 2, + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 1, }, [3] = { - ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", + ["CLSID"] = "B_8V20A_OFP2", ["num"] = 3, }, [4] = { - ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", - ["num"] = 4, + ["CLSID"] = "B_8V20A_OFP2", + ["num"] = 2, }, }, ["tasks"] = { [1] = 31, - [2] = 32, - [3] = 18, }, }, [3] = { - ["name"] = "SEAD", + ["displayName"] = "Retribution DEAD", + ["name"] = "Retribution DEAD", ["pylons"] = { [1] = { ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", - ["num"] = 1, + ["num"] = 4, }, [2] = { - ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", - ["num"] = 2, + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 1, }, [3] = { - ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", + ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", ["num"] = 3, }, [4] = { - ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", - ["num"] = 4, + ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", + ["num"] = 2, }, }, ["tasks"] = { [1] = 31, - [2] = 32, - [3] = 18, }, }, [4] = { - ["name"] = "ANTISHIP", + ["displayName"] = "Retribution OCA/Aircraft", + ["name"] = "Retribution OCA/Aircraft", ["pylons"] = { [1] = { - ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", - ["num"] = 1, + ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", + ["num"] = 4, }, [2] = { - ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", - ["num"] = 2, + ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", + ["num"] = 1, }, [3] = { ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", ["num"] = 3, }, [4] = { - ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", - ["num"] = 4, + ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", + ["num"] = 2, }, }, ["tasks"] = { [1] = 31, - [2] = 32, - [3] = 18, }, }, [5] = { - ["name"] = "STRIKE", + ["displayName"] = "Retribution Escort", + ["name"] = "Retribution Escort", ["pylons"] = { [1] = { - ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", - ["num"] = 1, + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 4, }, [2] = { - ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", - ["num"] = 2, + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 1, }, [3] = { ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", ["num"] = 3, }, [4] = { - ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", - ["num"] = 4, + ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", + ["num"] = 2, }, }, ["tasks"] = { [1] = 31, - [2] = 32, - [3] = 18, }, }, }, diff --git a/resources/customized_payloads/Ka-50_3.lua b/resources/customized_payloads/Ka-50_3.lua index 943afe2d..992f5b6e 100644 --- a/resources/customized_payloads/Ka-50_3.lua +++ b/resources/customized_payloads/Ka-50_3.lua @@ -2,7 +2,7 @@ local unitPayloads = { ["name"] = "Ka-50_3", ["payloads"] = { [1] = { - ["name"] = "CAS", + ["name"] = "Retribution CAS", ["pylons"] = { [1] = { ["CLSID"] = "{9S846_2xIGLA}", @@ -34,8 +34,8 @@ local unitPayloads = { }, }, [2] = { - ["displayName"] = "STRIKE", - ["name"] = "STRIKE", + ["displayName"] = "Retribution BAI", + ["name"] = "Retribution BAI", ["pylons"] = { [1] = { ["CLSID"] = "{9S846_2xIGLA}", @@ -54,20 +54,86 @@ local unitPayloads = { ["num"] = 1, }, [5] = { - ["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}", + ["CLSID"] = "B_8V20A_OFP2", ["num"] = 3, }, [6] = { - ["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}", + ["CLSID"] = "B_8V20A_OFP2", ["num"] = 2, }, }, ["tasks"] = { [1] = 31, - [2] = 32, }, }, [3] = { + ["displayName"] = "Retribution OCA/Aircraft", + ["name"] = "Retribution OCA/Aircraft", + ["pylons"] = { + [1] = { + ["CLSID"] = "{9S846_2xIGLA}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{9S846_2xIGLA}", + ["num"] = 5, + }, + [3] = { + ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", + ["num"] = 4, + }, + [4] = { + ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", + ["num"] = 1, + }, + [5] = { + ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", + ["num"] = 3, + }, + [6] = { + ["CLSID"] = "{6A4B9E69-64FE-439a-9163-3A87FB6A4D81}", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [4] = { + ["displayName"] = "Retribution DEAD", + ["name"] = "Retribution DEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{9S846_2xIGLA}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{9S846_2xIGLA}", + ["num"] = 5, + }, + [3] = { + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 4, + }, + [4] = { + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 1, + }, + [5] = { + ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", + ["num"] = 3, + }, + [6] = { + ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 31, + }, + }, + [5] = { + ["displayName"] = "Retribution Escort", ["name"] = "Retribution Escort", ["pylons"] = { [1] = { @@ -79,19 +145,19 @@ local unitPayloads = { ["num"] = 5, }, [3] = { - ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", ["num"] = 4, }, [4] = { - ["CLSID"] = "{A6FD14D3-6D30-4C85-88A7-8D17BEE120E2}", + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", ["num"] = 1, }, [5] = { - ["CLSID"] = "B_8V20A_OFP2", + ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", ["num"] = 3, }, [6] = { - ["CLSID"] = "B_8V20A_OFP2", + ["CLSID"] = "{FC56DF80-9B09-44C5-8976-DCFAFF219062}", ["num"] = 2, }, }, diff --git a/resources/customized_payloads/S-3B.lua b/resources/customized_payloads/S-3B.lua index bdbdd472..08e6f1e6 100644 --- a/resources/customized_payloads/S-3B.lua +++ b/resources/customized_payloads/S-3B.lua @@ -1,168 +1,174 @@ -local unitPayloads = { - ["name"] = "S-3B", - ["payloads"] = { - [1] = { - ["name"] = "SEAD", - ["pylons"] = { - [1] = { - ["CLSID"] = "{AF42E6DF-9A60-46D8-A9A0-1708B241AADB}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", - ["num"] = 3, - }, - [4] = { - ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", - ["num"] = 5, - }, - [6] = { - ["CLSID"] = "{AF42E6DF-9A60-46D8-A9A0-1708B241AADB}", - ["num"] = 6, - }, - }, - ["tasks"] = { - [1] = 29, - }, - }, - [2] = { - ["name"] = "ANTISHIP", - ["pylons"] = { - [1] = { - ["CLSID"] = "{8B7CADF9-4954-46B3-8CFB-93F2F5B90B03}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 3, - }, - [4] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 5, - }, - [6] = { - ["CLSID"] = "{8B7CADF9-4954-46B3-8CFB-93F2F5B90B03}", - ["num"] = 6, - }, - }, - ["tasks"] = { - [1] = 30, - }, - }, - [3] = { - ["name"] = "STRIKE", - ["pylons"] = { - [1] = { - ["CLSID"] = "{69DC8AE7-8F77-427B-B8AA-B19D3F478B66}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 3, - }, - [4] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 5, - }, - [6] = { - ["CLSID"] = "{69DC8AE7-8F77-427B-B8AA-B19D3F478B66}", - ["num"] = 6, - }, - }, - ["tasks"] = { - [1] = 32, - [1] = 33, - }, - }, - [4] = { - ["name"] = "CAS", - ["pylons"] = { - [1] = { - ["CLSID"] = "{A76344EB-32D2-4532-8FA2-0C1BDC00747E}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", - ["num"] = 3, - }, - [4] = { - ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", - ["num"] = 5, - }, - [6] = { - ["CLSID"] = "{A76344EB-32D2-4532-8FA2-0C1BDC00747E}", - ["num"] = 6, - }, - }, - ["tasks"] = { - [1] = 31, - }, - }, - }, - [5] = { - ["name"] = "RUNWAY_ATTACK", - ["pylons"] = { - [1] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 3, - }, - [4] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 5, - }, - [6] = { - ["CLSID"] = "{AB8B8299-F1CC-4359-89B5-2172E0CF4A5A}", - ["num"] = 6, - }, - }, - ["tasks"] = { - [1] = 34, - }, - }, - ["unitType"] = "S-3B", -} -return unitPayloads +local unitPayloads = { + ["name"] = "S-3B", + ["payloads"] = { + [1] = { + ["displayName"] = "Retribution OCA/Aircraft", + ["name"] = "Retribution OCA/Aircraft", + ["pylons"] = { + [1] = { + ["CLSID"] = "{B83CB620-5BBE-4BEA-910C-EB605A327EF9}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{B83CB620-5BBE-4BEA-910C-EB605A327EF9}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 3, + }, + [5] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 4, + }, + [6] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 5, + }, + }, + ["tasks"] = { + [1] = 30, + }, + }, + [2] = { + ["displayName"] = "Retribution DEAD", + ["name"] = "Retribution DEAD", + ["pylons"] = { + [1] = { + ["CLSID"] = "{AF42E6DF-9A60-46D8-A9A0-1708B241AADB}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{AF42E6DF-9A60-46D8-A9A0-1708B241AADB}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 30, + }, + }, + [3] = { + ["displayName"] = "Retribution Anti-ship", + ["name"] = "Retribution Anti-ship", + ["pylons"] = { + [1] = { + ["CLSID"] = "{8B7CADF9-4954-46B3-8CFB-93F2F5B90B03}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{8B7CADF9-4954-46B3-8CFB-93F2F5B90B03}", + ["num"] = 1, + }, + }, + ["tasks"] = { + [1] = 30, + }, + }, + [4] = { + ["name"] = "Retribution CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{444BA8AE-82A7-4345-842E-76154EFCCA46}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{444BA8AE-82A7-4345-842E-76154EFCCA46}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 3, + }, + [5] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 4, + }, + [6] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 5, + }, + }, + ["tasks"] = { + [1] = 30, + }, + }, + [5] = { + ["displayName"] = "Retribution BAI", + ["name"] = "Retribution BAI", + ["pylons"] = { + [1] = { + ["CLSID"] = "{69DC8AE7-8F77-427B-B8AA-B19D3F478B66}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{69DC8AE7-8F77-427B-B8AA-B19D3F478B66}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 5, + }, + [4] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 3, + }, + [6] = { + ["CLSID"] = "{ADD3FAE1-EBF6-4EF9-8EFC-B36B5DDF1E6B}", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 30, + }, + }, + [6] = { + ["displayName"] = "Retribution Strike", + ["name"] = "Retribution Strike", + ["pylons"] = { + [1] = { + ["CLSID"] = "{60CC734F-0AFA-4E2E-82B8-93B941AB11CF}", + ["num"] = 6, + }, + [2] = { + ["CLSID"] = "{60CC734F-0AFA-4E2E-82B8-93B941AB11CF}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 5, + }, + [4] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 4, + }, + [5] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 3, + }, + [6] = { + ["CLSID"] = "{BCE4E030-38E9-423E-98ED-24BE3DA87C32}", + ["num"] = 2, + }, + }, + ["tasks"] = { + [1] = 30, + }, + }, + }, + ["tasks"] = { + }, + ["unitType"] = "S-3B", +} +return unitPayloads diff --git a/resources/factions/US_UK_Falklands.json b/resources/factions/US_UK_Falklands.json index 8545e45d..c065947d 100644 --- a/resources/factions/US_UK_Falklands.json +++ b/resources/factions/US_UK_Falklands.json @@ -21,6 +21,7 @@ "S-3B Viking", "F/A-18C Hornet (Lot 20)", "F-14B Tomcat", + "F-14A Tomcat (Block 135-GR Late)", "UH-1H Iroquois", "B-1B Lancer" diff --git a/resources/factions/egypt_2000.json b/resources/factions/egypt_2000.json new file mode 100644 index 00000000..ce91a01f --- /dev/null +++ b/resources/factions/egypt_2000.json @@ -0,0 +1,96 @@ +{ + "country": "Egypt", + "name": "Egypt 2000", + "authors": "Starfire", + "description": "Egyptian military in the 21st century.
", + "locales": [ + "ar_SA" + ], + "aircrafts": [ + "MiG-29S Fulcrum-C", + "MiG-21bis Fishbed-N", + "Mirage 2000C", + "F-4E Phantom II", + "F-16CM Fighting Falcon (Block 50)", + "IL-76MD", + "C-130", + "C-130J-30 Super Hercules", + "AH-64D Apache Longbow", + "AH-64D Apache Longbow (AI)", + "SA 342L Gazelle", + "SA 342M Gazelle", + "CH-47D", + "Ka-50 Hokum", + "Ka-50 Hokum (Blackshark 3)", + "Mi-24V Hind-E", + "Mi-24P Hind-F", + "Mi-8MTV2 Hip" + ], + "awacs": [ + "E-2C Hawkeye" + ], + "frontline_units": [ + "M1A2 Abrams", + "M60A3 \"Patton\"", + "T-90A", + "T-55A", + "BMP-1", + "M113", + "BTR-80", + "M1043 HMMWV (M2 HMG)", + "M1045 HMMWV (BGM-71 TOW)", + "M1097 Heavy HMMWV Avenger", + "ZSU-23-4 Shilka", + "M163 Vulcan Air Defense System" + ], + "artillery_units": [ + "M109A6 Paladin", + "M270 Multiple Launch Rocket System" + ], + "logistics_units": [ + "Truck Ural-375", + "Truck Ural-4320T", + "Truck GAZ-66" + ], + "infantry_units": [ + "Infantry RPG", + "Infantry AK-74 Rus", + "MANPADS SA-18 Igla \"Grouse\"", + "MANPADS Stinger", + "Mortar 2B11 120mm", + "Paratrooper AKS", + "Paratrooper RPG-16" + ], + "preset_groups": [ + "SA-2/S-75", + "SA-6", + "SA-17", + "SA-10/S-300PS", + "SA-23/S-300VM", + "Patriot", + "Hawk" + ], + "naval_units": [ + "FFG Oliver Hazard Perry", + "Corvette 1241.1 Molniya", + "FAC La Combattante IIa" + ], + "missiles": [ + "SSM SS-1C Scud-B" + ], + "air_defense_units": [ + "EWR AN/FPS-117 Radar", + "EWR 55G6", + "M1097 Heavy HMMWV Avenger", + "M48 Chaparral", + "M163 Vulcan Air Defense System", + "SA-9 Strela", + "SA-15 Tor", + "ZSU-23-4 Shilka", + "AAA ZU-23 Closed Emplacement", + "ZU-23 on Ural-375", + "ZSU-57-2 'Sparka'" + ], + "has_jtac": true, + "jtac_unit": "MQ-9 Reaper" +} \ No newline at end of file diff --git a/resources/factions/final_countdown_2.json b/resources/factions/final_countdown_2.json index 80d68e4f..82614817 100644 --- a/resources/factions/final_countdown_2.json +++ b/resources/factions/final_countdown_2.json @@ -1,73 +1,73 @@ -{ - "country": "Combined Joint Task Forces Blue", - "name": "D-Day Allied Forces 1944 and 1990", - "authors": "Starfire", - "description": "Faction for Final Countdown II
", - "aircrafts": [ - "Boston Mk.III", - "Fortress Mk.III", - "Mustang Mk.IV (Late)", - "Spitfire LF Mk IX", - "Thunderbolt Mk.II (Late)", - "MosquitoFBMkVI", - "F-14B Tomcat", - "F/A-18C Hornet (Lot 20)", - "SH-60B Seahawk" - ], - "awacs": [ - "E-2C Hawkeye" - ], - "tankers": [ - "S-3B Tanker" - ], - "frontline_units": [ - "A17 Light Tank Mk VII Tetrarch", - "A22 Infantry Tank MK IV Churchill VII", - "A27L Cruiser Tank MK VIII Centaur IV", - "A27M Cruiser Tank MK VIII Cromwell IV", - "Daimler Armoured Car Mk I", - "M2A1 Half-Track", - "QF 40 mm Mark III", - "Sherman Firefly VC", - "Sherman III" - ], - "artillery_units": [ - "M12 Gun Motor Carriage" - ], - "logistics_units": [ - "Truck Bedford", - "Truck GMC \"Jimmy\" 6x6 Truck" - ], - "infantry_units": [ - "Infantry M1 Garand", - "Infantry SMLE No.4 Mk-1" - ], - "missiles": [], - "air_defense_units": [ - "Bofors 40 mm Gun" - ], - "preset_groups": [ - "Ally Flak", - "WW2LST" - ], - "locales": [ - "en_US" - ], - "naval_units": [ - "DDG Arleigh Burke IIa", - "CG Ticonderoga", - "CVN-74 John C. Stennis" - ], - "requirements": { - "WW2 Asset Pack": "https://www.digitalcombatsimulator.com/en/products/other/wwii_assets_pack/" - }, - "carrier_names": [ - "CVN-71 Theodore Roosevelt" - ], - "helicopter_carrier_names": [], - "has_jtac": true, - "doctrine": "ww2", - "unrestricted_satnav": true, - "building_set": "ww2ally", - "cargo_ship": "LST Mk.II" +{ + "country": "Combined Joint Task Forces Blue", + "name": "D-Day Allied Forces 1944 and 1990", + "authors": "Starfire", + "description": "Faction for Final Countdown II
", + "locales": [ + "en_US" + ], + "aircrafts": [ + "Boston Mk.III", + "Fortress Mk.III", + "Mustang Mk.IV (Late)", + "Spitfire LF Mk IX", + "Thunderbolt Mk.II (Late)", + "MosquitoFBMkVI", + "F-14B Tomcat", + "F/A-18C Hornet (Lot 20)", + "S-3B Viking", + "UH-60L", + "UH-60A" + ], + "awacs": [ + "E-2C Hawkeye" + ], + "tankers": [ + "S-3B Tanker" + ], + "frontline_units": [ + "A17 Light Tank Mk VII Tetrarch", + "A22 Infantry Tank MK IV Churchill VII", + "A27L Cruiser Tank MK VIII Centaur IV", + "A27M Cruiser Tank MK VIII Cromwell IV", + "Daimler Armoured Car Mk I", + "M2A1 Half-Track", + "QF 40 mm Mark III", + "Sherman Firefly VC", + "Sherman III" + ], + "artillery_units": [ + "M12 Gun Motor Carriage" + ], + "logistics_units": [ + "Truck Bedford", + "Truck GMC \"Jimmy\" 6x6 Truck" + ], + "infantry_units": [ + "Infantry M1 Garand" + ], + "naval_units": [ + "DDG Arleigh Burke IIa", + "CG Ticonderoga", + "CVN-74 John C. Stennis" + ], + "missiles": [], + "air_defense_units": [ + "Bofors 40 mm Gun" + ], + "preset_groups": [ + "Ally Flak" + ], + "requirements": { + "WW2 Asset Pack": "https://www.digitalcombatsimulator.com/en/products/other/wwii_assets_pack/" + }, + "carrier_names": [ + "CVN-71 Theodore Roosevelt" + ], + "has_jtac": true, + "jtac_unit": "MQ-9 Reaper", + "unrestricted_satnav": true, + "doctrine": "ww2", + "building_set": "ww2ally", + "cargo_ship": "LST Mk.II" } \ No newline at end of file diff --git a/resources/factions/nva_1970.json b/resources/factions/nva_1970.json new file mode 100644 index 00000000..392171e9 --- /dev/null +++ b/resources/factions/nva_1970.json @@ -0,0 +1,55 @@ +{ + "country": "Vietnam", + "name": "NVA 1970", + "authors": "Starfire", + "description": "North Vietnamese Army during the Vietnam War from 1965 to 1975
", + "locales": [ + "vi_Vn" + ], + "aircrafts": [ + "Mi-8MTV2 Hip", + "MiG-19P Farmer-B", + "MiG-21bis Fishbed-N" + ], + "awacs": [], + "tankers": [], + "frontline_units": [ + "T-55A", + "PT-76", + "M2A1 Half-Track", + "Grad MRL FDDM (FC)" + ], + "artillery_units": [ + "BM-21 Grad" + ], + "logistics_units": [ + "LUV UAZ-469 Jeep", + "Truck Ural-375" + ], + "infantry_units": [ + "Infantry AK-74 Rus", + "Infantry RPG" + ], + "missiles": [], + "preset_groups": [ + "SA-2/S-75", + "SA-3/S-125", + "KS-19/SON-9", + "Cold-War-Flak" + ], + "naval_units": [ + "Boat Armed Hi-speed", + "Boat Schnellboot type S130" + ], + "air_defense_units": [ + "SAM P19 \"Flat Face\" SR (SA-2/3)", + "S-60 57mm", + "8.8 cm Flak 18", + "ZSU-57-2 'Sparka'", + "AAA ZU-23 Emplacement", + "ZU-23 on Ural-375", + "ZSU-23-4 Shilka" + ], + "requirements": {}, + "doctrine": "coldwar" +} \ No newline at end of file diff --git a/resources/factions/redfor_china_2010.json b/resources/factions/redfor_china_2010.json index d5ffe9e6..b75e8082 100644 --- a/resources/factions/redfor_china_2010.json +++ b/resources/factions/redfor_china_2010.json @@ -1,120 +1,121 @@ -{ - "country": "China", - "name": "Redfor (China) 2010", - "authors": "Robert Peary", - "description": "Combined Redfor under China's leadership in the late 2000s, early 2010s.
", - "aircrafts": [ - "FC-1 Fierce Dragon", - "IL-76MD", - "J-11A Flanker-L", - "J-15 Flanker X-2", - "J-7B", - "Ka-50 Hokum", - "L-39ZA Albatros", - "Mi-24V Hind-E", - "Mi-24P Hind-F", - "Mi-28N Havoc", - "Mi-8MTV2 Hip", - "MiG-29S Fulcrum-C", - "MiG-31 Foxhound", - "Su-24M Fencer-D", - "Su-25 Frogfoot", - "Su-25T Frogfoot", - "Su-27 Flanker-B", - "Su-30MKK Flanker-G", - "Su-34 Fullback", - "Tu-22M3 Backfire-C", - "H-6J Badger" - ], - "awacs": [ - "KJ-2000" - ], - "tankers": [ - "IL-78M" - ], - "frontline_units": [ - "BMP-1", - "BMP-2", - "BMP-3", - "BTR-80", - "BTR-82A", - "HQ-7 Launcher", - "SA-19 Grison (2K22 Tunguska)", - "T-55A", - "T-72B3 model 2011", - "T-80UD", - "T-90A", - "Type 04A (ZBD-04A)", - "Type 96B (ZTZ-96B)" - ], - "artillery_units": [ - "2S19 Msta-S", - "2S9 Nona-S", - "BM-27 Uragan", - "BM-30 Smerch (9M55K5 HE Rockets)" - ], - "logistics_units": [ - "LUV UAZ-469 Jeep", - "Truck Ural-375" - ], - "infantry_units": [ - "Infantry AK-74 Rus", - "MANPADS SA-18 Igla \"Grouse\"", - "Mortar 2B11 120mm", - "Paratrooper AKS", - "Paratrooper RPG-16" - ], - "missiles": [], - "preset_groups": [ - "SA-2/S-75", - "HQ-2", - "SA-6", - "SA-11", - "HQ-7", - "SA-10/S-300PS", - "SA-10B/S-300PS", - "SA-17", - "SA-12/S-300V", - "SA-20/S-300PMU-1", - "SA-20B/S-300PMU-2", - "SA-23/S-300VM", - "Chinese Navy" - ], - "naval_units": [ - "Frigate 1135M Rezky", - "Type 052B Destroyer", - "Type 052C Destroyer", - "Corvette 1241.1 Molniya", - "Type 054A Frigate", - "CV 1143.5 Admiral Kuznetsov", - "Type 071 Amphibious Transport Dock" - ], - "air_defense_units": [ - "EWR 1L13", - "EWR 55G6", - "SAM SA-8 Osa \"Gecko\" TEL", - "SA-9 Strela", - "SA-13 Gopher (9K35 Strela-10M3)", - "SA-15 Tor", - "SA-19 Grison (2K22 Tunguska)", - "AAA ZU-23 Closed Emplacement", - "ZU-23 on Ural-375", - "ZSU-23-4 Shilka" - ], - "carrier_names": [ - "001 Liaoning", - "002 Shandong" - ], - "helicopter_carrier_names": [ - "Kunlun Shan", - "Jinggang Shan", - "Changbai Shan", - "Yimeng Shan", - "Longhu Shan", - "Wuzhi Shan", - "Wudang Shan" - ], - "requirements": {}, - "has_jtac": true, - "jtac_unit": "WingLoong-I" +{ + "country": "China", + "name": "Redfor (China) 2010", + "authors": "Robert Peary", + "description": "Combined Redfor under China's leadership in the late 2000s, early 2010s.
", + "aircrafts": [ + "FC-1 Fierce Dragon", + "IL-76MD", + "J-11A Flanker-L", + "J-15 Flanker X-2", + "J-7B", + "Ka-50 Hokum", + "Ka-50 Hokum (Blackshark 3)", + "L-39ZA Albatros", + "Mi-24V Hind-E", + "Mi-24P Hind-F", + "Mi-28N Havoc", + "Mi-8MTV2 Hip", + "MiG-29S Fulcrum-C", + "MiG-31 Foxhound", + "Su-24M Fencer-D", + "Su-25 Frogfoot", + "Su-25T Frogfoot", + "Su-27 Flanker-B", + "Su-30MKK Flanker-G", + "Su-34 Fullback", + "Tu-22M3 Backfire-C", + "H-6J Badger" + ], + "awacs": [ + "KJ-2000" + ], + "tankers": [ + "IL-78M" + ], + "frontline_units": [ + "BMP-1", + "BMP-2", + "BMP-3", + "BTR-80", + "BTR-82A", + "HQ-7 Launcher", + "SA-19 Grison (2K22 Tunguska)", + "T-55A", + "T-72B3 model 2011", + "T-80UD", + "T-90A", + "Type 04A (ZBD-04A)", + "Type 96B (ZTZ-96B)" + ], + "artillery_units": [ + "2S19 Msta-S", + "2S9 Nona-S", + "BM-27 Uragan", + "BM-30 Smerch (9M55K5 HE Rockets)" + ], + "logistics_units": [ + "LUV UAZ-469 Jeep", + "Truck Ural-375" + ], + "infantry_units": [ + "Infantry AK-74 Rus", + "MANPADS SA-18 Igla \"Grouse\"", + "Mortar 2B11 120mm", + "Paratrooper AKS", + "Paratrooper RPG-16" + ], + "missiles": [], + "preset_groups": [ + "SA-2/S-75", + "HQ-2", + "SA-6", + "SA-11", + "HQ-7", + "SA-10/S-300PS", + "SA-10B/S-300PS", + "SA-17", + "SA-12/S-300V", + "SA-20/S-300PMU-1", + "SA-20B/S-300PMU-2", + "SA-23/S-300VM", + "Chinese Navy" + ], + "naval_units": [ + "Frigate 1135M Rezky", + "Type 052B Destroyer", + "Type 052C Destroyer", + "Corvette 1241.1 Molniya", + "Type 054A Frigate", + "CV 1143.5 Admiral Kuznetsov", + "Type 071 Amphibious Transport Dock" + ], + "air_defense_units": [ + "EWR 1L13", + "EWR 55G6", + "SAM SA-8 Osa \"Gecko\" TEL", + "SA-9 Strela", + "SA-13 Gopher (9K35 Strela-10M3)", + "SA-15 Tor", + "SA-19 Grison (2K22 Tunguska)", + "AAA ZU-23 Closed Emplacement", + "ZU-23 on Ural-375", + "ZSU-23-4 Shilka" + ], + "carrier_names": [ + "001 Liaoning", + "002 Shandong" + ], + "helicopter_carrier_names": [ + "Kunlun Shan", + "Jinggang Shan", + "Changbai Shan", + "Yimeng Shan", + "Longhu Shan", + "Wuzhi Shan", + "Wudang Shan" + ], + "requirements": {}, + "has_jtac": true, + "jtac_unit": "WingLoong-I" } \ No newline at end of file diff --git a/resources/factions/usa_1970.json b/resources/factions/usa_1970.json new file mode 100644 index 00000000..04e3043d --- /dev/null +++ b/resources/factions/usa_1970.json @@ -0,0 +1,71 @@ +{ + "country": "USA", + "name": "USA 1970", + "authors": "Starfire", + "description": "US military during the Vietnam War from 1965 to 1975
", + "locales": [ + "en_US" + ], + "aircrafts": [ + "F-14A Tomcat (Block 135-GR Late)", + "F-4C Phantom II", + "F-4B Phantom II", + "F-4E Phantom II", + "F-5E Tiger II", + "A-4E Skyhawk", + "OV-10A Bronco", + "C-101CC Aviojet", + "B-52H Stratofortress", + "C-47 Skytrain", + "C-130", + "UH-1H Iroquois", + "AH-1W SuperCobra", + "OH-58D Kiowa Warrior", + "CH-47D", + "CH-53E" + ], + "awacs": [ + "E-2C Hawkeye" + ], + "tankers": [ + "KC-130", + "KC-135 Stratotanker" + ], + "frontline_units": [ + "M113", + "M163 Vulcan Air Defense System", + "M60A3 \"Patton\"" + ], + "artillery_units": [ + "M109A6 Paladin" + ], + "logistics_units": [ + "Truck M818 6x6", + "LARC-V" + ], + "infantry_units": [ + "Infantry M249", + "Infantry M4" + ], + "missiles": [], + "preset_groups": [ + "Hawk" + ], + "naval_units": [ + "FFG Oliver Hazard Perry", + "CV-59 Forrestal" + ], + "air_defense_units": [ + "SAM Hawk SR (AN/MPQ-50)", + "M163 Vulcan Air Defense System", + "M48 Chaparral" + ], + "carrier_names": [ + "CV-59 Forrestal", + "CV-60 Saratoga", + "CV-61 Ranger", + "CV-62 Independence" + ], + "requirements": {}, + "doctrine": "coldwar" +} \ No newline at end of file diff --git a/resources/factions/wrl_taskforceblue.json b/resources/factions/wrl_taskforceblue.json index b9651eac..dc69aa2b 100644 --- a/resources/factions/wrl_taskforceblue.json +++ b/resources/factions/wrl_taskforceblue.json @@ -106,7 +106,6 @@ "UH-1H Iroquois" ], "awacs": [ - "E-2C Hawkeye", "E-2D Advanced Hawkeye", "E-3A" ], diff --git a/resources/plugins/dismounts/plugin.json b/resources/plugins/dismounts/plugin.json index 5611caa4..0008d741 100644 --- a/resources/plugins/dismounts/plugin.json +++ b/resources/plugins/dismounts/plugin.json @@ -1,5 +1,5 @@ { - "nameInUI": "DCS Dismounts", + "nameInUI": "DCS Dismounts (FPS-killer)", "defaultValue": false, "specificOptions": [ { diff --git a/resources/plugins/pretense/pretense_compiled.lua b/resources/plugins/pretense/pretense_compiled.lua index 4a458bbd..34e2529c 100644 --- a/resources/plugins/pretense/pretense_compiled.lua +++ b/resources/plugins/pretense/pretense_compiled.lua @@ -23,6 +23,21 @@ Makes use of Mission scripting tools (Mist):