Compare commits

..

3 Commits

Author SHA1 Message Date
zhexu14
6acd35d58e Merge branch 'develop' into dependabot/npm_and_yarn/client/multi-7d5e57b41f 2025-03-16 15:07:37 +11:00
zhexu14
f611620276 Merge branch 'develop' into dependabot/npm_and_yarn/client/multi-7d5e57b41f 2024-11-11 20:47:09 +11:00
dependabot[bot]
ae51166701 Bump cookie, msw and express in /client
Bumps [cookie](https://github.com/jshttp/cookie) to 0.7.1 and updates ancestor dependencies [cookie](https://github.com/jshttp/cookie), [msw](https://github.com/mswjs/msw) and [express](https://github.com/expressjs/express). These dependencies need to be updated together.


Updates `cookie` from 0.4.2 to 0.7.1
- [Release notes](https://github.com/jshttp/cookie/releases)
- [Commits](https://github.com/jshttp/cookie/compare/v0.4.2...v0.7.1)

Updates `msw` from 1.2.2 to 2.6.0
- [Release notes](https://github.com/mswjs/msw/releases)
- [Changelog](https://github.com/mswjs/msw/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mswjs/msw/compare/v1.2.2...v2.6.0)

Updates `express` from 4.21.0 to 4.21.1
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.1/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.21.0...4.21.1)

---
updated-dependencies:
- dependency-name: cookie
  dependency-type: indirect
- dependency-name: msw
  dependency-type: direct:development
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 12:02:53 +00:00
74 changed files with 1392 additions and 2971 deletions

View File

@@ -4,7 +4,7 @@ runs:
using: composite
steps:
- name: Set up Node
uses: actions/setup-node@v4
uses: actions/setup-node@v2
with:
node-version: "16"
cache: npm

View File

@@ -4,7 +4,7 @@ runs:
using: composite
steps:
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v2
with:
python-version: "3.11.4"
cache: pip

View File

@@ -12,7 +12,7 @@ jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: true

View File

@@ -7,8 +7,8 @@ jobs:
name: Black
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: psf/black@stable
with:
version: ~=24.3.0
@@ -19,7 +19,7 @@ jobs:
name: Type checking
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: true

View File

@@ -14,7 +14,7 @@ jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: true

View File

@@ -5,7 +5,7 @@ jobs:
name: Python tests
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: true
@@ -24,7 +24,7 @@ jobs:
name: Typescript tests
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: Set up JS environment
uses: ./.github/actions/setup-liberation-js

View File

@@ -4,18 +4,11 @@ Saves from 13.x are not compatible with 14.0.0.
## Features/Improvements
* **[Engine]** Support for DCS 2.9.21.
* **[Engine]** Support for MiG-29 Fulcrum (full fidelity version).
* **[Engine]** Support for F-14A-135-GR Early.
* **[Mods]** A4EC mod version updated to 2.3.
* **[UI]** Allow saving after fast forwarding manually with sim speed controls (--show-sim-speed-controls option).
* **[UI]** Add new option to fast forward until player is at the IP.
* **[Engine]** Support for DCS 2.9.13.6818.
## Fixes
* **[Campaign]** Units are restored to full health when repaired.
* **[UI]** Air Wing and Transfers buttons disabled when no game is loaded as pressing them without a game loaded resulted in a crash.
* **[UI]** A package is cancelled (deleted) when the last flight in the package is cancelled instead of showing "No mission".
# 13.0.0

1927
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react-redux": "^7.1.24",
"axios": "^1.12.1",
"axios": "^1.8.3",
"electron-window-state": "^5.0.3",
"esri-leaflet": "^3.0.8",
"leaflet": "^1.9.2",
@@ -66,12 +66,12 @@
"@types/leaflet": "^1.8.0",
"@types/redux-logger": "^3.0.9",
"@types/websocket": "^1.0.5",
"electron": "^35.7.5",
"electron": "^22.3.25",
"electron-is-dev": "^2.0.0",
"generate-license-file": "^2.0.0",
"jest-transform-stub": "^2.0.0",
"license-checker": "^25.0.1",
"msw": "^1.2.2",
"msw": "^2.6.0",
"react-scripts": "5.0.1",
"ts-node": "^10.9.1",
"wait-on": "^8.0.0"

View File

@@ -12,7 +12,6 @@ from .flightmembers import FlightMembers
from .flightroster import FlightRoster
from .flightstate import FlightState, Navigating, Uninitialized
from .flightstate.killed import Killed
from .flighttype import FlightType
from ..sidc import (
Entity,
SidcDescribable,
@@ -32,6 +31,7 @@ if TYPE_CHECKING:
from game.data.weapons import WeaponType
from .flightmember import FlightMember
from .flightplans.flightplan import FlightPlan
from .flighttype import FlightType
from .flightwaypoint import FlightWaypoint
from .package import Package
from .starttype import StartType
@@ -58,8 +58,7 @@ class Flight(SidcDescribable):
self.coalition = squadron.coalition
self.squadron = squadron
self.flight_type = flight_type
if flight_type != FlightType.IDLE:
self.squadron.claim_inventory(count)
self.squadron.claim_inventory(count)
if roster is None:
self.roster = FlightMembers(self, initial_size=count)
else:
@@ -110,6 +109,19 @@ class Flight(SidcDescribable):
waypoint.actions.clear()
waypoint.options.clear()
def __getstate__(self) -> dict[str, Any]:
state = self.__dict__.copy()
# Avoid persisting the flight state since that's not (currently) used outside
# mission generation. This is a bit of a hack for the moment and in the future
# we will need to persist the flight state, but for now keep it out of save
# compat (it also contains a generator that cannot be pickled).
del state["state"]
return state
def __setstate__(self, state: dict[str, Any]) -> None:
state["state"] = Uninitialized(self, state["squadron"].settings)
self.__dict__.update(state)
@property
def blue(self) -> bool:
return self.squadron.player

View File

@@ -69,15 +69,6 @@ class FlightMembers(IFlightRoster):
self.flight.squadron.return_pilot(current_pilot)
self.members[index].pilot = pilot
def remove_pilot(self, pilot: Pilot) -> None:
for i, member in enumerate(self.members):
if member.pilot is not None and member.pilot.name == pilot.name:
self.members.pop(i)
if (code := member.tgp_laser_code) is not None:
code.release()
return
raise ValueError(f"Pilot {pilot.name} not a member")
def clear(self) -> None:
self.flight.squadron.return_pilots(
[p for p in self.iter_pilots() if p is not None]

View File

@@ -12,7 +12,7 @@ from game.utils import Distance, Heading, Speed, feet, knots, meters, nautical_m
class AewcFlightPlan(PatrollingFlightPlan[PatrollingLayout]):
@property
def patrol_duration(self) -> timedelta:
return self.flight.coalition.doctrine.aewc.duration
return timedelta(hours=4)
@property
def patrol_speed(self) -> Speed:

View File

@@ -64,7 +64,6 @@ class FlightPlanBuilderTypes:
FlightType.TRANSPORT: AirliftFlightPlan.builder_type(),
FlightType.FERRY: FerryFlightPlan.builder_type(),
FlightType.AIR_ASSAULT: AirAssaultFlightPlan.builder_type(),
FlightType.IDLE: BarCapFlightPlan.builder_type(),
}
try:
return builder_dict[flight.flight_type]

View File

@@ -21,14 +21,8 @@ class FlightState(ABC):
self.settings = settings
self.avoid_further_combat = False
def initialize(self, now: datetime) -> None:
from game.ato.flightstate import Uninitialized, WaitingForStart
# Flight objects are created with Uninitialized state. However when the simulation runs
# the flight state changes and may be serialized. We only want to initialize the state
# for newly created flights and not ones deserialized from a save file.
if type(self.flight.state) != Uninitialized:
return
def reinitialize(self, now: datetime) -> None:
from game.ato.flightstate import WaitingForStart
if self.flight.flight_plan.startup_time() <= now:
self._set_active_flight_state(now)

View File

@@ -3,7 +3,6 @@ from __future__ import annotations
from abc import ABC, abstractmethod
from collections import deque
from datetime import datetime, timedelta
import logging
from typing import TYPE_CHECKING
from dcs import Point
@@ -14,7 +13,6 @@ from game.ato.flightstate.flightstate import FlightState
from game.ato.flightwaypoint import FlightWaypoint
from game.ato.flightwaypointtype import FlightWaypointType
from game.ato.starttype import StartType
from game.settings.settings import FastForwardStopCondition
from game.utils import Distance, LBS_TO_KG, Speed, pairwise
if TYPE_CHECKING:
@@ -166,17 +164,3 @@ class InFlight(FlightState, ABC):
@property
def spawn_type(self) -> StartType:
return StartType.IN_FLIGHT
def should_halt_sim(self) -> bool:
if (
self.flight.client_count > 0
and self.settings.fast_forward_stop_condition
== FastForwardStopCondition.PLAYER_AT_IP
and self.is_at_ip
):
logging.info(
f"Interrupting simulation because {self.flight} has players and has "
"reached IP"
)
return True
return False

View File

@@ -20,7 +20,7 @@ class Uninitialized(FlightState):
def on_game_tick(
self, events: GameUpdateEvents, time: datetime, duration: timedelta
) -> None:
self.initialize(time)
self.reinitialize(time)
self.flight.state.on_game_tick(events, time, duration)
@property

View File

@@ -57,7 +57,6 @@ class FlightType(Enum):
REFUELING = "Refueling"
FERRY = "Ferry"
AIR_ASSAULT = "Air Assault"
IDLE = "Idle"
def __str__(self) -> str:
return self.value

View File

@@ -47,17 +47,6 @@ class MissionScheduler:
margin=5 * 60,
)
for package in self.coalition.ato.packages:
if package.time_over_target > datetime.min:
if package.primary_task in dca_types:
if (
package.mission_departure_time is not None
and package.mission_departure_time
> previous_cap_end_time[package.target]
):
previous_cap_end_time[package.target] = (
package.mission_departure_time
)
continue # If package already has TOT, leave it.
tot = TotEstimator(package).earliest_tot(now)
if package.primary_task in dca_types:
previous_end_time = previous_cap_end_time[package.target]

View File

@@ -24,7 +24,6 @@ from game.theater.theatergroundobject import (
VehicleGroupGroundObject,
)
from game.threatzones import ThreatZones
from game.ato.flighttype import FlightType
if TYPE_CHECKING:
from game import Game
@@ -78,8 +77,7 @@ class TheaterState(WorldState["TheaterState"]):
self.threatening_air_defenses.remove(target)
if target in self.detecting_air_defenses:
self.detecting_air_defenses.remove(target)
if target in self.enemy_air_defenses:
self.enemy_air_defenses.remove(target)
self.enemy_air_defenses.remove(target)
self._rebuild_threat_zones()
def eliminate_ship(self, target: NavalGroundObject) -> None:
@@ -87,8 +85,7 @@ class TheaterState(WorldState["TheaterState"]):
self.threatening_air_defenses.remove(target)
if target in self.detecting_air_defenses:
self.detecting_air_defenses.remove(target)
if target in self.enemy_ships:
self.enemy_ships.remove(target)
self.enemy_ships.remove(target)
self._rebuild_threat_zones()
def has_battle_position(self, target: VehicleGroupGroundObject) -> bool:
@@ -158,16 +155,21 @@ class TheaterState(WorldState["TheaterState"]):
tracer,
)
# Plan enough rounds of CAP that the target has coverage over the expected
# mission duration.
mission_duration = game.settings.desired_player_mission_duration.total_seconds()
barcap_duration = coalition.doctrine.cap.duration.total_seconds()
barcap_rounds = math.ceil(mission_duration / barcap_duration)
refueling_targets: list[MissionTarget] = []
theater_refuling_point = finder.preferred_theater_refueling_control_point()
if theater_refuling_point is not None:
refueling_targets.append(theater_refuling_point)
theater_state = TheaterState(
return TheaterState(
context=context,
barcaps_needed={
cp: cls._barcap_rounds(game, player, now, cp)
for cp in finder.vulnerable_control_points()
cp: barcap_rounds for cp in finder.vulnerable_control_points()
},
active_front_lines=list(finder.front_lines()),
front_line_stances={f: None for f in finder.front_lines()},
@@ -189,62 +191,3 @@ class TheaterState(WorldState["TheaterState"]):
enemy_barcaps=list(game.theater.control_points_for(not player)),
threat_zones=game.threat_zone_for(not player),
)
# Look through packages already planned in the ATO and eliminate from the
# list of targets.
for package in coalition.ato.packages:
if isinstance(package.target, NavalGroundObject):
theater_state.eliminate_ship(package.target)
if package.primary_task == FlightType.BAI and isinstance(
package.target, VehicleGroupGroundObject
):
theater_state.eliminate_battle_position(package.target)
if isinstance(package.target, IadsGroundObject):
theater_state.eliminate_air_defense(package.target)
if (
package.primary_task == FlightType.STRIKE
and isinstance(package.target, TheaterGroundObject)
and package.target in theater_state.strike_targets
):
theater_state.strike_targets.remove(package.target)
if package.primary_task == FlightType.AEWC:
# If a planned AEWC mission covers the target beyond the planned mission duration, it can safely be removed
if (
package.time_over_target + coalition.doctrine.aewc.duration
> now + game.settings.desired_player_mission_duration
) and package.target in theater_state.aewc_targets:
theater_state.aewc_targets.remove(package.target)
if (
package.primary_task
in (
FlightType.OCA_AIRCRAFT,
FlightType.OCA_RUNWAY,
)
and isinstance(package.target, ControlPoint)
and package.target in theater_state.oca_targets
):
theater_state.oca_targets.remove(package.target)
return theater_state
@classmethod
def _barcap_rounds(
cls, game: Game, player: bool, now: datetime, control_point: ControlPoint
) -> int:
"""Calculate number of additional rounds of CAP required to cover mission duration."""
coalition = game.coalition_for(player)
# Look through ATO for any existing planned CAP missions and calculate last planned CAP end
planned_cap_coverage_end_time = now
for package in coalition.ato.packages:
if package.target == control_point:
cap_end_time = (
package.time_over_target + coalition.doctrine.cap.duration
)
if cap_end_time > planned_cap_coverage_end_time:
planned_cap_coverage_end_time = cap_end_time
# When mission is expected to finish
mission_end_time = now + game.settings.desired_player_mission_duration
return math.ceil(
(mission_end_time - planned_cap_coverage_end_time).total_seconds()
/ coalition.doctrine.cap.duration.total_seconds()
)

View File

@@ -52,16 +52,6 @@ class Helicopter:
)
@dataclass
class Aewc:
#: The duration that AEWC flights will remain on-station
duration: timedelta
@staticmethod
def from_dict(data: dict[str, Any]) -> Aewc:
return Aewc(duration=timedelta(minutes=data["duration_minutes"]))
@dataclass
class Cas:
#: The duration that CAP flights will remain on-station.
@@ -179,9 +169,6 @@ class Doctrine:
#: Helicopter specific doctrines.
helicopter: Helicopter
#: Doctrine for AEWC missions.
aewc: Aewc
#: Doctrine for CAS missions.
cas: Cas
@@ -251,7 +238,6 @@ class Doctrine:
data["ground_unit_procurement_ratios"]
),
helicopter=Helicopter.from_dict(data["helicopter"]),
aewc=Aewc.from_dict(data["aewc"]),
cas=Cas.from_dict(data["cas"]),
cap=Cap.from_dict(data["cap"]),
sweep=Sweep.from_dict(data["sweep"]),

View File

@@ -38,7 +38,6 @@ from game.radio.channels import (
HindChannelNamer,
HipChannelNamer,
KiowaChannelNamer,
FulcrumChannelNamer,
)
from game.utils import (
Distance,
@@ -119,7 +118,6 @@ class RadioConfig:
"hind": HindChannelNamer,
"hip": HipChannelNamer,
"kiowa": KiowaChannelNamer,
"fulcrum": FulcrumChannelNamer,
}[config.get("namer", "default")]

View File

@@ -196,9 +196,6 @@ class StateData:
#: True if the mission ended. If False, the mission exited abnormally.
mission_ended: bool
#: Simulation time since mission start in seconds
simulation_time_seconds: float
#: Names of aircraft units that were killed during the mission.
killed_aircraft: List[str]
@@ -251,7 +248,6 @@ class StateData:
return cls(
mission_ended=data["mission_ended"],
simulation_time_seconds=data["simulation_time_seconds"],
killed_aircraft=killed_aircraft,
killed_ground_units=killed_ground_units,
destroyed_statics=data["destroyed_objects_positions"],

View File

@@ -125,11 +125,7 @@ class Game:
self.time_of_day_offset_for_start_time = list(TimeOfDay).index(
self.theater.daytime_map.best_guess_time_of_day_at(start_time)
)
# self.conditions.start_time is the time at the start of a turn and does not change within a turn.
# self.simulation_time tracks time progression within a turn and is synchronized with the
# MissionSimulation object.
self.conditions = self.generate_conditions(forced_time=start_time)
self.simulation_time = self.conditions.start_time
self.sanitize_sides(player_faction, enemy_faction)
self.blue = Coalition(self, player_faction, player_budget, player=True)
@@ -295,7 +291,6 @@ class Game:
# turn 1.
if self.turn > 1:
self.conditions = self.generate_conditions()
self.simulation_time = self.conditions.start_time
def begin_turn_0(self) -> None:
"""Initialization for the first turn of the game."""

View File

@@ -148,7 +148,7 @@ class AircraftGenerator:
faction.country,
squadron,
1,
FlightType.IDLE,
FlightType.BARCAP,
StartType.COLD,
divert=None,
)

View File

@@ -285,7 +285,7 @@ class FlightGroupConfigurator:
if (
unit_callsign.name is None
): # pydcs needs unit.callsign to be set for eastern callsigns
unit.callsign = str(unit_callsign)
unit.callsign = str(unit_callsign) # type: ignore
else: # Use western callsign
unit.callsign_dict = unit_callsign.pydcs_dict(
country=self.flight.country

View File

@@ -243,7 +243,11 @@ class FlightGroupSpawner:
for i in range(self.flight.count):
group.units[i].position = hpad.position
group.units[i].heading = hpad.heading
group.units[i].parking_id = str(i + 1)
# pydcs has just `parking_id = None`, so mypy thinks str is invalid. Ought
# to fix pydcs, but that's not the kind of change we want to pull into the
# 6.1 branch, and frankly we should probably just improve pydcs's handling
# of FARPs instead.
group.units[i].parking_id = str(i + 1) # type: ignore
return group
def dcs_start_type(self) -> DcsStartType:

View File

@@ -4,7 +4,7 @@ from datetime import datetime
from typing import Any, Iterable, Union
from dcs import Mission
from dcs.planes import AJS37, F_14A_135_GR, F_14A_135_GR_Early, F_14B, JF_17
from dcs.planes import AJS37, F_14B, JF_17
from dcs.point import MovingPoint, PointAction
from dcs.unitgroup import FlyingGroup
@@ -127,9 +127,5 @@ class PydcsWaypointBuilder:
for i, t in enumerate(targets):
if self.group.units[0].unit_type == JF_17 and i < 4:
self.group.add_nav_target_point(t.position, "PP" + str(i + 1))
if (
self.group.units[0].unit_type
in [F_14A_135_GR, F_14A_135_GR_Early, F_14B]
and i == 0
):
if self.group.units[0].unit_type == F_14B and i == 0:
self.group.add_nav_target_point(t.position, "ST")

View File

@@ -450,15 +450,3 @@ class KiowaChannelNamer(ChannelNamer):
@classmethod
def name(cls) -> str:
return "kiowa"
class FulcrumChannelNamer(ChannelNamer):
"""Channel namer for MiG-29A Fulcrum"""
@staticmethod
def channel_name(radio_id: int, channel_id: int) -> str:
return f"R862 Ch {channel_id}"
@classmethod
def name(cls) -> str:
return "fulcrum"

View File

@@ -234,6 +234,7 @@ RADIOS: List[Radio] = [
# Ka-50
# Note: Also capable of 100MHz-150MHz, but we can't model gaps.
Radio("R-800L1", (RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),)),
Radio("R-828", (RadioRange(MHz(20), MHz(60), kHz(25), Modulation.FM),)),
# UH-1H
Radio("AN/ARC-51BX", (RadioRange(MHz(225), MHz(400), kHz(50), Modulation.AM),)),
Radio("AN/ARC-131", (RadioRange(MHz(30), MHz(76), kHz(50), Modulation.FM),)),
@@ -297,16 +298,6 @@ RADIOS: List[Radio] = [
# Mi-8/Mi-24
Radio("R863", (RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),)),
Radio("R828", (RadioRange(MHz(20), MHz(60), kHz(25), Modulation.FM),)),
# MiG-29A
Radio(
"R862",
(
RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),
RadioRange(MHz(100), MHz(150), kHz(25), Modulation.AM),
RadioRange(MHz(220), MHz(400), kHz(25), Modulation.FM),
RadioRange(MHz(100), MHz(150), kHz(25), Modulation.FM),
),
),
]

View File

@@ -35,7 +35,6 @@ class FastForwardStopCondition(Enum):
PLAYER_TAKEOFF = "Player takeoff time"
PLAYER_TAXI = "Player taxi time"
PLAYER_STARTUP = "Player startup time"
PLAYER_AT_IP = "Player at IP"
MANUAL = "Manual fast forward control"
@@ -356,16 +355,6 @@ class Settings:
"your game after aborting take off."
),
)
turnless_mode: bool = boolean_option(
"Enable turnless mode (WIP)",
page=MISSION_GENERATOR_PAGE,
section=GAMEPLAY_SECTION,
default=False,
detail=(
"If enabled, turns do not end after mission completion. A new mission "
"can be started picking up from where the previous mission ended."
),
)
fast_forward_stop_condition: FastForwardStopCondition = choices_option(
"Fast forward until",
page=MISSION_GENERATOR_PAGE,
@@ -376,7 +365,6 @@ class Settings:
"Player startup time": FastForwardStopCondition.PLAYER_STARTUP,
"Player taxi time": FastForwardStopCondition.PLAYER_TAXI,
"Player takeoff time": FastForwardStopCondition.PLAYER_TAKEOFF,
"Player at IP": FastForwardStopCondition.PLAYER_AT_IP,
"First contact": FastForwardStopCondition.FIRST_CONTACT,
"Manual": FastForwardStopCondition.MANUAL,
},

View File

@@ -7,7 +7,9 @@ from datetime import datetime, timedelta
from typing_extensions import TYPE_CHECKING
from game.ato.flightstate import Uninitialized, Completed, InCombat
from game.ato.flightstate import (
Uninitialized,
)
from game.settings.settings import FastForwardStopCondition, CombatResolutionMethod
from .combat import CombatInitiator, FrozenCombat
from .gameupdateevents import GameUpdateEvents
@@ -25,20 +27,13 @@ class AircraftSimulation:
self.results = SimulationResults()
def begin_simulation(self) -> None:
self.reset()
self.set_initial_flight_states()
def on_game_tick(
self,
events: GameUpdateEvents,
time: datetime,
duration: timedelta,
combat_resolution_method: CombatResolutionMethod,
force_continue: bool,
self, events: GameUpdateEvents, time: datetime, duration: timedelta
) -> None:
if (
not self._auto_resolve_combat(combat_resolution_method, force_continue)
and self.combats
):
if not self._auto_resolve_combat() and self.combats:
logging.error(
"Cannot resume simulation because aircraft are in combat and "
"auto-resolve is disabled"
@@ -53,7 +48,7 @@ class AircraftSimulation:
duration,
self.results,
events,
combat_resolution_method,
self.game.settings.combat_resolution_method,
):
events.end_combat(combat)
else:
@@ -69,38 +64,22 @@ class AircraftSimulation:
# After updating all combat states, check for halts.
for flight in self.iter_flights():
if flight.should_halt_sim() and not force_continue:
if flight.should_halt_sim():
events.complete_simulation()
return
# Find completed flights, removing them from the ATO and returning aircraft
# and pilots back to the squadron.
for flight in self.iter_flights():
if type(flight.state) == Completed:
flight.package.remove_flight(flight)
if len(flight.package.flights) == 0:
flight.squadron.coalition.ato.remove_package(flight.package)
if (
not self._auto_resolve_combat(combat_resolution_method, force_continue)
and self.combats
):
if not self._auto_resolve_combat() and self.combats:
events.complete_simulation()
def set_initial_flight_states(self) -> None:
# Initialize flights in Uninitialized state
now = self.game.simulation_time
now = self.game.conditions.start_time
for flight in self.iter_flights():
flight.state.initialize(now)
flight.state.reinitialize(now)
# Recover combat instances from flight states. Flight state information is serialized
# when saving a game but the aircraft simulation state is not. Combat instances are
# de-duplicated as multiple flights can be involved in a single combat instance.
combats = set()
def reset(self) -> None:
for flight in self.iter_flights():
if type(flight.state) == InCombat:
combats.add(flight.state.combat)
self.combats = list(combats)
flight.set_state(Uninitialized(flight, self.game.settings))
self.combats = []
def iter_flights(self) -> Iterator[Flight]:
packages = itertools.chain(
@@ -109,9 +88,10 @@ class AircraftSimulation:
for package in packages:
yield from package.flights
def _auto_resolve_combat(
self, combat_resolution_method: CombatResolutionMethod, force_continue: bool
) -> bool:
if force_continue:
return True
return combat_resolution_method != CombatResolutionMethod.PAUSE
def _auto_resolve_combat(self) -> bool:
return (
self.game.settings.fast_forward_stop_condition
!= FastForwardStopCondition.DISABLED
and self.game.settings.combat_resolution_method
!= CombatResolutionMethod.PAUSE
)

View File

@@ -100,11 +100,7 @@ class GameLoop:
if not self.started:
raise RuntimeError("Attempted to tick game loop before initialization")
try:
self.sim.tick(
self.events,
self.game.settings.combat_resolution_method,
force_continue=False,
)
self.sim.tick(self.events)
self.completed = self.events.simulation_complete
if not suppress_events:
self.send_update(rate_limit=True)

View File

@@ -8,7 +8,6 @@ from game.ground_forces.combat_stance import CombatStance
from game.theater import ControlPoint
from .gameupdateevents import GameUpdateEvents
from ..ato.airtaaskingorder import AirTaskingOrder
from ..ato.flightstate.atdeparture import AtDeparture
if TYPE_CHECKING:
from ..game import Game
@@ -58,25 +57,6 @@ class MissionResultsProcessor:
logging.info(f"{aircraft} destroyed from {squadron}")
squadron.owned_aircraft -= 1
# Remove air losses from the flight. Remove the flight if all aircraft are lost.
# Remove the package if the flight is the last flight in the package.
# This logic is redundant if we are going to a new turn, since the whole ATO is
# regenerated. However if we want to keep the ATO to continue a turn, this update
# is necessary to make sure lost aircraft are removed from the ATO.
if loss.pilot is not None:
loss.flight.roster.remove_pilot(loss.pilot)
if loss.flight.count == 0: # Last aircraft in the flight, remove the flight
# If no flights in package, generally indicates that the loss is an aircraft
# that is not assigned to a mission and is parked on the ground. There is no need
# to remove the aircraft from the ATO as it was never in the ATO in the first place.
if len(loss.flight.package.flights) == 0:
continue
loss.flight.package.remove_flight(loss.flight)
if len(loss.flight.package.flights) == 0:
loss.flight.squadron.coalition.ato.remove_package(
loss.flight.package
)
@staticmethod
def _commit_pilot_experience(ato: AirTaskingOrder) -> None:
for package in ato.packages:
@@ -168,21 +148,10 @@ class MissionResultsProcessor:
iads_network.update_network(events)
return
def commit_damaged_runways(self, debriefing: Debriefing) -> None:
@staticmethod
def commit_damaged_runways(debriefing: Debriefing) -> None:
for damaged_runway in debriefing.damaged_runways:
damaged_runway.damage_runway()
# Remove any flight in ATO scheduled to take off from the damaged runway.
for coalition in self.game.coalitions:
for package in coalition.ato.packages:
for flight in package.flights:
if flight.departure.name == damaged_runway.name and isinstance(
flight.state, AtDeparture
):
flight.package.remove_flight(flight)
if len(flight.package.flights) == 0:
flight.squadron.coalition.ato.remove_package(
flight.package
)
def commit_captures(self, debriefing: Debriefing, events: GameUpdateEvents) -> None:
for captured in debriefing.base_captures:

View File

@@ -1,5 +1,5 @@
from __future__ import annotations
import copy
import json
from datetime import timedelta
from pathlib import Path
@@ -7,7 +7,6 @@ from typing import Optional, TYPE_CHECKING
from game.debriefing import Debriefing
from game.missiongenerator import MissionGenerator
from game.settings.settings import FastForwardStopCondition, CombatResolutionMethod
from game.unitmap import UnitMap
from .aircraftsimulation import AircraftSimulation
from .missionresultsprocessor import MissionResultsProcessor
@@ -32,31 +31,17 @@ class MissionSimulation:
self.unit_map: Optional[UnitMap] = None
self.aircraft_simulation = AircraftSimulation(self.game)
self.completed = False
self.time = self.game.simulation_time
self.time = self.game.conditions.start_time
def begin_simulation(self) -> None:
self.time = self.game.simulation_time
self.time = self.game.conditions.start_time
self.aircraft_simulation.begin_simulation()
def tick(
self,
events: GameUpdateEvents,
combat_resolution_method: CombatResolutionMethod,
force_continue: bool,
) -> GameUpdateEvents:
def tick(self, events: GameUpdateEvents) -> GameUpdateEvents:
self.time += TICK
self.game.simulation_time = self.time
if self.completed:
raise RuntimeError("Simulation already completed")
if (
self.game.settings.fast_forward_stop_condition
== FastForwardStopCondition.DISABLED
):
events.complete_simulation()
return events
self.aircraft_simulation.on_game_tick(
events, self.time, TICK, combat_resolution_method, force_continue
)
self.aircraft_simulation.on_game_tick(events, self.time, TICK)
self.completed = events.simulation_complete
return events
@@ -90,24 +75,6 @@ class MissionSimulation:
self.game.save_last_turn_state()
MissionResultsProcessor(self.game).commit(debriefing, events)
if self.game.settings.turnless_mode:
# Set completed to False to clear completion of any previous simulation tick.
self.completed = False
# If running in turnless mode, run sim to calculate planned positions of flights
# for the duration of time the DCS mission ran.
start_time = copy.deepcopy(self.time)
while self.time < start_time + timedelta(
seconds=int(debriefing.state_data.simulation_time_seconds)
):
# Always skip combat as we are processing results from DCS. Any combat has already
# been resolved in-game
self.tick(events, CombatResolutionMethod.SKIP, force_continue=True)
self.game.blue.plan_missions(self.game.simulation_time)
self.game.red.plan_missions(self.game.simulation_time)
self.game.game_stats.update(self.game)
# Generate begin_new_turn event which triggers a refresh of the React map screen to
# show newly planned missions.
events.begin_new_turn()
def finish(self) -> None:
self.unit_map = None

File diff suppressed because it is too large Load Diff

View File

@@ -9,11 +9,17 @@ from pydcs_extensions.weapon_injector import inject_weapons
class Su57Weapons:
Kh_59MK2 = {"clsid": "{KH_59MK2}", "name": "Kh-59MK2", "weight": None}
RVV_AE = {"clsid": "{RVV-AE}", "name": "RVV-AE", "weight": 250}
RVV_BD = {"clsid": "{RVV-BD}", "name": "RVV-BD", "weight": 600}
RVV_L = {"clsid": "{RVV-L}", "name": "RVV-L", "weight": 748}
RVV_M = {"clsid": "{RVV-M}", "name": "RVV-M", "weight": 190}
R_37M_Active_Rdr = {"clsid": "{RVV-BD}", "name": "R-37M Active Rdr", "weight": 600}
Su_57_Fuel_Tank = {
"clsid": "{SU_57Tank}",
"name": "Su-57 Fuel Tank",
"weight": 1561.421,
}
R_77PD_Active_rdr = {
"clsid": "{RVV-AE}",
"name": "R-77PD Active rdr",
@@ -50,10 +56,8 @@ class Su_57(PlaneType):
class Pylon1:
R_73__AA_11_Archer____Infra_Red = (1, Weapons.R_73__AA_11_Archer____Infra_Red)
KS_172_Passive_Rdr = (1, Weapons.KS_172_Passive_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (1, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (1, Weapons.K_77M_Active_Rdr)
R_77PD_Active_rdr = (1, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (1, Su57Weapons.K_77M_Active_Rdr)
L_081_Fantasmagoria_ELINT_pod = (1, Weapons.L_081_Fantasmagoria_ELINT_pod)
Smoke_Generator___red = (1, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (1, Weapons.Smoke_Generator___green)
@@ -89,37 +93,37 @@ class Su_57(PlaneType):
2,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
)
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = (
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
2,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
)
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = (
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
2,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
)
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
2,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
)
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = (
MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
2,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD,
Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
)
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
2,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
)
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = (
B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
2,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
)
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = (
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
2,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
)
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = (
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
2,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD,
Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
)
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
2,
@@ -129,12 +133,12 @@ class Su_57(PlaneType):
2,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
)
OFAB_250_270___250_kg_GP_Bomb_LD = (2, Weapons.OFAB_250_270___250_kg_GP_Bomb_LD)
FAB_250___250kg_GP_Bomb_LD = (2, Weapons.FAB_250___250kg_GP_Bomb_LD)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
2,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
)
FAB_500M_62___500_kg_GP_Bomb_LD = (2, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD)
FAB_500_M_62___500kg_GP_Bomb_LD = (2, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
2,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
@@ -152,20 +156,21 @@ class Su_57(PlaneType):
2,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
)
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = (
MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
2,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD,
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
)
R_37M_Active_Rdr = (2, Weapons.R_37M_Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (2, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (2, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (2, Weapons.KS_172_Passive_Rdr)
R_37M_Active_Rdr = (2, Su57Weapons.R_37M_Active_Rdr)
R_77PD_Active_rdr = (2, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (2, Su57Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (2, Su57Weapons.KS_172_Passive_Rdr)
Fuel_tank_800L_Wing = (2, Weapons.Fuel_tank_800L_Wing)
RN_28___260_kg__nuclear_bomb__free_fall = (
2,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
)
Su_57_Fuel_Tank = (2, Su57Weapons.Su_57_Fuel_Tank)
Kh_59MK2 = (2, Su57Weapons.Kh_59MK2)
Smoke_Generator___red = (2, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (2, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (2, Weapons.Smoke_Generator___blue)
@@ -209,37 +214,37 @@ class Su_57(PlaneType):
4,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
)
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = (
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
4,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
)
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = (
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
4,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
)
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
4,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
)
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = (
MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
4,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD,
Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
)
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
4,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
)
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = (
B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
4,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
)
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = (
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
4,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
)
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = (
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
4,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD,
Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
)
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
4,
@@ -249,12 +254,12 @@ class Su_57(PlaneType):
4,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
)
OFAB_250_270___250_kg_GP_Bomb_LD = (4, Weapons.OFAB_250_270___250_kg_GP_Bomb_LD)
FAB_250___250kg_GP_Bomb_LD = (4, Weapons.FAB_250___250kg_GP_Bomb_LD)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
4,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
)
FAB_500M_62___500_kg_GP_Bomb_LD = (4, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD)
FAB_500_M_62___500kg_GP_Bomb_LD = (4, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
4,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
@@ -272,61 +277,158 @@ class Su_57(PlaneType):
4,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
)
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = (
MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
4,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD,
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
)
R_37M_Active_Rdr = (4, Weapons.R_37M_Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (4, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (4, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (4, Weapons.KS_172_Passive_Rdr)
R_37M_Active_Rdr = (4, Su57Weapons.R_37M_Active_Rdr)
R_77PD_Active_rdr = (4, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (4, Su57Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (4, Su57Weapons.KS_172_Passive_Rdr)
RN_28___260_kg__nuclear_bomb__free_fall = (
4,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
)
Su_57_Fuel_Tank = (4, Su57Weapons.Su_57_Fuel_Tank)
Kh_59MK2 = (4, Su57Weapons.Kh_59MK2)
class Pylon5:
R_77__AA_12_Adder____Active_Rdr = (5, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (5, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (5, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (5, Weapons.KS_172_Passive_Rdr)
R_77PD_Active_rdr = (5, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (5, Su57Weapons.K_77M_Active_Rdr)
Kh_59MK2 = (5, Su57Weapons.Kh_59MK2)
class Pylon6:
R_77__AA_12_Adder____Active_Rdr = (6, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (6, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (6, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (6, Weapons.KS_172_Passive_Rdr)
R_77PD_Active_rdr = (6, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (6, Su57Weapons.K_77M_Active_Rdr)
Kh_59MK2 = (6, Su57Weapons.Kh_59MK2)
class Pylon7:
R_77__AA_12_Adder____Active_Rdr = (7, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (7, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (7, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (7, Weapons.KS_172_Passive_Rdr)
R_77PD_Active_rdr = (7, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (7, Su57Weapons.K_77M_Active_Rdr)
Kh_59MK2 = (7, Su57Weapons.Kh_59MK2)
class Pylon8:
R_77__AA_12_Adder____Active_Rdr = (8, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (8, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (8, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (8, Weapons.KS_172_Passive_Rdr)
R_77PD_Active_rdr = (8, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (8, Su57Weapons.K_77M_Active_Rdr)
Kh_59MK2 = (8, Su57Weapons.Kh_59MK2)
class Pylon9:
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
9,
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
)
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
9,
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
)
R_27T__AA_10_Alamo_B____Infra_Red = (
9,
Weapons.R_27T__AA_10_Alamo_B____Infra_Red,
)
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
9,
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
)
R_77__AA_12_Adder____Active_Rdr = (9, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (9, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (9, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (9, Weapons.KS_172_Passive_Rdr)
R_73__AA_11_Archer____Infra_Red = (9, Weapons.R_73__AA_11_Archer____Infra_Red)
Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr = (
9,
Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr,
)
Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr = (
9,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
)
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
9,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
)
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
9,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
)
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
9,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
)
MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
9,
Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
)
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
9,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
)
B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
9,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
)
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
9,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
)
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
9,
Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
)
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
9,
Weapons.KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag,
)
KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP = (
9,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
)
FAB_250___250kg_GP_Bomb_LD = (9, Weapons.FAB_250___250kg_GP_Bomb_LD)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
9,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
)
FAB_500_M_62___500kg_GP_Bomb_LD = (9, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
9,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
)
KAB_500LG___500kg_Laser_Guided_Bomb = (
9,
Weapons.KAB_500LG___500kg_Laser_Guided_Bomb,
)
KAB_500Kr___500kg_TV_Guided_Bomb = (9, Weapons.KAB_500Kr___500kg_TV_Guided_Bomb)
FAB_1500_M_54___1500kg_GP_Bomb_LD = (
9,
Weapons.FAB_1500_M_54___1500kg_GP_Bomb_LD,
)
KAB_1500L___1500kg_Laser_Guided_Bomb = (
9,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
)
MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
9,
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
)
R_37M_Active_Rdr = (9, Su57Weapons.R_37M_Active_Rdr)
R_77PD_Active_rdr = (9, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (9, Su57Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (9, Su57Weapons.KS_172_Passive_Rdr)
RN_28___260_kg__nuclear_bomb__free_fall = (
9,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
)
Su_57_Fuel_Tank = (9, Su57Weapons.Su_57_Fuel_Tank)
Kh_59MK2 = (9, Su57Weapons.Kh_59MK2)
class Pylon10:
R_77__AA_12_Adder____Active_Rdr = (10, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (10, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (10, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (10, Weapons.KS_172_Passive_Rdr)
R_73__AA_11_Archer____Infra_Red = (10, Weapons.R_73__AA_11_Archer____Infra_Red)
Smoke_Generator___red = (10, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (10, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (10, Weapons.Smoke_Generator___blue)
Smoke_Generator___white = (10, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (10, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (10, Weapons.Smoke_Generator___orange)
class Pylon11:
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
@@ -355,37 +457,37 @@ class Su_57(PlaneType):
11,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
)
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = (
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
11,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
)
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = (
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
11,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
)
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
11,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
)
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = (
MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
11,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD,
Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
)
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
11,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
)
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = (
B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
11,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
)
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = (
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
11,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
)
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = (
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
11,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD,
Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
)
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
11,
@@ -395,15 +497,12 @@ class Su_57(PlaneType):
11,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
)
OFAB_250_270___250_kg_GP_Bomb_LD = (
11,
Weapons.OFAB_250_270___250_kg_GP_Bomb_LD,
)
FAB_250___250kg_GP_Bomb_LD = (11, Weapons.FAB_250___250kg_GP_Bomb_LD)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
11,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
)
FAB_500M_62___500_kg_GP_Bomb_LD = (11, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD)
FAB_500_M_62___500kg_GP_Bomb_LD = (11, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
11,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
@@ -424,22 +523,33 @@ class Su_57(PlaneType):
11,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
)
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = (
MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
11,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD,
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
)
R_37M_Active_Rdr = (11, Weapons.R_37M_Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (11, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (11, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (11, Weapons.KS_172_Passive_Rdr)
# ERRR {R-33}
R_37M_Active_Rdr = (11, Su57Weapons.R_37M_Active_Rdr)
R_77PD_Active_rdr = (11, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (11, Su57Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (11, Su57Weapons.KS_172_Passive_Rdr)
Fuel_tank_800L_Wing = (11, Weapons.Fuel_tank_800L_Wing)
Su_57_Fuel_Tank = (11, Su57Weapons.Su_57_Fuel_Tank)
RN_28___260_kg__nuclear_bomb__free_fall = (
11,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
)
Smoke_Generator___red = (11, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (11, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (11, Weapons.Smoke_Generator___blue)
Smoke_Generator___white = (11, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (11, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (11, Weapons.Smoke_Generator___orange)
Kh_59MK2 = (11, Su57Weapons.Kh_59MK2)
class Pylon12:
R_73__AA_11_Archer____Infra_Red = (12, Weapons.R_73__AA_11_Archer____Infra_Red)
R_77PD_Active_rdr = (12, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (12, Su57Weapons.K_77M_Active_Rdr)
Smoke_Generator___red = (12, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (12, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (12, Weapons.Smoke_Generator___blue)
@@ -447,140 +557,7 @@ class Su_57(PlaneType):
Smoke_Generator___yellow = (12, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (12, Weapons.Smoke_Generator___orange)
class Pylon13:
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
13,
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
)
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
13,
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
)
R_27T__AA_10_Alamo_B____Infra_Red = (
13,
Weapons.R_27T__AA_10_Alamo_B____Infra_Red,
)
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
13,
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
)
R_77__AA_12_Adder____Active_Rdr = (13, Weapons.R_77__AA_12_Adder____Active_Rdr)
R_73__AA_11_Archer____Infra_Red = (13, Weapons.R_73__AA_11_Archer____Infra_Red)
Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr = (
13,
Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr,
)
Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr = (
13,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
)
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = (
13,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_,
)
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = (
13,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_,
)
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
13,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
)
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = (
13,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD,
)
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
13,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
)
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = (
13,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
)
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = (
13,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
)
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = (
13,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD,
)
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
13,
Weapons.KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag,
)
KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP = (
13,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
)
OFAB_250_270___250_kg_GP_Bomb_LD = (
13,
Weapons.OFAB_250_270___250_kg_GP_Bomb_LD,
)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
13,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
)
FAB_500M_62___500_kg_GP_Bomb_LD = (13, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
13,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
)
KAB_500LG___500kg_Laser_Guided_Bomb = (
13,
Weapons.KAB_500LG___500kg_Laser_Guided_Bomb,
)
KAB_500Kr___500kg_TV_Guided_Bomb = (
13,
Weapons.KAB_500Kr___500kg_TV_Guided_Bomb,
)
FAB_1500_M_54___1500kg_GP_Bomb_LD = (
13,
Weapons.FAB_1500_M_54___1500kg_GP_Bomb_LD,
)
KAB_1500L___1500kg_Laser_Guided_Bomb = (
13,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
)
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = (
13,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD,
)
# ERRR {R-33}
R_37M_Active_Rdr = (13, Weapons.R_37M_Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (13, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (13, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (13, Weapons.KS_172_Passive_Rdr)
Fuel_tank_800L_Wing = (13, Weapons.Fuel_tank_800L_Wing)
RN_28___260_kg__nuclear_bomb__free_fall = (
13,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
)
Smoke_Generator___red = (13, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (13, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (13, Weapons.Smoke_Generator___blue)
Smoke_Generator___white = (13, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (13, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (13, Weapons.Smoke_Generator___orange)
class Pylon14:
R_73__AA_11_Archer____Infra_Red = (14, Weapons.R_73__AA_11_Archer____Infra_Red)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (14, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (14, Weapons.K_77M_Active_Rdr)
Smoke_Generator___red = (14, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (14, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (14, Weapons.Smoke_Generator___blue)
Smoke_Generator___white = (14, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (14, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (14, Weapons.Smoke_Generator___orange)
class Pylon15:
Mercury_LLTV_Pod = (15, Weapons.Mercury_LLTV_Pod)
pylons: Set[int] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
pylons: Set[int] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
tasks = [
task.CAP,

View File

@@ -172,17 +172,6 @@ class PackageModel(QAbstractListModel):
else:
flight.abort()
EventStream.put_nowait(GameUpdateEvents().update_flight(flight))
# If there are no more flights in the package, delete the package.
if len(self.package.flights) == 0:
# Check if package is in ATO first as flight may still be "tentative" i.e.
# not added to the ATO yet.
if flight.package in flight.squadron.coalition.ato.packages:
flight.squadron.coalition.ato.remove_package(flight.package)
# Update ATO model so packages list is refreshed.
is_player = flight.squadron.coalition.player
self.game_model.ato_model_for(is_player).replace_from_game(
is_player
)
def delete_flight(self, flight: Flight) -> None:
"""Removes the given flight from the package."""
@@ -317,12 +306,9 @@ class AtoModel(QAbstractListModel):
index = self.ato.packages.index(package)
self.beginRemoveRows(QModelIndex(), index, index)
for flight in package.flights:
# Check if flight.callsign is None to handle case where callsign was not generated.
# This can happen when a module does not support the standard callsigns e.g. Kiowa.
if flight.callsign is not None:
self.game_model.game.blue.callsign_generator.release_callsign(
flight.callsign
)
self.game_model.game.blue.callsign_generator.release_callsign(
flight.callsign
)
self.ato.remove_package(package)
self.endRemoveRows()
# noinspection PyUnresolvedReferences

View File

@@ -65,17 +65,14 @@ class QTimeTurnWidget(QGroupBox):
else:
self.set_date_and_time(time)
def set_current_turn(
self, turn: int, conditions: Conditions, time: datetime
) -> None:
def set_current_turn(self, turn: int, conditions: Conditions) -> None:
"""Sets the turn information display.
:arg turn Current turn number.
:arg conditions Current weather conditions.
:arg time Current time.
:arg conditions Current time and weather conditions.
"""
self.daytime_icon.setPixmap(self.icons[conditions.time_of_day])
self.set_date_and_time(time)
self.set_date_and_time(conditions.start_time)
self.setTitle(f"Turn {turn}")
def set_date_and_time(self, time: datetime) -> None:
@@ -308,15 +305,12 @@ class QConditionsWidget(QFrame):
self.weather_widget.hide()
self.layout.addWidget(self.weather_widget, 0, 1)
def setCurrentTurn(
self, turn: int, conditions: Conditions, time: datetime | None
) -> None:
def setCurrentTurn(self, turn: int, conditions: Conditions) -> None:
"""Sets the turn information display.
:arg turn Current turn number.
:arg conditions Current weather conditions.
:arg time Current time.
:arg conditions Current time and weather conditions.
"""
self.time_turn_widget.set_current_turn(turn, conditions, time)
self.time_turn_widget.set_current_turn(turn, conditions)
self.weather_widget.setCurrentTurn(turn, conditions)
self.weather_widget.show()

View File

@@ -50,7 +50,10 @@ class QTopPanel(QFrame):
self.conditionsWidget = QConditionsWidget(sim_controller)
self.budgetBox = QBudgetBox(self.game)
self.passTurnButton = QPushButton(self._pass_turn_button_text(self.game))
pass_turn_text = "Pass Turn"
if not self.game or self.game.turn == 0:
pass_turn_text = "Begin Campaign"
self.passTurnButton = QPushButton(pass_turn_text)
self.passTurnButton.setIcon(CONST.ICONS["PassTurn"])
self.passTurnButton.setProperty("style", "btn-primary")
self.passTurnButton.clicked.connect(self.passTurn)
@@ -101,9 +104,7 @@ class QTopPanel(QFrame):
if game is None:
return
self.conditionsWidget.setCurrentTurn(
game.turn, game.conditions, game.simulation_time
)
self.conditionsWidget.setCurrentTurn(game.turn, game.conditions)
if game.conditions.weather.clouds:
base_m = game.conditions.weather.clouds.base
@@ -117,9 +118,11 @@ class QTopPanel(QFrame):
self.factionsInfos.setGame(game)
self.passTurnButton.setEnabled(True)
self.passTurnButton.setText(self._pass_turn_button_text(game))
if game and game.turn > 0:
self.passTurnButton.setText("Pass Turn")
if game and game.turn == 0:
self.passTurnButton.setText("Begin Campaign")
self.proceedButton.setEnabled(False)
else:
self.proceedButton.setEnabled(True)
@@ -278,11 +281,3 @@ class QTopPanel(QFrame):
def budget_update(self, game: Game):
self.budgetBox.setGame(game)
def _pass_turn_button_text(self, game: Game) -> None:
if game and game.turn > 0:
if game.settings.turnless_mode:
return "End Turn"
else:
return "Pass Turn"
return "Begin campaign"

View File

@@ -571,8 +571,7 @@ class QLiberationWindow(QMainWindow):
if state is not TurnState.CONTINUE:
GameOverDialog(won=state is TurnState.WIN, parent=self).exec()
else:
if not self.game.settings.turnless_mode:
self.game.pass_turn()
self.game.pass_turn()
GameUpdateSignal.get_instance().updateGame(self.game)
def open_tgo_info_dialog(self, tgo: TheaterGroundObject) -> None:

View File

@@ -23,7 +23,6 @@ from game.theater import ControlPoint, TheaterGroundObject
from game.theater.theatergroundobject import (
BuildingGroundObject,
)
from game.theater.theatergroup import TheaterUnit
from game.utils import Heading
from qt_ui.uiconstants import EVENT_ICONS, ICONS
from qt_ui.widgets.QBudgetBox import QBudgetBox
@@ -230,11 +229,10 @@ class QGroundObjectMenu(QDialog):
if self.sell_all_button is not None:
self.sell_all_button.setText("Disband (+$" + str(self.total_value) + "M)")
def repair_unit(self, unit: TheaterUnit, price: float):
def repair_unit(self, unit, price):
if self.game.blue.budget > price:
self.game.blue.budget -= price
unit.alive = True
unit.hit_points = unit.unit_type.hit_points # Restore unit health to full
GameUpdateSignal.get_instance().updateGame(self.game)
# Remove destroyed units in the vicinity

View File

@@ -843,7 +843,7 @@ class GeneratorOptions(QtWidgets.QWizardPage):
modLayout = QtWidgets.QGridLayout()
modLayout_row = 1
modLayout.addWidget(
QtWidgets.QLabel("A-4E Skyhawk (version 2.3.0)"), modLayout_row, 0
QtWidgets.QLabel("A-4E Skyhawk (version 2.2.0)"), modLayout_row, 0
)
modLayout.addWidget(a4_skyhawk, modLayout_row, 1)
modLayout_row += 1

View File

@@ -15,7 +15,7 @@ Faker==20.1.0
fastapi==0.115.8
filelock==3.13.1
future==0.18.3
h11==0.16.0
h11==0.14.0
httptools==0.6.1
identify==2.5.32
idna==3.7
@@ -36,8 +36,8 @@ pre-commit==3.5.0
pydantic==2.5.2
pydantic-settings==2.1.0
pydantic_core==2.14.5
pydcs @ git+https://github.com/dcs-liberation/dcs@046ed928de5d4aae1652251b87e46517ab334f6e
pyinstaller==6.0.0
pydcs @ git+https://github.com/dcs-liberation/dcs@d1c8e9557aa1113908f9705fbe084e7cf08d6000
pyinstaller==5.13.1
pyinstaller-hooks-contrib==2023.6
pyproj==3.6.1
PySide6==6.4.1

View File

@@ -178,15 +178,15 @@ local unitPayloads = {
["name"] = "Liberation SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}",
["CLSID"] = "{AGM_45A}",
["num"] = 5,
},
[2] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}",
["CLSID"] = "{AGM_45A}",
["num"] = 1,
},
[3] = {
["CLSID"] = "<CLEAN>",
["CLSID"] = "{AGM_45A}",
["num"] = 4,
},
[4] = {
@@ -194,7 +194,7 @@ local unitPayloads = {
["num"] = 3,
},
[5] = {
["CLSID"] = "<CLEAN>",
["CLSID"] = "{AGM_45A}",
["num"] = 2,
},
},
@@ -265,15 +265,15 @@ local unitPayloads = {
["name"] = "Liberation SEAD Escort",
["pylons"] = {
[1] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}",
["CLSID"] = "{AGM_45A}",
["num"] = 5,
},
[2] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}",
["CLSID"] = "{AGM_45A}",
["num"] = 1,
},
[3] = {
["CLSID"] = "<CLEAN>",
["CLSID"] = "{AGM_45A}",
["num"] = 4,
},
[4] = {
@@ -281,7 +281,7 @@ local unitPayloads = {
["num"] = 3,
},
[5] = {
["CLSID"] = "<CLEAN>",
["CLSID"] = "{AGM_45A}",
["num"] = 2,
},
},
@@ -352,11 +352,11 @@ local unitPayloads = {
["name"] = "Liberation DEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}",
["CLSID"] = "{AGM_45A}",
["num"] = 5,
},
[2] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}",
["CLSID"] = "{AGM_45A}",
["num"] = 1,
},
[3] = {

View File

@@ -1,344 +0,0 @@
local unitPayloads = {
["name"] = "F-14A",
["payloads"] = {
[1] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 L}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 R}",
["num"] = 9,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[2] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[4] = {
["CLSID"] = "{PHXBRU3242_2*LAU10 LS}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[3] = {
["name"] = "STRIKE",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[4] = {
["CLSID"] = "{SHOULDER AIM-7MH}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[4] = {
["name"] = "BAI",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[4] = {
["CLSID"] = "{PHXBRU3242_2*LAU10 LS}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{BRU-32 MK-20}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{BRU-32 MK-20}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[5] = {
["name"] = "ANTISHIP",
["pylons"] = {
[1] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[3] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[4] = {
["CLSID"] = "{PHXBRU3242_2*LAU10 LS}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 7,
},
[6] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 4,
},
[7] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 6,
},
[8] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 5,
},
[9] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[10] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
},
["tasks"] = {
[1] = 10,
},
},
[6] = {
["name"] = "Liberation DEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 L}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 R}",
["num"] = 9,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{MAK79_MK82 4}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{MAK79_MK82 3R}",
["num"] = 6,
},
[9] = {
["CLSID"] = "{MAK79_MK82 3L}",
["num"] = 5,
},
[10] = {
["CLSID"] = "{MAK79_MK82 4}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 31,
},
},
[7] = {
["displayName"] = "Liberation SEAD",
["name"] = "Liberation SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 L}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 R}",
["num"] = 9,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 6,
},
[9] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 5,
},
[10] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 31,
},
},
},
["unitType"] = "F-14A-135-GR-Early",
}
return unitPayloads

View File

@@ -1,224 +0,0 @@
local unitPayloads = {
["name"] = "MiG-29A",
["payloads"] = {
[1] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[2] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 5,
},
[3] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 6,
},
[4] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 3,
},
[5] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 2,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 30,
},
},
[2] = {
["name"] = "STRIKE",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
[5] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 6,
},
[7] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
},
["tasks"] = {
[1] = 32,
},
},
[3] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{9B25D316-0434-4954-868F-D51DB1A38DF0}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{9B25D316-0434-4954-868F-D51DB1A38DF0}",
["num"] = 5,
},
[5] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 6,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 10,
},
},
[4] = {
["name"] = "ANTISHIP",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[2] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 5,
},
[3] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 6,
},
[4] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 3,
},
[5] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 2,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 30,
},
},
[5] = {
["name"] = "SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[2] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 5,
},
[3] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 6,
},
[4] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 3,
},
[5] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 2,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 30,
},
},
[6] = {
["displayName"] = "OCA/Runway",
["name"] = "OCA/Runway",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
[5] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 6,
},
[7] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
},
["tasks"] = {
[1] = 34,
},
},
},
["unitType"] = "MiG-29 Fulcrum",
}
return unitPayloads

View File

@@ -6,8 +6,6 @@ max_ingress_distance_nm: 30
min_ingress_distance_nm: 10
rendezvous_altitude_ft_msl: 22000
combat_altitude_ft_msl: 18000
aewc:
duration_minutes: 240
cap:
duration_minutes: 30
min_track_length_nm: 12

View File

@@ -6,8 +6,6 @@ max_ingress_distance_nm: 45
min_ingress_distance_nm: 10
rendezvous_altitude_ft_msl: 25000
combat_altitude_ft_msl: 20000
aewc:
duration_minutes: 240
cap:
duration_minutes: 30
min_track_length_nm: 15

View File

@@ -6,8 +6,6 @@ max_ingress_distance_nm: 7
min_ingress_distance_nm: 5
rendezvous_altitude_ft_msl: 10000
combat_altitude_ft_msl: 8000
aewc:
duration_minutes: 240
cap:
duration_minutes: 30
min_track_length_nm: 8

View File

@@ -14,7 +14,6 @@ aircrafts:
- C-130
- C-130J-30 Super Hercules
- F-117A Nighthawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat
- F-15C Eagle

View File

@@ -15,7 +15,6 @@ aircrafts:
- C-130
- C-130J-30 Super Hercules
- F-117A Nighthawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat
- F-15C Eagle

View File

@@ -10,7 +10,6 @@ aircrafts:
- B-52H Stratofortress
- C-130
- C-130J-30 Super Hercules
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat
- F-4E-45MC Phantom II

View File

@@ -17,7 +17,6 @@ aircrafts:
- C-47 Dakota
- CH-47D
- CH-53E
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat
- F-15C Eagle

View File

@@ -7,7 +7,6 @@ locales:
- fa_IR
aircrafts:
- AH-1J SeaCobra
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-4E-45MC Phantom II
- F-5E Tiger II

View File

@@ -6,7 +6,6 @@ description: <p>Iranian 2010s faction</p>
locales:
- fa_IR
aircrafts:
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-4E-45MC Phantom II
- F-5E Tiger II
@@ -15,7 +14,6 @@ aircrafts:
- Mi-24P Hind-F
- Mi-28N Havoc
- MiG-21bis Fishbed-N
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A
- Mirage-F1EQ
- Su-22M4 Fitter-K

View File

@@ -13,7 +13,6 @@ aircrafts:
- MiG-21bis Fishbed-N
- MiG-23ML Flogger-G
- MiG-25PD Foxbat-E
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A
- Mirage-F1EQ
- SA 342M Gazelle

View File

@@ -11,7 +11,6 @@ aircrafts:
- MiG-19P Farmer-B
- MiG-21bis Fishbed-N
- MiG-23MLD Flogger-K
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A
awacs:
- A-50

View File

@@ -10,7 +10,6 @@ aircrafts:
- Mi-24V Hind-E
- Mi-24P Hind-F
- Mi-8MTV2 Hip
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A
- MiG-29G Fulcrum-A
- Su-22M4 Fitter-K

View File

@@ -13,7 +13,6 @@ aircrafts:
- MiG-21bis Fishbed-N
- MiG-23MLD Flogger-K
- MiG-25PD Foxbat-E
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A
- Su-17M4 Fitter-K
- Su-24M Fencer-D

View File

@@ -14,7 +14,6 @@ aircrafts:
- MiG-23MLD Flogger-K
- MiG-25PD Foxbat-E
- MiG-27K Flogger-J2
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A
- MiG-31 Foxhound
- Su-17M4 Fitter-K

View File

@@ -6,7 +6,6 @@ description: <p>US military during the Vietnam War from 1965 to 1975</p>
locales:
- en_US
aircrafts:
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-4C Phantom II
- F-4B Phantom II

View File

@@ -10,7 +10,6 @@ aircrafts:
- C-130
- CH-47D
- CH-53E
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-4E-45MC Phantom II
- F-4B Phantom II

View File

@@ -16,7 +16,6 @@ aircrafts:
- CH-47D
- CH-53E
- F-117A Nighthawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat
- F-15C Eagle

View File

@@ -8,7 +8,6 @@ locales:
aircrafts:
- AH-1W SuperCobra
- A-4E Skyhawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat
- F-4B Phantom II

View File

@@ -4,7 +4,6 @@ local WRITESTATE_SCHEDULE_IN_SECONDS = 60
logger = mist.Logger:new("DCSLiberation", "info")
logger:info("Check that json.lua is loaded : json = "..tostring(json))
simulation_time_seconds = 0
crash_events = {} -- killed aircraft will be added via S_EVENT_CRASH event
dead_events = {} -- killed units will be added via S_EVENT_DEAD event
unit_lost_events = {} -- killed units will be added via S_EVENT_UNIT_LOST
@@ -44,7 +43,6 @@ function write_state()
["destroyed_objects_positions"] = destroyed_objects_positions,
["killed_ground_units"] = killed_ground_units,
["unit_hit_point_updates"] = unit_hit_point_updates,
["simulation_time_seconds"] = simulation_time_seconds
}
if not json then
local message = string.format("Unable to save DCS Liberation state to %s, JSON library is not loaded !", _debriefing_file_location)
@@ -162,9 +160,6 @@ end
activeWeapons = {}
local function onEvent(event)
simulation_time_seconds = event.time
if event.id == world.event.S_EVENT_CRASH and event.initiator then
crash_events[#crash_events + 1] = event.initiator.getName(event.initiator)
write_state()
@@ -181,19 +176,16 @@ local function onEvent(event)
end
if event.id == world.event.S_EVENT_DEAD and event.initiator then
get_initiator_name_success, initiator_name = pcall(event.initiator.getName, event.initiator)
if get_initiator_name_success then
dead_events[#dead_events + 1] = event.initiator.getName(event.initiator)
local position = event.initiator.getPosition(event.initiator)
local destruction = {}
destruction.x = position.p.x
destruction.y = position.p.y
destruction.z = position.p.z
destruction.type = event.initiator:getTypeName()
destruction.orientation = mist.getHeading(event.initiator) * 57.3
destroyed_objects_positions[#destroyed_objects_positions + 1] = destruction
write_state()
end
dead_events[#dead_events + 1] = event.initiator.getName(event.initiator)
local position = event.initiator.getPosition(event.initiator)
local destruction = {}
destruction.x = position.p.x
destruction.y = position.p.y
destruction.z = position.p.z
destruction.type = event.initiator:getTypeName()
destruction.orientation = mist.getHeading(event.initiator) * 57.3
destroyed_objects_positions[#destroyed_objects_positions + 1] = destruction
write_state()
end
if event.id == world.event.S_EVENT_HIT then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,62 +0,0 @@
carrier_capable: true
description:
"The Grumman F-14 Tomcat is a two-crew, variable wing-geometry, maritime\
\ air superiority fighter that served with the US Navy for 32 years and continues\
\ to serve with the IRIAF in Iran. The F-14 was the US Navy's frontline fighter\
\ from the 1970s to the mid-2000s. Over the course of its long service it also became\
\ one of the US Navy\u2019s premier precision ground-attack platform and its lone\
\ airborne reconnaissance asset.\n\nNoteworthy features of the Tomcat are its swing-wing\
\ configuration, two-man crew, and the powerful AN/AWG-9 Weapons Control System\
\ (WCS) and radar. The AWG-9 allows employment of the long-range AIM-54 Phoenix\
\ air-to-air missile, and the LANTIRN targeting pod allows precision ground strikes\
\ using laser-guided bombs. The F-14 Tomcat was present in several historic events\
\ that include the two Gulf of Sidra incidents, Operations Desert Storm Iraqi Freedom,\
\ the Yugoslavian conflict, and Operation Enduring Freedom over Afghanistan. It\
\ was also immortalized in the iconic motion picture, Top Gun, and starred in several\
\ other feature films including The Final Countdown, Executive Decision, and others.\n\
\nThe Tomcat was also played a vital role in the Iran-Iraq war of the 1980s, where\
\ is flew for the Islamic Republic of Iran Air Force."
introduced: 1984
manufacturer: Grumman
origin: USA
price: 22
role: Carrier-based Air-Superiority Fighter/Fighter Bomber
max_range: 350
variants:
F-14A Tomcat (Block 135-GR Early): {}
radios:
intra_flight: AN/ARC-182
inter_flight: AN/ARC-159
channels:
type: common
namer: tomcat
intra_flight_radio_index: 2
inter_flight_radio_index: 1
default_overrides:
INSAlignmentStored: true
# ALE39Loadout: 0
# IlsChannel: 1
# KY28Key: 1
# LGB1: 8
# LGB10: 8
# LGB100: 6
# LGB1000: 1
# M61BURST: 0
# TacanBand: 0
# TacanChannel: 0
# UseLAU138: true
tasks:
BAI: 630
BARCAP: 520
CAS: 630
DEAD: 240
Escort: 520
Fighter sweep: 520
Intercept: 520
OCA/Aircraft: 630
OCA/Runway: 550
SEAD: 90
SEAD Escort: 90
Strike: 550
TARCAP: 520
hit_points: 20

View File

@@ -1,52 +0,0 @@
description:
'The MiG-29 "Fulcrum" is a Russian-designed, twin-engine, supersonic
fighter. First operational in the early 1980s, the Fulcrum is a "light weight" fighter,
comparable to the American F/A-18 Hornet and F-16. Designed to work in conjunction
with the larger Su-27 Flanker, the MiG-29 is armed with an internal 30mm cannon
and both infrared and radar guided air-to-air missiles. For air-to-ground tasks,
the MiG-29 can be armed with a large array of unguided bombs and rockets.
In addition to a sophisticated pulse doppler radar, the MiG-29 is also equipped
with a passive Infrared Search and Track (IRST) sensor that allows the Fulcrum to
detect and target enemy aircraft just based on target infrared emissions. This allows
the MiG-29 to make stealthy attacks with no warning!
The Fulcrum is a highly-maneuverable fighter in a dogfight, and when paired with
the helmet mounted sight and the AA-11 "Archer" air-to-air missile, it is a very
lethal adversary.
The MiG-29 has also been widely exported and has served in many countries that include
Germany, Iran, Ukraine, and Poland.'
introduced: 1983
manufacturer: Mikoyan
origin: USSR/Russia
price: 15
role: Multirole Fighter
max_range: 150
variants:
MIG-29-FULCRUM:
display_name: MiG-29A Fulcrum-A
kneeboard_units: "metric"
radios:
intra_flight: R862
inter_flight: R862
channels:
type: common
namer: fulcrum
intra_flight_radio_index: 1
inter_flight_radio_index: 1
tasks:
BAI: 530
BARCAP: 370
CAS: 530
Escort: 370
Fighter sweep: 370
Intercept: 370
OCA/Aircraft: 530
OCA/Runway: 410
Strike: 410
TARCAP: 370
hit_points: 16

View File

@@ -27,8 +27,7 @@ price: 15
role: Multirole Fighter
max_range: 150
variants:
MiG-29A Fulcrum-A:
display_name: MiG-29A Fulcrum-A (FC3)
MiG-29A Fulcrum-A: {}
kneeboard_units: "metric"
tasks:
BAI: 530